From 4d8d86bd6a27e9eea5bbf1440cbf317f02320519 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Tue, 29 May 2012 13:54:20 +0200 Subject: [PATCH 01/70] D3D11: Implement some PE pixel performance metrics. Super Mario Sunshine is using a cool trick: To determine how much goop has been cleaned in ep. 6 of Sirena Beach, it counts the number of pixels that are input to the blending stage. For that it's using the PE performance registers ;) Fixes issue 1498. --- Source/Core/VideoCommon/Src/BPMemory.h | 2 +- Source/Core/VideoCommon/Src/BPStructs.cpp | 13 +- Source/Core/VideoCommon/Src/PixelEngine.cpp | 71 +++++++--- Source/Core/VideoCommon/Src/PixelEngine.h | 27 ++-- Source/Core/VideoCommon/Src/RenderBase.h | 14 ++ .../VideoCommon/Src/VertexManagerBase.cpp | 2 + Source/Core/VideoCommon/Src/VideoConfig.cpp | 5 + Source/Core/VideoCommon/Src/VideoConfig.h | 2 + .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 133 ++++++++++++++++++ Source/Plugins/Plugin_VideoDX11/Src/Render.h | 6 + .../Plugin_VideoDX11/Src/VertexManager.cpp | 3 +- Source/Plugins/Plugin_VideoDX11/Src/main.cpp | 1 + Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 1 + Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 1 + 14 files changed, 245 insertions(+), 36 deletions(-) diff --git a/Source/Core/VideoCommon/Src/BPMemory.h b/Source/Core/VideoCommon/Src/BPMemory.h index 9284674aa1..ce65bcb824 100644 --- a/Source/Core/VideoCommon/Src/BPMemory.h +++ b/Source/Core/VideoCommon/Src/BPMemory.h @@ -62,7 +62,7 @@ #define BPMEM_COPYFILTER1 0x54 #define BPMEM_CLEARBBOX1 0x55 #define BPMEM_CLEARBBOX2 0x56 -#define BPMEM_UNKNOWN_57 0x57 +#define BPMEM_CLEAR_PIXEL_PERF 0x57 #define BPMEM_REVBITS 0x58 #define BPMEM_SCISSOROFFSET 0x59 #define BPMEM_PRELOAD_ADDR 0x60 diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index 179196e412..bc6de89bf2 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -62,7 +62,6 @@ void RenderToXFB(const BPCmd &bp, const EFBRectangle &rc, float yScale, float xf { Renderer::RenderToXFB(xfbAddr, dstWidth, dstHeight, rc, gamma); } - void BPWritten(const BPCmd& bp) { /* @@ -141,7 +140,8 @@ void BPWritten(const BPCmd& bp) || bp.address == BPMEM_LOADTLUT0 || bp.address == BPMEM_LOADTLUT1 || bp.address == BPMEM_TEXINVALIDATE - || bp.address == BPMEM_PRELOAD_MODE)) + || bp.address == BPMEM_PRELOAD_MODE + || bp.address == BPMEM_CLEAR_PIXEL_PERF)) { return; } @@ -265,6 +265,8 @@ void BPWritten(const BPCmd& bp) UPE_Copy PE_copy = bpmem.triggerEFBCopy; + g_renderer->ResumePixelPerf(true); + // Check if we are to copy from the EFB or draw to the XFB if (PE_copy.copy_to_xfb == 0) { @@ -303,6 +305,8 @@ void BPWritten(const BPCmd& bp) s_gammaLUT[PE_copy.gamma]); } + g_renderer->PausePixelPerf(true); + // Clear the rectangular region after copying it. if (PE_copy.clear) { @@ -481,8 +485,9 @@ void BPWritten(const BPCmd& bp) case BPMEM_REVBITS: // Always set to 0x0F when GX_InitRevBits() is called. break; - case BPMEM_UNKNOWN_57: // Sunshine alternates this register between values 0x000 and 0xAAA - DEBUG_LOG(VIDEO, "Unknown BP Reg 0x57: %08x", bp.newvalue); + case BPMEM_CLEAR_PIXEL_PERF: + // GXClearPixMetric writes 0xAAA here, Sunshine alternates this register between values 0x000 and 0xAAA + g_renderer->ResetPixelPerf(); break; case BPMEM_PRELOAD_ADDR: diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index a488e52b42..4aac3c2456 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -28,6 +28,7 @@ #include "ConfigManager.h" #include "PixelEngine.h" +#include "RenderBase.h" #include "CommandProcessor.h" #include "HW/ProcessorInterface.h" #include "DLCache.h" @@ -255,23 +256,59 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) break; } - case PE_PERF_0L: - case PE_PERF_0H: - case PE_PERF_1L: - case PE_PERF_1H: - case PE_PERF_2L: - case PE_PERF_2H: - case PE_PERF_3L: - case PE_PERF_3H: - case PE_PERF_4L: - case PE_PERF_4H: - case PE_PERF_5L: - case PE_PERF_5H: - INFO_LOG(PIXELENGINE, "(r16) perf counter @ %08x", _iAddress); - // git r90a2096a24f4 (svn r3663) added the PE_PERF cases, without setting - // _uReturnValue to anything, this reverts to the previous behaviour which allows - // The timer in SMS:Scrubbing Serena Beach to countdown correctly - _uReturnValue = 1; + // NOTE(neobrain): only PE_PERF_ZCOMP_OUTPUT is implemented in D3D11, but the other values shouldn't be contradictionary to the value of that register (i.e. INPUT registers should always be greater or equal to their corresponding OUTPUT registers). + case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L: + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_INPUT_ZCOMPLOC) & 0xFFFF; + break; + + case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H: + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_INPUT_ZCOMPLOC) >> 16; + break; + + case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L: + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_OUTPUT_ZCOMPLOC) & 0xFFFF; + break; + + case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H: + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_OUTPUT_ZCOMPLOC) >> 16; + break; + + case PE_PERF_ZCOMP_INPUT_L: + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_INPUT) & 0xFFFF; + break; + + case PE_PERF_ZCOMP_INPUT_H: + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_INPUT) >> 16; + break; + + case PE_PERF_ZCOMP_OUTPUT_L: + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_OUTPUT) & 0xFFFF; + break; + + case PE_PERF_ZCOMP_OUTPUT_H: + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_OUTPUT) >> 16; + break; + + case PE_PERF_BLEND_INPUT_L: + // Super Mario Sunshine uses this register in episode 6 of Sirena Beach: + // The amount of remaining goop is determined by checking how many pixels reach the blending stage. + // Once this register falls below a particular value (around 0x90), the game regards the challenge finished. + // In very old builds, Dolphin only returned 0. That caused the challenge to be immediately finished without any goop being cleaned (the timer just didn't even start counting from 3:00:00). + // Later builds returned 1 for the high register. That caused the timer to actually count down, but made the challenge unbeatable because the game always thought you didn't clear any goop at all. + // Note that currently this functionality is only implemented in the D3D11 backend. + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_BLEND_INPUT) & 0xFFFF; + break; + + case PE_PERF_BLEND_INPUT_H: + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_BLEND_INPUT) >> 16; + break; + + case PE_PERF_EFB_COPY_CLOCKS_L: + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_EFB_COPY_CLOCKS) & 0xFFFF; + break; + + case PE_PERF_EFB_COPY_CLOCKS_H: + _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_EFB_COPY_CLOCKS) >> 16; break; default: diff --git a/Source/Core/VideoCommon/Src/PixelEngine.h b/Source/Core/VideoCommon/Src/PixelEngine.h index 64f959009f..eaf55f0031 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.h +++ b/Source/Core/VideoCommon/Src/PixelEngine.h @@ -36,19 +36,20 @@ enum PE_BBOX_TOP = 0x14, // Flip Top PE_BBOX_BOTTOM = 0x16, // Flip Bottom - // These have not yet been RE:d. They are the perf counters. - PE_PERF_0L = 0x18, - PE_PERF_0H = 0x1a, - PE_PERF_1L = 0x1c, - PE_PERF_1H = 0x1e, - PE_PERF_2L = 0x20, - PE_PERF_2H = 0x22, - PE_PERF_3L = 0x24, - PE_PERF_3H = 0x26, - PE_PERF_4L = 0x28, - PE_PERF_4H = 0x2a, - PE_PERF_5L = 0x2c, - PE_PERF_5H = 0x2e, + // NOTE: Order not verified + // These indicate the number of quads that are being used as input/output for each particular stage + PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L = 0x18, + PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H = 0x1a, + PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L = 0x1c, + PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H = 0x1e, + PE_PERF_ZCOMP_INPUT_L = 0x20, + PE_PERF_ZCOMP_INPUT_H = 0x22, + PE_PERF_ZCOMP_OUTPUT_L = 0x24, + PE_PERF_ZCOMP_OUTPUT_H = 0x26, + PE_PERF_BLEND_INPUT_L = 0x28, + PE_PERF_BLEND_INPUT_H = 0x2a, + PE_PERF_EFB_COPY_CLOCKS_L = 0x2c, + PE_PERF_EFB_COPY_CLOCKS_H = 0x2e, }; namespace PixelEngine diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index e8d4c55a20..4d288143c0 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -52,6 +52,15 @@ public: Renderer(); virtual ~Renderer(); + enum PixelPerfQuery { + PP_ZCOMP_INPUT_ZCOMPLOC, + PP_ZCOMP_OUTPUT_ZCOMPLOC, + PP_ZCOMP_INPUT, + PP_ZCOMP_OUTPUT, + PP_BLEND_INPUT, + PP_EFB_COPY_CLOCKS + }; + virtual void SetColorMask() = 0; virtual void SetBlendMode(bool forceUpdate) = 0; virtual void SetScissorRect(const TargetRectangle& rc) = 0; @@ -119,6 +128,11 @@ public: static unsigned int GetPrevPixelFormat() { return prev_efb_format; } static void StorePixelFormat(unsigned int new_format) { prev_efb_format = new_format; } + virtual void ResetPixelPerf() {}; + virtual void ResumePixelPerf(bool efb_copies) {}; + virtual void PausePixelPerf(bool efb_copies) {}; + virtual u32 GetPixelPerfResult(PixelPerfQuery type) { return 0; }; + // TODO: doesn't belong here virtual void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) = 0; virtual void SetPSConstant4fv(unsigned int const_number, const float *f) = 0; diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp index 4118e3dcbd..86dd891386 100644 --- a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp @@ -253,7 +253,9 @@ void VertexManager::Flush() //if (g_nativeVertexFmt) g_nativeVertexFmt->SetupVertexPointers(); + g_renderer->ResumePixelPerf(false); g_vertex_manager->Draw(stride, false); + g_renderer->PausePixelPerf(false); // run through vertex groups again to set alpha if (false == g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate) diff --git a/Source/Core/VideoCommon/Src/VideoConfig.cpp b/Source/Core/VideoCommon/Src/VideoConfig.cpp index c5628c19a1..5f464c3322 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.cpp +++ b/Source/Core/VideoCommon/Src/VideoConfig.cpp @@ -104,6 +104,7 @@ void VideoConfig::Load(const char *ini_file) iniFile.Get("Hacks", "EFBScaledCopy", &bCopyEFBScaled, true); iniFile.Get("Hacks", "EFBCopyCacheEnable", &bEFBCopyCacheEnable, false); iniFile.Get("Hacks", "EFBEmulateFormatChanges", &bEFBEmulateFormatChanges, false); + iniFile.Get("Hacks", "DisablePixelPerf", &bDisablePixelPerf, true); iniFile.Get("Hardware", "Adapter", &iAdapter, 0); @@ -153,6 +154,7 @@ void VideoConfig::GameIniLoad(const char *ini_file) iniFile.GetIfExists("Video_Hacks", "EFBScaledCopy", &bCopyEFBScaled); iniFile.GetIfExists("Video_Hacks", "EFBCopyCacheEnable", &bEFBCopyCacheEnable); iniFile.GetIfExists("Video_Hacks", "EFBEmulateFormatChanges", &bEFBEmulateFormatChanges); + iniFile.GetIfExists("Video_Hacks", "DisablePixelPerf", &bDisablePixelPerf); iniFile.GetIfExists("Video", "ProjectionHack", &iPhackvalue[0]); iniFile.GetIfExists("Video", "PH_SZNear", &iPhackvalue[1]); @@ -172,6 +174,7 @@ void VideoConfig::VerifyValidity() if (!backend_info.bSupports3DVision) b3DVision = false; if (!backend_info.bSupportsFormatReinterpretation) bEFBEmulateFormatChanges = false; if (!backend_info.bSupportsPixelLighting) bEnablePixelLighting = false; + if (!backend_info.bSupportsPixelPerfQuery) bDisablePixelPerf = true; } void VideoConfig::Save(const char *ini_file) @@ -231,6 +234,7 @@ void VideoConfig::Save(const char *ini_file) iniFile.Set("Hacks", "EFBScaledCopy", bCopyEFBScaled); iniFile.Set("Hacks", "EFBCopyCacheEnable", bEFBCopyCacheEnable); iniFile.Set("Hacks", "EFBEmulateFormatChanges", bEFBEmulateFormatChanges); + iniFile.Set("Hacks", "DisablePixelPerf", bDisablePixelPerf); iniFile.Set("Hardware", "Adapter", iAdapter); @@ -287,6 +291,7 @@ void VideoConfig::GameIniSave(const char* default_ini, const char* game_ini) SET_IF_DIFFERS("Video_Hacks", "EFBScaledCopy", bCopyEFBScaled); SET_IF_DIFFERS("Video_Hacks", "EFBCopyCacheEnable", bEFBCopyCacheEnable); SET_IF_DIFFERS("Video_Hacks", "EFBEmulateFormatChanges", bEFBEmulateFormatChanges); + SET_IF_DIFFERS("Video_Hacks", "DisablePixelPerf", bDisablePixelPerf); iniFile.Save(game_ini); } diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h index 7653972ec8..8593de4fd7 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.h +++ b/Source/Core/VideoCommon/Src/VideoConfig.h @@ -133,6 +133,7 @@ struct VideoConfig bool bUseBBox; bool bEnablePixelLighting; bool bEnablePerPixelDepth; + bool bDisablePixelPerf; int iLog; // CONF_ bits int iSaveTargetId; // TODO: Should be dropped @@ -161,6 +162,7 @@ struct VideoConfig bool bSupportsDualSourceBlend; // only supported by D3D11 and OpenGL bool bSupportsFormatReinterpretation; bool bSupportsPixelLighting; + bool bSupportsPixelPerfQuery; } backend_info; }; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 3a725452e7..3f88d7f99d 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -65,6 +65,19 @@ ID3D11RasterizerState* resetraststate = NULL; static ID3D11Texture2D* s_screenshot_texture = NULL; +// Using a vector of query objects to avoid flushing the gpu pipeline all the time +// TODO: Could probably optimized further by using a ring buffer or something +#define MAX_PIXEL_PERF_QUERIES 20 // 20 is an arbitrary guess +std::vector pixel_perf_queries; +static int pixel_perf_query_index = 0; + +static u64 pixel_perf = 0; +static bool pixel_perf_active = false; +static bool pixel_perf_dirty = false; + +ID3D11Query* gpu_finished_query = NULL; + + // GX pipeline state struct { @@ -302,6 +315,9 @@ void SetupDeviceObjects() D3D::SetDebugObjectName((ID3D11DeviceChild*)resetraststate, "rasterizer state for Renderer::ResetAPIState"); s_screenshot_texture = NULL; + + D3D11_QUERY_DESC qdesc = CD3D11_QUERY_DESC(D3D11_QUERY_EVENT, 0); + D3D::device->CreateQuery(&qdesc, &gpu_finished_query); } // Kill off all device objects @@ -309,6 +325,12 @@ void TeardownDeviceObjects() { delete g_framebuffer_manager; + while (!pixel_perf_queries.empty()) + { + SAFE_RELEASE(pixel_perf_queries.back()); + pixel_perf_queries.pop_back(); + } + SAFE_RELEASE(gpu_finished_query); SAFE_RELEASE(access_efb_cbuf); SAFE_RELEASE(clearblendstates[0]); SAFE_RELEASE(clearblendstates[1]); @@ -357,6 +379,11 @@ Renderer::Renderer() s_LastEFBScale = g_ActiveConfig.iEFBScale; CalculateTargetSize(); + pixel_perf_query_index = 0; + pixel_perf = 0; + pixel_perf_active = false; + pixel_perf_dirty = false; + SetupDeviceObjects(); @@ -777,6 +804,112 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); } +void Renderer::ResetPixelPerf() +{ + if (g_ActiveConfig.bDisablePixelPerf) + return; + + if (pixel_perf_active) + PausePixelPerf(false); + + pixel_perf_query_index = 0; + pixel_perf = 0; +} + +void Renderer::ResumePixelPerf(bool efb_copies) +{ + if (g_ActiveConfig.bDisablePixelPerf) + return; + + if (efb_copies) + return; + + if(pixel_perf_active) + return; + + if (pixel_perf_queries.size() < pixel_perf_query_index+1 && pixel_perf_query_index < MAX_PIXEL_PERF_QUERIES) + { + D3D11_QUERY_DESC qdesc = CD3D11_QUERY_DESC(D3D11_QUERY_OCCLUSION, 0); + ID3D11Query* tmpquery = NULL; + D3D::device->CreateQuery(&qdesc, &tmpquery); + pixel_perf_queries.push_back(tmpquery); + pixel_perf_query_index = pixel_perf_queries.size() - 1; + } + else if (pixel_perf_queries.size() < pixel_perf_query_index+1) + { + StorePixelPerfResult(PP_ZCOMP_OUTPUT); + pixel_perf_query_index = 0; + } + // This will spam the D3D11 debug runtime output with QUERY_BEGIN_ABANDONING_PREVIOUS_RESULTS warnings which safely can be ignored. Mute them in the DX control panel if you need to read the debug runtime output. + D3D::context->Begin(pixel_perf_queries[pixel_perf_query_index]); + pixel_perf_active = true; + pixel_perf_dirty = true; +} + +void Renderer::PausePixelPerf(bool efb_copies) +{ + if (g_ActiveConfig.bDisablePixelPerf) + return; + + if(!pixel_perf_active) + return; + + D3D::context->End(pixel_perf_queries[pixel_perf_query_index]); + pixel_perf_query_index++; + pixel_perf_active = false; +} + +void Renderer::StorePixelPerfResult(PixelPerfQuery type) +{ + // First, make sure the GPU has finished rendering so that query results are valid + D3D::context->End(gpu_finished_query); + BOOL gpu_finished = FALSE; + while (!gpu_finished) + { + // If nothing goes horribly wrong here, this should complete in finite time... + D3D::context->GetData(gpu_finished_query, &gpu_finished, sizeof(gpu_finished), 0); + } + + for(int i = 0; i < pixel_perf_query_index; ++i) + { + UINT64 buf = 0; + D3D::context->GetData(pixel_perf_queries[i], &buf, sizeof(buf), 0); + + // Reported pixel metrics should be referenced to native resolution: + pixel_perf += buf * EFB_WIDTH * EFB_HEIGHT / GetTargetWidth() / GetTargetHeight(); + } + pixel_perf_dirty = false; +} + +u32 Renderer::GetPixelPerfResult(PixelPerfQuery type) +{ + if (g_ActiveConfig.bDisablePixelPerf) + return 0; + + if (type == PP_EFB_COPY_CLOCKS) + { + // not implemented + return 0; + } + + if (type == PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L || + type == PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H || + type == PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L || + type == PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H) + { + // return zero for now because ZCOMP_OUTPUT_ZCOMPLOC + ZCOMP_OUTPUT should equal BLEND_INPUT + // TODO: Instead, should keep separate counters for zcomploc and non-zcomploc registers. + return 0; + } + + // Basically we only implement PP_ZCOMP_OUTPUT, but we're returning the same value for PP_ZCOMP_INPUT and PP_BLEND_INPUT anyway + if (pixel_perf_dirty) + StorePixelPerfResult(PP_ZCOMP_OUTPUT); + + // Dividing by 4 because we're expected to return the number of 2x2 quads instead of pixels + return std::min(pixel_perf / 4, (u64)0xFFFFFFFF); +} + void SetSrcBlend(D3D11_BLEND val) { // Colors should blend against SRC_ALPHA diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.h b/Source/Plugins/Plugin_VideoDX11/Src/Render.h index 8f6c78fae1..6db829c205 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.h @@ -46,6 +46,12 @@ public: void ReinterpretPixelData(unsigned int convtype); + void ResetPixelPerf(); + void ResumePixelPerf(bool efb_copies); + void PausePixelPerf(bool efb_copies); + u32 GetPixelPerfResult(PixelPerfQuery type); + void StorePixelPerfResult(PixelPerfQuery type); // internal + void UpdateViewport(Matrix44& vpCorrection); bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index 58bad98cc6..4bb04bc302 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -198,7 +198,6 @@ void VertexManager::Draw(UINT stride) if (IndexGenerator::GetNumLines() > 0 || IndexGenerator::GetNumPoints() > 0) ((DX11::Renderer*)g_renderer)->RestoreCull(); } - void VertexManager::vFlush() { if (LocalVBuffer == s_pCurBufferPointer) return; @@ -266,7 +265,9 @@ void VertexManager::vFlush() g_renderer->ApplyState(useDstAlpha); LoadBuffers(); + g_renderer->ResumePixelPerf(false); Draw(stride); + g_renderer->PausePixelPerf(false); GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index cb348b8684..161321cf08 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -94,6 +94,7 @@ void InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsFormatReinterpretation = true; g_Config.backend_info.bSupportsPixelLighting = true; + g_Config.backend_info.bSupportsPixelPerfQuery = true; IDXGIFactory* factory; IDXGIAdapter* ad; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index 5aeca6751d..1d1a2db112 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -96,6 +96,7 @@ void InitBackendInfo() g_Config.backend_info.bSupports3DVision = true; g_Config.backend_info.bSupportsDualSourceBlend = false; g_Config.backend_info.bSupportsFormatReinterpretation = true; + g_Config.backend_info.bSupportsPixelPerfQuery = false; g_Config.backend_info.bSupportsPixelLighting = C_PLIGHTS + 40 <= maxConstants && C_PMATERIALS + 4 <= maxConstants; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index 543fb9824d..2c8f6d4716 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -135,6 +135,7 @@ void InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = false; // supported, but broken g_Config.backend_info.bSupportsFormatReinterpretation = false; g_Config.backend_info.bSupportsPixelLighting = true; + g_Config.backend_info.bSupportsPixelPerfQuery = false; // aamodes const char* caamodes[] = {"None", "2x", "4x", "8x", "8x CSAA", "8xQ CSAA", "16x CSAA", "16xQ CSAA"}; From cf8744cf2c1de2231d180348c4b55ebc2b35240f Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sun, 17 Jun 2012 13:58:29 +0200 Subject: [PATCH 02/70] OGL: Implement pixel metrics (untested) --- Source/Core/VideoCommon/CMakeLists.txt | 1 + Source/Core/VideoCommon/Src/BPStructs.cpp | 3 +- Source/Core/VideoCommon/Src/PerfQueryBase.cpp | 3 + Source/Core/VideoCommon/Src/PerfQueryBase.h | 39 ++++++++++ Source/Core/VideoCommon/Src/PixelEngine.cpp | 26 ++++--- Source/Plugins/Plugin_VideoOGL/CMakeLists.txt | 1 + .../Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp | 78 +++++++++++++++++++ .../Plugins/Plugin_VideoOGL/Src/PerfQuery.h | 22 ++++++ .../Plugin_VideoOGL/Src/VertexManager.cpp | 4 + Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 2 + 10 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 Source/Core/VideoCommon/Src/PerfQueryBase.cpp create mode 100644 Source/Core/VideoCommon/Src/PerfQueryBase.h create mode 100644 Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp create mode 100644 Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index d0e28f571c..5a4ed87c1d 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -16,6 +16,7 @@ set(SRCS Src/BPFunctions.cpp Src/OpcodeDecoding.cpp Src/OpenCL.cpp Src/OpenCL/OCLTextureDecoder.cpp + Src/PerfQueryBase.cpp Src/PixelEngine.cpp Src/PixelShaderGen.cpp Src/PixelShaderManager.cpp diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index bc6de89bf2..cda0f7c7c0 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -31,6 +31,7 @@ #include "VertexShaderManager.h" #include "Thread.h" #include "HW/Memmap.h" +#include "PerfQueryBase.h" using namespace BPFunctions; @@ -487,7 +488,7 @@ void BPWritten(const BPCmd& bp) case BPMEM_CLEAR_PIXEL_PERF: // GXClearPixMetric writes 0xAAA here, Sunshine alternates this register between values 0x000 and 0xAAA - g_renderer->ResetPixelPerf(); + g_perf_query->ResetQuery(); break; case BPMEM_PRELOAD_ADDR: diff --git a/Source/Core/VideoCommon/Src/PerfQueryBase.cpp b/Source/Core/VideoCommon/Src/PerfQueryBase.cpp new file mode 100644 index 0000000000..c537d176f6 --- /dev/null +++ b/Source/Core/VideoCommon/Src/PerfQueryBase.cpp @@ -0,0 +1,3 @@ +#include "PerfQueryBase.h" + +PerfQueryBase* g_perf_query = 0; diff --git a/Source/Core/VideoCommon/Src/PerfQueryBase.h b/Source/Core/VideoCommon/Src/PerfQueryBase.h new file mode 100644 index 0000000000..0520e9244c --- /dev/null +++ b/Source/Core/VideoCommon/Src/PerfQueryBase.h @@ -0,0 +1,39 @@ +#ifndef _PERFQUERY_BASE_H_ +#define _PERFQUERY_BASE_H_ + +#include "CommonTypes.h" + +enum PerfQueryType +{ + PQ_ZCOMP_INPUT_ZCOMPLOC = 0, + PQ_ZCOMP_OUTPUT_ZCOMPLOC, + PQ_ZCOMP_INPUT, + PQ_ZCOMP_OUTPUT, + PQ_BLEND_INPUT, + PQ_EFB_COPY_CLOCKS, + PQ_NUM_MEMBERS +}; + +enum PerfQueryGroup +{ + PQG_ZCOMP_ZCOMPLOC, + PQG_ZCOMP, + PQG_EFB_COPY_CLOCKS, + PQG_NUM_MEMBERS, +}; + +class PerfQueryBase +{ +public: + PerfQueryBase() {}; + virtual ~PerfQueryBase() {} + + virtual void EnableQuery(PerfQueryGroup type) {} + virtual void DisableQuery(PerfQueryGroup type) {} + virtual void ResetQuery() {} + virtual u32 GetQueryResult(PerfQueryType type) { return 0; } +}; + +extern PerfQueryBase* g_perf_query; + +#endif // _PERFQUERY_H_ diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index 4aac3c2456..005468f63c 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -33,6 +33,8 @@ #include "HW/ProcessorInterface.h" #include "DLCache.h" #include "State.h" +#include "PerfQueryBase.h" + namespace PixelEngine { @@ -258,35 +260,35 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) // NOTE(neobrain): only PE_PERF_ZCOMP_OUTPUT is implemented in D3D11, but the other values shouldn't be contradictionary to the value of that register (i.e. INPUT registers should always be greater or equal to their corresponding OUTPUT registers). case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L: - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_INPUT_ZCOMPLOC) & 0xFFFF; + _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) & 0xFFFF; break; case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H: - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_INPUT_ZCOMPLOC) >> 16; + _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) >> 16; break; case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L: - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_OUTPUT_ZCOMPLOC) & 0xFFFF; + _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) & 0xFFFF; break; case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H: - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_OUTPUT_ZCOMPLOC) >> 16; + _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) >> 16; break; case PE_PERF_ZCOMP_INPUT_L: - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_INPUT) & 0xFFFF; + _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_INPUT) & 0xFFFF; break; case PE_PERF_ZCOMP_INPUT_H: - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_INPUT) >> 16; + _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_INPUT) >> 16; break; case PE_PERF_ZCOMP_OUTPUT_L: - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_OUTPUT) & 0xFFFF; + _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_OUTPUT) & 0xFFFF; break; case PE_PERF_ZCOMP_OUTPUT_H: - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_ZCOMP_OUTPUT) >> 16; + _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_OUTPUT) >> 16; break; case PE_PERF_BLEND_INPUT_L: @@ -296,19 +298,19 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) // In very old builds, Dolphin only returned 0. That caused the challenge to be immediately finished without any goop being cleaned (the timer just didn't even start counting from 3:00:00). // Later builds returned 1 for the high register. That caused the timer to actually count down, but made the challenge unbeatable because the game always thought you didn't clear any goop at all. // Note that currently this functionality is only implemented in the D3D11 backend. - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_BLEND_INPUT) & 0xFFFF; + _uReturnValue = g_perf_query->GetQueryResult(PQ_BLEND_INPUT) & 0xFFFF; break; case PE_PERF_BLEND_INPUT_H: - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_BLEND_INPUT) >> 16; + _uReturnValue = g_perf_query->GetQueryResult(PQ_BLEND_INPUT) >> 16; break; case PE_PERF_EFB_COPY_CLOCKS_L: - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_EFB_COPY_CLOCKS) & 0xFFFF; + _uReturnValue = g_perf_query->GetQueryResult(PQ_EFB_COPY_CLOCKS) & 0xFFFF; break; case PE_PERF_EFB_COPY_CLOCKS_H: - _uReturnValue = g_renderer->GetPixelPerfResult(Renderer::PP_EFB_COPY_CLOCKS) >> 16; + _uReturnValue = g_perf_query->GetQueryResult(PQ_EFB_COPY_CLOCKS) >> 16; break; default: diff --git a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt index b506087106..834e905faa 100644 --- a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt +++ b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt @@ -2,6 +2,7 @@ set(SRCS Src/FramebufferManager.cpp Src/GLUtil.cpp Src/main.cpp Src/NativeVertexFormat.cpp + Src/PerfQuery.cpp Src/PixelShaderCache.cpp Src/PostProcessing.cpp Src/RasterFont.cpp diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp new file mode 100644 index 0000000000..cb659e6921 --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp @@ -0,0 +1,78 @@ +#include "GLUtil.h" +#include "PerfQuery.h" + +namespace OGL { + +u32 results[PQG_NUM_MEMBERS] = { 0 }; +GLuint query_id; + +PerfQueryGroup active_query; + +PerfQuery::PerfQuery() +{ + glGenQueries(1, &query_id); +} + +PerfQuery::~PerfQuery() +{ + glDeleteQueries(1, &query_id); +} + +void PerfQuery::EnableQuery(PerfQueryGroup type) +{ + // start query + if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) + { + glBeginQuery(GL_SAMPLES_PASSED, query_id); + } + active_query = type; +} + +void PerfQuery::DisableQuery(PerfQueryGroup type) +{ + // stop query + if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) + { + glEndQuery(GL_SAMPLES_PASSED); + + GLuint query_result = GL_FALSE; + while (query_result != GL_TRUE) + { + glGetQueryObjectuiv(query_id, GL_QUERY_RESULT_AVAILABLE, &query_result); + } + + glGetQueryObjectuiv(query_id, GL_QUERY_RESULT, &query_result); + + results[active_query] += query_result; + } +} + +void PerfQuery::ResetQuery() +{ + memset(results, 0, sizeof(results)); +} + +u32 PerfQuery::GetQueryResult(PerfQueryType type) +{ + if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC || type == PQ_BLEND_INPUT) + { + + } + if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT || type == PQ_BLEND_INPUT) + { + + } + if (type == PQ_BLEND_INPUT) + { + results[PQ_BLEND_INPUT] = results[PQ_ZCOMP_OUTPUT] + results[PQ_ZCOMP_OUTPUT_ZCOMPLOC]; + } + + if (type == PQ_EFB_COPY_CLOCKS) + { + // TODO + } + + return results[type]; +} + +} // namespace diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h new file mode 100644 index 0000000000..776c576e2d --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h @@ -0,0 +1,22 @@ +#ifndef _PERFQUERY_H_ +#define _PERFQUERY_H_ + +#include "PerfQueryBase.h" + +namespace OGL { + +class PerfQuery : public PerfQueryBase +{ +public: + PerfQuery(); + ~PerfQuery(); + + void EnableQuery(PerfQueryGroup type); + void DisableQuery(PerfQueryGroup type); + void ResetQuery(); + u32 GetQueryResult(PerfQueryType type); +}; + +} // namespace + +#endif // _PERFQUERY_H_ diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index 0a37b0e654..b2f55adec5 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -40,6 +40,7 @@ #include "OpcodeDecoding.h" #include "FileUtil.h" #include "Debugger.h" +#include "PerfQueryBase.h" #include "main.h" @@ -207,7 +208,10 @@ void VertexManager::vFlush() if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid); // Lego Star Wars crashes here. if (vs) VertexShaderCache::SetCurrentShader(vs->glprogid); + g_perf_query->EnableQuery(bpmem.zcontrol.zcomploc ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); Draw(); + g_perf_query->DisableQuery(bpmem.zcontrol.zcomploc ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); + ERROR_LOG(VIDEO, "PerfQuery result: %d", g_perf_query->GetQueryResult(bpmem.zcontrol.zcomploc ? PQ_ZCOMP_OUTPUT_ZCOMPLOC : PQ_ZCOMP_OUTPUT)); // run through vertex groups again to set alpha if (useDstAlpha && !dualSourcePossible) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index 2c8f6d4716..329d131ded 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -93,6 +93,7 @@ Make AA apply instantly during gameplay if possible #include "FramebufferManager.h" #include "Core.h" #include "Host.h" +#include "PerfQuery.h" #include "VideoState.h" #include "VideoBackend.h" @@ -194,6 +195,7 @@ void VideoBackend::Video_Prepare() BPInit(); g_vertex_manager = new VertexManager; + g_perf_query = new PerfQuery; Fifo_Init(); // must be done before OpcodeDecoder_Init() OpcodeDecoder_Init(); VertexShaderCache::Init(); From 26de63a8cd3e0b05c1ca01bd19e25ace5631943f Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sun, 17 Jun 2012 19:49:48 +0200 Subject: [PATCH 03/70] Video_Software: Implement PE pixel metrics --- .../Plugin_VideoSoftware/Src/BPMemLoader.cpp | 9 ++++++++ .../Plugin_VideoSoftware/Src/Rasterizer.cpp | 15 ++++++++---- .../Plugin_VideoSoftware/Src/SWPixelEngine.h | 23 +++++++++++++++++++ .../Plugins/Plugin_VideoSoftware/Src/Tev.cpp | 18 +++++++++++---- 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp index 95ec555181..ad730a485c 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp @@ -90,6 +90,15 @@ void SWBPWritten(int address, int newvalue) SWPixelEngine::pereg.boxBottom = newvalue >> 10; SWPixelEngine::pereg.boxTop = newvalue & 0x3ff; break; + case BPMEM_CLEAR_PIXEL_PERF: + // TODO: Parameter? + SWPixelEngine::pereg.perfZcompInputZcomploc = 0; + SWPixelEngine::pereg.perfZcompOutputZcomploc = 0; + SWPixelEngine::pereg.perfZcompInput = 0; + SWPixelEngine::pereg.perfZcompOutput = 0; + SWPixelEngine::pereg.perfBlendInput = 0; + SWPixelEngine::pereg.perfEfbCopyClocks = 0; + break; case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here. break; case BPMEM_LOADTLUT1: // Load a Texture Look Up Table diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp index c212c93601..a23d85f27f 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp @@ -23,6 +23,7 @@ #include "BPMemLoader.h" #include "XFMemLoader.h" #include "Tev.h" +#include "SWPixelEngine.h" #include "SWStatistics.h" #include "SWVideoConfig.h" @@ -125,11 +126,17 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi) if (z < 0 || z > 0x00ffffff) return; - if (bpmem.zcontrol.zcomploc && bpmem.zmode.testenable) + if (bpmem.zcontrol.zcomploc) { - // early z - if (!EfbInterface::ZCompare(x, y, z)) - return; + // TODO: Verify that perf regs are being incremented even if test is disabled + SWPixelEngine::pereg.perfZcompInputZcomploc++; + if (bpmem.zmode.testenable) + { + // early z + if (!EfbInterface::ZCompare(x, y, z)) + return; + } + SWPixelEngine::pereg.perfZcompOutputZcomploc++; } RasterBlockPixel& pixel = rasterBlock.Pixel[xi][yi]; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h index 6a87143e8c..764488c32e 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h @@ -38,6 +38,21 @@ namespace SWPixelEngine PE_BBOX_RIGHT = 0x012, // Flip Right PE_BBOX_TOP = 0x014, // Flip Top PE_BBOX_BOTTOM = 0x016, // Flip Bottom + + // NOTE: Order not verified + // These indicate the number of quads that are being used as input/output for each particular stage + PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L = 0x18, + PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H = 0x1a, + PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L = 0x1c, + PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H = 0x1e, + PE_PERF_ZCOMP_INPUT_L = 0x20, + PE_PERF_ZCOMP_INPUT_H = 0x22, + PE_PERF_ZCOMP_OUTPUT_L = 0x24, + PE_PERF_ZCOMP_OUTPUT_H = 0x26, + PE_PERF_BLEND_INPUT_L = 0x28, + PE_PERF_BLEND_INPUT_H = 0x2a, + PE_PERF_EFB_COPY_CLOCKS_L = 0x2c, + PE_PERF_EFB_COPY_CLOCKS_H = 0x2e, }; union UPEZConfReg @@ -125,10 +140,18 @@ namespace SWPixelEngine UPECtrlReg ctrl; u16 unk0; u16 token; + u16 boxLeft; u16 boxRight; u16 boxTop; u16 boxBottom; + + u16 perfZcompInputZcomploc; + u16 perfZcompOutputZcomploc; + u16 perfZcompInput; + u16 perfZcompOutput; + u16 perfBlendInput; + u16 perfEfbCopyClocks; }; extern PEReg pereg; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp index c67ee53837..83d9de2784 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp @@ -20,6 +20,7 @@ #include "Tev.h" #include "EfbInterface.h" #include "TextureSampler.h" +#include "SWPixelEngine.h" #include "SWStatistics.h" #include "SWVideoConfig.h" #include "DebugUtil.h" @@ -784,11 +785,16 @@ void Tev::Draw() output[BLU_C] = (output[BLU_C] * invFog + fogInt * bpmem.fog.color.b) >> 8; } - if (!bpmem.zcontrol.zcomploc && bpmem.zmode.testenable) - { - if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2])) - return; - } + if (!bpmem.zcontrol.zcomploc) + { + SWPixelEngine::pereg.perfZcompInput++; + if (bpmem.zmode.testenable) + { + if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2])) + return; + } + SWPixelEngine::pereg.perfZcompOutput++; + } #if ALLOW_TEV_DUMPS if (g_SWVideoConfig.bDumpTevStages) @@ -812,6 +818,8 @@ void Tev::Draw() INCSTAT(swstats.thisFrame.tevPixelsOut); + SWPixelEngine::pereg.perfBlendInput++; + EfbInterface::BlendTev(Position[0], Position[1], output); } From 1c1ae63b697fa5589772c92a78a635ef68f67f83 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Tue, 19 Jun 2012 23:05:39 +0200 Subject: [PATCH 04/70] Windows build fix. --- Source/Core/VideoCommon/VideoCommon.vcxproj | 2 ++ Source/Core/VideoCommon/VideoCommon.vcxproj.filters | 6 ++++++ Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj | 2 ++ .../Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters | 6 ++++++ 4 files changed, 16 insertions(+) diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index f53c18cb37..e458a8d87c 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -194,6 +194,7 @@ + @@ -240,6 +241,7 @@ + diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters index c933fbc939..0a61595c45 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters @@ -119,6 +119,9 @@ Shader Generators + + Base + @@ -246,6 +249,9 @@ Shader Generators + + Base + diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj index 18b8ac4d84..8d73bfda05 100644 --- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj +++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj @@ -200,6 +200,7 @@ + @@ -222,6 +223,7 @@ + diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters index cd170691da..f423a77f0b 100644 --- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters +++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters @@ -36,6 +36,9 @@ Render + + Render + @@ -72,6 +75,9 @@ Render + + Render + From 4607ebea2ad5fb472a53d5772af0c395c6f73810 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sun, 26 Aug 2012 20:21:51 +0200 Subject: [PATCH 05/70] Video_Software: Fix a small issue that prevented perf queries from working at all. --- Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp index 33a6164b01..525b39b0b6 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp @@ -77,7 +77,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) u16 address = _iAddress & 0xFFF; - if (address <= 0x16) + if (address <= 0x2e) _uReturnValue = ((u16*)&pereg)[address >> 1]; } @@ -109,7 +109,7 @@ void Write16(const u16 _iValue, const u32 _iAddress) } break; default: - if (address <= 0x16) + if (address <= 0x2e) ((u16*)&pereg)[address >> 1] = _iValue; break; } From 87d8feb53df8499e61096e4df022d00e25edb3c3 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sun, 26 Aug 2012 20:25:00 +0200 Subject: [PATCH 06/70] Video_Software: Add some debugging logs for PE perf queries --- Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp index 525b39b0b6..9ae13d4e3b 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp @@ -79,6 +79,11 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) if (address <= 0x2e) _uReturnValue = ((u16*)&pereg)[address >> 1]; + + if (address > 0x16) + { + ERROR_LOG(PIXELENGINE, "Read from address %#08x, returning %#08x\n", address, _uReturnValue); + } } void Write32(const u32 _iValue, const u32 _iAddress) From d734a5b486059d724f55e6662cf019fd71995c2b Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 27 Aug 2012 00:57:17 +0200 Subject: [PATCH 07/70] More debugging logs for RDilux --- Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp index 9ae13d4e3b..63885513f5 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp @@ -82,7 +82,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) if (address > 0x16) { - ERROR_LOG(PIXELENGINE, "Read from address %#08x, returning %#08x\n", address, _uReturnValue); + ERROR_LOG(PIXELENGINE, "addr %#08x, ret %#08x; %#08x, %#08x, %#08x, %#08x, %#08x, %#08x\n", address, _uReturnValue, pereg.perfZcompInputZcomploc, pereg.perfZcompOutputZcomploc, pereg.perfZcompInput, pereg.perfZcompOutput, pereg.perfBlendInput, pereg.perfEfbCopyClocks); } } From 49d1da5e7e0e9ba3aecc8fc02285ca537623c3ea Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 27 Aug 2012 23:51:35 +0200 Subject: [PATCH 08/70] Video_Software: Fix stuff. --- .../Plugin_VideoSoftware/Src/BPMemLoader.cpp | 18 ++++++++++++------ .../Plugin_VideoSoftware/Src/Rasterizer.cpp | 7 +++++-- .../Plugin_VideoSoftware/Src/SWPixelEngine.cpp | 2 +- .../Plugin_VideoSoftware/Src/SWPixelEngine.h | 18 ++++++++++++------ .../Plugins/Plugin_VideoSoftware/Src/Tev.cpp | 9 ++++++--- 5 files changed, 36 insertions(+), 18 deletions(-) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp index ad730a485c..4de9f435fa 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp @@ -92,12 +92,18 @@ void SWBPWritten(int address, int newvalue) break; case BPMEM_CLEAR_PIXEL_PERF: // TODO: Parameter? - SWPixelEngine::pereg.perfZcompInputZcomploc = 0; - SWPixelEngine::pereg.perfZcompOutputZcomploc = 0; - SWPixelEngine::pereg.perfZcompInput = 0; - SWPixelEngine::pereg.perfZcompOutput = 0; - SWPixelEngine::pereg.perfBlendInput = 0; - SWPixelEngine::pereg.perfEfbCopyClocks = 0; + SWPixelEngine::pereg.perfZcompInputZcomplocLo = 0; + SWPixelEngine::pereg.perfZcompInputZcomplocHi = 0; + SWPixelEngine::pereg.perfZcompOutputZcomplocLo = 0; + SWPixelEngine::pereg.perfZcompOutputZcomplocHi = 0; + SWPixelEngine::pereg.perfZcompInputLo = 0; + SWPixelEngine::pereg.perfZcompInputHi = 0; + SWPixelEngine::pereg.perfZcompOutputLo = 0; + SWPixelEngine::pereg.perfZcompOutputHi = 0; + SWPixelEngine::pereg.perfBlendInputLo = 0; + SWPixelEngine::pereg.perfBlendInputHi = 0; + SWPixelEngine::pereg.perfEfbCopyClocksLo = 0; + SWPixelEngine::pereg.perfEfbCopyClocksHi = 0; break; case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here. break; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp index a23d85f27f..c9c3b8c26c 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp @@ -129,14 +129,17 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi) if (bpmem.zcontrol.zcomploc) { // TODO: Verify that perf regs are being incremented even if test is disabled - SWPixelEngine::pereg.perfZcompInputZcomploc++; + if (++SWPixelEngine::pereg.perfZcompInputZcomplocLo == 0) + SWPixelEngine::pereg.perfZcompInputZcomplocHi++; + if (bpmem.zmode.testenable) { // early z if (!EfbInterface::ZCompare(x, y, z)) return; } - SWPixelEngine::pereg.perfZcompOutputZcomploc++; + if (++SWPixelEngine::pereg.perfZcompOutputZcomplocLo == 0) + SWPixelEngine::pereg.perfZcompOutputZcomplocHi++; } RasterBlockPixel& pixel = rasterBlock.Pixel[xi][yi]; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp index 63885513f5..d489d033ae 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp @@ -82,7 +82,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) if (address > 0x16) { - ERROR_LOG(PIXELENGINE, "addr %#08x, ret %#08x; %#08x, %#08x, %#08x, %#08x, %#08x, %#08x\n", address, _uReturnValue, pereg.perfZcompInputZcomploc, pereg.perfZcompOutputZcomploc, pereg.perfZcompInput, pereg.perfZcompOutput, pereg.perfBlendInput, pereg.perfEfbCopyClocks); + ERROR_LOG(PIXELENGINE, "addr %#08x, ret %#08x\n", address, _uReturnValue); } } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h index 764488c32e..7deb69a164 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h @@ -146,12 +146,18 @@ namespace SWPixelEngine u16 boxTop; u16 boxBottom; - u16 perfZcompInputZcomploc; - u16 perfZcompOutputZcomploc; - u16 perfZcompInput; - u16 perfZcompOutput; - u16 perfBlendInput; - u16 perfEfbCopyClocks; + u16 perfZcompInputZcomplocLo; + u16 perfZcompInputZcomplocHi; + u16 perfZcompOutputZcomplocLo; + u16 perfZcompOutputZcomplocHi; + u16 perfZcompInputLo; + u16 perfZcompInputHi; + u16 perfZcompOutputLo; + u16 perfZcompOutputHi; + u16 perfBlendInputLo; + u16 perfBlendInputHi; + u16 perfEfbCopyClocksLo; + u16 perfEfbCopyClocksHi; }; extern PEReg pereg; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp index 83d9de2784..fad8806a9f 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp @@ -787,13 +787,15 @@ void Tev::Draw() if (!bpmem.zcontrol.zcomploc) { - SWPixelEngine::pereg.perfZcompInput++; + if (++SWPixelEngine::pereg.perfZcompInputLo == 0) + SWPixelEngine::pereg.perfZcompInputHi++; if (bpmem.zmode.testenable) { if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2])) return; } - SWPixelEngine::pereg.perfZcompOutput++; + if (++SWPixelEngine::pereg.perfZcompOutputLo == 0) + SWPixelEngine::pereg.perfZcompOutputHi++; } #if ALLOW_TEV_DUMPS @@ -818,7 +820,8 @@ void Tev::Draw() INCSTAT(swstats.thisFrame.tevPixelsOut); - SWPixelEngine::pereg.perfBlendInput++; + if (++SWPixelEngine::pereg.perfBlendInputLo) + SWPixelEngine::pereg.perfBlendInputHi++; EfbInterface::BlendTev(Position[0], Position[1], output); } From 3d56ce18fb60a5617ba037d988f7918f7d29aae5 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 31 Aug 2012 20:49:59 +0200 Subject: [PATCH 09/70] Video_Software: Fix moar stuff --- Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp index fad8806a9f..80d68833b6 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp @@ -820,7 +820,7 @@ void Tev::Draw() INCSTAT(swstats.thisFrame.tevPixelsOut); - if (++SWPixelEngine::pereg.perfBlendInputLo) + if (++SWPixelEngine::pereg.perfBlendInputLo == 0) SWPixelEngine::pereg.perfBlendInputHi++; EfbInterface::BlendTev(Position[0], Position[1], output); From 54947b1e2246804ddf5ec0378f8111905a6d04bd Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 31 Aug 2012 21:30:12 +0200 Subject: [PATCH 10/70] Video_Software: Some more debugging logs. --- Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp index d489d033ae..ad19eb87ee 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp @@ -82,7 +82,13 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) if (address > 0x16) { - ERROR_LOG(PIXELENGINE, "addr %#08x, ret %#08x\n", address, _uReturnValue); + ERROR_LOG(PIXELENGINE, "addr %#08x, ret %#04x; %#04x%04x, %#04x%04x, %#04x%04x, %#04x%04x, %#04x%04x, %#04x%04x\n", address, _uReturnValue, + pereg.perfZcompInputZcomplocHi, pereg.perfZcompInputZcomplocLo, + pereg.perfZcompOutputZcomplocHi, pereg.perfZcompOutputZcomplocLo, + pereg.perfZcompInputHi, pereg.perfZcompInputLo, + pereg.perfZcompOutputHi, pereg.perfZcompOutputLo, + pereg.perfBlendInputHi, pereg.perfBlendInputLo, + pereg.perfEfbCopyClocksHi, pereg.perfEfbCopyClocksLo); } } From 53aec6c476b0ec9db4d301eaafedbb26eb3697f4 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 16 Feb 2013 17:50:40 -0600 Subject: [PATCH 11/70] Fix OGL perf queries and make them not slow! --- Source/Core/Common/Src/VideoBackendBase.h | 6 +- Source/Core/VideoCommon/Src/MainBase.cpp | 43 +++++++ Source/Core/VideoCommon/Src/PerfQueryBase.h | 2 + Source/Core/VideoCommon/Src/PixelEngine.cpp | 25 ++-- .../Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp | 111 +++++++++++++----- .../Plugins/Plugin_VideoOGL/Src/PerfQuery.h | 24 ++++ .../Plugin_VideoOGL/Src/VertexManager.cpp | 2 +- .../Plugin_VideoSoftware/Src/SWmain.cpp | 6 + .../Plugin_VideoSoftware/Src/VideoBackend.h | 2 + 9 files changed, 178 insertions(+), 43 deletions(-) diff --git a/Source/Core/Common/Src/VideoBackendBase.h b/Source/Core/Common/Src/VideoBackendBase.h index d09288ebc7..4e602526d2 100644 --- a/Source/Core/Common/Src/VideoBackendBase.h +++ b/Source/Core/Common/Src/VideoBackendBase.h @@ -22,6 +22,7 @@ #include #include "ChunkFile.h" +#include "PerfQueryBase.h" typedef void (*writeFn16)(const u16,const u32); typedef void (*writeFn32)(const u32,const u32); @@ -107,6 +108,7 @@ public: virtual void Video_EndField() = 0; virtual u32 Video_AccessEFB(EFBAccessType, u32, u32, u32) = 0; + virtual u32 Video_GetQueryResult(PerfQueryType type) = 0; virtual void Video_AddMessage(const char* pstr, unsigned int milliseconds) = 0; virtual void Video_ClearMessages() = 0; @@ -154,8 +156,10 @@ class VideoBackendHardware : public VideoBackend void Video_ExitLoop(); void Video_BeginField(u32, FieldType, u32, u32); void Video_EndField(); - u32 Video_AccessEFB(EFBAccessType, u32, u32, u32); + u32 Video_AccessEFB(EFBAccessType, u32, u32, u32); + u32 Video_GetQueryResult(PerfQueryType type); + void Video_AddMessage(const char* pstr, unsigned int milliseconds); void Video_ClearMessages(); bool Video_Screenshot(const char* filename); diff --git a/Source/Core/VideoCommon/Src/MainBase.cpp b/Source/Core/VideoCommon/Src/MainBase.cpp index cb6dc7ae5b..e8de52addb 100644 --- a/Source/Core/VideoCommon/Src/MainBase.cpp +++ b/Source/Core/VideoCommon/Src/MainBase.cpp @@ -21,6 +21,10 @@ volatile u32 s_swapRequested = false; u32 s_efbAccessRequested = false; volatile u32 s_FifoShuttingDown = false; +std::condition_variable s_perf_query_cond; +std::mutex s_perf_query_lock; +static volatile bool s_perf_query_requested; + static volatile struct { u32 xfbAddr; @@ -169,6 +173,43 @@ u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 return 0; } +static bool QueryResultIsReady() +{ + return !s_perf_query_requested || s_FifoShuttingDown; +} + +void VideoFifo_CheckPerfQueryRequest() +{ + if (s_perf_query_requested) + { + g_perf_query->FlushResults(); + + { + std::lock_guard lk(s_perf_query_lock); + s_perf_query_requested = false; + } + + s_perf_query_cond.notify_one(); + } +} + +u32 VideoBackendHardware::Video_GetQueryResult(PerfQueryType type) +{ + // Is this check sane? + if (!g_perf_query->IsFlushed()) + { + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread) + { + s_perf_query_requested = true; + std::unique_lock lk(s_perf_query_lock); + s_perf_query_cond.wait(lk, QueryResultIsReady); + } + else + g_perf_query->FlushResults(); + } + + return g_perf_query->GetQueryResult(type); +} void VideoBackendHardware::InitializeShared() { @@ -176,6 +217,7 @@ void VideoBackendHardware::InitializeShared() s_swapRequested = 0; s_efbAccessRequested = 0; + s_perf_query_requested = false; s_FifoShuttingDown = 0; memset((void*)&s_beginFieldArgs, 0, sizeof(s_beginFieldArgs)); memset(&s_accessEFBArgs, 0, sizeof(s_accessEFBArgs)); @@ -223,6 +265,7 @@ void VideoFifo_CheckAsyncRequest() { VideoFifo_CheckSwapRequest(); VideoFifo_CheckEFBAccess(); + VideoFifo_CheckPerfQueryRequest(); } void VideoBackendHardware::Video_GatherPipeBursted() diff --git a/Source/Core/VideoCommon/Src/PerfQueryBase.h b/Source/Core/VideoCommon/Src/PerfQueryBase.h index 0520e9244c..2643482379 100644 --- a/Source/Core/VideoCommon/Src/PerfQueryBase.h +++ b/Source/Core/VideoCommon/Src/PerfQueryBase.h @@ -32,6 +32,8 @@ public: virtual void DisableQuery(PerfQueryGroup type) {} virtual void ResetQuery() {} virtual u32 GetQueryResult(PerfQueryType type) { return 0; } + virtual void FlushResults() {} + virtual bool IsFlushed() const { return true; } }; extern PerfQueryBase* g_perf_query; diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index 005468f63c..2d6275096c 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -260,35 +260,35 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) // NOTE(neobrain): only PE_PERF_ZCOMP_OUTPUT is implemented in D3D11, but the other values shouldn't be contradictionary to the value of that register (i.e. INPUT registers should always be greater or equal to their corresponding OUTPUT registers). case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L: - _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) & 0xFFFF; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) & 0xFFFF; break; case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H: - _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) >> 16; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) >> 16; break; case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L: - _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) & 0xFFFF; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) & 0xFFFF; break; case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H: - _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) >> 16; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) >> 16; break; case PE_PERF_ZCOMP_INPUT_L: - _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_INPUT) & 0xFFFF; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT) & 0xFFFF; break; case PE_PERF_ZCOMP_INPUT_H: - _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_INPUT) >> 16; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT) >> 16; break; case PE_PERF_ZCOMP_OUTPUT_L: - _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_OUTPUT) & 0xFFFF; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT) & 0xFFFF; break; case PE_PERF_ZCOMP_OUTPUT_H: - _uReturnValue = g_perf_query->GetQueryResult(PQ_ZCOMP_OUTPUT) >> 16; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT) >> 16; break; case PE_PERF_BLEND_INPUT_L: @@ -298,19 +298,20 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) // In very old builds, Dolphin only returned 0. That caused the challenge to be immediately finished without any goop being cleaned (the timer just didn't even start counting from 3:00:00). // Later builds returned 1 for the high register. That caused the timer to actually count down, but made the challenge unbeatable because the game always thought you didn't clear any goop at all. // Note that currently this functionality is only implemented in the D3D11 backend. - _uReturnValue = g_perf_query->GetQueryResult(PQ_BLEND_INPUT) & 0xFFFF; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_BLEND_INPUT) & 0xFFFF; + //ERROR_LOG(VIDEO, "PQ_BLEND_INPUT: %d", g_video_backend->Video_GetQueryResult(PQ_BLEND_INPUT)); break; case PE_PERF_BLEND_INPUT_H: - _uReturnValue = g_perf_query->GetQueryResult(PQ_BLEND_INPUT) >> 16; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_BLEND_INPUT) >> 16; break; case PE_PERF_EFB_COPY_CLOCKS_L: - _uReturnValue = g_perf_query->GetQueryResult(PQ_EFB_COPY_CLOCKS) & 0xFFFF; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_EFB_COPY_CLOCKS) & 0xFFFF; break; case PE_PERF_EFB_COPY_CLOCKS_H: - _uReturnValue = g_perf_query->GetQueryResult(PQ_EFB_COPY_CLOCKS) >> 16; + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_EFB_COPY_CLOCKS) >> 16; break; default: diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp index cb659e6921..8cee426e98 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp @@ -1,31 +1,47 @@ #include "GLUtil.h" #include "PerfQuery.h" -namespace OGL { - -u32 results[PQG_NUM_MEMBERS] = { 0 }; -GLuint query_id; - -PerfQueryGroup active_query; +namespace OGL +{ PerfQuery::PerfQuery() + : m_query_read_pos() + , m_query_count() { - glGenQueries(1, &query_id); + for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + glGenQueries(1, &m_query_buffer[i].query_id); + + ResetQuery(); } PerfQuery::~PerfQuery() { - glDeleteQueries(1, &query_id); + for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + glDeleteQueries(1, &m_query_buffer[i].query_id); } void PerfQuery::EnableQuery(PerfQueryGroup type) { + // Is this sane? + if (m_query_count > ARRAYSIZE(m_query_buffer) / 2) + WeakFlush(); + + if (ARRAYSIZE(m_query_buffer) == m_query_count) + { + FlushOne(); + //ERROR_LOG(VIDEO, "flushed query buffer early!"); + } + // start query if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) { - glBeginQuery(GL_SAMPLES_PASSED, query_id); + auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ARRAYSIZE(m_query_buffer)]; + + glBeginQuery(GL_SAMPLES_PASSED, entry.query_id); + entry.query_type = type; + + ++m_query_count; } - active_query = type; } void PerfQuery::DisableQuery(PerfQueryGroup type) @@ -34,45 +50,82 @@ void PerfQuery::DisableQuery(PerfQueryGroup type) if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) { glEndQuery(GL_SAMPLES_PASSED); + } +} - GLuint query_result = GL_FALSE; - while (query_result != GL_TRUE) +bool PerfQuery::IsFlushed() const +{ + return 0 == m_query_count; +} + +void PerfQuery::FlushOne() +{ + auto& entry = m_query_buffer[m_query_read_pos]; + + GLuint result = 0; + glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT, &result); + + m_results[entry.query_type] += result; + + m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); + --m_query_count; +} + +// TODO: could selectively flush things, but I don't think that will do much +void PerfQuery::FlushResults() +{ + while (!IsFlushed()) + FlushOne(); +} + +void PerfQuery::WeakFlush() +{ + while (!IsFlushed()) + { + auto& entry = m_query_buffer[m_query_read_pos]; + + GLuint result = GL_FALSE; + glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT_AVAILABLE, &result); + + if (GL_TRUE == result) { - glGetQueryObjectuiv(query_id, GL_QUERY_RESULT_AVAILABLE, &query_result); + FlushOne(); + } + else + { + break; } - - glGetQueryObjectuiv(query_id, GL_QUERY_RESULT, &query_result); - - results[active_query] += query_result; } } void PerfQuery::ResetQuery() { - memset(results, 0, sizeof(results)); + m_query_count = 0; + std::fill_n(m_results, ARRAYSIZE(m_results), 0); } u32 PerfQuery::GetQueryResult(PerfQueryType type) { - if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC || type == PQ_BLEND_INPUT) + u32 result = 0; + + if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC) { - + result = m_results[PQG_ZCOMP_ZCOMPLOC]; } - if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT || type == PQ_BLEND_INPUT) + else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT) { - + result = m_results[PQG_ZCOMP]; } - if (type == PQ_BLEND_INPUT) + else if (type == PQ_BLEND_INPUT) { - results[PQ_BLEND_INPUT] = results[PQ_ZCOMP_OUTPUT] + results[PQ_ZCOMP_OUTPUT_ZCOMPLOC]; + result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC]; } - - if (type == PQ_EFB_COPY_CLOCKS) + else if (type == PQ_EFB_COPY_CLOCKS) { - // TODO + result = m_results[PQG_EFB_COPY_CLOCKS]; } - - return results[type]; + + return result / 4; } } // namespace diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h index 776c576e2d..76040272e3 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h @@ -15,6 +15,30 @@ public: void DisableQuery(PerfQueryGroup type); void ResetQuery(); u32 GetQueryResult(PerfQueryType type); + void FlushResults(); + bool IsFlushed() const; + +private: + struct ActiveQuery + { + GLuint query_id; + PerfQueryGroup query_type; + }; + + // when testing in SMS: 64 was too small, 128 was ok + static const int PERF_QUERY_BUFFER_SIZE = 512; + + void WeakFlush(); + // Only use when non-empty + void FlushOne(); + + // This contains gl query objects with unretrieved results. + ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE]; + int m_query_read_pos; + + // TODO: sloppy + volatile int m_query_count; + volatile u32 m_results[PQG_NUM_MEMBERS]; }; } // namespace diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index b2f55adec5..85a23e1c1d 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -211,7 +211,7 @@ void VertexManager::vFlush() g_perf_query->EnableQuery(bpmem.zcontrol.zcomploc ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); Draw(); g_perf_query->DisableQuery(bpmem.zcontrol.zcomploc ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); - ERROR_LOG(VIDEO, "PerfQuery result: %d", g_perf_query->GetQueryResult(bpmem.zcontrol.zcomploc ? PQ_ZCOMP_OUTPUT_ZCOMPLOC : PQ_ZCOMP_OUTPUT)); + //ERROR_LOG(VIDEO, "PerfQuery result: %d", g_perf_query->GetQueryResult(bpmem.zcontrol.zcomploc ? PQ_ZCOMP_OUTPUT_ZCOMPLOC : PQ_ZCOMP_OUTPUT)); // run through vertex groups again to set alpha if (useDstAlpha && !dualSourcePossible) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp index 3c6fdcca38..100ff55bf4 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp @@ -176,6 +176,12 @@ u32 VideoSoftware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputDa return value; } +u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type) +{ + // TODO: + return 0; +} + bool VideoSoftware::Video_Screenshot(const char *_szFilename) { return false; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h b/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h index c0309c95c1..2ba282788b 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h @@ -26,7 +26,9 @@ class VideoSoftware : public VideoBackend void Video_ExitLoop(); void Video_BeginField(u32, FieldType, u32, u32); void Video_EndField(); + u32 Video_AccessEFB(EFBAccessType, u32, u32, u32); + u32 Video_GetQueryResult(PerfQueryType type); void Video_AddMessage(const char* pstr, unsigned int milliseconds); void Video_ClearMessages(); From 0f617183a8a74f066d1d01a3ed50042cc9824bf8 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 18 Feb 2013 14:54:24 +0000 Subject: [PATCH 12/70] Add a possible TODO. Dunno if the hardware behaves like this, but it likely does. --- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index f10634ba18..19f18ae855 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -1464,6 +1464,7 @@ void Renderer::SetDepthMode() else { // if the test is disabled write is disabled too + // TODO: When PE performance metrics are being emulated via occlusion queries, we should (probably?) enable depth test with depth function ALWAYS here glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); } From 415a2f17c95db405309d9d259134a40f21a3582d Mon Sep 17 00:00:00 2001 From: Rachel Bryk Date: Mon, 25 Feb 2013 20:05:02 -0500 Subject: [PATCH 13/70] Begin implementing save states to video software. Kind of works, sometimes. --- .../Plugin_VideoSoftware/Src/EfbInterface.cpp | 7 +++++++ .../Plugins/Plugin_VideoSoftware/Src/EfbInterface.h | 1 + .../Plugin_VideoSoftware/Src/OpcodeDecoder.cpp | 12 ++++++++++++ .../Plugin_VideoSoftware/Src/OpcodeDecoder.h | 3 +++ .../Plugin_VideoSoftware/Src/SWCommandProcessor.cpp | 5 +++++ .../Plugin_VideoSoftware/Src/SWVertexLoader.cpp | 13 ++++++++++++- .../Plugin_VideoSoftware/Src/SWVertexLoader.h | 3 ++- Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp | 10 ++++++++-- .../Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp | 7 +++++++ Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h | 2 ++ 10 files changed, 59 insertions(+), 4 deletions(-) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp index 6722ec7935..8fdc0425a4 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp @@ -28,6 +28,7 @@ u8 efb[EFB_WIDTH*EFB_HEIGHT*6]; namespace EfbInterface { + u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; inline u32 GetColorOffset(u16 x, u16 y) @@ -40,6 +41,12 @@ namespace EfbInterface return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START; } + void DoState(PointerWrap &p) + { + p.DoArray(efb, EFB_WIDTH*EFB_HEIGHT*6); + p.DoArray(efbColorTexture, EFB_WIDTH*EFB_HEIGHT*4); + } + void SetPixelAlphaOnly(u32 offset, u8 a) { switch (bpmem.zcontrol.pixel_format) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h index 15d19e7783..fdad69567c 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h @@ -47,6 +47,7 @@ namespace EfbInterface void UpdateColorTexture(); extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format + void DoState(PointerWrap &p); } #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp index 0091e4eaca..396a5a54af 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp @@ -46,6 +46,18 @@ static bool inObjectStream; static u8 lastPrimCmd; +void DoState(PointerWrap &p) +{ + p.Do(minCommandSize); + vertexLoader.DoState(p); + p.Do(streamSize); + p.Do(streamAddress); + p.Do(readOpcode); + p.Do(inObjectStream); + p.Do(lastPrimCmd); + //p.Do(currentFunction); +} + void DecodePrimitiveStream(u32 iBufferSize) { u32 vertexSize = vertexLoader.GetVertexSize(); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h index 635fcc24ee..53715b2832 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h @@ -20,6 +20,7 @@ #define _OPCODEDECODER_H_ #include "CommonTypes.h" +#include "ChunkFile.h" namespace OpcodeDecoder { @@ -57,6 +58,8 @@ namespace OpcodeDecoder bool CommandRunnable(u32 iBufferSize); void Run(u32 iBufferSize); + + void DoState(PointerWrap &p); } #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp index b9afc1abb5..97a99ff710 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp @@ -57,6 +57,11 @@ CPReg cpreg; // shared between gfx and emulator thread void DoState(PointerWrap &p) { p.Do(cpreg); + p.Do(readPos); + p.Do(writePos); + p.Do(et_UpdateInterrupts); + p.Do(interruptSet); + p.Do(interruptWaiting); } // does it matter that there is no synchronization between threads during writes? diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp index cc5ee66772..3142fc4262 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp @@ -328,4 +328,15 @@ void SWVertexLoader::LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData vertexLoader->m_texCoordLoader[index](); } - +void SWVertexLoader::DoState(PointerWrap &p) +{ + p.DoArray(m_AttributeLoaders, sizeof m_AttributeLoaders); + p.Do(m_VertexSize); + p.Do(m_CurrentVat); + p.Do(m_positionLoader); + p.Do(m_normalLoader); + p.DoArray(m_colorLoader, sizeof m_colorLoader); + p.Do(m_NumAttributeLoaders); + m_SetupUnit->DoState(p); + p.Do(m_TexGenSpecialCase); +} \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h index 91a0d8e911..e05346a7a5 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h @@ -22,6 +22,7 @@ #include "NativeVertexFormat.h" #include "CPMemLoader.h" +#include "ChunkFile.h" class SetupUnit; @@ -69,7 +70,7 @@ public: u32 GetVertexSize() { return m_VertexSize; } void LoadVertex(); - + void DoState(PointerWrap &p); }; #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp index 332e83d0e8..096315af4e 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp @@ -39,6 +39,8 @@ #include "FileUtil.h" #include "VideoBackend.h" #include "Core.h" +#include "OpcodeDecoder.h" +#include "SWVertexLoader.h" #define VSYNC_ENABLED 0 @@ -93,9 +95,13 @@ bool VideoSoftware::Initialize(void *&window_handle) return true; } -void VideoSoftware::DoState(PointerWrap&) +void VideoSoftware::DoState(PointerWrap& p) { - // NYI + // TODO: incomplete + SWCommandProcessor::DoState(p); + SWPixelEngine::DoState(p); + EfbInterface::DoState(p); + OpcodeDecoder::DoState(p); } void VideoSoftware::CheckInvalidState() diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp index 6e0fab57d8..57d69af7bd 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp @@ -169,3 +169,10 @@ void SetupUnit::SetupLineStrip() void SetupUnit::SetupPoint() {} + +void SetupUnit::DoState(PointerWrap &p) +{ + p.Do(m_PrimType); + p.Do(m_VertexCounter); + p.DoArray(m_Vertices, sizeof m_Vertices); +} \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h index 45a575afcb..f337de21a2 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h @@ -21,6 +21,7 @@ #include "Common.h" #include "NativeVertexFormat.h" +#include "ChunkFile.h" class SetupUnit { @@ -45,6 +46,7 @@ public: OutputVertexData* GetVertex() { return m_VertWritePointer; } void SetupVertex(); + void DoState(PointerWrap &p); }; #endif From db838e759b8935e213fa225be88ac0bfc78c27f7 Mon Sep 17 00:00:00 2001 From: Rachel Bryk Date: Mon, 25 Feb 2013 23:49:24 -0500 Subject: [PATCH 14/70] Improve VideoSoftware save states. They are fairly stable, but not perfect. OpcodeDecoder::DoState() needs to be fixed. --- .../Plugin_VideoSoftware/Src/Clipper.cpp | 7 +++++ .../Plugin_VideoSoftware/Src/Clipper.h | 3 ++ .../Src/NativeVertexFormat.h | 13 +++++++++ .../Src/OpcodeDecoder.cpp | 10 ++++--- .../Plugin_VideoSoftware/Src/Rasterizer.cpp | 22 ++++++++++++++ .../Plugin_VideoSoftware/Src/Rasterizer.h | 9 ++++++ .../Src/SWCommandProcessor.cpp | 4 +++ .../Src/SWPixelEngine.cpp | 2 ++ .../Src/SWVertexLoader.cpp | 2 +- .../Plugin_VideoSoftware/Src/SWmain.cpp | 13 +++++++++ .../Plugin_VideoSoftware/Src/SetupUnit.cpp | 29 +++++++++++++------ .../Plugins/Plugin_VideoSoftware/Src/Tev.cpp | 28 ++++++++++++++++++ Source/Plugins/Plugin_VideoSoftware/Src/Tev.h | 3 ++ .../Plugins/Plugin_VideoSoftware/Src/Vec3.h | 7 +++++ 14 files changed, 138 insertions(+), 14 deletions(-) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp index e9a3525d84..c4755b50bf 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp @@ -65,6 +65,13 @@ namespace Clipper OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES]; OutputVertexData *Vertices[NUM_INDICES]; + void DoState(PointerWrap &p) + { + p.DoArray(m_ViewOffset,2); + for (int i = 0; i< NUM_CLIPPED_VERTICES; ++i) + ClippedVertices[i].DoState(p); + } + void Init() { for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h index 5e5dd4d02c..babc8b4e88 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h @@ -21,6 +21,7 @@ #include "Common.h" #include "NativeVertexFormat.h" +#include "ChunkFile.h" namespace Clipper @@ -36,6 +37,8 @@ namespace Clipper bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface); void PerspectiveDivide(OutputVertexData *vertex); + + void DoState(PointerWrap &p); } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h b/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h index d19844105f..e2d87e207e 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h @@ -19,6 +19,7 @@ #define _NATIVEVERTEXFORMAT_H #include "Vec3.h" +#include "ChunkFile.h" #ifdef WIN32 #define LOADERDECL __cdecl @@ -92,6 +93,18 @@ struct OutputVertexData #undef LINTERP #undef LINTERP_INT } + void DoState(PointerWrap &p) + { + mvPosition.DoState(p); + p.Do(projectedPosition); + screenPosition.DoState(p); + for (int i = 0; i < 3;++i) + normal[i].DoState(p); + p.DoArray(color, sizeof color); + for (int i = 0; i < 8;++i) + texCoords[i].DoState(p); + } + }; #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp index 396a5a54af..4401916e1f 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp @@ -35,7 +35,6 @@ typedef void (*DecodingFunction)(u32); namespace OpcodeDecoder { - static DecodingFunction currentFunction = NULL; static u32 minCommandSize; static u16 streamSize; @@ -49,12 +48,15 @@ static u8 lastPrimCmd; void DoState(PointerWrap &p) { p.Do(minCommandSize); - vertexLoader.DoState(p); - p.Do(streamSize); - p.Do(streamAddress); + // Not sure what is wrong with this. Something(s) in here is causing dolphin to crash/hang when loading states saved from another run of dolphin. Doesn't seem too important anyway... + //vertexLoader.DoState(p); p.Do(readOpcode); p.Do(inObjectStream); p.Do(lastPrimCmd); + p.Do(streamSize); + p.Do(streamAddress); + // not sure how to save this... It seems to be the only thing left that is really important. + // uncommenting this will prevent all error messages, and any crashes/hangs on load, but then obviously it'll segfault once you restart dolphin. //p.Do(currentFunction); } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp index 225400e08b..5eed912dcb 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp @@ -62,6 +62,28 @@ s32 scissorBottom = 0; Tev tev; RasterBlock rasterBlock; +void DoState(PointerWrap &p) +{ + ZSlope.DoState(p); + WSlope.DoState(p); + for (int i=0;i<2;++i) + for (int n=0; n<4; ++n) + ColorSlopes[i][n].DoState(p); + for (int i=0;i<8;++i) + for (int n=0; n<3; ++n) + TexSlopes[i][n].DoState(p); + p.Do(vertex0X); + p.Do(vertex0Y); + p.Do(vertexOffsetX); + p.Do(vertexOffsetY); + p.Do(scissorLeft); + p.Do(scissorTop); + p.Do(scissorRight); + p.Do(scissorBottom); + tev.DoState(p); + p.Do(rasterBlock); +} + void Init() { tev.Init(); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h index f8850571a9..784c4a8d62 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h @@ -19,6 +19,7 @@ #define _RASTERIZER_H_ #include "NativeVertexFormat.h" +#include "ChunkFile.h" namespace Rasterizer { @@ -37,6 +38,12 @@ namespace Rasterizer float f0; float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); } + void DoState(PointerWrap &p) + { + p.Do(dfdx); + p.Do(dfdy); + p.Do(f0); + } }; struct RasterBlockPixel @@ -53,6 +60,8 @@ namespace Rasterizer s32 TextureLod[16]; bool TextureLinear[16]; }; + + void DoState(PointerWrap &p); } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp index 97a99ff710..c15a02f93e 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp @@ -57,11 +57,15 @@ CPReg cpreg; // shared between gfx and emulator thread void DoState(PointerWrap &p) { p.Do(cpreg); + p.DoArray(commandBuffer, commandBufferSize); p.Do(readPos); p.Do(writePos); p.Do(et_UpdateInterrupts); p.Do(interruptSet); p.Do(interruptWaiting); + + // Is this right? + p.DoArray(g_pVideoData,writePos); } // does it matter that there is no synchronization between threads during writes? diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp index 33a6164b01..e9d2c1fe96 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp @@ -53,6 +53,8 @@ void DoState(PointerWrap &p) p.Do(pereg); p.Do(g_bSignalTokenInterrupt); p.Do(g_bSignalFinishInterrupt); + p.Do(et_SetTokenOnMainThread); + p.Do(et_SetFinishOnMainThread); } void UpdateInterrupts(); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp index 3142fc4262..1c1eeb2005 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp @@ -332,7 +332,7 @@ void SWVertexLoader::DoState(PointerWrap &p) { p.DoArray(m_AttributeLoaders, sizeof m_AttributeLoaders); p.Do(m_VertexSize); - p.Do(m_CurrentVat); + p.Do(*m_CurrentVat); p.Do(m_positionLoader); p.Do(m_normalLoader); p.DoArray(m_colorLoader, sizeof m_colorLoader); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp index 096315af4e..d78b8ba13b 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp @@ -102,6 +102,19 @@ void VideoSoftware::DoState(PointerWrap& p) SWPixelEngine::DoState(p); EfbInterface::DoState(p); OpcodeDecoder::DoState(p); + Clipper::DoState(p); + p.Do(swxfregs); + p.Do(bpmem); + + // CP Memory + p.DoArray(arraybases, 16); + p.DoArray(arraystrides, 16); + p.Do(MatrixIndexA); + p.Do(MatrixIndexB); + p.Do(g_VtxDesc.Hex); + p.DoArray(g_VtxAttr, 8); + p.DoMarker("CP Memory"); + } void VideoSoftware::CheckInvalidState() diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp index 57d69af7bd..d2185e31d5 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp @@ -25,13 +25,13 @@ void SetupUnit::Init(u8 primitiveType) { - m_PrimType = primitiveType; + m_PrimType = primitiveType; - m_VertexCounter = 0; - m_VertPointer[0] = &m_Vertices[0]; - m_VertPointer[1] = &m_Vertices[1]; - m_VertPointer[2] = &m_Vertices[2]; - m_VertWritePointer = m_VertPointer[0]; + m_VertexCounter = 0; + m_VertPointer[0] = &m_Vertices[0]; + m_VertPointer[1] = &m_Vertices[1]; + m_VertPointer[2] = &m_Vertices[2]; + m_VertWritePointer = m_VertPointer[0]; } void SetupUnit::SetupVertex() @@ -172,7 +172,18 @@ void SetupUnit::SetupPoint() void SetupUnit::DoState(PointerWrap &p) { - p.Do(m_PrimType); + // TODO: some or all of this is making the save states stop working once dolphin is closed...sometimes (usually) + // I have no idea what specifically is wrong, or if this is even important. Disabling it doesn't seem to make any noticible difference... +/* p.Do(m_PrimType); p.Do(m_VertexCounter); - p.DoArray(m_Vertices, sizeof m_Vertices); -} \ No newline at end of file + for (int i = 0; i < 3; ++i) + m_Vertices[i].DoState(p); + + if (p.GetMode() == PointerWrap::MODE_READ) + { + m_VertPointer[0] = &m_Vertices[0]; + m_VertPointer[1] = &m_Vertices[1]; + m_VertPointer[2] = &m_Vertices[2]; + m_VertWritePointer = m_VertPointer[0]; + }*/ +} diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp index 927f8931e9..0f4b4fce20 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp @@ -827,3 +827,31 @@ void Tev::SetRegColor(int reg, int comp, bool konst, s16 color) Reg[reg][comp] = color; } } + +void Tev::DoState(PointerWrap &p) +{ + p.DoArray(Reg, sizeof(Reg)); + + p.DoArray(KonstantColors, sizeof(KonstantColors)); + p.DoArray(TexColor,4); + p.DoArray(RasColor,4); + p.DoArray(StageKonst,4); + p.DoArray(Zero16,4); + + p.DoArray(FixedConstants,9); + p.Do(AlphaBump); + p.DoArray(IndirectTex, sizeof(IndirectTex)); + p.Do(TexCoord); + + p.DoArray(m_BiasLUT,4); + p.DoArray(m_ScaleLShiftLUT,4); + p.DoArray(m_ScaleRShiftLUT,4); + + p.DoArray(Position,3); + p.DoArray(Color, sizeof(Color)); + p.DoArray(Uv, 8); + p.DoArray(IndirectLod,4); + p.DoArray(IndirectLinear,4); + p.DoArray(TextureLod,16); + p.DoArray(TextureLinear,16); +} diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h index bdd265170c..1d1bc8d2ba 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h @@ -19,6 +19,7 @@ #define _TEV_H_ #include "BPMemLoader.h" +#include "ChunkFile.h" class Tev { @@ -96,6 +97,8 @@ public: void SetRegColor(int reg, int comp, bool konst, s16 color); enum { ALP_C, BLU_C, GRN_C, RED_C }; + + void DoState(PointerWrap &p); }; #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h b/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h index 3a36a13307..80460edd60 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h @@ -20,6 +20,7 @@ #include #include +#include "ChunkFile.h" class Vec3 { @@ -111,6 +112,12 @@ public: { memset((void *)this,0,sizeof(float)*3); } + void DoState(PointerWrap &p) + { + p.Do(x); + p.Do(y); + p.Do(z); + } }; #endif From 717b9768750dfef39120d4457a832ce7558bd879 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 26 Feb 2013 13:49:00 -0600 Subject: [PATCH 15/70] ARM Support without GLSL --- CMakeLists.txt | 344 +-- Source/Core/AudioCommon/CMakeLists.txt | 5 + Source/Core/AudioCommon/Src/AudioCommon.cpp | 7 +- .../Core/AudioCommon/Src/OpenSLESStream.cpp | 145 ++ Source/Core/AudioCommon/Src/OpenSLESStream.h | 48 + Source/Core/Common/CMakeLists.txt | 23 +- Source/Core/Common/Common.vcxproj | 9 +- Source/Core/Common/Common.vcxproj.filters | 9 +- Source/Core/Common/Src/ArmCPUDetect.cpp | 160 ++ Source/Core/Common/Src/ArmEmitter.cpp | 967 ++++++++ Source/Core/Common/Src/ArmEmitter.h | 587 +++++ Source/Core/Common/Src/CPUDetect.h | 23 +- Source/Core/Common/Src/Common.h | 6 +- Source/Core/Common/Src/CommonFuncs.h | 14 +- Source/Core/Common/Src/CommonPaths.h | 5 + Source/Core/Common/Src/FPURoundMode.h | 51 + Source/Core/Common/Src/FileUtil.cpp | 5 +- .../Core/Common/Src/GenericFPURoundMode.cpp | 41 + Source/Core/Common/Src/LogManager.cpp | 7 +- Source/Core/Common/Src/MathUtil.cpp | 24 - Source/Core/Common/Src/MathUtil.h | 13 +- Source/Core/Common/Src/MemArena.cpp | 34 + Source/Core/Common/Src/MemoryUtil.cpp | 5 +- Source/Core/Common/Src/StdConditionVariable.h | 2 +- Source/Core/Common/Src/StdMutex.h | 2 +- Source/Core/Common/Src/StdThread.h | 2 +- Source/Core/Common/Src/StringUtil.cpp | 38 +- Source/Core/Common/Src/Thread.cpp | 2 +- Source/Core/Common/Src/Thread.h | 2 - .../Core/Common/Src/{ABI.cpp => x64ABI.cpp} | 2 +- Source/Core/Common/Src/{ABI.h => x64ABI.h} | 0 .../Src/{CPUDetect.cpp => x64CPUDetect.cpp} | 6 +- Source/Core/Common/Src/x64Emitter.cpp | 2 +- Source/Core/Common/Src/x64Emitter.h | 2 +- Source/Core/Common/Src/x64FPURoundMode.cpp | 120 + .../Common/Src/{Thunk.cpp => x64Thunk.cpp} | 3 +- Source/Core/Core/CMakeLists.txt | 36 +- Source/Core/Core/Core.vcxproj | 12 +- Source/Core/Core/Core.vcxproj.filters | 9 +- Source/Core/Core/Src/ArmMemTools.cpp | 103 + Source/Core/Core/Src/ConfigManager.h | 2 +- Source/Core/Core/Src/Core.cpp | 7 +- Source/Core/Core/Src/DSP/DSPEmitter.cpp | 2 +- Source/Core/Core/Src/DSP/DSPHWInterface.cpp | 2 + .../Core/Src/DSP/Jit/DSPJitArithmetic.cpp | 2 +- Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp | 2 +- Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp | 2 +- Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp | 2 +- .../Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp | 2 +- Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp | 2 +- .../Core/Src/DSP/Jit/DSPJitMultiplier.cpp | 2 +- Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp | 2 +- Source/Core/Core/Src/HW/Memmap.cpp | 126 - Source/Core/Core/Src/HW/Memmap.h | 5 - .../Interpreter/Interpreter_FloatingPoint.cpp | 4 +- .../Interpreter/Interpreter_LoadStore.cpp | 21 +- .../Interpreter_SystemRegisters.cpp | 51 +- .../Interpreter/Interpreter_Tables.cpp | 2 +- Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp | 4 +- Source/Core/Core/Src/PowerPC/Jit64/Jit.h | 2 +- Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp | 6 +- Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h | 1 - .../Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp | 2 +- .../PowerPC/Jit64/Jit_LoadStoreFloating.cpp | 2 +- .../Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp | 2 +- .../Src/PowerPC/Jit64/Jit_SystemRegisters.cpp | 2 +- .../Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp | 10 +- .../Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp | 2 +- Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h | 2 +- .../Core/Src/PowerPC/Jit64IL/JitILAsm.cpp | 8 +- .../Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp | 2 +- .../Jit64IL/JitIL_LoadStoreFloating.cpp | 2 +- .../PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp | 2 +- .../PowerPC/Jit64IL/JitIL_SystemRegisters.cpp | 2 +- Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp | 498 ++++ Source/Core/Core/Src/PowerPC/JitArm32/Jit.h | 186 ++ .../Core/Src/PowerPC/JitArm32/JitArmCache.cpp | 46 + .../Core/Src/PowerPC/JitArm32/JitArmCache.h | 33 + .../Src/PowerPC/JitArm32/JitArm_BackPatch.cpp | 164 ++ .../Src/PowerPC/JitArm32/JitArm_Branch.cpp | 347 +++ .../PowerPC/JitArm32/JitArm_FloatingPoint.cpp | 80 + .../Src/PowerPC/JitArm32/JitArm_Integer.cpp | 297 +++ .../Src/PowerPC/JitArm32/JitArm_LoadStore.cpp | 414 ++++ .../JitArm32/JitArm_LoadStoreFloating.cpp | 72 + .../JitArm32/JitArm_SystemRegisters.cpp | 111 + .../Src/PowerPC/JitArm32/JitArm_Tables.cpp | 502 ++++ .../Core/Src/PowerPC/JitArm32/JitArm_Tables.h | 29 + .../Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp | 174 ++ .../Core/Core/Src/PowerPC/JitArm32/JitAsm.h | 43 + .../Core/Src/PowerPC/JitArm32/JitRegCache.cpp | 167 ++ .../Core/Src/PowerPC/JitArm32/JitRegCache.h | 92 + .../Src/PowerPC/JitCommon/JitAsmCommon.cpp | 4 +- .../Core/Src/PowerPC/JitCommon/JitAsmCommon.h | 25 +- .../Src/PowerPC/JitCommon/JitBackpatch.cpp | 4 +- .../Core/Src/PowerPC/JitCommon/JitBackpatch.h | 4 + .../Core/Core/Src/PowerPC/JitCommon/JitBase.h | 26 +- .../Core/Src/PowerPC/JitCommon/JitCache.cpp | 94 +- .../Core/Src/PowerPC/JitCommon/JitCache.h | 16 +- .../Core/Src/PowerPC/JitCommon/Jit_Util.cpp | 2 +- Source/Core/Core/Src/PowerPC/JitInterface.cpp | 350 +++ Source/Core/Core/Src/PowerPC/JitInterface.h | 56 + Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp | 3 +- Source/Core/Core/Src/PowerPC/PPCCache.cpp | 7 +- Source/Core/Core/Src/PowerPC/PPCTables.cpp | 18 +- Source/Core/Core/Src/PowerPC/PowerPC.cpp | 70 +- Source/Core/Core/Src/PowerPC/Profiler.cpp | 78 +- Source/Core/Core/Src/PowerPC/Profiler.h | 9 + .../Src/{MemTools.cpp => x64MemTools.cpp} | 12 +- Source/Core/DiscIO/Src/BannerLoader.cpp | 6 + Source/Core/DolphinWX/CMakeLists.txt | 187 +- .../DolphinWX/Src/Debugger/CodeWindow.cpp | 14 +- Source/Core/DolphinWX/Src/Frame.cpp | 2 +- Source/Core/DolphinWX/Src/GLInterface.h | 13 +- .../Src/GLInterface/{EGL.cpp => EGL_X11.cpp} | 2 +- .../Src/GLInterface/{EGL.h => EGL_X11.h} | 0 .../DolphinWX/Src/GLInterface/InterfaceBase.h | 10 +- Source/Core/DolphinWX/Src/MainAndroid.cpp | 149 ++ Source/Core/VideoCommon/CMakeLists.txt | 10 +- Source/Core/VideoCommon/Src/Fifo.cpp | 6 +- .../Core/VideoCommon/Src/GenericDLCache.cpp | 52 + .../VideoCommon/Src/GenericTextureDecoder.cpp | 2182 +++++++++++++++++ Source/Core/VideoCommon/Src/VertexLoader.cpp | 18 +- Source/Core/VideoCommon/Src/VertexLoader.h | 7 + .../Src/{DLCache.cpp => x64DLCache.cpp} | 2 +- ...xtureDecoder.cpp => x64TextureDecoder.cpp} | 93 - Source/Core/VideoCommon/VideoCommon.vcxproj | 10 +- .../VideoCommon/VideoCommon.vcxproj.filters | 12 +- .../Src/NativeVertexFormat.cpp | 2 +- Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp | 4 +- .../Src/NativeVertexFormat.cpp | 2 +- Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 4 + .../Src/OpcodeDecoder.cpp | 6 +- .../Src/SWCommandProcessor.cpp | 6 +- 133 files changed, 9048 insertions(+), 948 deletions(-) create mode 100644 Source/Core/AudioCommon/Src/OpenSLESStream.cpp create mode 100644 Source/Core/AudioCommon/Src/OpenSLESStream.h create mode 100644 Source/Core/Common/Src/ArmCPUDetect.cpp create mode 100644 Source/Core/Common/Src/ArmEmitter.cpp create mode 100644 Source/Core/Common/Src/ArmEmitter.h create mode 100644 Source/Core/Common/Src/FPURoundMode.h create mode 100644 Source/Core/Common/Src/GenericFPURoundMode.cpp rename Source/Core/Common/Src/{ABI.cpp => x64ABI.cpp} (99%) rename Source/Core/Common/Src/{ABI.h => x64ABI.h} (100%) rename Source/Core/Common/Src/{CPUDetect.cpp => x64CPUDetect.cpp} (98%) create mode 100644 Source/Core/Common/Src/x64FPURoundMode.cpp rename Source/Core/Common/Src/{Thunk.cpp => x64Thunk.cpp} (98%) create mode 100644 Source/Core/Core/Src/ArmMemTools.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/Jit.h create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.h create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitArm_BackPatch.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.h create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.h create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.h create mode 100644 Source/Core/Core/Src/PowerPC/JitInterface.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitInterface.h rename Source/Core/Core/Src/{MemTools.cpp => x64MemTools.cpp} (96%) rename Source/Core/DolphinWX/Src/GLInterface/{EGL.cpp => EGL_X11.cpp} (99%) rename Source/Core/DolphinWX/Src/GLInterface/{EGL.h => EGL_X11.h} (100%) create mode 100644 Source/Core/DolphinWX/Src/MainAndroid.cpp create mode 100644 Source/Core/VideoCommon/Src/GenericDLCache.cpp create mode 100644 Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp rename Source/Core/VideoCommon/Src/{DLCache.cpp => x64DLCache.cpp} (99%) rename Source/Core/VideoCommon/Src/{TextureDecoder.cpp => x64TextureDecoder.cpp} (97%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4598eaa9e2..ea531f030c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,9 +106,22 @@ if(DOLPHIN_IS_STABLE) else() set(DOLPHIN_VERSION_PATCH ${DOLPHIN_WC_REVISION}) endif() +message(${CMAKE_SYSTEM_PROCESSOR}) +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm") + set(_M_GENERIC 1) + set(_M_ARM 1) + add_definitions(-marm -march=armv7-a) + add_definitions(-D_M_ARM=1) + add_definitions(-D_M_GENERIC=1) +endif() +# Set these next two lines to test generic +#set(_M_GENERIC 1) +#add_definitions(-D_M_GENERIC=1) # Various compile flags -add_definitions(-msse2) +if(NOT _M_GENERIC) + add_definitions(-msse2) +endif() include(CheckCXXCompilerFlag) macro(check_and_add_flag var flag) @@ -258,135 +271,141 @@ if(USE_EGL) endif() add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE) +option(ANDROID "Enables a build for Android" OFF) +if(ANDROID) + message("Building for Android") + add_definitions(-DANDROID) +endif() ######################################## # Dependency checking # # TODO: We should have options for dependencies included in the externals to # override autodetection of system libraries and force the usage of the # externals. +if(NOT ANDROID) + include(CheckLib) -include(CheckLib) - -include(FindOpenGL) -include_directories(${OPENGL_INCLUDE_DIR}) -if(NOT OPENGL_GLU_FOUND) - message(FATAL_ERROR "GLU is required but not found") -endif() - -if(OPENMP) - include(FindOpenMP OPTIONAL) - if(OPENMP_FOUND) - message("OpenMP parallelization enabled") - add_definitions("${OpenMP_CXX_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}") + include(FindOpenGL) + include_directories(${OPENGL_INCLUDE_DIR}) + if(NOT OPENGL_GLU_FOUND) + message(FATAL_ERROR "GLU is required but not found") endif() -endif() -if(NOT OPENMP_FOUND) - add_definitions(-Wno-unknown-pragmas) - message("OpenMP parallelization disabled") -endif() -include(FindALSA OPTIONAL) -if(ALSA_FOUND) - add_definitions(-DHAVE_ALSA=1) - message("ALSA found, enabling ALSA sound backend") -else() - add_definitions(-DHAVE_ALSA=0) - message("ALSA NOT found, disabling ALSA sound backend") -endif(ALSA_FOUND) + if(OPENMP) + include(FindOpenMP OPTIONAL) + if(OPENMP_FOUND) + message("OpenMP parallelization enabled") + add_definitions("${OpenMP_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}") + endif() + endif() + if(NOT OPENMP_FOUND) + add_definitions(-Wno-unknown-pragmas) + message("OpenMP parallelization disabled") + endif() -check_lib(AO ao QUIET) -if(AO_FOUND) - add_definitions(-DHAVE_AO=1) - message("ao found, enabling ao sound backend") -else() - add_definitions(-DHAVE_AO=0) - message("ao NOT found, disabling ao sound backend") -endif(AO_FOUND) + include(FindALSA OPTIONAL) + if(ALSA_FOUND) + add_definitions(-DHAVE_ALSA=1) + message("ALSA found, enabling ALSA sound backend") + else() + add_definitions(-DHAVE_ALSA=0) + message("ALSA NOT found, disabling ALSA sound backend") + endif(ALSA_FOUND) -check_lib(BLUEZ bluez QUIET) -if(BLUEZ_FOUND) - add_definitions(-DHAVE_BLUEZ=1) - message("bluez found, enabling bluetooth support") -else() - add_definitions(-DHAVE_BLUEZ=0) - message("bluez NOT found, disabling bluetooth support") -endif(BLUEZ_FOUND) + check_lib(AO ao QUIET) + if(AO_FOUND) + add_definitions(-DHAVE_AO=1) + message("ao found, enabling ao sound backend") + else() + add_definitions(-DHAVE_AO=0) + message("ao NOT found, disabling ao sound backend") + endif(AO_FOUND) -check_lib(PULSEAUDIO libpulse-simple QUIET) -if(PULSEAUDIO_FOUND) - add_definitions(-DHAVE_PULSEAUDIO=1) - message("PulseAudio found, enabling PulseAudio sound backend") -else() - add_definitions(-DHAVE_PULSEAUDIO=0) - message("PulseAudio NOT found, disabling PulseAudio sound backend") -endif(PULSEAUDIO_FOUND) + check_lib(BLUEZ bluez QUIET) + if(BLUEZ_FOUND) + add_definitions(-DHAVE_BLUEZ=1) + message("bluez found, enabling bluetooth support") + else() + add_definitions(-DHAVE_BLUEZ=0) + message("bluez NOT found, disabling bluetooth support") + endif(BLUEZ_FOUND) -include(FindOpenAL OPTIONAL) -if(OPENAL_FOUND) - add_definitions(-DHAVE_OPENAL=1) - include_directories(${OPENAL_INCLUDE_DIR}) - message("OpenAL found, enabling OpenAL sound backend") -else() - add_definitions(-DHAVE_OPENAL=0) - message("OpenAL NOT found, disabling OpenAL sound backend") -endif(OPENAL_FOUND) + check_lib(PULSEAUDIO libpulse QUIET) + if(PULSEAUDIO_FOUND) + add_definitions(-DHAVE_PULSEAUDIO=1) + message("PulseAudio found, enabling PulseAudio sound backend") + else() + add_definitions(-DHAVE_PULSEAUDIO=0) + message("PulseAudio NOT found, disabling PulseAudio sound backend") + endif(PULSEAUDIO_FOUND) + + include(FindOpenAL OPTIONAL) + if(OPENAL_FOUND) + add_definitions(-DHAVE_OPENAL=1) + include_directories(${OPENAL_INCLUDE_DIR}) + message("OpenAL found, enabling OpenAL sound backend") + else() + add_definitions(-DHAVE_OPENAL=0) + message("OpenAL NOT found, disabling OpenAL sound backend") + endif(OPENAL_FOUND) # Note: We do not need to explicitly check for X11 as it is done in the cmake # FindOpenGL module on linux. -if(UNIX AND NOT APPLE) + if(UNIX AND NOT APPLE) + if(X11_FOUND) + add_definitions(-DHAVE_X11=1) + include_directories(${X11_INCLUDE_DIR}) + message("X11 found") + else() + message(FATAL_ERROR "X11 is required but not found") + endif(X11_FOUND) + else() + add_definitions(-DHAVE_X11=0) + endif() + if(X11_FOUND) - add_definitions(-DHAVE_X11=1) - include_directories(${X11_INCLUDE_DIR}) - message("X11 found") + check_lib(XRANDR Xrandr) + endif() + if(XRANDR_FOUND) + add_definitions(-DHAVE_XRANDR=1) else() - message(FATAL_ERROR "X11 is required but not found") - endif(X11_FOUND) -else() - add_definitions(-DHAVE_X11=0) -endif() + add_definitions(-DHAVE_XRANDR=0) + endif(XRANDR_FOUND) -if(X11_FOUND) - check_lib(XRANDR Xrandr) -endif() -if(XRANDR_FOUND) - add_definitions(-DHAVE_XRANDR=1) -else() - add_definitions(-DHAVE_XRANDR=0) -endif(XRANDR_FOUND) + if(ENCODE_FRAMEDUMPS) + check_libav() + endif() -if(ENCODE_FRAMEDUMPS) - check_libav() -endif() - -include(CheckCXXSourceRuns) -set(CMAKE_REQUIRED_LIBRARIES portaudio) -CHECK_CXX_SOURCE_RUNS( - "#include - int main(int argc, char **argv) - { if(Pa_GetVersion() >= 1890) return 0; else return 1; }" - PORTAUDIO) -if(PORTAUDIO) - message("PortAudio found, enabling mic support") - add_definitions(-DHAVE_PORTAUDIO=1) - set(PORTAUDIO_FOUND TRUE) -else() - message("PortAudio not found, disabling mic support") - add_definitions(-DHAVE_PORTAUDIO=0) - set(PORTAUDIO_FOUND FALSE) -endif(PORTAUDIO) - -if(OPROFILING) - check_lib(OPROFILE opagent opagent.h) - check_lib(BFD bfd bfd.h) - if(OPROFILE_FOUND AND BFD_FOUND) - message("oprofile found, enabling profiling support") - add_definitions(-DUSE_OPROFILE=1) + include(CheckCXXSourceRuns) + set(CMAKE_REQUIRED_LIBRARIES portaudio) + CHECK_CXX_SOURCE_RUNS( + "#include + int main(int argc, char **argv) + { if(Pa_GetVersion() >= 1890) return 0; else return 1; }" + PORTAUDIO) + if(PORTAUDIO) + message("PortAudio found, enabling mic support") + add_definitions(-DHAVE_PORTAUDIO=1) + set(PORTAUDIO_FOUND TRUE) else() - message(FATAL_ERROR "oprofile or bfd not found. Can't build profiling support.") + message("PortAudio not found, disabling mic support") + add_definitions(-DHAVE_PORTAUDIO=0) + set(PORTAUDIO_FOUND FALSE) + endif(PORTAUDIO) + + option(OPROFILING "Enable profiling" OFF) + if(OPROFILING) + check_lib(OPROFILE opagent opagent.h) + check_lib(BFD bfd bfd.h) + if(OPROFILE_FOUND AND BFD_FOUND) + message("oprofile found, enabling profiling support") + add_definitions(-DUSE_OPROFILE=1) + else() + message(FATAL_ERROR "oprofile or bfd not found. Can't build profiling support.") + endif() endif() endif() - ######################################## # Setup include directories (and make sure they are preferred over the Externals) # @@ -401,7 +420,6 @@ include_directories(Source/Core/InputCommon/Src) include_directories(Source/Core/VideoCommon/Src) include_directories(Source/Core/VideoUICommon/Src) - ######################################## # Process externals and setup their include directories # @@ -415,7 +433,7 @@ include_directories(Source/Core/VideoUICommon/Src) add_subdirectory(Externals/Bochs_disasm) include_directories(Externals/Bochs_disasm) -if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) check_lib(LZO lzo2 lzo/lzo1x.h QUIET) endif() if(LZO_FOUND) @@ -440,15 +458,16 @@ if(OPENAL_FOUND) endif() endif() -if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - include(FindSDL2 OPTIONAL) -endif() -if(SDL2_FOUND) - message("Using shared SDL2") - include_directories(${SDL2_INCLUDE_DIR}) -else(SDL2_FOUND) - # SDL2 not found, try SDL +if(NOT ANDROID) if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + include(FindSDL2 OPTIONAL) + endif() + if(SDL2_FOUND) + message("Using shared SDL2") + include_directories(${SDL2_INCLUDE_DIR}) + else(SDL2_FOUND) + # SDL2 not found, try SDL + if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") include(FindSDL OPTIONAL) endif() if(SDL_FOUND) @@ -460,12 +479,13 @@ else(SDL2_FOUND) include_directories(Externals/SDL/SDL Externals/SDL Externals/SDL/include) add_subdirectory(Externals/SDL) endif(SDL_FOUND) -endif(SDL2_FOUND) + endif(SDL2_FOUND) +endif() set(SFML_FIND_VERSION TRUE) set(SFML_FIND_VERSION_MAJOR 1) set(SFML_FIND_VERSION_MINOR 5) -if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) include(FindSFML OPTIONAL) endif() if(SFML_FOUND AND NOT SFML_VERSION_MAJOR) # SFML 1.x doesn't define SFML_VERSION_MAJOR @@ -476,7 +496,7 @@ else() include_directories(Externals/SFML/include) endif() -if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) check_lib(SOIL SOIL SOIL/SOIL.h QUIET) endif() if(SOIL_FOUND) @@ -506,26 +526,19 @@ if(WIN32) find_library(GLEW glew32s PATHS Externals/GLew) include_directories(Externals/GLew/include) else() - if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - check_lib(GLEW GLEW GL/glew.h) + if(NOT ANDROID) + if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + check_lib(GLEW GLEW GL/glew.h) + endif() + if(NOT GLEW_FOUND) + message("Using static GLEW from Externals") + add_subdirectory(Externals/GLew) + include_directories(Externals/GLew/include) + endif(NOT GLEW_FOUND) endif() - if(NOT GLEW_FOUND) - message("Using static GLEW from Externals") - add_subdirectory(Externals/GLew) - include_directories(Externals/GLew/include) - endif(NOT GLEW_FOUND) - - if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - check_lib(CG Cg Cg/cg.h) - endif() - if(NOT CG_FOUND) - message("Using static Cg from Externals") - include_directories(Externals) - endif(NOT CG_FOUND) - check_lib(CGGL CgGL Cg/cgGL.h) endif() -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) find_library(CL OpenCL) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-weak_framework,OpenCL") else() @@ -533,10 +546,25 @@ else() add_subdirectory(Externals/CLRun) endif() -if(NOT DISABLE_WX) +if(NOT DISABLE_WX AND NOT ANDROID) include(FindwxWidgets OPTIONAL) FIND_PACKAGE(wxWidgets COMPONENTS core aui adv) + if(wxWidgets_FOUND) + EXECUTE_PROCESS( + COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}" + ${wxWidgets_CONFIG_OPTIONS} --version + OUTPUT_VARIABLE wxWidgets_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + message("Found wxWidgets version ${wxWidgets_VERSION}") + if(${wxWidgets_VERSION} VERSION_LESS "2.8.9") + message("At least 2.8.9 is required; ignoring found version") + unset(wxWidgets_FOUND) + endif() + endif(wxWidgets_FOUND) + if(wxWidgets_FOUND) EXECUTE_PROCESS( COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}" @@ -557,26 +585,26 @@ if(NOT DISABLE_WX) endif() endif(wxWidgets_FOUND) - if(UNIX AND NOT APPLE) - # There is a bug in the FindGTK module in cmake version 2.8.2 that - # does not find gdk-pixbuf-2.0. On the other hand some 2.8.3 - # users have complained that pkg-config does not find - # gdk-pixbuf-2.0. On yet another hand, cmake version 2.8.3 in - # Ubuntu Natty does not find the glib libraries correctly. - # Ugly!!! - execute_process(COMMAND lsb_release -c -s - OUTPUT_VARIABLE DIST_NAME - ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) - if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} - VERSION_EQUAL 2.8.2 OR "${DIST_NAME}" STREQUAL "natty") - check_lib(GTK2 gtk+-2.0 gtk.h REQUIRED) - else() - include(FindGTK2) - if(GTK2_FOUND) - include_directories(${GTK2_INCLUDE_DIRS}) + if(UNIX AND NOT APPLE) + # There is a bug in the FindGTK module in cmake version 2.8.2 that + # does not find gdk-pixbuf-2.0. On the other hand some 2.8.3 + # users have complained that pkg-config does not find + # gdk-pixbuf-2.0. On yet another hand, cmake version 2.8.3 in + # Ubuntu Natty does not find the glib libraries correctly. + # Ugly!!! + execute_process(COMMAND lsb_release -c -s + OUTPUT_VARIABLE DIST_NAME + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} + VERSION_EQUAL 2.8.2 OR "${DIST_NAME}" STREQUAL "natty") + check_lib(GTK2 gtk+-2.0 gtk.h REQUIRED) + else() + include(FindGTK2) + if(GTK2_FOUND) + include_directories(${GTK2_INCLUDE_DIRS}) + endif() endif() endif() - endif() if(wxWidgets_FOUND) include(${wxWidgets_USE_FILE}) @@ -608,7 +636,7 @@ if(NOT DISABLE_WX) set(wxWidgets_LIBRARIES "wx") endif(wxWidgets_FOUND) add_definitions(-DHAVE_WX=1) -endif(NOT DISABLE_WX) +endif(NOT DISABLE_WX AND NOT ANDROID) ######################################## @@ -682,4 +710,4 @@ list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_BINARY_DIR}") # CPack must be included after the CPACK_* variables are set in order for those # variables to take effect. -include(CPack) +Include(CPack) diff --git a/Source/Core/AudioCommon/CMakeLists.txt b/Source/Core/AudioCommon/CMakeLists.txt index 3b6d0cea4d..939956460d 100644 --- a/Source/Core/AudioCommon/CMakeLists.txt +++ b/Source/Core/AudioCommon/CMakeLists.txt @@ -6,6 +6,11 @@ set(SRCS Src/AudioCommon.cpp set(LIBS "") +if(ANDROID) + set(SRCS ${SRCS} Src/OpenSLESStream.cpp) + set(LIBS ${LIBS} OpenSLES) +endif(ANDROID) + if(ALSA_FOUND) set(SRCS ${SRCS} Src/AlsaSoundStream.cpp) set(LIBS ${LIBS} ${ALSA_LIBRARIES}) diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp index e14b9ac45e..2f299d0edb 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp @@ -26,6 +26,7 @@ #include "CoreAudioSoundStream.h" #include "OpenALStream.h" #include "PulseAudioStream.h" +#include "OpenSLESStream.h" #include "../../Core/Src/Movie.h" #include "../../Core/Src/ConfigManager.h" @@ -55,7 +56,8 @@ namespace AudioCommon soundStream = new CoreAudioSound(mixer); else if (backend == BACKEND_PULSEAUDIO && PulseAudio::isValid()) soundStream = new PulseAudio(mixer); - + else if (backend == BACKEND_OPENSLES && OpenSLESStream::isValid()) + soundStream = new OpenSLESStream(mixer); if (soundStream != NULL) { UpdateSoundStream(); @@ -116,7 +118,8 @@ namespace AudioCommon backends.push_back(BACKEND_PULSEAUDIO); if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL); - + if (OpenSLESStream::isValid()) + backends.push_back(BACKEND_OPENSLES); return backends; } diff --git a/Source/Core/AudioCommon/Src/OpenSLESStream.cpp b/Source/Core/AudioCommon/Src/OpenSLESStream.cpp new file mode 100644 index 0000000000..b0913a1895 --- /dev/null +++ b/Source/Core/AudioCommon/Src/OpenSLESStream.cpp @@ -0,0 +1,145 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifdef ANDROID +#include "Common.h" +#include +#include "OpenSLESStream.h" + +#include +#include + +// engine interfaces +static SLObjectItf engineObject; +static SLEngineItf engineEngine; +static SLObjectItf outputMixObject; + +// buffer queue player interfaces +static SLObjectItf bqPlayerObject = NULL; +static SLPlayItf bqPlayerPlay; +static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; +static SLMuteSoloItf bqPlayerMuteSolo; +static SLVolumeItf bqPlayerVolume; +static CMixer *g_mixer; +#define BUFFER_SIZE 512 +#define BUFFER_SIZE_IN_SAMPLES (BUFFER_SIZE / 2) + +// Double buffering. +static short buffer[2][BUFFER_SIZE]; +static int curBuffer = 0; + +static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { + assert(bq == bqPlayerBufferQueue); + assert(NULL == context); + + short *nextBuffer = buffer[curBuffer]; + int nextSize = sizeof(buffer[0]); + + SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); + + // Comment from sample code: + // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, + // which for this code example would indicate a programming error + assert(SL_RESULT_SUCCESS == result); + + curBuffer ^= 1; // Switch buffer + // Render to the fresh buffer + g_mixer->Mix(reinterpret_cast(buffer[curBuffer]), BUFFER_SIZE_IN_SAMPLES); +} +bool OpenSLESStream::Start() +{ + SLresult result; + // create engine + result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); + assert(SL_RESULT_SUCCESS == result); + result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); + assert(SL_RESULT_SUCCESS == result); + result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0); + assert(SL_RESULT_SUCCESS == result); + result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + + SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; + SLDataFormat_PCM format_pcm = { + SL_DATAFORMAT_PCM, + 2, + SL_SAMPLINGRATE_44_1, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, + SL_BYTEORDER_LITTLEENDIAN + }; + + SLDataSource audioSrc = {&loc_bufq, &format_pcm}; + + // configure audio sink + SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; + SLDataSink audioSnk = {&loc_outmix, NULL}; + + // create audio player + const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; + const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; + result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); + assert(SL_RESULT_SUCCESS == result); + + result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, + &bqPlayerBufferQueue); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); + assert(SL_RESULT_SUCCESS == result); + + // Render and enqueue a first buffer. (or should we just play the buffer empty?) + curBuffer = 0; + + result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[curBuffer])); + if (SL_RESULT_SUCCESS != result) { + return false; + } + curBuffer ^= 1; + g_mixer = m_mixer; + return true; +} + +void OpenSLESStream::Stop() +{ + if (bqPlayerObject != NULL) { + (*bqPlayerObject)->Destroy(bqPlayerObject); + bqPlayerObject = NULL; + bqPlayerPlay = NULL; + bqPlayerBufferQueue = NULL; + bqPlayerMuteSolo = NULL; + bqPlayerVolume = NULL; + } + if (outputMixObject != NULL) { + (*outputMixObject)->Destroy(outputMixObject); + outputMixObject = NULL; + } + if (engineObject != NULL) { + (*engineObject)->Destroy(engineObject); + engineObject = NULL; + engineEngine = NULL; + } +} +#endif diff --git a/Source/Core/AudioCommon/Src/OpenSLESStream.h b/Source/Core/AudioCommon/Src/OpenSLESStream.h new file mode 100644 index 0000000000..f49160c4bc --- /dev/null +++ b/Source/Core/AudioCommon/Src/OpenSLESStream.h @@ -0,0 +1,48 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _OPENSLSTREAM_H_ +#define _OPENSLSTREAM_H_ + +#include "Thread.h" +#include "SoundStream.h" + +class OpenSLESStream : public SoundStream +{ +#ifdef ANDROID +public: + OpenSLESStream(CMixer *mixer, void *hWnd = NULL) + : SoundStream(mixer) + {}; + + virtual ~OpenSLESStream() {}; + + virtual bool Start(); + virtual void Stop(); + static bool isValid() { return true; } + virtual bool usesMixer() const { return true; } + +private: + std::thread thread; + Common::Event soundSyncEvent; +#else +public: + OpenSLESStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {} +#endif // HAVE_OPENSL +}; + +#endif diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 92d2bec668..480a08a0fc 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -1,9 +1,7 @@ -set(SRCS Src/ABI.cpp - Src/BreakPoints.cpp +set(SRCS Src/BreakPoints.cpp Src/CDUtils.cpp Src/ColorUtil.cpp Src/ConsoleListener.cpp - Src/CPUDetect.cpp Src/FileSearch.cpp Src/FileUtil.cpp Src/Hash.cpp @@ -20,10 +18,10 @@ set(SRCS Src/ABI.cpp Src/SymbolDB.cpp Src/SysConf.cpp Src/Thread.cpp - Src/Thunk.cpp Src/Timer.cpp Src/Version.cpp Src/VideoBackendBase.cpp + Src/x64ABI.cpp Src/x64Analyzer.cpp Src/x64Emitter.cpp Src/Crypto/aes_cbc.cpp @@ -33,6 +31,23 @@ set(SRCS Src/ABI.cpp Src/Crypto/md5.cpp Src/Crypto/sha1.cpp) +if(_M_ARM) #ARM + set(SRCS ${SRCS} + Src/ArmCPUDetect.cpp + Src/ArmEmitter.cpp) +else() + if(NOT _M_GENERIC) #X86 + set(SRCS ${SRCS} + Src/x64FPURoundMode.cpp + Src/x64Thunk.cpp + ) + endif() + set(SRCS ${SRCS} Src/x64CPUDetect.cpp) +endif() +if(_M_GENERIC) #Generic + set(SRCS ${SRCS} + Src/GenericFPURoundMode.cpp) +endif() if(WIN32) set(SRCS ${SRCS} Src/ExtendedTrace.cpp) endif(WIN32) diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 0128a75a09..626a4df909 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -158,12 +158,10 @@ - - @@ -195,15 +193,17 @@ - + + + + - @@ -251,6 +251,7 @@ + diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index 8b05ecbba4..d427b70cdd 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -1,11 +1,9 @@  - - @@ -23,7 +21,6 @@ - @@ -53,9 +50,12 @@ Crypto + + + + - @@ -121,6 +121,7 @@ + diff --git a/Source/Core/Common/Src/ArmCPUDetect.cpp b/Source/Core/Common/Src/ArmCPUDetect.cpp new file mode 100644 index 0000000000..c03ab08c48 --- /dev/null +++ b/Source/Core/Common/Src/ArmCPUDetect.cpp @@ -0,0 +1,160 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "CPUDetect.h" +#include "StringUtil.h" + +const char procfile[] = "/proc/cpuinfo"; + +char *GetCPUString() +{ + const char marker[] = "Hardware\t: "; + char *cpu_string = 0; + // Count the number of processor lines in /proc/cpuinfo + char buf[1024]; + FILE *fp; + + fp = fopen(procfile, "r"); + if (!fp) + return 0; + + while (fgets(buf, sizeof(buf), fp)) + { + if (strncmp(buf, marker, sizeof(marker) - 1)) + continue; + cpu_string = buf + sizeof(marker) - 1; + cpu_string = strndup(cpu_string, strlen(cpu_string) - 1); // Strip the newline + break; + } + return cpu_string; +} +bool CheckCPUFeature(const char *feature) +{ + const char marker[] = "Features\t: "; + char buf[1024]; + FILE *fp; + + fp = fopen(procfile, "r"); + if (!fp) + return 0; + + while (fgets(buf, sizeof(buf), fp)) + { + if (strncmp(buf, marker, sizeof(marker) - 1)) + continue; + char *featurestring = buf + sizeof(marker) - 1; + char *token = strtok(featurestring, " "); + while (token != NULL) + { + if (strstr(token, feature)) + return true; + token = strtok(NULL, " "); + } + } + return false; +} +int GetCoreCount() +{ + const char marker[] = "processor\t: "; + int cores = 0; + char buf[1024]; + FILE *fp; + + fp = fopen(procfile, "r"); + if (!fp) + return 0; + + while (fgets(buf, sizeof(buf), fp)) + { + if (strncmp(buf, marker, sizeof(marker) - 1)) + continue; + ++cores; + } + return cores; +} + +CPUInfo cpu_info; + +CPUInfo::CPUInfo() { + Detect(); +} + +// Detects the various cpu features +void CPUInfo::Detect() +{ + // Set some defaults here + // When ARMv8 cpus come out, these need to be updated. + HTT = false; + OS64bit = false; + CPU64bit = false; + Mode64bit = false; + vendor = VENDOR_ARM; + + // Get the information about the CPU + strncpy(cpu_string, GetCPUString(), sizeof(cpu_string)); + num_cores = GetCoreCount(); + bSwp = CheckCPUFeature("swp"); + bHalf = CheckCPUFeature("half"); + bThumb = CheckCPUFeature("thumb"); + bFastMult = CheckCPUFeature("fastmult"); + bVFP = CheckCPUFeature("vfp"); + bEDSP = CheckCPUFeature("edsp"); + bThumbEE = CheckCPUFeature("thumbee"); + bNEON = CheckCPUFeature("neon"); + bVFPv3 = CheckCPUFeature("vfpv3"); + bTLS = CheckCPUFeature("tls"); + bVFPv4 = CheckCPUFeature("vfpv4"); + bIDIVa = CheckCPUFeature("idiva"); + bIDIVt = CheckCPUFeature("idivt"); + // These two are ARMv8 specific. + bFP = CheckCPUFeature("fp"); + bASIMD = CheckCPUFeature("asimd"); + + +#if defined(__ARM_ARCH_7A__) + bArmV7 = true; +#else + bArmV7 = false; +#endif +} + +// Turn the cpu info into a string we can show +std::string CPUInfo::Summarize() +{ + std::string sum; + if (num_cores == 1) + sum = StringFromFormat("%s, %i core", cpu_string, num_cores); + else + sum = StringFromFormat("%s, %i cores", cpu_string, num_cores); + + if (bSwp) sum += ", SWP"; + if (bHalf) sum += ", Half"; + if (bThumb) sum += ", Thumb"; + if (bFastMult) sum += ", FastMult"; + if (bVFP) sum += ", VFP"; + if (bEDSP) sum += ", EDSP"; + if (bThumbEE) sum += ", ThumbEE"; + if (bNEON) sum += ", NEON"; + if (bVFPv3) sum += ", VFPv3"; + if (bTLS) sum += ", TLS"; + if (bVFPv4) sum += ", VFPv4"; + if (bIDIVa) sum += ", IDIVa"; + if (bIDIVt) sum += ", IDIVt"; + + return sum; +} diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp new file mode 100644 index 0000000000..6463dbe2ef --- /dev/null +++ b/Source/Core/Common/Src/ArmEmitter.cpp @@ -0,0 +1,967 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "ArmEmitter.h" +#include "CPUDetect.h" + +#include +#include + +// For cache flushing on Symbian/Blackberry +#ifdef __SYMBIAN32__ +#include +#endif + +#ifdef BLACKBERRY +#include +#endif + +namespace ArmGen +{ + +inline u32 RotR(u32 a, int amount) { + if (!amount) return a; + return (a >> amount) | (a << (32 - amount)); +} + +inline u32 RotL(u32 a, int amount) { + if (!amount) return a; + return (a << amount) | (a >> (32 - amount)); +} + +bool TryMakeOperand2(u32 imm, Operand2 &op2) { + // Just brute force it. + for (int i = 0; i < 16; i++) { + int mask = RotR(0xFF, i * 2); + if ((imm & mask) == imm) { + op2 = Operand2((u8)(RotL(imm, i * 2)), (u8)i); + return true; + } + } + return false; +} + +bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse) +{ + if (!TryMakeOperand2(imm, op2)) { + *inverse = true; + return TryMakeOperand2(~imm, op2); + } else { + *inverse = false; + return true; + } +} + +bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated) +{ + if (!TryMakeOperand2(imm, op2)) { + *negated = true; + return TryMakeOperand2(-imm, op2); + } else { + *negated = false; + return true; + } +} + +void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize) +{ + Operand2 op2; + bool 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 + MVN(reg, op2); + } else { + if (cpu_info.bArmV7) { + // ARMv7 - can use MOVT/MOVW, best choice + MOVW(reg, val & 0xFFFF); + if(val & 0xFFFF0000) + MOVT(reg, val, true); + } else { + // ARMv6 - fallback sequence. + // TODO: Optimize further. Can for example choose negation etc. + // Literal pools is another way to do this but much more complicated + // so I can't really be bothered for an outdated CPU architecture like ARMv6. + bool first = true; + int shift = 16; + for (int i = 0; i < 4; i++) { + if (val & 0xFF) { + if (first) { + MOV(reg, Operand2((u8)val, (u8)(shift & 0xF))); + first = false; + } else { + ORR(reg, reg, Operand2((u8)val, (u8)(shift & 0xF))); + } + } + shift -= 4; + val >>= 8; + } + } + } +} +// 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); +} + +void ARMXEmitter::SetCodePtr(u8 *ptr) +{ + code = ptr; + startcode = code; +} + +const u8 *ARMXEmitter::GetCodePtr() const +{ + return code; +} + +u8 *ARMXEmitter::GetWritableCodePtr() +{ + return code; +} + +void ARMXEmitter::ReserveCodeSpace(u32 bytes) +{ + for (u32 i = 0; i < bytes/4; i++) + Write32(0xE1200070); //bkpt 0 +} + +const u8 *ARMXEmitter::AlignCode16() +{ + ReserveCodeSpace((-(s32)code) & 15); + return code; +} + +const u8 *ARMXEmitter::AlignCodePage() +{ + ReserveCodeSpace((-(s32)code) & 4095); + return code; +} + +void ARMXEmitter::FlushIcache() +{ + FlushIcacheSection(lastCacheFlushEnd, code); + lastCacheFlushEnd = code; +} + +void ARMXEmitter::FlushIcacheSection(u8 *start, u8 *end) +{ +#ifdef __SYMBIAN32__ + User::IMB_Range( start, end); +#elif defined(BLACKBERRY) + msync(start, end - start, MS_SYNC | MS_INVALIDATE_ICACHE); +#else +#ifndef _WIN32 +#ifdef ANDROID + __builtin___clear_cache (start, end); +#else + // If on Linux, we HAVE to clear from start addr or else everything gets /really/ unstable + __builtin___clear_cache (startcode, end); +#endif +#endif +#endif +} + +void ARMXEmitter::SetCC(CCFlags cond) +{ + condition = cond << 28; +} + +void ARMXEmitter::NOP(int count) +{ + for (int i = 0; i < count; i++) { + Write32(condition | 0x01A00000); + } +} + +void ARMXEmitter::SETEND(bool BE) +{ + //SETEND is non-conditional + Write32( 0xF1010000 | (BE << 9)); +} +void ARMXEmitter::BKPT(u16 arg) +{ + Write32(condition | 0x01200070 | (arg << 4 & 0x000FFF00) | (arg & 0x0000000F)); +} +void ARMXEmitter::YIELD() +{ + Write32(condition | 0x0320F001); +} + +FixupBranch ARMXEmitter::B() +{ + FixupBranch branch; + branch.type = 0; // Zero for B + branch.ptr = code; + branch.condition = condition; + //We'll write NOP here for now. + Write32(condition | 0x01A00000); + return branch; +} +FixupBranch ARMXEmitter::BL() +{ + FixupBranch branch; + branch.type = 1; // Zero for B + branch.ptr = code; + branch.condition = condition; + //We'll write NOP here for now. + Write32(condition | 0x01A00000); + return branch; +} + +FixupBranch ARMXEmitter::B_CC(CCFlags Cond) +{ + FixupBranch branch; + branch.type = 0; // Zero for B + branch.ptr = code; + branch.condition = Cond << 28; + //We'll write NOP here for now. + Write32(condition | 0x01A00000); + return branch; +} +void ARMXEmitter::B_CC(CCFlags Cond, const void *fnptr) +{ + s32 distance = (s32)fnptr - (s32(code) + 8); + _assert_msg_(DYNA_REC, distance > -33554432 + && distance <= 33554432, + "B_CC out of range (%p calls %p)", code, fnptr); + + Write32((Cond << 28) | 0x0A000000 | ((distance >> 2) & 0x00FFFFFF)); +} +FixupBranch ARMXEmitter::BL_CC(CCFlags Cond) +{ + FixupBranch branch; + branch.type = 1; // Zero for B + branch.ptr = code; + branch.condition = Cond << 28; + //We'll write NOP here for now. + Write32(condition | 0x01A00000); + return branch; +} +void ARMXEmitter::SetJumpTarget(FixupBranch const &branch) +{ + s32 distance = (s32(code) - 8) - (s32)branch.ptr; + _assert_msg_(DYNA_REC, distance > -33554432 + && distance <= 33554432, + "SetJumpTarget out of range (%p calls %p)", code, + branch.ptr); + if(branch.type == 0) // B + *(u32*)branch.ptr = (u32)(branch.condition | (10 << 24) | ((distance >> 2) & + 0x00FFFFFF)); + else // BL + *(u32*)branch.ptr = (u32)(branch.condition | 0x0B000000 | ((distance >> 2) + & 0x00FFFFFF)); +} +void ARMXEmitter::B (const void *fnptr) +{ + s32 distance = (s32)fnptr - (s32(code) + 8); + _assert_msg_(DYNA_REC, distance > -33554432 + && distance <= 33554432, + "B out of range (%p calls %p)", code, fnptr); + + Write32(condition | 0x0A000000 | ((distance >> 2) & 0x00FFFFFF)); +} + +void ARMXEmitter::B(ARMReg src) +{ + Write32(condition | 0x12FFF10 | src); +} + +void ARMXEmitter::BL(const void *fnptr) +{ + s32 distance = (s32)fnptr - (s32(code) + 8); + _assert_msg_(DYNA_REC, distance > -33554432 + && distance <= 33554432, + "BL out of range (%p calls %p)", code, fnptr); + Write32(condition | 0x0B000000 | ((distance >> 2) & 0x00FFFFFF)); +} +void ARMXEmitter::BL(ARMReg src) +{ + Write32(condition | 0x12FFF30 | src); +} +void ARMXEmitter::PUSH(const int num, ...) +{ + u16 RegList = 0; + u8 Reg; + int i; + va_list vl; + va_start(vl, num); + for (i=0;i> 16 : Rm); } + +void ARMXEmitter::WriteInstruction (u32 Op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags) // This can get renamed later +{ + s32 op = InstOps[Op][Rm.GetType()]; // Type always decided by last operand + u32 Data = Rm.GetData(); + if (Rm.GetType() == TYPE_IMM) + { + switch (Op) + { + // MOV cases that support IMM16 + case 16: + case 17: + Data = Rm.Imm16(); + break; + default: + break; + } + } + 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); +} + +// Data Operations +void ARMXEmitter::WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2) +{ + Write32(condition | (0x7 << 24) | (Op << 20) | (dest << 16) | (Op2 << 12) | (r1 << 8) | (Op3 << 5) | (1 << 4) | r2); +} +void ARMXEmitter::UDIV(ARMReg dest, ARMReg dividend, ARMReg divisor) +{ + if (!cpu_info.bIDIVa) + PanicAlert("Trying to use integer divide on hardware that doesn't support it. Bad programmer."); + WriteSignedMultiply(3, 0xF, 0, dest, divisor, dividend); +} +void ARMXEmitter::SDIV(ARMReg dest, ARMReg dividend, ARMReg divisor) +{ + if (!cpu_info.bIDIVa) + PanicAlert("Trying to use integer divide on hardware that doesn't support it. Bad programmer."); + WriteSignedMultiply(1, 0xF, 0, dest, divisor, dividend); +} +void ARMXEmitter::LSL (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, false, dest, src, op2);} +void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, true, dest, src, op2);} +void ARMXEmitter::LSL (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, false, dest, src, op2);} +void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, true, dest, src, op2);} +void ARMXEmitter::MUL (ARMReg dest, ARMReg src, ARMReg op2) +{ + Write32(condition | (dest << 16) | (src << 8) | (9 << 4) | op2); +} +void ARMXEmitter::MULS(ARMReg dest, ARMReg src, ARMReg op2) +{ + Write32(condition | (1 << 20) | (dest << 16) | (src << 8) | (9 << 4) | op2); +} + +void ARMXEmitter::Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn) { + Write32(condition | (op << 20) | (destHi << 16) | (destLo << 12) | (rm << 8) | (9 << 4) | rn); +} + +void ARMXEmitter::UMULL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn) +{ + Write4OpMultiply(0x8, destLo, destHi, rn, rm); +} + +void ARMXEmitter::SMULL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn) +{ + Write4OpMultiply(0xC, destLo, destHi, rn, rm); +} +void ARMXEmitter::SXTB (ARMReg dest, ARMReg op2) +{ + Write32(condition | (0x6AF << 16) | (dest << 12) | (7 << 4) | op2); +} +void ARMXEmitter::SXTH (ARMReg dest, ARMReg op2, u8 rotation) +{ + SXTAH(dest, (ARMReg)15, op2, rotation); +} +void ARMXEmitter::SXTAH(ARMReg dest, ARMReg src, ARMReg op2, u8 rotation) +{ + // bits ten and 11 are the rotation amount, see 8.8.232 for more + // information + Write32(condition | (0x6B << 20) | (src << 16) | (dest << 12) | (rotation << 10) | (7 << 4) | op2); +} +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) +{ + Write32(condition | (0x320F << 12) | (write_nzcvq << 19) | (write_g << 18) | op2.Imm12Mod()); +} +void ARMXEmitter::_MSR (bool write_nzcvq, bool write_g, ARMReg src) +{ + Write32(condition | (0x120F << 12) | (write_nzcvq << 19) | (write_g << 18) | src); +} +void ARMXEmitter::MRS (ARMReg dest) +{ + Write32(condition | (16 << 20) | (15 << 16) | (dest << 12)); +} +void ARMXEmitter::WriteStoreOp(u32 op, ARMReg dest, ARMReg src, Operand2 op2) +{ + if (op2.GetData() == 0) // Don't index + Write32(condition | 0x01800000 | (op << 20) | (dest << 16) | (src << 12) | op2.Imm12()); + else + Write32(condition | (op << 20) | (3 << 23) | (dest << 16) | (src << 12) | op2.Imm12()); +} +void ARMXEmitter::STR (ARMReg dest, ARMReg src, Operand2 op) { WriteStoreOp(0x40, dest, src, op);} +void ARMXEmitter::STRB(ARMReg dest, ARMReg src, Operand2 op) { WriteStoreOp(0x44, dest, src, op);} +void ARMXEmitter::STR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add) +{ + Write32(condition | (0x60 << 20) | (Index << 24) | (Add << 23) | (dest << 16) | (base << 12) | offset); +} +void ARMXEmitter::LDREX(ARMReg dest, ARMReg base) +{ + Write32(condition | (25 << 20) | (base << 16) | (dest << 12) | 0xF9F); +} +void ARMXEmitter::STREX(ARMReg dest, ARMReg base, ARMReg op) +{ + _assert_msg_(DYNA_REC, (dest != base && dest != op), "STREX dest can't be other two registers"); + Write32(condition | (24 << 20) | (base << 16) | (dest << 12) | (0xF9 << 4) | op); +} +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) +{ + Write32(condition | (0x61 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (dest << 12) | offset); +} +void ARMXEmitter::WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList) +{ + Write32(condition | (op << 20) | (WriteBack << 21) | (dest << 16) | RegList); +} +void ARMXEmitter::STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...) +{ + u16 RegList = 0; + u8 Reg; + int i; + va_list vl; + va_start(vl, Regnum); + for (i=0;i= 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 >= D0, "Pass invalid register to VADD(integer)"); + _assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VADD(integer) when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + // 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) | (register_quad << 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, u16 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 & 3), "Offset needs to be word aligned"); + bool single_reg = Dest < D0; + + Dest = SubBase(Dest); + + if (single_reg) + { + Write32(NO_COND | (0x1B << 23) | ((Dest & 0x1) << 22) | (1 << 20) | (Base << 16) \ + | ((Dest & 0x1E) << 11) | (10 << 8) | (op >> 2)); + + } + else + { + Write32(NO_COND | (0x1B << 23) | ((Dest & 0x10) << 18) | (1 << 20) | (Base << 16) \ + | ((Dest & 0xF) << 12) | (11 << 8) | (op >> 2)); + } +} +void ARMXEmitter::VSTR(ARMReg Src, ARMReg Base, u16 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 & 3), "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 >> 2)); + + } + else + { + Write32(NO_COND | (0x1B << 23) | ((Src & 0x10) << 18) | (Base << 16) \ + | ((Src & 0xF) << 12) | (11 << 8) | (op >> 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) << 15) \ + | ((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::VABS(ARMReg Vd, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd < Q0, "VABS doesn't currently support Quad reg"); + _assert_msg_(DYNA_REC, Vd >= S0, "VABS doesn't support ARM Regs"); + bool single_reg = Vd < D0; + + Vd = SubBase(Vd); + Vm = SubBase(Vm); + + if (single_reg) + { + Write32(NO_COND | (0xEB << 20) | ((Vd & 0x1) << 6) | ((Vd & 0x1E) << 11) \ + | (0xAC << 4) | ((Vm & 0x1) << 5) | (Vm >> 1)); + } + else + { + Write32(NO_COND | (0xEB << 20) | ((Vd & 0x10) << 18) | ((Vd & 0xF) << 12) \ + | (0xBC << 4) | ((Vm & 0x10) << 1) | (Vm & 0xF)); + } +} +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) << 11) | (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) << 11) | (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, bool high) +{ + _assert_msg_(DYNA_REC, Src < S0, "This VMOV doesn't support SRC other than ARM Reg"); + _assert_msg_(DYNA_REC, Dest >= D0, "This VMOV doesn't support DEST other than VFP"); + + Dest = SubBase(Dest); + + Write32(NO_COND | (0xE << 24) | (high << 21) | ((Dest & 0xF) << 16) | (Src << 12) \ + | (11 << 8) | ((Dest & 0x10) << 3) | (1 << 4)); +} +void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src) +{ + if (Dest > R15) + { + if (Src < S0) + { + if (Dest < D0) + { + // Moving to a Neon register FROM ARM Reg + Dest = (ARMReg)(Dest - S0); + Write32(NO_COND | (0xE0 << 20) | ((Dest & 0x1E) << 15) | (Src << 12) \ + | (0xA << 8) | ((Dest & 0x1) << 7) | (1 << 4)); + return; + } + else + { + // Move 64bit from Arm reg + _assert_msg_(DYNA_REC, false, "This VMOV doesn't support moving 64bit ARM to NEON"); + return; + } + } + } + else + { + if (Src > R15) + { + if (Src < D0) + { + // Moving to ARM Reg from Neon Register + 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 + { + // Move Arm reg to Arm reg + _assert_msg_(DYNA_REC, false, "VMOV doesn't support moving ARM registers"); + } + } + // Moving NEON registers + 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) + { + 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 + 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 + 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 + { + Write32(NO_COND | (0x1D << 23) | ((Dest & 0x10) << 18) | (0x3 << 20) | ((Dest & 0xF) << 12) \ + | (0x2D << 6) | ((Src & 0x10) << 1) | (Src & 0xF)); + } + } +} + +} diff --git a/Source/Core/Common/Src/ArmEmitter.h b/Source/Core/Common/Src/ArmEmitter.h new file mode 100644 index 0000000000..13635867a9 --- /dev/null +++ b/Source/Core/Common/Src/ArmEmitter.h @@ -0,0 +1,587 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// WARNING - THIS LIBRARY IS NOT THREAD SAFE!!! + +#ifndef _DOLPHIN_ARM_CODEGEN_ +#define _DOLPHIN_ARM_CODEGEN_ + +#include "Common.h" +#include "MemoryUtil.h" +#if defined(__SYMBIAN32__) || defined(PANDORA) +#include +#endif + +#undef _IP +#undef R0 +#undef _SP +#undef _LR +#undef _PC + +namespace ArmGen +{ +enum ARMReg +{ + // GPRs + R0 = 0, R1, R2, R3, R4, R5, + R6, R7, R8, R9, R10, R11, + + // SPRs + // R13 - R15 are SP, LR, and PC. + // Almost always referred to by name instead of register number + R12 = 12, R13 = 13, R14 = 14, R15 = 15, + _IP = 12, _SP = 13, _LR = 14, _PC = 15, + + + // VFP single precision registers + S0, S1, S2, S3, S4, S5, S6, + S7, S8, S9, S10, S11, S12, S13, + S14, S15, S16, S17, S18, S19, S20, + S21, S22, S23, S24, S25, S26, S27, + S28, S29, S30, S31, + + // VFP Double Precision registers + D0, D1, D2, D3, D4, D5, D6, D7, + D8, D9, D10, D11, D12, D13, D14, D15, + D16, D17, D18, D19, D20, D21, D22, D23, + D24, D25, D26, D27, D28, D29, D30, D31, + + // ASIMD Quad-Word registers + Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, + Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, + INVALID_REG = 0xFFFFFFFF +}; + +enum CCFlags +{ + CC_EQ = 0, // Equal + CC_NEQ, // Not equal + CC_CS, // Carry Set + CC_CC, // Carry Clear + CC_MI, // Minus (Negative) + CC_PL, // Plus + CC_VS, // Overflow + CC_VC, // No Overflow + CC_HI, // Unsigned higher + CC_LS, // Unsigned lower or same + CC_GE, // Signed greater than or equal + CC_LT, // Signed less than + CC_GT, // Signed greater than + CC_LE, // Signed less than or equal + CC_AL, // Always (unconditional) 14 + CC_HS = CC_CS, // Alias of CC_CS Unsigned higher or same + CC_LO = CC_CC, // Alias of CC_CC Unsigned lower +}; +const u32 NO_COND = 0xE0000000; + +enum ShiftType +{ + ST_LSL = 0, + ST_ASL = 0, + ST_LSR = 1, + ST_ASR = 2, + ST_ROR = 3, + ST_RRX = 4 +}; +enum IntegerSize +{ + I_I8 = 0, + I_I16, + I_I32, + I_I64 +}; + +enum +{ + NUMGPRs = 13, +}; + +class ARMXEmitter; + +enum OpType +{ + TYPE_IMM = 0, + TYPE_REG, + TYPE_IMMSREG, + TYPE_RSR, + TYPE_MEM +}; + +// This is no longer a proper operand2 class. Need to split up. +class Operand2 +{ + friend class ARMXEmitter; +protected: + u32 Value; + +private: + OpType Type; + + // IMM types + u8 Rotation; // Only for u8 values + + // Register types + u8 IndexOrShift; + ShiftType Shift; +public: + OpType GetType() + { + return Type; + } + Operand2() {} + Operand2(u32 imm, OpType type = TYPE_IMM) + { + Type = type; + Value = imm; + Rotation = 0; + } + + Operand2(ARMReg Reg) + { + Type = TYPE_REG; + Value = Reg; + Rotation = 0; + } + Operand2(u8 imm, u8 rotation) + { + Type = TYPE_IMM; + Value = imm; + Rotation = rotation; + } + Operand2(ARMReg base, ShiftType type, ARMReg shift) // RSR + { + Type = TYPE_RSR; + _assert_msg_(DYNA_REC, type != ST_RRX, "Invalid Operand2: RRX does not take a register shift amount"); + IndexOrShift = shift; + Shift = type; + Value = base; + } + + Operand2(u8 shift, ShiftType type, ARMReg base)// For IMM shifted register + { + if(shift == 32) shift = 0; + switch (type) + { + case ST_LSL: + _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: LSL %u", shift); + break; + case ST_LSR: + _assert_msg_(DYNA_REC, shift <= 32, "Invalid Operand2: LSR %u", shift); + if (!shift) + type = ST_LSL; + if (shift == 32) + shift = 0; + break; + case ST_ASR: + _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: LSR %u", shift); + if (!shift) + type = ST_LSL; + if (shift == 32) + shift = 0; + break; + case ST_ROR: + _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: ROR %u", shift); + if (!shift) + type = ST_LSL; + break; + case ST_RRX: + _assert_msg_(DYNA_REC, shift == 0, "Invalid Operand2: RRX does not take an immediate shift amount"); + type = ST_ROR; + break; + } + IndexOrShift = shift; + Shift = type; + Value = base; + Type = TYPE_IMMSREG; + } + const u32 GetData() + { + switch(Type) + { + case TYPE_IMM: + return Imm12Mod(); // This'll need to be changed later + case TYPE_REG: + return Rm(); + case TYPE_IMMSREG: + return IMMSR(); + case TYPE_RSR: + return RSR(); + default: + _assert_msg_(DYNA_REC, false, "GetData with Invalid Type"); + return 0; + } + } + const u32 IMMSR() // IMM shifted register + { + _assert_msg_(DYNA_REC, Type = TYPE_IMMSREG, "IMMSR must be imm shifted register"); + return ((IndexOrShift & 0x1f) << 7 | (Shift << 5) | Value); + } + const u32 RSR() // Register shifted register + { + _assert_msg_(DYNA_REC, Type == TYPE_RSR, "RSR must be RSR Of Course"); + return (IndexOrShift << 8) | (Shift << 5) | 0x10 | Value; + } + const u32 Rm() + { + _assert_msg_(DYNA_REC, Type == TYPE_REG, "Rm must be with Reg"); + return Value; + } + + const u32 Imm5() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm5 not IMM value"); + return ((Value & 0x0000001F) << 7); + } + const u32 Imm8() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value"); + return Value & 0xFF; + } + const u32 Imm8Rot() // IMM8 with Rotation + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value"); + _assert_msg_(DYNA_REC, (Rotation & 0xE1) != 0, "Invalid Operand2: immediate rotation %u", Rotation); + return (1 << 25) | (Rotation << 7) | (Value & 0x000000FF); + } + const u32 Imm12() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12 not IMM"); + return (Value & 0x00000FFF); + } + + const u32 Imm12Mod() + { + // This is a IMM12 with the top four bits being rotation and the + // bottom eight being a IMM. This is for instructions that need to + // expand a 8bit IMM to a 32bit value and gives you some rotation as + // well. + // Each rotation rotates to the right by 2 bits + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12Mod not IMM"); + return ((Rotation & 0xF) << 8) | (Value & 0xFF); + } + const u32 Imm16() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM"); + return ( (Value & 0xF000) << 4) | (Value & 0x0FFF); + } + const u32 Imm16Low() + { + return Imm16(); + } + const u32 Imm16High() // Returns high 16bits + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM"); + return ( ((Value >> 16) & 0xF000) << 4) | ((Value >> 16) & 0x0FFF); + } + const u32 Imm24() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM"); + return (Value & 0x0FFFFFFF); + } + // NEON and ASIMD specific + const u32 Imm8ASIMD() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8ASIMD not IMM"); + return ((Value & 0x80) << 17) | ((Value & 0x70) << 12) | (Value & 0xF); + } + const u32 Imm8VFP() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8VFP not IMM"); + return ((Value & 0xF0) << 12) | (Value & 0xF); + } +}; + +// Use these when you don't know if an imm can be represented as an operand2. +// This lets you generate both an optimal and a fallback solution by checking +// the return value, which will be false if these fail to find a Operand2 that +// represents your 32-bit imm value. +bool TryMakeOperand2(u32 imm, Operand2 &op2); +bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse); +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 +{ + u8 *ptr; + u32 condition; // Remembers our codition at the time + int type; //0 = B 1 = BL +}; + +typedef const u8* JumpTarget; + +class ARMXEmitter +{ + friend struct OpArg; // for Write8 etc +private: + u8 *code, *startcode; + u8 *lastCacheFlushEnd; + u32 condition; + + void WriteStoreOp(u32 op, ARMReg dest, ARMReg src, Operand2 op2); + void WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList); + void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, ARMReg op2); + void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2); + void WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2); + + void Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm); + + // New Ops + void WriteInstruction(u32 op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags = false); + +protected: + inline void Write32(u32 value) {*(u32*)code = value; code+=4;} + +public: + ARMXEmitter() : code(0), startcode(0), lastCacheFlushEnd(0) { + condition = CC_AL << 28; + } + ARMXEmitter(u8 *code_ptr) { + code = code_ptr; + lastCacheFlushEnd = code_ptr; + startcode = code_ptr; + condition = CC_AL << 28; + } + virtual ~ARMXEmitter() {} + + void SetCodePtr(u8 *ptr); + void ReserveCodeSpace(u32 bytes); + const u8 *AlignCode16(); + const u8 *AlignCodePage(); + const u8 *GetCodePtr() const; + void FlushIcache(); + void FlushIcacheSection(u8 *start, u8 *end); + u8 *GetWritableCodePtr(); + + void SetCC(CCFlags cond = CC_AL); + + // Special purpose instructions + + // Dynamic Endian Switching + void SETEND(bool BE); + // Debug Breakpoint + void BKPT(u16 arg); + + // Hint instruction + void YIELD(); + + // Do nothing + void NOP(int count = 1); //nop padding - TODO: fast nop slides, for amd and intel (check their manuals) + +#ifdef CALL +#undef CALL +#endif + + // Branching + FixupBranch B(); + FixupBranch B_CC(CCFlags Cond); + void B_CC(CCFlags Cond, const void *fnptr); + FixupBranch BL(); + FixupBranch BL_CC(CCFlags Cond); + void SetJumpTarget(FixupBranch const &branch); + + void B (const void *fnptr); + void B (ARMReg src); + void BL(const void *fnptr); + void BL(ARMReg src); + + void PUSH(const int num, ...); + void POP(const int num, ...); + + // New Data Ops + void AND (ARMReg Rd, ARMReg Rn, Operand2 Rm); + void ANDS(ARMReg Rd, ARMReg Rn, Operand2 Rm); + void EOR (ARMReg dest, ARMReg src, Operand2 op2); + void EORS(ARMReg dest, ARMReg src, Operand2 op2); + void SUB (ARMReg dest, ARMReg src, Operand2 op2); + void SUBS(ARMReg dest, ARMReg src, Operand2 op2); + void RSB (ARMReg dest, ARMReg src, Operand2 op2); + void RSBS(ARMReg dest, ARMReg src, Operand2 op2); + void ADD (ARMReg dest, ARMReg src, Operand2 op2); + void ADDS(ARMReg dest, ARMReg src, Operand2 op2); + void ADC (ARMReg dest, ARMReg src, Operand2 op2); + void ADCS(ARMReg dest, ARMReg src, Operand2 op2); + void LSL (ARMReg dest, ARMReg src, Operand2 op2); + void LSL (ARMReg dest, ARMReg src, ARMReg op2); + void LSLS(ARMReg dest, ARMReg src, Operand2 op2); + void LSLS(ARMReg dest, ARMReg src, ARMReg op2); + 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); + void TEQ ( ARMReg src, Operand2 op2); + void CMP ( ARMReg src, Operand2 op2); + void CMN ( ARMReg src, Operand2 op2); + void ORR (ARMReg dest, ARMReg src, Operand2 op2); + void ORRS(ARMReg dest, ARMReg src, Operand2 op2); + void MOV (ARMReg dest, Operand2 op2); + void MOVS(ARMReg dest, Operand2 op2); + void BIC (ARMReg dest, ARMReg src, Operand2 op2); // BIC = ANDN + void BICS(ARMReg dest, ARMReg src, Operand2 op2); + void MVN (ARMReg dest, Operand2 op2); + void MVNS(ARMReg dest, Operand2 op2); + void MOVW(ARMReg dest, Operand2 op2); + void MOVT(ARMReg dest, Operand2 op2, bool TopBits = false); + + // UDIV and SDIV are only available on CPUs that have + // the idiva hardare capacity + void UDIV(ARMReg dest, ARMReg dividend, ARMReg divisor); + void SDIV(ARMReg dest, ARMReg dividend, ARMReg divisor); + + void MUL (ARMReg dest, ARMReg src, ARMReg op2); + void MULS(ARMReg dest, ARMReg src, ARMReg op2); + + void UMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm); + void SMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm); + + void SXTB(ARMReg dest, ARMReg op2); + void SXTH(ARMReg dest, ARMReg op2, u8 rotation = 0); + void SXTAH(ARMReg dest, ARMReg src, ARMReg op2, u8 rotation = 0); + // Using just MSR here messes with our defines on the PPC side of stuff (when this code was in dolphin...) + // Just need to put an underscore here, bit annoying. + void _MSR (bool nzcvq, bool g, Operand2 op2); + void _MSR (bool nzcvq, bool g, ARMReg src ); + void MRS (ARMReg dest); + + // Memory load/store operations + 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 + void STR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add); + + void STRB(ARMReg dest, ARMReg src, Operand2 op2 = 0); + void STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...); + void LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...); + + // Exclusive Access operations + void LDREX(ARMReg dest, ARMReg base); + // 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. + // 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); + + // VFP Only + void VLDR(ARMReg Dest, ARMReg Base, u16 op); + void VSTR(ARMReg Src, ARMReg Base, u16 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 VABS(ARMReg Vd, ARMReg Vm); + void VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm); + + void VMOV(ARMReg Dest, ARMReg Src, bool high); + void VMOV(ARMReg Dest, ARMReg Src); + + void QuickCallFunction(ARMReg scratchreg, void *func); + // Utility functions + void MOVI2R(ARMReg reg, u32 val, bool optimize = true); + void ARMABI_MOVI2M(Operand2 op, Operand2 val); +}; // class ARMXEmitter + + +// Everything that needs to generate X86 code should inherit from this. +// You get memory management for free, plus, you can use all the MOV etc functions without +// having to prefix them with gen-> or something similar. +class ARMXCodeBlock : public ARMXEmitter +{ +protected: + u8 *region; + size_t region_size; + +public: + ARMXCodeBlock() : region(NULL), region_size(0) {} + virtual ~ARMXCodeBlock() { if (region) FreeCodeSpace(); } + + // Call this before you generate any code. + void AllocCodeSpace(int size) + { + region_size = size; + region = (u8*)AllocateExecutableMemory(region_size); + SetCodePtr(region); + } + + // Always clear code space with breakpoints, so that if someone accidentally executes + // uninitialized, it just breaks into the debugger. + void ClearCodeSpace() + { + // x86/64: 0xCC = breakpoint + memset(region, 0xCC, region_size); + ResetCodePtr(); + } + + // Call this when shutting down. Don't rely on the destructor, even though it'll do the job. + void FreeCodeSpace() + { + FreeMemoryPages(region, region_size); + region = NULL; + region_size = 0; + } + + bool IsInSpace(u8 *ptr) + { + return ptr >= region && ptr < region + region_size; + } + + // Cannot currently be undone. Will write protect the entire code region. + // Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()). + void WriteProtect() + { + WriteProtectMemory(region, region_size, true); + } + + void ResetCodePtr() + { + SetCodePtr(region); + } + + size_t GetSpaceLeft() const + { + return region_size - (GetCodePtr() - region); + } +}; + +} // namespace + +#endif // _DOLPHIN_INTEL_CODEGEN_ diff --git a/Source/Core/Common/Src/CPUDetect.h b/Source/Core/Common/Src/CPUDetect.h index 928b34c109..351120e3a2 100644 --- a/Source/Core/Common/Src/CPUDetect.h +++ b/Source/Core/Common/Src/CPUDetect.h @@ -25,7 +25,8 @@ enum CPUVendor { VENDOR_INTEL = 0, VENDOR_AMD = 1, - VENDOR_OTHER = 2, + VENDOR_ARM = 2, + VENDOR_OTHER = 3, }; struct CPUInfo @@ -55,6 +56,26 @@ struct CPUInfo bool bAES; bool bLAHFSAHF64; bool bLongMode; + + // ARM specific CPUInfo + bool bSwp; + bool bHalf; + bool bThumb; + bool bFastMult; + bool bVFP; + bool bEDSP; + bool bThumbEE; + bool bNEON; + bool bVFPv3; + bool bTLS; + bool bVFPv4; + bool bIDIVa; + bool bIDIVt; + bool bArmV7; // enable MOVT, MOVW etc + + // ARMv8 specific + bool bFP; + bool bASIMD; // Call Detect() explicit CPUInfo(); diff --git a/Source/Core/Common/Src/Common.h b/Source/Core/Common/Src/Common.h index 0132915a5c..904095e255 100644 --- a/Source/Core/Common/Src/Common.h +++ b/Source/Core/Common/Src/Common.h @@ -133,7 +133,9 @@ private: // wxWidgets does not have a true dummy macro for this. #define _trans(a) a -#if defined __GNUC__ +#if defined _M_GENERIC +# define _M_SSE 0x0 +#elif defined __GNUC__ # if defined __SSE4_2__ # define _M_SSE 0x402 # elif defined __SSE4_1__ @@ -144,7 +146,7 @@ private: # define _M_SSE 0x300 # endif #elif (_MSC_VER >= 1500) || __INTEL_COMPILER // Visual Studio 2008 -# define _M_SSE 0x402 +# define _M_SSE 0x402 #endif // Host communication. diff --git a/Source/Core/Common/Src/CommonFuncs.h b/Source/Core/Common/Src/CommonFuncs.h index 585fe0999a..7c6bcdc703 100644 --- a/Source/Core/Common/Src/CommonFuncs.h +++ b/Source/Core/Common/Src/CommonFuncs.h @@ -35,7 +35,7 @@ template<> struct CompileTimeAssert {}; #define b32(x) (b16(x) | (b16(x) >>16) ) #define ROUND_UP_POW2(x) (b32(x - 1) + 1) -#if defined __GNUC__ && !defined __SSSE3__ +#if defined __GNUC__ && !defined __SSSE3__ && !defined _M_GENERIC #include static __inline __m128i __attribute__((__always_inline__)) _mm_shuffle_epi8(__m128i a, __m128i mask) @@ -60,6 +60,8 @@ _mm_shuffle_epi8(__m128i a, __m128i mask) // go to debugger mode #ifdef GEKKO #define Crash() + #elif defined _M_GENERIC + #define Crash() { exit(1); } #else #define Crash() {asm ("int $3");} #endif @@ -136,6 +138,15 @@ inline u8 swap8(u8 _data) {return _data;} inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);} inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);} inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);} +#elif _M_ARM +#ifdef ANDROID +#undef swap16 +#undef swap32 +#undef swap64 +#endif +inline u16 swap16 (u16 _data) { u32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (u16)data;} +inline u32 swap32 (u32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;} +inline u64 swap64(u64 _data) {return ((u64)swap32(_data) << 32) | swap32(_data >> 32);} #elif __linux__ inline u16 swap16(u16 _data) {return bswap_16(_data);} inline u32 swap32(u32 _data) {return bswap_32(_data);} @@ -161,7 +172,6 @@ inline u64 swap64(u64 data) {return ((u64)swap32(data) << 32) | swap32(data >> 3 inline u16 swap16(const u8* _pData) {return swap16(*(const u16*)_pData);} inline u32 swap32(const u8* _pData) {return swap32(*(const u32*)_pData);} inline u64 swap64(const u8* _pData) {return swap64(*(const u64*)_pData);} - } // Namespace Common #endif // _COMMONFUNCS_H_ diff --git a/Source/Core/Common/Src/CommonPaths.h b/Source/Core/Common/Src/CommonPaths.h index 9e14d7cf7e..cab7ce3762 100644 --- a/Source/Core/Common/Src/CommonPaths.h +++ b/Source/Core/Common/Src/CommonPaths.h @@ -36,6 +36,9 @@ // You can use the File::GetUserPath() util for this #define USERDATA_DIR "Contents/Resources/User" #define DOLPHIN_DATA_DIR "Library/Application Support/Dolphin" +#elif defined ANDROID + #define USERDATA_DIR "user" + #define DOLPHIN_DATA_DIR "/sdcard/dolphin-emu" #else #define USERDATA_DIR "user" #ifdef USER_DIR @@ -52,6 +55,8 @@ #define SYSDATA_DIR "Contents/Resources/Sys" #define SHARED_USER_DIR File::GetBundleDirectory() + \ DIR_SEP USERDATA_DIR DIR_SEP +#elif defined ANDROID + #define SYSDATA_DIR "/sdcard/dolphin-emu" #else #ifdef DATA_DIR #define SYSDATA_DIR DATA_DIR "sys" diff --git a/Source/Core/Common/Src/FPURoundMode.h b/Source/Core/Common/Src/FPURoundMode.h new file mode 100644 index 0000000000..acfd89c313 --- /dev/null +++ b/Source/Core/Common/Src/FPURoundMode.h @@ -0,0 +1,51 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#ifndef FPU_ROUND_MODE_H_ +#define FPU_ROUND_MODE_H_ +#include "Common.h" + +namespace FPURoundMode +{ + enum RoundModes + { + ROUND_NEAR = 0, + ROUND_CHOP, + ROUND_UP, + ROUND_DOWN + }; + enum PrecisionModes { + PREC_24 = 0, + PREC_53, + PREC_64 + }; + void SetRoundMode(u32 mode); + + void SetPrecisionMode(u32 mode); + + void SetSIMDMode(u32 mode); + + /* + There are two different flavors of float to int conversion: + _mm_cvtps_epi32() and _mm_cvttps_epi32(). The first rounds + according to the MXCSR rounding bits. The second one always + uses round towards zero. + */ + void SaveSIMDState(); + void LoadSIMDState(); + void LoadDefaultSIMDState(); +} +#endif diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp index 491db88e41..f42c204396 100644 --- a/Source/Core/Common/Src/FileUtil.cpp +++ b/Source/Core/Common/Src/FileUtil.cpp @@ -668,9 +668,10 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath) if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; else - paths[D_USER_IDX] = std::string(getenv("HOME") ? getenv("HOME") : getenv("PWD")) + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP; + paths[D_USER_IDX] = std::string(getenv("HOME") ? + getenv("HOME") : getenv("PWD") ? + getenv("PWD") : "") + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP; #endif - INFO_LOG(COMMON, "GetUserPath: Setting user directory to %s:", paths[D_USER_IDX].c_str()); paths[D_GCUSER_IDX] = paths[D_USER_IDX] + GC_USER_DIR DIR_SEP; paths[D_WIIROOT_IDX] = paths[D_USER_IDX] + WII_USER_DIR; diff --git a/Source/Core/Common/Src/GenericFPURoundMode.cpp b/Source/Core/Common/Src/GenericFPURoundMode.cpp new file mode 100644 index 0000000000..cc878291a1 --- /dev/null +++ b/Source/Core/Common/Src/GenericFPURoundMode.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "FPURoundMode.h" + +// Generic, do nothing +namespace FPURoundMode +{ + void SetRoundMode(u32 mode) + { + } + void SetPrecisionMode(u32 mode) + { + } + void SetSIMDMode(u32 mode) + { + } + void SaveSIMDState() + { + } + void LoadSIMDState() + { + } + void LoadDefaultSIMDState() + { + } +} diff --git a/Source/Core/Common/Src/LogManager.cpp b/Source/Core/Common/Src/LogManager.cpp index a79c413cf8..3beae08c15 100644 --- a/Source/Core/Common/Src/LogManager.cpp +++ b/Source/Core/Common/Src/LogManager.cpp @@ -17,6 +17,9 @@ #include +#ifdef ANDROID +#include "Host.h" +#endif #include "LogManager.h" #include "ConsoleListener.h" #include "Timer.h" @@ -132,7 +135,9 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, Common::Timer::GetTimeFormatted().c_str(), file, line, level_to_char[(int)level], log->GetShortName(), temp); - +#ifdef ANDROID + Host_SysMessage(msg); +#endif log->Trigger(level, msg); } diff --git a/Source/Core/Common/Src/MathUtil.cpp b/Source/Core/Common/Src/MathUtil.cpp index e078db2e9d..b97d55e62c 100644 --- a/Source/Core/Common/Src/MathUtil.cpp +++ b/Source/Core/Common/Src/MathUtil.cpp @@ -21,13 +21,6 @@ #include #include -namespace { - -static u32 saved_sse_state = _mm_getcsr(); -static const u32 default_sse_state = _mm_getcsr(); - -} - namespace MathUtil { @@ -114,23 +107,6 @@ u32 ClassifyFloat(float fvalue) } // namespace -void LoadDefaultSSEState() -{ - _mm_setcsr(default_sse_state); -} - - -void LoadSSEState() -{ - _mm_setcsr(saved_sse_state); -} - - -void SaveSSEState() -{ - saved_sse_state = _mm_getcsr(); -} - inline void MatrixMul(int n, const float *a, const float *b, float *result) { for (int i = 0; i < n; ++i) diff --git a/Source/Core/Common/Src/MathUtil.h b/Source/Core/Common/Src/MathUtil.h index a6290ff602..114a91bf3c 100644 --- a/Source/Core/Common/Src/MathUtil.h +++ b/Source/Core/Common/Src/MathUtil.h @@ -20,8 +20,8 @@ #include "Common.h" -#include #include +#include "FPURoundMode.h" namespace MathUtil { @@ -147,17 +147,6 @@ struct Rectangle inline float pow2f(float x) {return x * x;} inline double pow2(double x) {return x * x;} - -/* - There are two different flavors of float to int conversion: - _mm_cvtps_epi32() and _mm_cvttps_epi32(). The first rounds - according to the MXCSR rounding bits. The second one always - uses round towards zero. - */ - -void SaveSSEState(); -void LoadSSEState(); -void LoadDefaultSSEState(); float MathFloatVectorSum(const std::vector&); #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) diff --git a/Source/Core/Common/Src/MemArena.cpp b/Source/Core/Common/Src/MemArena.cpp index 1dcdef6672..0a2b9e0306 100644 --- a/Source/Core/Common/Src/MemArena.cpp +++ b/Source/Core/Common/Src/MemArena.cpp @@ -27,6 +27,10 @@ #include #include #include +#ifdef ANDROID +#include +#include +#endif #endif #if defined(__APPLE__) @@ -34,11 +38,41 @@ static const char* ram_temp_file = "/tmp/gc_mem.tmp"; #elif !defined(_WIN32) // non OSX unixes static const char* ram_temp_file = "/dev/shm/gc_mem.tmp"; #endif +#ifdef ANDROID +#define ASHMEM_DEVICE "/dev/ashmem" + +int AshmemCreateFileMapping(const char *name, size_t size) +{ + int fd, ret; + fd = open(ASHMEM_DEVICE, O_RDWR); + if (fd < 0) + return fd; + + // We don't really care if we can't set the name, it is optional + ret = ioctl(fd, ASHMEM_SET_NAME, name); + + ret = ioctl(fd, ASHMEM_SET_SIZE, size); + if (ret < 0) + { + close(fd); + NOTICE_LOG(MEMMAP, "Ashmem returned error: 0x%08x", ret); + return ret; + } + return fd; +} +#endif void MemArena::GrabLowMemSpace(size_t size) { #ifdef _WIN32 hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), NULL); +#elif defined(ANDROID) + fd = AshmemCreateFileMapping("Dolphin-emu", size); + if (fd < 0) + { + NOTICE_LOG(MEMMAP, "Ashmem allocation failed"); + return; + } #else mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; fd = open(ram_temp_file, O_RDWR | O_CREAT, mode); diff --git a/Source/Core/Common/Src/MemoryUtil.cpp b/Source/Core/Common/Src/MemoryUtil.cpp index 0888746d42..ff50347799 100644 --- a/Source/Core/Common/Src/MemoryUtil.cpp +++ b/Source/Core/Common/Src/MemoryUtil.cpp @@ -117,9 +117,12 @@ void* AllocateAlignedMemory(size_t size,size_t alignment) void* ptr = _aligned_malloc(size,alignment); #else void* ptr = NULL; +#ifdef ANDROID + ptr = memalign(alignment, size); +#else if (posix_memalign(&ptr, alignment, size) != 0) ERROR_LOG(MEMMAP, "Failed to allocate aligned memory"); -; +#endif #endif // printf("Mapped memory at %p (size %ld)\n", ptr, diff --git a/Source/Core/Common/Src/StdConditionVariable.h b/Source/Core/Common/Src/StdConditionVariable.h index 1b81766ee0..11de6536b4 100644 --- a/Source/Core/Common/Src/StdConditionVariable.h +++ b/Source/Core/Common/Src/StdConditionVariable.h @@ -5,7 +5,7 @@ #define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ +#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID // GCC 4.4 provides #include #else diff --git a/Source/Core/Common/Src/StdMutex.h b/Source/Core/Common/Src/StdMutex.h index 8949e905ac..8a5d22f928 100644 --- a/Source/Core/Common/Src/StdMutex.h +++ b/Source/Core/Common/Src/StdMutex.h @@ -5,7 +5,7 @@ #define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ +#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID // GCC 4.4 provides #include #else diff --git a/Source/Core/Common/Src/StdThread.h b/Source/Core/Common/Src/StdThread.h index fea058c874..6897235658 100644 --- a/Source/Core/Common/Src/StdThread.h +++ b/Source/Core/Common/Src/StdThread.h @@ -5,7 +5,7 @@ #define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ +#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID // GCC 4.4 provides #ifndef _GLIBCXX_USE_SCHED_YIELD #define _GLIBCXX_USE_SCHED_YIELD diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index e5c70b2c6b..6ef3d91a73 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -245,7 +245,7 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st while(1) { const int pos = result.find(src); - if (pos == -1) break; + if (pos == 16) break; result.replace(pos, src.size(), dest); } return result; @@ -263,25 +263,25 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st const char HEX2DEC[256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - /* 0 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 1 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 2 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1, + /* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* 1 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* 2 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16, 16,16,16,16, - /* 4 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 5 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 6 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 7 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + /* 4 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16, + /* 5 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* 6 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16, + /* 7 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* 8 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 9 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* A */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* B */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + /* 8 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* 9 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* A */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* B */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* C */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* D */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* E */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* F */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 + /* C */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* D */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* E */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* F */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16 }; std::string UriDecode(const std::string & sSrc) @@ -303,8 +303,8 @@ std::string UriDecode(const std::string & sSrc) if (*pSrc == '%') { char dec1, dec2; - if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)]) - && -1 != (dec2 = HEX2DEC[*(pSrc + 2)])) + if (16 != (dec1 = HEX2DEC[*(pSrc + 1)]) + && 16 != (dec2 = HEX2DEC[*(pSrc + 2)])) { *pEnd++ = (dec1 << 4) + dec2; pSrc += 3; diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp index 73f83c204f..3e8440b74f 100644 --- a/Source/Core/Common/Src/Thread.cpp +++ b/Source/Core/Common/Src/Thread.cpp @@ -105,7 +105,7 @@ void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) #ifdef __APPLE__ thread_policy_set(pthread_mach_thread_np(thread), THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1); -#elif defined __linux__ || defined BSD4_4 +#elif (defined __linux__ || defined BSD4_4) && !(defined ANDROID) cpu_set_t cpu_set; CPU_ZERO(&cpu_set); diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index e711fcab5c..8b38be1de1 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -33,8 +33,6 @@ #define INFINITE 0xffffffff #endif -#include - //for gettimeofday and struct time(spec|val) #include #include diff --git a/Source/Core/Common/Src/ABI.cpp b/Source/Core/Common/Src/x64ABI.cpp similarity index 99% rename from Source/Core/Common/Src/ABI.cpp rename to Source/Core/Common/Src/x64ABI.cpp index 63a8e76934..cd2f410dbf 100644 --- a/Source/Core/Common/Src/ABI.cpp +++ b/Source/Core/Common/Src/x64ABI.cpp @@ -17,7 +17,7 @@ #include "Common.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; diff --git a/Source/Core/Common/Src/ABI.h b/Source/Core/Common/Src/x64ABI.h similarity index 100% rename from Source/Core/Common/Src/ABI.h rename to Source/Core/Common/Src/x64ABI.h diff --git a/Source/Core/Common/Src/CPUDetect.cpp b/Source/Core/Common/Src/x64CPUDetect.cpp similarity index 98% rename from Source/Core/Common/Src/CPUDetect.cpp rename to Source/Core/Common/Src/x64CPUDetect.cpp index 282929e7b2..2898b91bec 100644 --- a/Source/Core/Common/Src/CPUDetect.cpp +++ b/Source/Core/Common/Src/x64CPUDetect.cpp @@ -30,7 +30,9 @@ #else //#include +#ifndef _M_GENERIC #include +#endif #if defined __FreeBSD__ #include @@ -39,7 +41,9 @@ static inline void do_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { -#ifdef _LP64 +#if defined _M_GENERIC + (*eax) = (*ebx) = (*ecx) = (*edx) = 0; +#elif defined _LP64 // Note: EBX is reserved on Mac OS X and in PIC on Linux, so it has to // restored at the end of the asm block. __asm__ ( diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 5f8d0a66f1..9f15845875 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -17,7 +17,7 @@ #include "Common.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "CPUDetect.h" namespace Gen diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h index 3b699c81a0..6b8c59b5a5 100644 --- a/Source/Core/Common/Src/x64Emitter.h +++ b/Source/Core/Common/Src/x64Emitter.h @@ -757,7 +757,7 @@ public: region_size = 0; } - bool IsInCodeSpace(u8 *ptr) + bool IsInSpace(u8 *ptr) { return ptr >= region && ptr < region + region_size; } diff --git a/Source/Core/Common/Src/x64FPURoundMode.cpp b/Source/Core/Common/Src/x64FPURoundMode.cpp new file mode 100644 index 0000000000..0beefd860a --- /dev/null +++ b/Source/Core/Common/Src/x64FPURoundMode.cpp @@ -0,0 +1,120 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "FPURoundMode.h" + +#ifndef _WIN32 +static const unsigned short FPU_ROUND_NEAR = 0 << 10; +static const unsigned short FPU_ROUND_DOWN = 1 << 10; +static const unsigned short FPU_ROUND_UP = 2 << 10; +static const unsigned short FPU_ROUND_CHOP = 3 << 10; +static const unsigned short FPU_ROUND_MASK = 3 << 10; +#include +#endif + +const u32 MASKS = 0x1F80; // mask away the interrupts. +const u32 DAZ = 0x40; +const u32 FTZ = 0x8000; + +namespace FPURoundMode +{ + // Get the default SSE states here. + static u32 saved_sse_state = _mm_getcsr(); + static const u32 default_sse_state = _mm_getcsr(); + + void SetRoundMode(u32 mode) + { + // Set FPU rounding mode to mimic the PowerPC's + #ifdef _M_IX86 + // This shouldn't really be needed anymore since we use SSE + #ifdef _WIN32 + const int table[4] = + { + _RC_NEAR, + _RC_CHOP, + _RC_UP, + _RC_DOWN + }; + _set_controlfp(_MCW_RC, table[mode]); + #else + const unsigned short table[4] = + { + FPU_ROUND_NEAR, + FPU_ROUND_CHOP, + FPU_ROUND_UP, + FPU_ROUND_DOWN + }; + unsigned short _mode; + asm ("fstcw %0" : "=m" (_mode) : ); + _mode = (_mode & ~FPU_ROUND_MASK) | table[mode]; + asm ("fldcw %0" : : "m" (_mode)); + #endif + #endif + } + + void SetPrecisionMode(u32 mode) + { + #ifdef _M_IX86 + // sets the floating-point lib to 53-bit + // PowerPC has a 53bit floating pipeline only + // eg: sscanf is very sensitive + #ifdef _WIN32 + _control87(_PC_53, MCW_PC); + #else + const unsigned short table[4] = { + 0 << 8, // FPU_PREC_24 + 2 << 8, // FPU_PREC_53 + 3 << 8, // FPU_PREC_64 + 3 << 8, // FPU_PREC_MASK + }; + unsigned short _mode; + asm ("fstcw %0" : : "m" (_mode)); + _mode = (_mode & ~table[4]) | table[mode]; + asm ("fldcw %0" : : "m" (_mode)); + #endif + #else + //x64 doesn't need this - fpu is done with SSE + //but still - set any useful sse options here + #endif + } + void SetSIMDMode(u32 mode) + { + static const u32 ssetable[4] = + { + (0 << 13) | MASKS, + (3 << 13) | MASKS, + (2 << 13) | MASKS, + (1 << 13) | MASKS, + }; + u32 csr = ssetable[mode]; + _mm_setcsr(csr); + } + + void SaveSIMDState() + { + saved_sse_state = _mm_getcsr(); + } + void LoadSIMDState() + { + _mm_setcsr(saved_sse_state); + } + void LoadDefaultSIMDState() + { + _mm_setcsr(default_sse_state); + } +} diff --git a/Source/Core/Common/Src/Thunk.cpp b/Source/Core/Common/Src/x64Thunk.cpp similarity index 98% rename from Source/Core/Common/Src/Thunk.cpp rename to Source/Core/Common/Src/x64Thunk.cpp index 1792df3e77..b9fd54f354 100644 --- a/Source/Core/Common/Src/Thunk.cpp +++ b/Source/Core/Common/Src/x64Thunk.cpp @@ -18,9 +18,8 @@ #include #include "Common.h" -#include "x64Emitter.h" #include "MemoryUtil.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #define THUNK_ARENA_SIZE 1024*1024*1 diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 6ffeeaec3a..b8976f42ea 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -9,7 +9,6 @@ set(SRCS Src/ActionReplay.cpp Src/DSPEmulator.cpp Src/GeckoCodeConfig.cpp Src/GeckoCode.cpp - Src/MemTools.cpp Src/Movie.cpp Src/NetPlay.cpp Src/NetPlayClient.cpp @@ -153,6 +152,7 @@ set(SRCS Src/ActionReplay.cpp Src/PowerPC/PPCTables.cpp Src/PowerPC/Profiler.cpp Src/PowerPC/SignatureDB.cpp + Src/PowerPC/JitInterface.cpp Src/PowerPC/Interpreter/Interpreter_Branch.cpp Src/PowerPC/Interpreter/Interpreter.cpp Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -162,6 +162,15 @@ set(SRCS Src/ActionReplay.cpp Src/PowerPC/Interpreter/Interpreter_Paired.cpp Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp Src/PowerPC/Interpreter/Interpreter_Tables.cpp + Src/PowerPC/JitCommon/JitAsmCommon.cpp + Src/PowerPC/JitCommon/JitBackpatch.cpp + Src/PowerPC/JitCommon/JitBase.cpp + Src/PowerPC/JitCommon/JitCache.cpp + Src/PowerPC/JitCommon/Jit_Util.cpp) + +if(NOT _M_GENERIC) + set(SRCS ${SRCS} + Src/x64MemTools.cpp Src/PowerPC/Jit64IL/IR.cpp Src/PowerPC/Jit64IL/IR_X86.cpp Src/PowerPC/Jit64IL/JitILAsm.cpp @@ -186,12 +195,25 @@ set(SRCS Src/ActionReplay.cpp Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp Src/PowerPC/Jit64/Jit_Paired.cpp Src/PowerPC/Jit64/JitRegCache.cpp - Src/PowerPC/Jit64/Jit_SystemRegisters.cpp - Src/PowerPC/JitCommon/JitAsmCommon.cpp - Src/PowerPC/JitCommon/JitBackpatch.cpp - Src/PowerPC/JitCommon/JitBase.cpp - Src/PowerPC/JitCommon/JitCache.cpp - Src/PowerPC/JitCommon/Jit_Util.cpp) + Src/PowerPC/Jit64/Jit_SystemRegisters.cpp) +endif() +if(_M_ARM) + set(SRCS ${SRCS} + Src/ArmMemTools.cpp + Src/PowerPC/JitArm32/Jit.cpp + Src/PowerPC/JitArm32/JitAsm.cpp + Src/PowerPC/JitArm32/JitArm_BackPatch.cpp + Src/PowerPC/JitArm32/JitArm_Tables.cpp + Src/PowerPC/JitArm32/JitArmCache.cpp + Src/PowerPC/JitArm32/JitRegCache.cpp + Src/PowerPC/JitArm32/JitFPRCache.cpp + Src/PowerPC/JitArm32/JitArm_Branch.cpp + Src/PowerPC/JitArm32/JitArm_Integer.cpp + Src/PowerPC/JitArm32/JitArm_LoadStore.cpp + Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp + Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp + Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp) +endif() set(LIBS bdisasm inputcommon videosoftware sfml-network) diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index bd3d97f11b..1dd547b2ea 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -332,7 +332,7 @@ - + @@ -378,6 +378,7 @@ + @@ -387,10 +388,10 @@ - false - false - false - + false + false + false + Create Create @@ -563,6 +564,7 @@ + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 246dafd972..b4f3f47be7 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -5,9 +5,8 @@ - - + @@ -562,6 +561,9 @@ HW %28Flipper/Hollywood%29\GCMemcard + + PowerPC + @@ -1048,6 +1050,9 @@ HW %28Flipper/Hollywood%29\GCMemcard + + PowerPC + diff --git a/Source/Core/Core/Src/ArmMemTools.cpp b/Source/Core/Core/Src/ArmMemTools.cpp new file mode 100644 index 0000000000..34a0c34b7d --- /dev/null +++ b/Source/Core/Core/Src/ArmMemTools.cpp @@ -0,0 +1,103 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include +#include +#ifdef ANDROID +#include +#else +#include // Look in here for the context definition. +#include +#endif + +#include "Common.h" +#include "MemTools.h" +#include "HW/Memmap.h" +#include "PowerPC/PowerPC.h" +#include "PowerPC/JitInterface.h" +#include "PowerPC/JitCommon/JitBase.h" + +namespace EMM +{ +#ifdef ANDROID +typedef struct sigcontext mcontext_t; +typedef struct ucontext { + uint32_t uc_flags; + struct ucontext* uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + // Other fields are not used by Google Breakpad. Don't define them. +} ucontext_t; +#endif + +void sigsegv_handler(int signal, siginfo_t *info, void *raw_context) +{ + if (signal != SIGSEGV) + { + // We are not interested in other signals - handle it as usual. + return; + } + ucontext_t *context = (ucontext_t *)raw_context; + int sicode = info->si_code; + if (sicode != SEGV_MAPERR && sicode != SEGV_ACCERR) + { + // Huh? Return. + return; + } + + + // Get all the information we can out of the context. + mcontext_t *ctx = &context->uc_mcontext; + + void *fault_memory_ptr = (void*)ctx->arm_r10; + u8 *fault_instruction_ptr = (u8 *)ctx->arm_pc; + + if (!JitInterface::IsInCodeSpace(fault_instruction_ptr)) { + // Let's not prevent debugging. + return; + } + + u64 bad_address = (u64)fault_memory_ptr; + u64 memspace_bottom = (u64)Memory::base; + if (bad_address < memspace_bottom) { + PanicAlertT("Exception handler - access below memory space. %08llx%08llx", + bad_address >> 32, bad_address); + } + + u32 em_address = (u32)(bad_address - memspace_bottom); + + int access_type = 0; + + CONTEXT fake_ctx; + fake_ctx.reg_pc = ctx->arm_pc; + const u8 *new_rip = jit->BackPatch(fault_instruction_ptr, access_type, em_address, &fake_ctx); + if (new_rip) { + ctx->arm_pc = fake_ctx.reg_pc; + } +} + +void InstallExceptionHandler() +{ + struct sigaction sa; + sa.sa_handler = 0; + sa.sa_sigaction = &sigsegv_handler; + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sigaction(SIGSEGV, &sa, NULL); +} +} // namespace diff --git a/Source/Core/Core/Src/ConfigManager.h b/Source/Core/Core/Src/ConfigManager.h index 0c4ceffa9f..4a36b37335 100644 --- a/Source/Core/Core/Src/ConfigManager.h +++ b/Source/Core/Core/Src/ConfigManager.h @@ -35,7 +35,7 @@ #define BACKEND_OPENAL "OpenAL" #define BACKEND_PULSEAUDIO "Pulse" #define BACKEND_XAUDIO2 "XAudio2" - +#define BACKEND_OPENSLES "OpenSLES" struct SConfig : NonCopyable { // Wii Devices diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index a6c07eeaaa..f7337def45 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -54,7 +54,6 @@ #include "IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "PowerPC/PowerPC.h" -#include "PowerPC/JitCommon/JitBase.h" #include "DSPEmulator.h" #include "ConfigManager.h" @@ -140,7 +139,7 @@ void DisplayMessage(const char *message, int time_in_ms) if (_CoreParameter.bRenderToMain && SConfig::GetInstance().m_InterfaceStatusbar) { - Host_UpdateStatusBar(message); + Host_UpdateStatusBar(message); } else Host_UpdateTitle(message); @@ -189,7 +188,7 @@ bool IsGPUThread() return IsCPUThread(); } } - + // This is called from the GUI thread. See the booting call schedule in // BootManager.cpp bool Init() @@ -310,7 +309,7 @@ void CpuThread() g_video_backend->Video_Prepare(); } - #if defined(_M_X64) + #if defined(_M_X64) || _M_ARM EMM::InstallExceptionHandler(); // Let's run under memory watch #endif diff --git a/Source/Core/Core/Src/DSP/DSPEmitter.cpp b/Source/Core/Core/Src/DSP/DSPEmitter.cpp index 2ce441bf31..12dac52e31 100644 --- a/Source/Core/Core/Src/DSP/DSPEmitter.cpp +++ b/Source/Core/Core/Src/DSP/DSPEmitter.cpp @@ -25,7 +25,7 @@ #include "DSPAnalyzer.h" #include "Jit/DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #define MAX_BLOCK_SIZE 250 #define DSP_IDLE_SKIP_CYCLES 0x1000 diff --git a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp index f2cbbc2b9f..e4c81e4a7a 100644 --- a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp +++ b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp @@ -252,7 +252,9 @@ static void gdsp_idma_out(u16 dsp_addr, u32 addr, u32 size) ERROR_LOG(DSPLLE, "*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)", dsp_addr / 2, addr, size); } +#if _M_SSE >= 0x301 static const __m128i s_mask = _mm_set_epi32(0x0E0F0C0DL, 0x0A0B0809L, 0x06070405L, 0x02030001L); +#endif // TODO: These should eat clock cycles. static void gdsp_ddma_in(u16 dsp_addr, u32 addr, u32 size) diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp index 0b75431de6..185ada8ba3 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp @@ -25,7 +25,7 @@ #include "DSPJitUtil.h" #endif #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; // CLR $acR diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp index 8ca770e35d..252550b84c 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp @@ -21,7 +21,7 @@ #include "../DSPAnalyzer.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp index e382b6114a..be7675378d 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp @@ -24,7 +24,7 @@ #include "../DSPEmitter.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; // In: RAX: s64 _Value diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp index 8203f7cde1..40e39a89e9 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp @@ -18,7 +18,7 @@ #include "../DSPEmitter.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp index a784e2dd2d..248ed8f945 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp @@ -22,7 +22,7 @@ #include "../DSPEmitter.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; // SRS @M, $(0x18+S) diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp index 8d8a635536..d0bf7a3822 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp @@ -20,7 +20,7 @@ #include "../DSPEmitter.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; //clobbers: diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp index 1323de002d..0dcbf41877 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp @@ -27,7 +27,7 @@ #include "DSPJitUtil.h" #endif #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; // Returns s64 in RAX diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp index b9e166f698..2fb18f83da 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp @@ -20,7 +20,7 @@ #include "../DSPEmitter.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; diff --git a/Source/Core/Core/Src/HW/Memmap.cpp b/Source/Core/Core/Src/HW/Memmap.cpp index 88f6b2c358..6a6fb14212 100644 --- a/Source/Core/Core/Src/HW/Memmap.cpp +++ b/Source/Core/Core/Src/HW/Memmap.cpp @@ -419,132 +419,6 @@ u32 Read_Instruction(const u32 em_address) return inst.hex; } -u32 Read_Opcode_JIT_Uncached(const u32 _Address) -{ - u8* iCache; - u32 addr; - if (_Address & JIT_ICACHE_VMEM_BIT) - { - iCache = jit->GetBlockCache()->GetICacheVMEM(); - addr = _Address & JIT_ICACHE_MASK; - } - else if (_Address & JIT_ICACHE_EXRAM_BIT) - { - iCache = jit->GetBlockCache()->GetICacheEx(); - addr = _Address & JIT_ICACHEEX_MASK; - } - else - { - iCache = jit->GetBlockCache()->GetICache(); - addr = _Address & JIT_ICACHE_MASK; - } - u32 inst = *(u32*)(iCache + addr); - if (inst == JIT_ICACHE_INVALID_WORD) - { - u32 cache_block_start = addr & ~0x1f; - u32 mem_block_start = _Address & ~0x1f; - u8 *pMem = Memory::GetPointer(mem_block_start); - memcpy(iCache + cache_block_start, pMem, 32); - inst = *(u32*)(iCache + addr); - } - inst = Common::swap32(inst); - - if ((inst & 0xfc000000) == 0) - { - inst = jit->GetBlockCache()->GetOriginalFirstOp(inst); - } - - return inst; -} - -u32 Read_Opcode_JIT(u32 _Address) -{ -#ifdef FAST_ICACHE - if (bMMU && !bFakeVMEM && (_Address & ADDR_MASK_MEM1)) - { - _Address = Memory::TranslateAddress(_Address, FLAG_OPCODE); - if (_Address == 0) - { - return 0; - } - } - u32 inst = 0; - - // Bypass the icache for the external interrupt exception handler - if ( (_Address & 0x0FFFFF00) == 0x00000500 ) - inst = Read_Opcode_JIT_Uncached(_Address); - else - inst = PowerPC::ppcState.iCache.ReadInstruction(_Address); -#else - u32 inst = Memory::ReadUnchecked_U32(_Address); -#endif - return inst; -} - -// The following function is deprecated in favour of FAST_ICACHE -u32 Read_Opcode_JIT_LC(const u32 _Address) -{ -#ifdef JIT_UNLIMITED_ICACHE - if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 && - (_Address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area - (_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000) - { - PanicAlertT("iCacheJIT: Reading Opcode from %x. Please report.", _Address); - ERROR_LOG(MEMMAP, "iCacheJIT: Reading Opcode from %x. Please report.", _Address); - return 0; - } - u8* iCache; - u32 addr; - if (_Address & JIT_ICACHE_VMEM_BIT) - { - iCache = jit->GetBlockCache()->GetICacheVMEM(); - addr = _Address & JIT_ICACHE_MASK; - } - else if (_Address & JIT_ICACHE_EXRAM_BIT) - { - iCache = jit->GetBlockCache()->GetICacheEx(); - addr = _Address & JIT_ICACHEEX_MASK; - } - else - { - iCache = jit->GetBlockCache()->GetICache(); - addr = _Address & JIT_ICACHE_MASK; - } - u32 inst = *(u32*)(iCache + addr); - if (inst == JIT_ICACHE_INVALID_WORD) - inst = Memory::ReadUnchecked_U32(_Address); - else - inst = Common::swap32(inst); -#else - u32 inst = Memory::ReadUnchecked_U32(_Address); -#endif - if ((inst & 0xfc000000) == 0) - { - inst = jit->GetBlockCache()->GetOriginalFirstOp(inst); - } - return inst; -} - -// WARNING! No checks! -// We assume that _Address is cached -void Write_Opcode_JIT(const u32 _Address, const u32 _Value) -{ -#ifdef JIT_UNLIMITED_ICACHE - if (_Address & JIT_ICACHE_VMEM_BIT) - { - *(u32*)(jit->GetBlockCache()->GetICacheVMEM() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value); - } - else if (_Address & JIT_ICACHE_EXRAM_BIT) - { - *(u32*)(jit->GetBlockCache()->GetICacheEx() + (_Address & JIT_ICACHEEX_MASK)) = Common::swap32(_Value); - } - else - *(u32*)(jit->GetBlockCache()->GetICache() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value); -#else - Memory::WriteUnchecked_U32(_Value, _Address); -#endif -} - void WriteBigEData(const u8 *_pData, const u32 _Address, const u32 _iSize) { memcpy(GetPointer(_Address), _pData, _iSize); diff --git a/Source/Core/Core/Src/HW/Memmap.h b/Source/Core/Core/Src/HW/Memmap.h index 42ceb737ca..8662804185 100644 --- a/Source/Core/Core/Src/HW/Memmap.h +++ b/Source/Core/Core/Src/HW/Memmap.h @@ -119,11 +119,6 @@ inline u32 ReadFast32(const u32 _Address) // used by interpreter to read instructions, uses iCache u32 Read_Opcode(const u32 _Address); -// used by JIT to read instructions -u32 Read_Opcode_JIT(const u32 _Address); -// used by JIT. uses iCacheJIT. Reads in the "Locked cache" mode -u32 Read_Opcode_JIT_LC(const u32 _Address); -void Write_Opcode_JIT(const u32 _Address, const u32 _Value); // this is used by Debugger a lot. // For now, just reads from memory! u32 Read_Instruction(const u32 _Address); diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index 1d6ea2e70d..ffaea0e868 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -28,8 +28,6 @@ #undef _interlockedbittestandreset #undef _interlockedbittestandset64 #undef _interlockedbittestandreset64 -#else -#include #endif #include "../../Core.h" @@ -514,4 +512,4 @@ void Interpreter::fsqrtx(UGeckoInstruction _inst) rPS0(_inst.FD) = sqrt(b); UpdateFPRF(rPS0(_inst.FD)); if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD)); -} \ No newline at end of file +} diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 5e665eb38e..8e406dbfab 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -24,8 +24,7 @@ #include "Interpreter.h" #include "../../Core.h" -#include "../JitCommon/JitBase.h" -#include "../JitCommon/JitCache.h" +#include "../JitInterface.h" #include "Interpreter_FPUtils.h" @@ -363,34 +362,24 @@ void Interpreter::dcbf(UGeckoInstruction _inst) { NPC = PC + 12; }*/ - // Invalidate the jit block cache on dcbf - if (jit) - { u32 address = Helper_Get_EA_X(_inst); - jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32); - } + JitInterface::InvalidateICache(address & ~0x1f, 32); } void Interpreter::dcbi(UGeckoInstruction _inst) { // Removes a block from data cache. Since we don't emulate the data cache, we don't need to do anything to the data cache // However, we invalidate the jit block cache on dcbi - if (jit) - { u32 address = Helper_Get_EA_X(_inst); - jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32); - } + JitInterface::InvalidateICache(address & ~0x1f, 32); } void Interpreter::dcbst(UGeckoInstruction _inst) { // Cache line flush. Since we don't emulate the data cache, we don't need to do anything. // Invalidate the jit block cache on dcbst in case new code has been loaded via the data cache - if (jit) - { u32 address = Helper_Get_EA_X(_inst); - jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32); - } + JitInterface::InvalidateICache(address & ~0x1f, 32); } void Interpreter::dcbt(UGeckoInstruction _inst) @@ -409,7 +398,7 @@ void Interpreter::dcbz(UGeckoInstruction _inst) // HACK but works... we think if (!Core::g_CoreStartupParameter.bDCBZOFF) Memory::Memset(Helper_Get_EA_X(_inst) & (~31), 0, 32); - if (!jit) + if (!JitInterface::GetCore()) PowerPC::CheckExceptions(); } diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 5a199b56c8..ff65f52471 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -26,13 +26,6 @@ #undef _interlockedbittestandreset #undef _interlockedbittestandset64 #undef _interlockedbittestandreset64 -#else -static const unsigned short FPU_ROUND_NEAR = 0 << 10; -static const unsigned short FPU_ROUND_DOWN = 1 << 10; -static const unsigned short FPU_ROUND_UP = 2 << 10; -static const unsigned short FPU_ROUND_CHOP = 3 << 10; -static const unsigned short FPU_ROUND_MASK = 3 << 10; -#include #endif #include "CPUDetect.h" @@ -43,6 +36,7 @@ static const unsigned short FPU_ROUND_MASK = 3 << 10; #include "../../HW/SystemTimers.h" #include "../../Core.h" #include "Interpreter.h" +#include "FPURoundMode.h" #include "Interpreter_FPUtils.h" @@ -61,38 +55,11 @@ mffsx: 80036650 (huh?) // That is, set rounding mode etc when entering jit code or the interpreter loop // Restore rounding mode when calling anything external -const u32 MASKS = 0x1F80; // mask away the interrupts. -const u32 DAZ = 0x40; -const u32 FTZ = 0x8000; - static void FPSCRtoFPUSettings(UReg_FPSCR fp) { - // Set FPU rounding mode to mimic the PowerPC's -#ifdef _M_IX86 - // This shouldn't really be needed anymore since we use SSE -#ifdef _WIN32 - const int table[4] = - { - _RC_NEAR, - _RC_CHOP, - _RC_UP, - _RC_DOWN - }; - _set_controlfp(_MCW_RC, table[fp.RN]); -#else - const unsigned short table[4] = - { - FPU_ROUND_NEAR, - FPU_ROUND_CHOP, - FPU_ROUND_UP, - FPU_ROUND_DOWN - }; - unsigned short mode; - asm ("fstcw %0" : "=m" (mode) : ); - mode = (mode & ~FPU_ROUND_MASK) | table[fp.RN]; - asm ("fldcw %0" : : "m" (mode)); -#endif -#endif + + FPURoundMode::SetRoundMode(fp.RN); + if (fp.VE || fp.OE || fp.UE || fp.ZE || fp.XE) { //PanicAlert("FPSCR - exceptions enabled. Please report. VE=%i OE=%i UE=%i ZE=%i XE=%i", @@ -101,14 +68,6 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp) } // Also corresponding SSE rounding mode setting - static const u32 ssetable[4] = - { - (0 << 13) | MASKS, - (3 << 13) | MASKS, - (2 << 13) | MASKS, - (1 << 13) | MASKS, - }; - u32 csr = ssetable[FPSCR.RN]; if (FPSCR.NI) { // Either one of these two breaks Beyond Good & Evil. @@ -116,7 +75,7 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp) // csr |= DAZ; // csr |= FTZ; } - _mm_setcsr(csr); + FPURoundMode::SetSIMDMode(FPSCR.RN); } void Interpreter::mtfsb0x(UGeckoInstruction _inst) diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp index 07219218a2..fee8ed70d8 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp @@ -267,7 +267,7 @@ static GekkoOPTemplate table31[] = {19, Interpreter::mfcr, {"mfcr", OPTYPE_SYSTEM, FL_OUT_D, 0, 0, 0, 0}}, {83, Interpreter::mfmsr, {"mfmsr", OPTYPE_SYSTEM, FL_OUT_D, 0, 0, 0, 0}}, {144, Interpreter::mtcrf, {"mtcrf", OPTYPE_SYSTEM, 0, 0, 0, 0, 0}}, - {146, Interpreter::mtmsr, {"mtmsr", OPTYPE_SYSTEM, FL_ENDBLOCK, 0, 0, 0, 0}}, + {146, Interpreter::mtmsr, {"mtmsr", OPTYPE_SYSTEM, FL_IN_S | FL_ENDBLOCK, 0, 0, 0, 0}}, {210, Interpreter::mtsr, {"mtsr", OPTYPE_SYSTEM, 0, 0, 0, 0, 0}}, {242, Interpreter::mtsrin, {"mtsrin", OPTYPE_SYSTEM, 0, 0, 0, 0, 0}}, {339, Interpreter::mfspr, {"mfspr", OPTYPE_SPR, FL_OUT_D, 0, 0, 0, 0}}, diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp index 900a8475f7..710984571e 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp @@ -24,7 +24,7 @@ #include "Common.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "../../HLE/HLE.h" #include "../../Core.h" @@ -357,7 +357,7 @@ void Jit64::WriteExternalExceptionExit() MOV(32, R(EAX), M(&PC)); MOV(32, M(&NPC), R(EAX)); ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExternalExceptions)); - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); + SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); JMP(asm_routines.dispatcher, true); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index 1ebd476134..1d856d6291 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h @@ -62,7 +62,7 @@ if (js.memcheck) \ SetJumpTarget(memException); -class Jit64 : public JitBase +class Jit64 : public Jitx86Base { private: GPRRegCache gpr; diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp index f7082cd1cc..df27a3a641 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp @@ -15,7 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include "ABI.h" +#include "x64ABI.h" #include "x64Emitter.h" #include "../../HW/Memmap.h" @@ -24,7 +24,7 @@ #include "../../CoreTiming.h" #include "MemoryUtil.h" -#include "ABI.h" +#include "x64ABI.h" #include "Jit.h" #include "../JitCommon/JitCache.h" @@ -204,7 +204,7 @@ void Jit64AsmRoutineManager::Generate() MOV(32, M(&NPC), R(EAX)); ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExternalExceptions)); SetJumpTarget(noExtException); - + TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); J_CC(CC_Z, outerLoop, true); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h index e8df0877f7..19e1f41ba8 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h @@ -18,7 +18,6 @@ #ifndef _JIT64ASM_H #define _JIT64ASM_H -#include "x64Emitter.h" #include "../JitCommon/JitAsmCommon.h" // In Dolphin, we don't use inline assembly. Instead, we generate all machine-near diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp index 04e4d09cc9..7c1d60ad09 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp @@ -28,7 +28,7 @@ #include "../../HW/Memmap.h" #include "../PPCTables.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Jit.h" #include "JitAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp index 9f61e097b8..5766eb3177 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp @@ -27,7 +27,7 @@ #include "../PPCTables.h" #include "CPUDetect.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Jit.h" #include "JitAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp index 3b14179cd4..924758ab3a 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp @@ -28,7 +28,7 @@ #include "../PPCTables.h" #include "CPUDetect.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Jit.h" #include "JitAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp index 14827129f8..0b6c0462d9 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -23,7 +23,7 @@ #include "../PowerPC.h" #include "../PPCTables.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "Jit.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp index ce47e2c3ac..3638ba8da6 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp @@ -1991,8 +1991,10 @@ void JitIL::WriteCode() { } void ProfiledReJit() { - jit->SetCodePtr(jit->js.rewriteStart); - DoWriteCode(&((JitIL *)jit)->ibuild, (JitIL *)jit, true, false); - jit->js.curBlock->codeSize = (int)(jit->GetCodePtr() - jit->js.rewriteStart); - jit->GetBlockCache()->FinalizeBlock(jit->js.curBlock->blockNum, jit->jo.enableBlocklink, jit->js.curBlock->normalEntry); + JitIL *jitil = (JitIL *)jit; + jitil->SetCodePtr(jitil->js.rewriteStart); + DoWriteCode(&jitil->ibuild, jitil, true, false); + jitil->js.curBlock->codeSize = (int)(jitil->GetCodePtr() - jitil->js.rewriteStart); + jitil->GetBlockCache()->FinalizeBlock(jitil->js.curBlock->blockNum, jitil->jo.enableBlocklink, + jitil->js.curBlock->normalEntry); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp index d56c9ffee8..dc21228858 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp @@ -19,7 +19,7 @@ #include "Common.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "../../HLE/HLE.h" #include "../../Core.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h index fdda098e44..8c579fa4bd 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h @@ -57,7 +57,7 @@ #define DISABLE64 #endif -class JitIL : public JitBase +class JitIL : public Jitx86Base { private: diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp index 74c290aa9c..aaa155072e 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp @@ -15,7 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include "ABI.h" +#include "x64ABI.h" #include "x64Emitter.h" #include "../../HW/Memmap.h" @@ -25,7 +25,7 @@ #include "MemoryUtil.h" #include "CPUDetect.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "../../HW/GPFifo.h" @@ -211,14 +211,14 @@ void JitILAsmRoutineManager::Generate() doTiming = GetCodePtr(); ABI_CallFunction(reinterpret_cast(&CoreTiming::Advance)); - + testExceptions = GetCodePtr(); MOV(32, R(EAX), M(&PC)); MOV(32, M(&NPC), R(EAX)); ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExceptions)); MOV(32, R(EAX), M(&NPC)); MOV(32, M(&PC), R(EAX)); - + TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); J_CC(CC_Z, outer_loop, true); //Landing pad for drec space diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp index 45ceda694a..96902434a6 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp @@ -27,7 +27,7 @@ #include "../../HW/Memmap.h" #include "../PPCTables.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "JitIL.h" #include "JitILAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp index e06d289cc4..c74abfd8e9 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp @@ -27,7 +27,7 @@ #include "../PPCTables.h" #include "CPUDetect.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "JitIL.h" #include "JitILAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp index 2f0a0762fd..6e86804bec 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp @@ -25,7 +25,7 @@ #include "../PPCTables.h" #include "CPUDetect.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "JitIL.h" #include "JitILAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp index f3e25dc2dd..70a6ea4843 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp @@ -23,7 +23,7 @@ #include "../PowerPC.h" #include "../PPCTables.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "JitIL.h" diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp new file mode 100644 index 0000000000..e4b0ffd714 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp @@ -0,0 +1,498 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#include "Common.h" +#include "../../HLE/HLE.h" +#include "../../Core.h" +#include "../../PatchEngine.h" +#include "../../CoreTiming.h" +#include "../../ConfigManager.h" +#include "../PowerPC.h" +#include "../Profiler.h" +#include "../PPCTables.h" +#include "../PPCAnalyst.h" +#include "../../HW/Memmap.h" +#include "../../HW/GPFifo.h" +#include "Jit.h" +#include "JitArm_Tables.h" +#include "ArmEmitter.h" +#include "../JitInterface.h" + +using namespace ArmGen; +using namespace PowerPC; + +static int CODE_SIZE = 1024*1024*32; +namespace CPUCompare +{ + extern u32 m_BlockStart; +} + +void JitArm::Init() +{ + AllocCodeSpace(CODE_SIZE); + blocks.Init(); + asm_routines.Init(); + // TODO: Investigate why the register cache crashes when only doing Init with + // the pointer to this. Seems for some reason it doesn't set the emitter pointer + // In the class for some reason? + gpr.Init(this); + gpr.SetEmitter(this); + fpr.Init(this); + fpr.SetEmitter(this); + jo.enableBlocklink = true; + jo.optimizeGatherPipe = false; +} + +void JitArm::ClearCache() +{ + ClearCodeSpace(); + blocks.Clear(); +} + +void JitArm::Shutdown() +{ + FreeCodeSpace(); + blocks.Shutdown(); + asm_routines.Shutdown(); +} + +// This is only called by Default() in this file. It will execute an instruction with the interpreter functions. +void JitArm::WriteCallInterpreter(UGeckoInstruction inst) +{ + gpr.Flush(); + fpr.Flush(); + Interpreter::_interpreterInstruction instr = GetInterpreterOp(inst); + MOVI2R(R0, inst.hex); + MOVI2R(R12, (u32)instr); + BL(R12); +} +void JitArm::unknown_instruction(UGeckoInstruction inst) +{ + PanicAlert("unknown_instruction %08x - Fix me ;)", inst.hex); +} + +void JitArm::Default(UGeckoInstruction _inst) +{ + WriteCallInterpreter(_inst.hex); +} + +void JitArm::HLEFunction(UGeckoInstruction _inst) +{ + gpr.Flush(); + fpr.Flush(); + MOVI2R(R0, js.compilerPC); + MOVI2R(R1, _inst.hex); + QuickCallFunction(R14, (void*)&HLE::Execute); + ARMReg rA = gpr.GetReg(); + LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, npc)); + WriteExitDestInR(rA); +} + +void JitArm::DoNothing(UGeckoInstruction _inst) +{ + // Yup, just don't do anything. +} + +static const bool ImHereDebug = false; +static const bool ImHereLog = false; +static std::map been_here; + +static void ImHere() +{ + static File::IOFile f; + if (ImHereLog) + { + if (!f) + { + f.Open("log32.txt", "w"); + } + fprintf(f.GetHandle(), "%08x\n", PC); + } + if (been_here.find(PC) != been_here.end()) + { + been_here.find(PC)->second++; + if ((been_here.find(PC)->second) & 1023) + return; + } + DEBUG_LOG(DYNA_REC, "I'm here - PC = %08x , LR = %08x", PC, LR); + been_here[PC] = 1; +} + +void JitArm::Cleanup() +{ + if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0) + QuickCallFunction(R14, (void*)&GPFifo::CheckGatherPipe); +} +void JitArm::DoDownCount() +{ + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + MOVI2R(rA, (u32)&CoreTiming::downcount); + LDR(rB, rA); + if(js.downcountAmount < 255) // We can enlarge this if we used rotations + { + SUBS(rB, rB, js.downcountAmount); + STR(rA, rB); + } + else + { + ARMReg rC = gpr.GetReg(false); + MOVI2R(rC, js.downcountAmount); + SUBS(rB, rB, rC); + STR(rA, rB); + } + gpr.Unlock(rA, rB); +} +void JitArm::WriteExitDestInR(ARMReg Reg) +{ + STR(R9, Reg, STRUCT_OFF(PowerPC::ppcState, pc)); + Cleanup(); + DoDownCount(); + MOVI2R(Reg, (u32)asm_routines.dispatcher); + B(Reg); + gpr.Unlock(Reg); +} +void JitArm::WriteRfiExitDestInR(ARMReg Reg) +{ + STR(R9, Reg, STRUCT_OFF(PowerPC::ppcState, pc)); + Cleanup(); + DoDownCount(); + + MOVI2R(Reg, (u32)asm_routines.testExceptions); + B(Reg); + gpr.Unlock(Reg); // This was locked in the instruction beforehand +} +void JitArm::WriteExceptionExit() +{ + ARMReg A = gpr.GetReg(false); + Cleanup(); + DoDownCount(); + + MOVI2R(A, (u32)asm_routines.testExceptions); + B(A); +} +void JitArm::WriteExit(u32 destination, int exit_num) +{ + Cleanup(); + + DoDownCount(); + //If nobody has taken care of this yet (this can be removed when all branches are done) + JitBlock *b = js.curBlock; + b->exitAddress[exit_num] = destination; + b->exitPtrs[exit_num] = GetWritableCodePtr(); + + // Link opportunity! + int block = blocks.GetBlockNumberFromStartAddress(destination); + if (block >= 0 && jo.enableBlocklink) + { + // It exists! Joy of joy! + B(blocks.GetBlock(block)->checkedEntry); + b->linkStatus[exit_num] = true; + } + else + { + ARMReg A = gpr.GetReg(false); + MOVI2R(A, destination); + STR(R9, A, STRUCT_OFF(PowerPC::ppcState, pc)); + MOVI2R(A, (u32)asm_routines.dispatcher); + B(A); + } +} + +void STACKALIGN JitArm::Run() +{ + CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode; + pExecAddr(); +} + +void JitArm::SingleStep() +{ + CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode; + pExecAddr(); +} + +void JitArm::Trace() +{ + char regs[500] = ""; + char fregs[750] = ""; + +#ifdef JIT_LOG_GPR + for (int i = 0; i < 32; i++) + { + char reg[50]; + sprintf(reg, "r%02d: %08x ", i, PowerPC::ppcState.gpr[i]); + strncat(regs, reg, 500); + } +#endif + +#ifdef JIT_LOG_FPR + for (int i = 0; i < 32; i++) + { + char reg[50]; + sprintf(reg, "f%02d: %016x ", i, riPS0(i)); + strncat(fregs, reg, 750); + } +#endif + + DEBUG_LOG(DYNA_REC, "JITARM PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s", + PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], + PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, + PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs, fregs); +} + +void JitArm::PrintDebug(UGeckoInstruction inst, u32 level) +{ + if (level > 0) + printf("Start: %08x OP '%s' Info\n", (u32)GetCodePtr(), PPCTables::GetInstructionName(inst)); + if (level > 1) + { + GekkoOPInfo* Info = GetOpInfo(inst.hex); + printf("\tOuts\n"); + if (Info->flags & FL_OUT_A) + printf("\t-OUT_A: %x\n", inst.RA); + if(Info->flags & FL_OUT_D) + printf("\t-OUT_D: %x\n", inst.RD); + printf("\tIns\n"); + // A, AO, B, C, S + if(Info->flags & FL_IN_A) + printf("\t-IN_A: %x\n", inst.RA); + if(Info->flags & FL_IN_A0) + printf("\t-IN_A0: %x\n", inst.RA); + if(Info->flags & FL_IN_B) + printf("\t-IN_B: %x\n", inst.RB); + if(Info->flags & FL_IN_C) + printf("\t-IN_C: %x\n", inst.RC); + if(Info->flags & FL_IN_S) + printf("\t-IN_S: %x\n", inst.RS); + } +} + +void STACKALIGN JitArm::Jit(u32 em_address) +{ + if (GetSpaceLeft() < 0x10000 || blocks.IsFull() || Core::g_CoreStartupParameter.bJITNoBlockCache) + { + ClearCache(); + } + + int block_num = blocks.AllocateBlock(em_address); + JitBlock *b = blocks.GetBlock(block_num); + const u8* BlockPtr = DoJit(em_address, &code_buffer, b); + blocks.FinalizeBlock(block_num, jo.enableBlocklink, BlockPtr); +} +void JitArm::Break(UGeckoInstruction inst) +{ + BKPT(0x4444); +} + +const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b) +{ + int blockSize = code_buf->GetSize(); + + // Memory exception on instruction fetch + bool memory_exception = false; + + // A broken block is a block that does not end in a branch + bool broken_block = false; + + if (Core::g_CoreStartupParameter.bEnableDebugging) + { + // Comment out the following to disable breakpoints (speed-up) + blockSize = 1; + broken_block = true; + Trace(); + } + + if (em_address == 0) + { + Core::SetState(Core::CORE_PAUSE); + PanicAlert("ERROR: Compiling at 0. LR=%08x CTR=%08x", LR, CTR); + } + + if (Core::g_CoreStartupParameter.bMMU && (em_address & JIT_ICACHE_VMEM_BIT)) + { + if (!Memory::TranslateAddress(em_address, Memory::FLAG_OPCODE)) + { + // Memory exception occurred during instruction fetch + memory_exception = true; + } + } + + + int size = 0; + js.isLastInstruction = false; + js.blockStart = em_address; + js.fifoBytesThisBlock = 0; + js.curBlock = b; + js.block_flags = 0; + js.cancel = false; + + // Analyze the block, collect all instructions it is made of (including inlining, + // if that is enabled), reorder instructions for optimal performance, and join joinable instructions. + u32 nextPC = em_address; + u32 merged_addresses[32]; + const int capacity_of_merged_addresses = sizeof(merged_addresses) / sizeof(merged_addresses[0]); + int size_of_merged_addresses = 0; + if (!memory_exception) + { + // If there is a memory exception inside a block (broken_block==true), compile up to that instruction. + nextPC = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses); + } + PPCAnalyst::CodeOp *ops = code_buf->codebuffer; + + const u8 *start = GetCodePtr(); + b->checkedEntry = start; + b->runCount = 0; + + // Downcount flag check, Only valid for linked blocks + { + FixupBranch skip = B_CC(CC_PL); + ARMABI_MOVI2M((u32)&PC, js.blockStart); + ARMReg rA = gpr.GetReg(false); + MOVI2R(rA, (u32)asm_routines.doTiming); + B(rA); + SetJumpTarget(skip); + } + + const u8 *normalEntry = GetCodePtr(); + b->normalEntry = normalEntry; + + if(ImHereDebug) + QuickCallFunction(R14, (void *)&ImHere); //Used to get a trace of the last few blocks before a crash, sometimes VERY useful + + if (js.fpa.any) + { + // This block uses FPU - needs to add FP exception bailout + ARMReg A = gpr.GetReg(); + ARMReg C = gpr.GetReg(); + Operand2 Shift(2, 10); // 1 << 13 + MOVI2R(C, js.blockStart); // R3 + LDR(A, R9, STRUCT_OFF(PowerPC::ppcState, msr)); + TST(A, Shift); + FixupBranch b1 = B_CC(CC_NEQ); + STR(R9, C, STRUCT_OFF(PowerPC::ppcState, pc)); + MOVI2R(A, (u32)asm_routines.fpException); + B(A); + SetJumpTarget(b1); + gpr.Unlock(A, C); + } + // Conditionally add profiling code. + if (Profiler::g_ProfileBlocks) { + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + MOVI2R(rA, (u32)&b->runCount); // Load in to register + LDR(rB, rA); // Load the actual value in to R11. + ADD(rB, rB, 1); // Add one to the value + STR(rA, rB); // Now store it back in the memory location + // get start tic + PROFILER_QUERY_PERFORMANCE_COUNTER(&b->ticStart); + gpr.Unlock(rA, rB); + } + gpr.Start(js.gpa); + fpr.Start(js.fpa); + js.downcountAmount = 0; + if (!Core::g_CoreStartupParameter.bEnableDebugging) + { + for (int i = 0; i < size_of_merged_addresses; ++i) + { + const u32 address = merged_addresses[i]; + js.downcountAmount += PatchEngine::GetSpeedhackCycles(address); + } + } + + js.skipnext = false; + js.blockSize = size; + js.compilerPC = nextPC; + // Translate instructions + for (int i = 0; i < (int)size; i++) + { + js.compilerPC = ops[i].address; + js.op = &ops[i]; + js.instructionNumber = i; + const GekkoOPInfo *opinfo = ops[i].opinfo; + js.downcountAmount += (opinfo->numCyclesMinusOne + 1); + + if (i == (int)size - 1) + { + // WARNING - cmp->branch merging will screw this up. + js.isLastInstruction = true; + js.next_inst = 0; + if (Profiler::g_ProfileBlocks) { + // CAUTION!!! push on stack regs you use, do your stuff, then pop + PROFILER_VPUSH; + // get end tic + PROFILER_QUERY_PERFORMANCE_COUNTER(&b->ticStop); + // tic counter += (end tic - start tic) + PROFILER_ADD_DIFF_LARGE_INTEGER(&b->ticCounter, &b->ticStop, &b->ticStart); + PROFILER_VPOP; + } + } + else + { + // help peephole optimizations + js.next_inst = ops[i + 1].inst; + js.next_compilerPC = ops[i + 1].address; + } + if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32) + { + js.fifoBytesThisBlock -= 32; + // TODO: This needs thunkmanager for ARM + //ARMABI_CallFunction(thunks.ProtectFunction((void *)&GPFifo::CheckGatherPipe, 0)); + } + if (Core::g_CoreStartupParameter.bEnableDebugging) + { + // Add run count + ARMReg RA = gpr.GetReg(); + ARMReg RB = gpr.GetReg(); + MOVI2R(RA, (u32)&opinfo->runCount); + LDR(RB, RA); + ADD(RB, RB, 1); + STR(RA, RB); + gpr.Unlock(RA, RB); + } + if (!ops[i].skip) + { + PrintDebug(ops[i].inst, 0); + if (js.memcheck && (opinfo->flags & FL_USE_FPU)) + { + // Don't do this yet + BKPT(0x7777); + } + JitArmTables::CompileInstruction(ops[i]); + if (js.memcheck && (opinfo->flags & FL_LOADSTORE)) + { + // Don't do this yet + BKPT(0x666); + } + } + } + if (memory_exception) + BKPT(0x500); + if (broken_block) + { + printf("Broken Block going to 0x%08x\n", nextPC); + WriteExit(nextPC, 0); + } + + b->flags = js.block_flags; + b->codeSize = (u32)(GetCodePtr() - normalEntry); + b->originalSize = size; + FlushIcache(); + return start; +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h new file mode 100644 index 0000000000..c736ae77a1 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h @@ -0,0 +1,186 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// ======================== +// See comments in Jit.cpp. +// ======================== + +// Mystery: Capcom vs SNK 800aa278 + +// CR flags approach: +// * Store that "N+Z flag contains CR0" or "S+Z flag contains CR3". +// * All flag altering instructions flush this +// * A flush simply does a conditional write to the appropriate CRx. +// * If flag available, branch code can become absolutely trivial. + +// Settings +// ---------- +#ifndef _JITARM_H +#define _JITARM_H +#include "../CPUCoreBase.h" +#include "../PPCAnalyst.h" +#include "JitArmCache.h" +#include "JitRegCache.h" +#include "JitFPRCache.h" +#include "JitAsm.h" +#include "../JitCommon/JitBase.h" + +// Use these to control the instruction selection +// #define INSTRUCTION_START Default(inst); return; +// #define INSTRUCTION_START PPCTables::CountInstruction(inst); +#define INSTRUCTION_START +#define JITDISABLE(type) \ + if (Core::g_CoreStartupParameter.bJITOff || \ + Core::g_CoreStartupParameter.bJIT##type##Off) \ + {Default(inst); return;} + +class JitArm : public JitBase, public ArmGen::ARMXCodeBlock +{ +private: + JitArmBlockCache blocks; + + JitArmAsmRoutineManager asm_routines; + + // TODO: Make arm specific versions of these, shouldn't be too hard to + // make it so we allocate some space at the start(?) of code generation + // and keep the registers in a cache. Will burn this bridge when we get to + // it. + ArmRegCache gpr; + ArmFPRCache fpr; + + PPCAnalyst::CodeBuffer code_buffer; + void DoDownCount(); + + void PrintDebug(UGeckoInstruction inst, u32 level); + + void Helper_UpdateCR1(ARMReg value); +public: + JitArm() : code_buffer(32000) {} + ~JitArm() {} + + void Init(); + void Shutdown(); + + // Jit! + + void Jit(u32 em_address); + const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b); + + JitBaseBlockCache *GetBlockCache() { return &blocks; } + + const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx); + + bool IsInCodeSpace(u8 *ptr) { return IsInSpace(ptr); } + + void Trace(); + + void ClearCache(); + + const u8 *GetDispatcher() { + return asm_routines.dispatcher; + } + CommonAsmRoutinesBase *GetAsmRoutines() { + return &asm_routines; + } + + const char *GetName() { + return "JITARM"; + } + // Run! + + void Run(); + void SingleStep(); + + // Utilities for use by opcodes + + void WriteExit(u32 destination, int exit_num); + void WriteExitDestInR(ARMReg Reg); + void WriteRfiExitDestInR(ARMReg Reg); + void WriteExceptionExit(); + void WriteCallInterpreter(UGeckoInstruction _inst); + void Cleanup(); + + void GenerateRC(int cr = 0); + void ComputeRC(int cr = 0); + + // TODO: This shouldn't be here + void StoreFromReg(ARMReg dest, ARMReg value, int accessSize, s32 offset); + void LoadToReg(ARMReg dest, ARMReg addr, int accessSize, s32 offset); + + // OPCODES + void unknown_instruction(UGeckoInstruction _inst); + void Default(UGeckoInstruction _inst); + void DoNothing(UGeckoInstruction _inst); + void HLEFunction(UGeckoInstruction _inst); + + void DynaRunTable4(UGeckoInstruction _inst); + void DynaRunTable19(UGeckoInstruction _inst); + void DynaRunTable31(UGeckoInstruction _inst); + void DynaRunTable59(UGeckoInstruction _inst); + void DynaRunTable63(UGeckoInstruction _inst); + + // Breakin shit + void Break(UGeckoInstruction _inst); + // Branch + void bx(UGeckoInstruction _inst); + void bcx(UGeckoInstruction _inst); + void bclrx(UGeckoInstruction _inst); + void sc(UGeckoInstruction _inst); + void rfi(UGeckoInstruction _inst); + void bcctrx(UGeckoInstruction _inst); + + // Integer + void addi(UGeckoInstruction _inst); + void addis(UGeckoInstruction _inst); + void addx(UGeckoInstruction _inst); + void cmp (UGeckoInstruction _inst); + void cmpi(UGeckoInstruction _inst); + void cmpli(UGeckoInstruction _inst); + void negx(UGeckoInstruction _inst); + void mulli(UGeckoInstruction _inst); + void ori(UGeckoInstruction _inst); + void oris(UGeckoInstruction _inst); + void orx(UGeckoInstruction _inst); + void rlwimix(UGeckoInstruction _inst); + void rlwinmx(UGeckoInstruction _inst); + void extshx(UGeckoInstruction inst); + void extsbx(UGeckoInstruction inst); + + // System Registers + void mtmsr(UGeckoInstruction _inst); + void mtspr(UGeckoInstruction _inst); + void mfspr(UGeckoInstruction _inst); + + // LoadStore + void icbi(UGeckoInstruction _inst); + void lbz(UGeckoInstruction _inst); + void lhz(UGeckoInstruction _inst); + void lwz(UGeckoInstruction _inst); + void lwzx(UGeckoInstruction _inst); + void stw(UGeckoInstruction _inst); + void stwu(UGeckoInstruction _inst); + + // Floating point + void fabsx(UGeckoInstruction _inst); + void faddx(UGeckoInstruction _inst); + void fmrx(UGeckoInstruction _inst); + + // Floating point loadStore + void lfs(UGeckoInstruction _inst); +}; + +#endif // _JIT64_H diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp new file mode 100644 index 0000000000..296ca736a9 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// Enable define below to enable oprofile integration. For this to work, +// it requires at least oprofile version 0.9.4, and changing the build +// system to link the Dolphin executable against libopagent. Since the +// dependency is a little inconvenient and this is possibly a slight +// performance hit, it's not enabled by default, but it's useful for +// locating performance issues. + +#include "../JitInterface.h" +#include "JitArmCache.h" + + +using namespace ArmGen; + + void JitArmBlockCache::WriteLinkBlock(u8* location, const u8* address) + { + ARMXEmitter emit(location); + emit.B(address); + } + void JitArmBlockCache::WriteDestroyBlock(const u8* location, u32 address) + { + ARMXEmitter emit((u8 *)location); + emit.MOVI2R(R10, (u32)&PC); + emit.MOVI2R(R11, address); + emit.MOVI2R(R12, (u32)jit->GetAsmRoutines()->dispatcher); + emit.STR(R10, R11); + emit.B(R12); + } + + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.h new file mode 100644 index 0000000000..103947d5ad --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.h @@ -0,0 +1,33 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _JITARMCACHE_H +#define _JITARMCACHE_H + +#include "../JitCommon/JitCache.h" + + +typedef void (*CompiledCode)(); + +class JitArmBlockCache : public JitBaseBlockCache +{ +private: + void WriteLinkBlock(u8* location, const u8* address); + void WriteDestroyBlock(const u8* location, u32 address); +}; + +#endif diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_BackPatch.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_BackPatch.cpp new file mode 100644 index 0000000000..677dc238a8 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_BackPatch.cpp @@ -0,0 +1,164 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#include "Common.h" + +#include "../../HW/Memmap.h" +#include "Jit.h" +#include "../JitCommon/JitBackpatch.h" +#include "StringUtil.h" + +#ifdef _M_X64 +static void BackPatchError(const std::string &text, u8 *codePtr, u32 emAddress) { + u64 code_addr = (u64)codePtr; + disassembler disasm; + char disbuf[256]; + memset(disbuf, 0, 256); +#ifdef _M_IX86 + disasm.disasm32(0, code_addr, codePtr, disbuf); +#else + disasm.disasm64(0, code_addr, codePtr, disbuf); +#endif + PanicAlert("%s\n\n" + "Error encountered accessing emulated address %08x.\n" + "Culprit instruction: \n%s\nat %#llx", + text.c_str(), emAddress, disbuf, code_addr); + return; +} +#endif + +// This generates some fairly heavy trampolines, but: +// 1) It's really necessary. We don't know anything about the context. +// 2) It doesn't really hurt. Only instructions that access I/O will get these, and there won't be +// that many of them in a typical program/game. +bool DisamLoadStore(const u32 inst, ARMReg &rD, u8 &accessSize, bool &Store) +{ + u8 op = (inst >> 20) & 0xFF; + printf("op: 0x%08x\n", op); + switch (op) + { + case 0x58: // STR + { + rD = (ARMReg)((inst >> 16) & 0xF); + Store = true; + accessSize = 32; + } + break; + case 0x59: // LDR + { + rD = (ARMReg)((inst >> 16) & 0xF); + Store = false; + accessSize = 32; + } + break; + case 0x05: // LDRH + { + rD = (ARMReg)((inst >> 16) & 0xF); + Store = false; + accessSize = 16; + } + break; + case 0x45 + 0x18: // LDRB + { + rD = (ARMReg)((inst >> 16) & 0xF); + Store = false; + accessSize = 8; + } + break; + case 0x44 + 0x18: // STRB + default: + return false; + } + return true; +} +const u8 *JitArm::BackPatch(u8 *codePtr, int accessType, u32 emAddress, void *ctx_void) +{ + // TODO: This ctx needs to be filled with our information + CONTEXT *ctx = (CONTEXT *)ctx_void; + + // We need to get the destination register before we start + u32 Value = *(u32*)codePtr; + ARMReg rD; + u8 accessSize; + bool Store; + + if (!DisamLoadStore(Value, rD, accessSize, Store)) + { + printf("Invalid backpatch at location 0x%08x(0x%08x)\n", ctx->reg_pc, Value); + exit(0); + } + + if (Store) + { + const u32 ARMREGOFFSET = 4 * 7; + ARMXEmitter emitter(codePtr - ARMREGOFFSET); + switch (accessSize) + { + case 8: // 8bit + //emitter.MOVI2R(R14, (u32)&Memory::Write_U8, false); // 1-2 + return 0; + break; + case 16: // 16bit + //emitter.MOVI2R(R14, (u32)&Memory::Write_U16, false); // 1-2 + return 0; + break; + case 32: // 32bit + emitter.MOVI2R(R14, (u32)&Memory::Write_U32, false); // 1-2 + break; + } + emitter.PUSH(4, R0, R1, R2, R3); // 3 + emitter.MOV(R0, rD); // Value - 4 + emitter.MOV(R1, R10); // Addr- 5 + emitter.BL(R14); // 6 + emitter.POP(4, R0, R1, R2, R3); // 7 + emitter.NOP(1); // 8 + u32 newPC = ctx->reg_pc - (ARMREGOFFSET + 4 * 4); + ctx->reg_pc = newPC; + emitter.FlushIcache(); + return codePtr; + } + else + { + const u32 ARMREGOFFSET = 4 * 6; + ARMXEmitter emitter(codePtr - ARMREGOFFSET); + switch (accessSize) + { + case 8: // 8bit + emitter.MOVI2R(R14, (u32)&Memory::Read_U8, false); // 2 + break; + case 16: // 16bit + emitter.MOVI2R(R14, (u32)&Memory::Read_U16, false); // 2 + break; + case 32: // 32bit + emitter.MOVI2R(R14, (u32)&Memory::Read_U32, false); // 2 + break; + } + emitter.PUSH(4, R0, R1, R2, R3); // 3 + emitter.MOV(R0, R10); // 4 + emitter.BL(R14); // 5 + emitter.MOV(R14, R0); // 6 + emitter.POP(4, R0, R1, R2, R3); // 7 + emitter.MOV(rD, R14); // 8 + ctx->reg_pc -= ARMREGOFFSET + (4 * 4); + emitter.FlushIcache(); + return codePtr; + } + return 0; +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp new file mode 100644 index 0000000000..27d5c23141 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp @@ -0,0 +1,347 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitAsm.h" + +// The branches are known good, or at least reasonably good. +// No need for a disable-mechanism. + +// If defined, clears CR0 at blr and bl-s. If the assumption that +// flags never carry over between functions holds, then the task for +// an optimizer becomes much easier. + +// #define ACID_TEST + +// Zelda and many more games seem to pass the Acid Test. + + +using namespace ArmGen; +void JitArm::sc(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + + gpr.Flush(); + fpr.Flush(); + + ARMABI_MOVI2M((u32)&PC, js.compilerPC + 4); // Destroys R12 and R14 + ARMReg rA = gpr.GetReg(); + LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions)); + ORR(rA, rA, EXCEPTION_SYSCALL); + STR(R9, rA, STRUCT_OFF(PowerPC::ppcState, Exceptions)); + gpr.Unlock(rA); + + WriteExceptionExit(); +} + +void JitArm::rfi(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + + gpr.Flush(); + fpr.Flush(); + + // See Interpreter rfi for details + const u32 mask = 0x87C0FFFF; + const u32 clearMSR13 = 0xFFFBFFFF; // Mask used to clear the bit MSR[13] + // MSR = ((MSR & ~mask) | (SRR1 & mask)) & clearMSR13; + // R0 = MSR location + // R1 = MSR contents + // R2 = Mask + // R3 = Mask + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + ARMReg rC = gpr.GetReg(); + ARMReg rD = gpr.GetReg(); + MOVI2R(rA, (u32)&MSR); + MOVI2R(rB, (~mask) & clearMSR13); + MOVI2R(rC, mask & clearMSR13); + + LDR(rD, rA); + + AND(rD, rD, rB); // rD = Masked MSR + STR(rA, rD); + + MOVI2R(rB, (u32)&SRR1); + LDR(rB, rB); // rB contains SRR1 here + + AND(rB, rB, rC); // rB contains masked SRR1 here + ORR(rB, rD, rB); // rB = Masked MSR OR masked SRR1 + + STR(rA, rB); // STR rB in to rA + + MOVI2R(rA, (u32)&SRR0); + LDR(rA, rA); + + gpr.Unlock(rB, rC, rD); + WriteRfiExitDestInR(rA); // rA gets unlocked here + //AND(32, M(&MSR), Imm32((~mask) & clearMSR13)); + //MOV(32, R(EAX), M(&SRR1)); + //AND(32, R(EAX), Imm32(mask & clearMSR13)); + //OR(32, M(&MSR), R(EAX)); + // NPC = SRR0; + //MOV(32, R(EAX), M(&SRR0)); + //WriteRfiExitDestInEAX(); +} + +void JitArm::bx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + // We must always process the following sentence + // even if the blocks are merged by PPCAnalyst::Flatten(). + if (inst.LK) + ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); + + // If this is not the last instruction of a block, + // we will skip the rest process. + // Because PPCAnalyst::Flatten() merged the blocks. + if (!js.isLastInstruction) { + return; + } + + gpr.Flush(); + fpr.Flush(); + + u32 destination; + if (inst.AA) + destination = SignExt26(inst.LI << 2); + else + destination = js.compilerPC + SignExt26(inst.LI << 2); + #ifdef ACID_TEST + // TODO: Not implemented yet. + //if (inst.LK) + //AND(32, M(&PowerPC::ppcState.cr), Imm32(~(0xFF000000))); + #endif + if (destination == js.compilerPC) + { + //PanicAlert("Idle loop detected at %08x", destination); + // CALL(ProtectFunction(&CoreTiming::Idle, 0)); + // JMP(Asm::testExceptions, true); + // make idle loops go faster + js.downcountAmount += 8; + } + WriteExit(destination, 0); +} + +void JitArm::bcx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + // USES_CR + _assert_msg_(DYNA_REC, js.isLastInstruction, "bcx not last instruction of block"); + + gpr.Flush(); + fpr.Flush(); + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + FixupBranch pCTRDontBranch; + if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR + { + MOVI2R(rA, (u32)&CTR); + LDR(rB, rA); + SUBS(rB, rB, 1); + STR(rA, rB); + + //SUB(32, M(&CTR), Imm8(1)); + if (inst.BO & BO_BRANCH_IF_CTR_0) + pCTRDontBranch = B_CC(CC_NEQ); + else + pCTRDontBranch = B_CC(CC_EQ); + } + + FixupBranch pConditionDontBranch; + if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit + { + LDRB(rA, R9, STRUCT_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2)); + TST(rA, 8 >> (inst.BI & 3)); + + //TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3))); + if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch + pConditionDontBranch = B_CC(CC_EQ); // Zero + else + pConditionDontBranch = B_CC(CC_NEQ); // Not Zero + } + gpr.Unlock(rA, rB); + if (inst.LK) + ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); // Careful, destroys R14, R12 + + u32 destination; + if(inst.AA) + destination = SignExt16(inst.BD << 2); + else + destination = js.compilerPC + SignExt16(inst.BD << 2); + WriteExit(destination, 0); + + if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) + SetJumpTarget( pConditionDontBranch ); + if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) + SetJumpTarget( pCTRDontBranch ); + + WriteExit(js.compilerPC + 4, 1); +} +void JitArm::bcctrx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + + gpr.Flush(); + fpr.Flush(); + + // bcctrx doesn't decrement and/or test CTR + _dbg_assert_msg_(POWERPC, inst.BO_2 & BO_DONT_DECREMENT_FLAG, "bcctrx with decrement and test CTR option is invalid!"); + + if (inst.BO_2 & BO_DONT_CHECK_CONDITION) + { + // BO_2 == 1z1zz -> b always + + //NPC = CTR & 0xfffffffc; + if(inst.LK_3) + ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + MOVI2R(rA, (u32)&CTR); + MVN(rB, 0x3); // 0xFFFFFFFC + LDR(rA, rA); + AND(rA, rA, rB); + gpr.Unlock(rB); + WriteExitDestInR(rA); + } + else + { + // Rare condition seen in (just some versions of?) Nintendo's NES Emulator + + // BO_2 == 001zy -> b if false + // BO_2 == 011zy -> b if true + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + + LDRB(rA, R9, STRUCT_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2)); + TST(rA, 8 >> (inst.BI & 3)); + CCFlags branch; + if (inst.BO_2 & BO_BRANCH_IF_TRUE) + branch = CC_EQ; + else + branch = CC_NEQ; + FixupBranch b = B_CC(branch); + + MOVI2R(rA, (u32)&CTR); + LDR(rA, rA); + MVN(rB, 0x3); // 0xFFFFFFFC + AND(rA, rA, rB); + + if (inst.LK_3){ + ARMReg rC = gpr.GetReg(false); + u32 Jumpto = js.compilerPC + 4; + MOVI2R(rB, (u32)&LR); + MOVI2R(rC, Jumpto); + STR(rB, rC); + //ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); + } + gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR + WriteExitDestInR(rA); + + SetJumpTarget(b); + WriteExit(js.compilerPC + 4, 1); + } +} +void JitArm::bclrx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + if (!js.isLastInstruction && + (inst.BO & (1 << 4)) && (inst.BO & (1 << 2))) { + if (inst.LK) + { + ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); + } + return; + } + gpr.Flush(); + fpr.Flush(); + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + FixupBranch pCTRDontBranch; + if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR + { + MOVI2R(rA, (u32)&CTR); + LDR(rB, rA); + SUBS(rB, rB, 1); + STR(rA, rB); + + //SUB(32, M(&CTR), Imm8(1)); + if (inst.BO & BO_BRANCH_IF_CTR_0) + pCTRDontBranch = B_CC(CC_NEQ); + else + pCTRDontBranch = B_CC(CC_EQ); + } + + FixupBranch pConditionDontBranch; + if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit + { + LDRB(rA, R9, STRUCT_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2)); + TST(rA, 8 >> (inst.BI & 3)); + //TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3))); + if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch + pConditionDontBranch = B_CC(CC_EQ); // Zero + else + pConditionDontBranch = B_CC(CC_NEQ); // Not Zero + } + + // This below line can be used to prove that blr "eats flags" in practice. + // This observation will let us do a lot of fun observations. + #ifdef ACID_TEST + // TODO: Not yet implemented + // AND(32, M(&PowerPC::ppcState.cr), Imm32(~(0xFF000000))); + #endif + + //MOV(32, R(EAX), M(&LR)); + //AND(32, R(EAX), Imm32(0xFFFFFFFC)); + MOVI2R(rA, (u32)&LR); + MVN(rB, 0x3); // 0xFFFFFFFC + LDR(rA, rA); + AND(rA, rA, rB); + if (inst.LK){ + ARMReg rC = gpr.GetReg(false); + u32 Jumpto = js.compilerPC + 4; + MOVI2R(rB, (u32)&LR); + MOVI2R(rC, Jumpto); + STR(rB, rC); + //ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); + } + gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR + WriteExitDestInR(rA); + + if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) + SetJumpTarget( pConditionDontBranch ); + if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) + SetJumpTarget( pCTRDontBranch ); + WriteExit(js.compilerPC + 4, 1); +} diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp new file mode 100644 index 0000000000..fe4c0e3f22 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp @@ -0,0 +1,80 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../ConfigManager.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" +#include "../../HW/Memmap.h" + + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitFPRCache.h" +#include "JitAsm.h" + +void JitArm::Helper_UpdateCR1(ARMReg value) +{ + // Should just update exception flags, not do any compares. + PanicAlert("CR1"); +} + +void JitArm::fabsx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(FloatingPoint) + + ARMReg vD = fpr.R0(inst.FD); + ARMReg vB = fpr.R0(inst.FB); + + VABS(vD, vB); + + if (inst.Rc) Helper_UpdateCR1(vD); +} + +void JitArm::faddx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(FloatingPoint) + + ARMReg vD = fpr.R0(inst.FD); + ARMReg vA = fpr.R0(inst.FA); + ARMReg vB = fpr.R0(inst.FB); + + VADD(vD, vA, vB); + if (inst.Rc) Helper_UpdateCR1(vD); +} + +void JitArm::fmrx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(FloatingPoint) + Default(inst); return; + + ARMReg vD = fpr.R0(inst.FD); + ARMReg vB = fpr.R0(inst.FB); + + VMOV(vD, vB); + + if (inst.Rc) Helper_UpdateCR1(vD); +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp new file mode 100644 index 0000000000..63c96b21fd --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp @@ -0,0 +1,297 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitAsm.h" +extern u32 Helper_Mask(u8 mb, u8 me); +// ADDI and RLWINMX broken for now + +// Assumes that Sign and Zero flags were set by the last operation. Preserves all flags and registers. +// Jit64 ComputerRC is signed +// JIT64 GenerateRC is unsigned +void JitArm::GenerateRC(int cr) { + ARMReg rB = gpr.GetReg(); + + MOV(rB, 0x4); // Result > 0 + SetCC(CC_EQ); MOV(rB, 0x2); // Result == 0 + SetCC(CC_MI); MOV(rB, 0x8); // Result < 0 + SetCC(); + + STRB(R9, rB, STRUCT_OFF(PowerPC::ppcState, cr_fast) + cr); + gpr.Unlock(rB); +} +void JitArm::ComputeRC(int cr) { + ARMReg rB = gpr.GetReg(); + + MOV(rB, 0x2); // Result == 0 + SetCC(CC_LT); MOV(rB, 0x8); // Result < 0 + SetCC(CC_GT); MOV(rB, 0x4); // Result > 0 + SetCC(); + + STRB(R9, rB, STRUCT_OFF(PowerPC::ppcState, cr_fast) + cr); + gpr.Unlock(rB); +} + +void JitArm::addi(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RD = gpr.R(inst.RD); + + if (inst.RA) + { + ARMReg rA = gpr.GetReg(false); + ARMReg RA = gpr.R(inst.RA); + MOVI2R(rA, (u32)inst.SIMM_16); + ADD(RD, RA, rA); + } + else + MOVI2R(RD, inst.SIMM_16); +} +void JitArm::addis(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RD = gpr.R(inst.RD); + if (inst.RA) + { + ARMReg rA = gpr.GetReg(false); + ARMReg RA = gpr.R(inst.RA); + MOVI2R(rA, inst.SIMM_16 << 16); + ADD(RD, RA, rA); + } + else + MOVI2R(RD, inst.SIMM_16 << 16); +} +void JitArm::addx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + ARMReg RB = gpr.R(inst.RB); + ARMReg RD = gpr.R(inst.RD); + ADDS(RD, RA, RB); + if (inst.Rc) ComputeRC(); +} +// Wrong - 28/10/2012 +void JitArm::mulli(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + Default(inst); return; + ARMReg RA = gpr.R(inst.RA); + ARMReg RD = gpr.R(inst.RD); + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, inst.SIMM_16); + MUL(RD, RA, rA); + gpr.Unlock(rA); +} +void JitArm::ori(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + ARMReg RS = gpr.R(inst.RS); + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, inst.UIMM); + ORR(RA, RS, rA); + gpr.Unlock(rA); +} +void JitArm::oris(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + ARMReg RS = gpr.R(inst.RS); + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, inst.UIMM << 16); + ORR(RA, RS, rA); + gpr.Unlock(rA); +} +void JitArm::orx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg rA = gpr.R(inst.RA); + ARMReg rS = gpr.R(inst.RS); + ARMReg rB = gpr.R(inst.RB); + ORRS(rA, rS, rB); + if (inst.Rc) + ComputeRC(); +} + +void JitArm::extshx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + ARMReg RA, RS; + RA = gpr.R(inst.RA); + RS = gpr.R(inst.RS); + SXTH(RA, RS); + if (inst.Rc){ + CMP(RA, 0); + ComputeRC(); + } +} +void JitArm::extsbx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + ARMReg RA, RS; + RA = gpr.R(inst.RA); + RS = gpr.R(inst.RS); + SXTB(RA, RS); + if (inst.Rc){ + CMP(RA, 0); + ComputeRC(); + } +} +void JitArm::cmp (UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + ARMReg RB = gpr.R(inst.RB); + int crf = inst.CRFD; + CMP(RA, RB); + ComputeRC(crf); +} +void JitArm::cmpi(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + ARMReg rA = gpr.GetReg(); + int crf = inst.CRFD; + MOVI2R(rA, inst.SIMM_16); + CMP(RA, rA); + gpr.Unlock(rA); + ComputeRC(crf); +} +void JitArm::cmpli(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + ARMReg rA = gpr.GetReg(); + int crf = inst.CRFD; + MOVI2R(rA, (u32)inst.UIMM); + CMP(RA, rA); + + // Unsigned GenerateRC() + + MOV(rA, 0x2); // Result == 0 + SetCC(CC_LO); MOV(rA, 0x8); // Result < 0 + SetCC(CC_HI); MOV(rA, 0x4); // Result > 0 + SetCC(); + + STRB(R9, rA, STRUCT_OFF(PowerPC::ppcState, cr_fast) + crf); + gpr.Unlock(rA); + +} +// Wrong - 27/10/2012 +void JitArm::negx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + Default(inst);return; + ARMReg RA = gpr.R(inst.RA); + ARMReg RD = gpr.R(inst.RD); + + RSBS(RD, RA, 0); + if (inst.Rc) + { + GenerateRC(); + } + if (inst.OE) + { + BKPT(0x333); + //GenerateOverflow(); + } +} +void JitArm::rlwimix(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + u32 mask = Helper_Mask(inst.MB,inst.ME); + ARMReg RA = gpr.R(inst.RA); + ARMReg RS = gpr.R(inst.RS); + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + MOVI2R(rA, mask); + + Operand2 Shift(32 - inst.SH, ST_ROR, RS); // This rotates left, while ARM has only rotate right, so swap it. + if (inst.Rc) + { + BIC (rB, RA, rA); // RA & ~mask + AND (rA, rA, Shift); + ORRS(RA, rB, rA); + GenerateRC(); + } + else + { + BIC (rB, RA, rA); // RA & ~mask + AND (rA, rA, Shift); + ORR(RA, rB, rA); + } + gpr.Unlock(rA, rB); +} +void JitArm::rlwinmx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + u32 mask = Helper_Mask(inst.MB,inst.ME); + ARMReg RA = gpr.R(inst.RA); + ARMReg RS = gpr.R(inst.RS); + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, mask); + + Operand2 Shift(32 - inst.SH, ST_ROR, RS); // This rotates left, while ARM has only rotate right, so swap it. + if (inst.Rc) + { + ANDS(RA, rA, Shift); + GenerateRC(); + } + else + AND (RA, rA, Shift); + gpr.Unlock(rA); + + //m_GPR[inst.RA] = _rotl(m_GPR[inst.RS],inst.SH) & mask; +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp new file mode 100644 index 0000000000..80c8a96cbb --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp @@ -0,0 +1,414 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../ConfigManager.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" +#include "../../HW/Memmap.h" + + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitAsm.h" + +#ifdef ANDROID +#define FASTMEM 0 +#else +#define FASTMEM 0 +#endif +void JitArm::stw(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg RS = gpr.R(inst.RS); +#if FASTMEM + // R10 contains the dest address + ARMReg Value = R11; + ARMReg RA; + if (inst.RA) + RA = gpr.R(inst.RA); + MOV(Value, RS); + if (inst.RA) + { + MOVI2R(R10, inst.SIMM_16, false); + ADD(R10, R10, RA); + } + else + { + MOVI2R(R10, (u32)inst.SIMM_16, false); + NOP(1); + } + StoreFromReg(R10, Value, 32, 0); +#else + ARMReg ValueReg = gpr.GetReg(); + ARMReg Addr = gpr.GetReg(); + ARMReg Function = gpr.GetReg(); + + MOV(ValueReg, RS); + if (inst.RA) + { + MOVI2R(Addr, inst.SIMM_16); + ARMReg RA = gpr.R(inst.RA); + ADD(Addr, Addr, RA); + } + else + MOVI2R(Addr, (u32)inst.SIMM_16); + + MOVI2R(Function, (u32)&Memory::Write_U32); + PUSH(4, R0, R1, R2, R3); + MOV(R0, ValueReg); + MOV(R1, Addr); + BL(Function); + POP(4, R0, R1, R2, R3); + gpr.Unlock(ValueReg, Addr, Function); +#endif +} +void JitArm::stwu(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg RA = gpr.R(inst.RA); + ARMReg RS = gpr.R(inst.RS); + ARMReg ValueReg = gpr.GetReg(); + ARMReg Addr = gpr.GetReg(); + ARMReg Function = gpr.GetReg(); + + MOVI2R(Addr, inst.SIMM_16); + ADD(Addr, Addr, RA); + + // Check and set the update before writing since calling a function can + // mess with the "special registers R11+ which may cause some issues. + LDR(Function, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions)); + CMP(Function, EXCEPTION_DSI); + FixupBranch DoNotWrite = B_CC(CC_EQ); + MOV(RA, Addr); + SetJumpTarget(DoNotWrite); + + MOV(ValueReg, RS); + + MOVI2R(Function, (u32)&Memory::Write_U32); + PUSH(4, R0, R1, R2, R3); + MOV(R0, ValueReg); + MOV(R1, Addr); + BL(Function); + POP(4, R0, R1, R2, R3); + + gpr.Unlock(ValueReg, Addr, Function); +} +void JitArm::StoreFromReg(ARMReg dest, ARMReg value, int accessSize, s32 offset) +{ + ARMReg rA = gpr.GetReg(); + + // All this gets replaced on backpatch + MOVI2R(rA, Memory::MEMVIEW32_MASK, false); // 1-2 + AND(dest, dest, rA); // 3 + MOVI2R(rA, (u32)Memory::base, false); // 4-5 + ADD(dest, dest, rA); // 6 + switch (accessSize) + { + case 32: + REV(value, value); // 7 + break; + case 16: + REV16(value, value); + break; + case 8: + NOP(1); + break; + } + switch (accessSize) + { + case 32: + STR(dest, value); // 8 + break; + case 16: + // Not implemented + break; + case 8: + // Not implemented + break; + } + gpr.Unlock(rA); +} +void JitArm::LoadToReg(ARMReg dest, ARMReg addr, int accessSize, s32 offset) +{ + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, offset, false); // -3 + ADD(addr, addr, rA); // - 1 + + // All this gets replaced on backpatch + MOVI2R(rA, Memory::MEMVIEW32_MASK, false); // 2 + AND(addr, addr, rA); // 3 + MOVI2R(rA, (u32)Memory::base, false); // 5 + ADD(addr, addr, rA); // 6 + switch (accessSize) + { + case 32: + LDR(dest, addr); // 7 + break; + case 16: + LDRH(dest, addr); + break; + case 8: + LDRB(dest, addr); + break; + } + switch (accessSize) + { + case 32: + REV(dest, dest); // 9 + break; + case 16: + REV16(dest, dest); + break; + case 8: + NOP(1); + break; + + } + gpr.Unlock(rA); +} +void JitArm::lbz(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + ARMReg RD = gpr.R(inst.RD); + LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions)); + CMP(rA, EXCEPTION_DSI); + FixupBranch DoNotLoad = B_CC(CC_EQ); +#if FASTMEM + // Backpatch route + // Gets loaded in to RD + // Address is in R10 + gpr.Unlock(rA, rB); + if (inst.RA) + { + ARMReg RA = gpr.R(inst.RA); + MOV(R10, RA); // - 4 + } + else + MOV(R10, 0); // - 4 + LoadToReg(RD, R10, 8, inst.SIMM_16); +#else + + if (inst.RA) + { + MOVI2R(rB, inst.SIMM_16); + ARMReg RA = gpr.R(inst.RA); + ADD(rB, rB, RA); + } + else + MOVI2R(rB, (u32)inst.SIMM_16); + + MOVI2R(rA, (u32)&Memory::Read_U8); + PUSH(4, R0, R1, R2, R3); + MOV(R0, rB); + BL(rA); + MOV(rA, R0); + POP(4, R0, R1, R2, R3); + MOV(RD, rA); + gpr.Unlock(rA, rB); +#endif + SetJumpTarget(DoNotLoad); +} + +void JitArm::lhz(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + ARMReg RD = gpr.R(inst.RD); + LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions)); + CMP(rA, EXCEPTION_DSI); + FixupBranch DoNotLoad = B_CC(CC_EQ); +#if 0 // FASTMEM + // Backpatch route + // Gets loaded in to RD + // Address is in R10 + gpr.Unlock(rA, rB); + if (inst.RA) + { + ARMReg RA = gpr.R(inst.RA); + printf("lhz jump to here: 0x%08x\n", (u32)GetCodePtr()); + MOV(R10, RA); // - 4 + } + else + { + printf("lhz jump to here: 0x%08x\n", (u32)GetCodePtr()); + MOV(R10, 0); // - 4 + } + LoadToReg(RD, R10, 16, (u32)inst.SIMM_16); +#else + + if (inst.RA) + { + MOVI2R(rB, inst.SIMM_16); + ARMReg RA = gpr.R(inst.RA); + ADD(rB, rB, RA); + } + else + MOVI2R(rB, (u32)inst.SIMM_16); + + MOVI2R(rA, (u32)&Memory::Read_U16); + PUSH(4, R0, R1, R2, R3); + MOV(R0, rB); + BL(rA); + MOV(rA, R0); + POP(4, R0, R1, R2, R3); + MOV(RD, rA); + gpr.Unlock(rA, rB); +#endif + SetJumpTarget(DoNotLoad); +} +void JitArm::lwz(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + ARMReg RD = gpr.R(inst.RD); + LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions)); + CMP(rA, EXCEPTION_DSI); + FixupBranch DoNotLoad = B_CC(CC_EQ); + +#if FASTMEM + // Backpatch route + // Gets loaded in to RD + // Address is in R10 + gpr.Unlock(rA, rB); + if (inst.RA) + { + ARMReg RA = gpr.R(inst.RA); + MOV(R10, RA); // - 4 + } + else + MOV(R10, 0); // - 4 + LoadToReg(RD, R10, 32, (u32)inst.SIMM_16); +#else + if (inst.RA) + { + MOVI2R(rB, inst.SIMM_16); + ARMReg RA = gpr.R(inst.RA); + ADD(rB, rB, RA); + } + else + MOVI2R(rB, (u32)inst.SIMM_16); + + MOVI2R(rA, (u32)&Memory::Read_U32); + PUSH(4, R0, R1, R2, R3); + MOV(R0, rB); + BL(rA); + MOV(rA, R0); + POP(4, R0, R1, R2, R3); + MOV(RD, rA); + gpr.Unlock(rA, rB); +#endif + SetJumpTarget(DoNotLoad); + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle && + (inst.hex & 0xFFFF0000) == 0x800D0000 && + (Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 || + (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) && + Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8) + { + gpr.Flush(); + fpr.Flush(); + + // if it's still 0, we can wait until the next event + TST(RD, RD); + FixupBranch noIdle = B_CC(CC_NEQ); + rA = gpr.GetReg(); + + MOVI2R(rA, (u32)&PowerPC::OnIdle); + MOVI2R(R0, PowerPC::ppcState.gpr[inst.RA] + (s32)(s16)inst.SIMM_16); + BL(rA); + + gpr.Unlock(rA); + WriteExceptionExit(); + + SetJumpTarget(noIdle); + + //js.compilerPC += 8; + return; + } +} +void JitArm::lwzx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + + ARMReg RB = gpr.R(inst.RB); + ARMReg RD = gpr.R(inst.RD); + LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions)); + CMP(rA, EXCEPTION_DSI); + FixupBranch DoNotLoad = B_CC(CC_EQ); +#if FASTMEM + // Backpatch route + // Gets loaded in to RD + // Address is in R10 + gpr.Unlock(rA, rB); + if (inst.RA) + { + ARMReg RA = gpr.R(inst.RA); + ADD(R10, RA, RB); // - 4 + } + else + MOV(R10, RB); // -4 + LoadToReg(RD, R10, 32, 0); +#else + if (inst.RA) + { + ARMReg RA = gpr.R(inst.RA); + ADD(rB, RA, RB); + } + else + MOV(rB, RB); + + MOVI2R(rA, (u32)&Memory::Read_U32); + PUSH(4, R0, R1, R2, R3); + MOV(R0, rB); + BL(rA); + MOV(rA, R0); + POP(4, R0, R1, R2, R3); + MOV(RD, rA); + gpr.Unlock(rA, rB); +#endif + SetJumpTarget(DoNotLoad); + //// u32 temp = Memory::Read_U32(_inst.RA ? (m_GPR[_inst.RA] + m_GPR[_inst.RB]) : m_GPR[_inst.RB]); +} +void JitArm::icbi(UGeckoInstruction inst) +{ + Default(inst); + WriteExit(js.compilerPC + 4, 0); +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp new file mode 100644 index 0000000000..d9e320ab22 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp @@ -0,0 +1,72 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../ConfigManager.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" +#include "../../HW/Memmap.h" + + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitFPRCache.h" +#include "JitAsm.h" + +void JitArm::lfs(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStoreFloating) + Default(inst); return; + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions)); + CMP(rA, EXCEPTION_DSI); + FixupBranch DoNotLoad = B_CC(CC_EQ); + + if (inst.RA) + { + MOVI2R(rB, inst.SIMM_16); + ARMReg RA = gpr.R(inst.RA); + ADD(rB, rB, RA); + } + else + MOVI2R(rB, (u32)inst.SIMM_16); + + MOVI2R(rA, (u32)&Memory::Read_U32); + PUSH(4, R0, R1, R2, R3); + MOV(R0, rB); + BL(rA); + MOV(rA, R0); + POP(4, R0, R1, R2, R3); + + ARMReg v0 = fpr.R0(inst.FD, false); + ARMReg v1 = fpr.R1(inst.FD, false); + + VMOV(v0, rA, false); + VMOV(v1, rA, false); + + gpr.Unlock(rA, rB); + SetJumpTarget(DoNotLoad); +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp new file mode 100644 index 0000000000..a99114df67 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp @@ -0,0 +1,111 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitAsm.h" + +void JitArm::mtspr(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(SystemRegisters) + + u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F); + ARMReg RD = gpr.R(inst.RD); + + switch (iIndex) + { + case SPR_LR: + case SPR_CTR: + case SPR_XER: + // These are safe to do the easy way, see the bottom of this function. + break; + + case SPR_GQR0: + case SPR_GQR0 + 1: + case SPR_GQR0 + 2: + case SPR_GQR0 + 3: + case SPR_GQR0 + 4: + case SPR_GQR0 + 5: + case SPR_GQR0 + 6: + case SPR_GQR0 + 7: + // Prevent recompiler from compiling in old quantizer values. + // If the value changed, destroy all blocks using this quantizer + // This will create a little bit of block churn, but hopefully not too bad. + { + /* + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[iIndex])); // Load old value + CMP(32, R(EAX), gpr.R(inst.RD)); + FixupBranch skip_destroy = J_CC(CC_E, false); + int gqr = iIndex - SPR_GQR0; + ABI_CallFunctionC(ProtectFunction(&Jit64::DestroyBlocksWithFlag, 1), (u32)BLOCK_USE_GQR0 << gqr); + SetJumpTarget(skip_destroy);*/ + } + // TODO - break block if quantizers are written to. + default: + Default(inst); + return; + } + + // OK, this is easy. + ARMReg rA = gpr.GetReg(false); + MOVI2R(rA, (u32)&PowerPC::ppcState.spr); + STR(rA, RD, iIndex * 4); +} + +void JitArm::mfspr(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(SystemRegisters) + + u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F); + ARMReg RD = gpr.R(inst.RD); + switch (iIndex) + { + case SPR_WPAR: + case SPR_DEC: + case SPR_TL: + case SPR_TU: + Default(inst); + return; + default: + ARMReg rA = gpr.GetReg(false); + MOVI2R(rA, (u32)&PowerPC::ppcState.spr); + LDR(RD, rA, iIndex * 4); + break; + } +} +void JitArm::mtmsr(UGeckoInstruction inst) +{ + INSTRUCTION_START + // Don't interpret this, if we do we get thrown out + //JITDISABLE(SystemRegisters) + + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, (u32)&MSR); + STR(rA, gpr.R(inst.RS)); + gpr.Unlock(rA); + WriteExit(js.compilerPC + 4, 0); +} diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp new file mode 100644 index 0000000000..1929705df2 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp @@ -0,0 +1,502 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Jit.h" +#include "../JitInterface.h" +#include "JitArm_Tables.h" + +// Should be moved in to the Jit class +typedef void (JitArm::*_Instruction) (UGeckoInstruction instCode); + +static _Instruction dynaOpTable[64]; +static _Instruction dynaOpTable4[1024]; +static _Instruction dynaOpTable19[1024]; +static _Instruction dynaOpTable31[1024]; +static _Instruction dynaOpTable59[32]; +static _Instruction dynaOpTable63[1024]; + +void JitArm::DynaRunTable4(UGeckoInstruction _inst) {(this->*dynaOpTable4 [_inst.SUBOP10])(_inst);} +void JitArm::DynaRunTable19(UGeckoInstruction _inst) {(this->*dynaOpTable19[_inst.SUBOP10])(_inst);} +void JitArm::DynaRunTable31(UGeckoInstruction _inst) {(this->*dynaOpTable31[_inst.SUBOP10])(_inst);} +void JitArm::DynaRunTable59(UGeckoInstruction _inst) {(this->*dynaOpTable59[_inst.SUBOP5 ])(_inst);} +void JitArm::DynaRunTable63(UGeckoInstruction _inst) {(this->*dynaOpTable63[_inst.SUBOP10])(_inst);} + +struct GekkoOPTemplate +{ + int opcode; + _Instruction Inst; + //GekkoOPInfo opinfo; // Doesn't need opinfo, Interpreter fills it out +}; + +static GekkoOPTemplate primarytable[] = +{ + {4, &JitArm::DynaRunTable4}, //"RunTable4", OPTYPE_SUBTABLE | (4<<24), 0}}, + {19, &JitArm::DynaRunTable19}, //"RunTable19", OPTYPE_SUBTABLE | (19<<24), 0}}, + {31, &JitArm::DynaRunTable31}, //"RunTable31", OPTYPE_SUBTABLE | (31<<24), 0}}, + {59, &JitArm::DynaRunTable59}, //"RunTable59", OPTYPE_SUBTABLE | (59<<24), 0}}, + {63, &JitArm::DynaRunTable63}, //"RunTable63", OPTYPE_SUBTABLE | (63<<24), 0}}, + + {16, &JitArm::bcx}, //"bcx", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + {18, &JitArm::bx}, //"bx", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + + {1, &JitArm::HLEFunction}, //"HLEFunction", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + {2, &JitArm::Default}, //"DynaBlock", OPTYPE_SYSTEM, 0}}, + {3, &JitArm::Break}, //"twi", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + {17, &JitArm::sc}, //"sc", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}}, + + {7, &JitArm::mulli}, //"mulli", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_RC_BIT, 2}}, + {8, &JitArm::Default}, //"subfic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}}, + {10, &JitArm::cmpli}, //"cmpli", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}}, + {11, &JitArm::cmpi}, //"cmpi", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}}, + {12, &JitArm::Default}, //"addic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}}, + {13, &JitArm::Default}, //"addic_rc", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CR0}}, + {14, &JitArm::addi}, //"addi", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}}, + {15, &JitArm::addis}, //"addis", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}}, + + {20, &JitArm::rlwimix}, //"rlwimix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_A | FL_IN_S | FL_RC_BIT}}, + {21, &JitArm::rlwinmx}, //"rlwinmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}}, + {23, &JitArm::Default}, //"rlwnmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_IN_B | FL_RC_BIT}}, + + {24, &JitArm::ori}, //"ori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}}, + {25, &JitArm::oris}, //"oris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}}, + {26, &JitArm::Default}, //"xori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}}, + {27, &JitArm::Default}, //"xoris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}}, + {28, &JitArm::Default}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}}, + {29, &JitArm::Default}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}}, + + {32, &JitArm::lwz}, //"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, + {33, &JitArm::Default}, //"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, + {34, &JitArm::lbz}, //"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, + {35, &JitArm::Default}, //"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, + {40, &JitArm::lhz}, //"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, + {41, &JitArm::Default}, //"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, + {42, &JitArm::Default}, //"lha", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, + {43, &JitArm::Default}, //"lhau", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, + + {44, &JitArm::Default}, //"sth", OPTYPE_STORE, FL_IN_A | FL_IN_S}}, + {45, &JitArm::Default}, //"sthu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}}, + {36, &JitArm::stw}, //"stw", OPTYPE_STORE, FL_IN_A | FL_IN_S}}, + {37, &JitArm::stwu}, //"stwu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}}, + {38, &JitArm::Default}, //"stb", OPTYPE_STORE, FL_IN_A | FL_IN_S}}, + {39, &JitArm::Default}, //"stbu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}}, + + {46, &JitArm::Default}, //"lmw", OPTYPE_SYSTEM, FL_EVIL, 10}}, + {47, &JitArm::Default}, //"stmw", OPTYPE_SYSTEM, FL_EVIL, 10}}, + + {48, &JitArm::lfs}, //"lfs", OPTYPE_LOADFP, FL_IN_A}}, + {49, &JitArm::Default}, //"lfsu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}}, + {50, &JitArm::Default}, //"lfd", OPTYPE_LOADFP, FL_IN_A}}, + {51, &JitArm::Default}, //"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}}, + + {52, &JitArm::Default}, //"stfs", OPTYPE_STOREFP, FL_IN_A}}, + {53, &JitArm::Default}, //"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}}, + {54, &JitArm::Default}, //"stfd", OPTYPE_STOREFP, FL_IN_A}}, + {55, &JitArm::Default}, //"stfdu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}}, + + {56, &JitArm::Default}, //"psq_l", OPTYPE_PS, FL_IN_A}}, + {57, &JitArm::Default}, //"psq_lu", OPTYPE_PS, FL_OUT_A | FL_IN_A}}, + {60, &JitArm::Default}, //"psq_st", OPTYPE_PS, FL_IN_A}}, + {61, &JitArm::Default}, //"psq_stu", OPTYPE_PS, FL_OUT_A | FL_IN_A}}, + + //missing: 0, 5, 6, 9, 22, 30, 62, 58 + {0, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {5, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {6, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {9, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {22, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {30, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {62, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {58, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, +}; + +static GekkoOPTemplate table4[] = +{ //SUBOP10 + {0, &JitArm::Default}, //"ps_cmpu0", OPTYPE_PS, FL_SET_CRn}}, + {32, &JitArm::Default}, //"ps_cmpo0", OPTYPE_PS, FL_SET_CRn}}, + {40, &JitArm::Default}, //"ps_neg", OPTYPE_PS, FL_RC_BIT}}, + {136, &JitArm::Default}, //"ps_nabs", OPTYPE_PS, FL_RC_BIT}}, + {264, &JitArm::Default}, //"ps_abs", OPTYPE_PS, FL_RC_BIT}}, + {64, &JitArm::Default}, //"ps_cmpu1", OPTYPE_PS, FL_RC_BIT}}, + {72, &JitArm::Default}, //"ps_mr", OPTYPE_PS, FL_RC_BIT}}, + {96, &JitArm::Default}, //"ps_cmpo1", OPTYPE_PS, FL_RC_BIT}}, + {528, &JitArm::Default}, //"ps_merge00", OPTYPE_PS, FL_RC_BIT}}, + {560, &JitArm::Default}, //"ps_merge01", OPTYPE_PS, FL_RC_BIT}}, + {592, &JitArm::Default}, //"ps_merge10", OPTYPE_PS, FL_RC_BIT}}, + {624, &JitArm::Default}, //"ps_merge11", OPTYPE_PS, FL_RC_BIT}}, + + {1014, &JitArm::Default}, //"dcbz_l", OPTYPE_SYSTEM, 0}}, +}; + +static GekkoOPTemplate table4_2[] = +{ + {10, &JitArm::Default}, //"ps_sum0", OPTYPE_PS, 0}}, + {11, &JitArm::Default}, //"ps_sum1", OPTYPE_PS, 0}}, + {12, &JitArm::Default}, //"ps_muls0", OPTYPE_PS, 0}}, + {13, &JitArm::Default}, //"ps_muls1", OPTYPE_PS, 0}}, + {14, &JitArm::Default}, //"ps_madds0", OPTYPE_PS, 0}}, + {15, &JitArm::Default}, //"ps_madds1", OPTYPE_PS, 0}}, + {18, &JitArm::Default}, //"ps_div", OPTYPE_PS, 0, 16}}, + {20, &JitArm::Default}, //"ps_sub", OPTYPE_PS, 0}}, + {21, &JitArm::Default}, //"ps_add", OPTYPE_PS, 0}}, + {23, &JitArm::Default}, //"ps_sel", OPTYPE_PS, 0}}, + {24, &JitArm::Default}, //"ps_res", OPTYPE_PS, 0}}, + {25, &JitArm::Default}, //"ps_mul", OPTYPE_PS, 0}}, + {26, &JitArm::Default}, //"ps_rsqrte", OPTYPE_PS, 0, 1}}, + {28, &JitArm::Default}, //"ps_msub", OPTYPE_PS, 0}}, + {29, &JitArm::Default}, //"ps_madd", OPTYPE_PS, 0}}, + {30, &JitArm::Default}, //"ps_nmsub", OPTYPE_PS, 0}}, + {31, &JitArm::Default}, //"ps_nmadd", OPTYPE_PS, 0}}, +}; + + +static GekkoOPTemplate table4_3[] = +{ + {6, &JitArm::Default}, //"psq_lx", OPTYPE_PS, 0}}, + {7, &JitArm::Default}, //"psq_stx", OPTYPE_PS, 0}}, + {38, &JitArm::Default}, //"psq_lux", OPTYPE_PS, 0}}, + {39, &JitArm::Default}, //"psq_stux", OPTYPE_PS, 0}}, +}; + +static GekkoOPTemplate table19[] = +{ + {528, &JitArm::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}}, + {16, &JitArm::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}}, + {257, &JitArm::Default}, //"crand", OPTYPE_CR, FL_EVIL}}, + {129, &JitArm::Default}, //"crandc", OPTYPE_CR, FL_EVIL}}, + {289, &JitArm::Default}, //"creqv", OPTYPE_CR, FL_EVIL}}, + {225, &JitArm::Default}, //"crnand", OPTYPE_CR, FL_EVIL}}, + {33, &JitArm::Default}, //"crnor", OPTYPE_CR, FL_EVIL}}, + {449, &JitArm::Default}, //"cror", OPTYPE_CR, FL_EVIL}}, + {417, &JitArm::Default}, //"crorc", OPTYPE_CR, FL_EVIL}}, + {193, &JitArm::Default}, //"crxor", OPTYPE_CR, FL_EVIL}}, + + {150, &JitArm::DoNothing}, //"isync", OPTYPE_ICACHE, FL_EVIL}}, + {0, &JitArm::Default}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}}, + + {50, &JitArm::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}}, + {18, &JitArm::Break}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}} +}; + + +static GekkoOPTemplate table31[] = +{ + {28, &JitArm::Default}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {60, &JitArm::Default}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {444, &JitArm::orx}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {124, &JitArm::Default}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {316, &JitArm::Default}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {412, &JitArm::Default}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {476, &JitArm::Default}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {284, &JitArm::Default}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {0, &JitArm::cmp}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}}, + {32, &JitArm::Default}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}}, + {26, &JitArm::Default}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}}, + {922, &JitArm::extshx}, //"extshx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}}, + {954, &JitArm::extsbx}, //"extsbx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}}, + {536, &JitArm::Default}, //"srwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, + {792, &JitArm::Default}, //"srawx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, + {824, &JitArm::Default}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, + {24, &JitArm::Default}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, + + {54, &JitArm::Default}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, + {86, &JitArm::Default}, //"dcbf", OPTYPE_DCACHE, 0, 4}}, + {246, &JitArm::Default}, //"dcbtst", OPTYPE_DCACHE, 0, 1}}, + {278, &JitArm::Default}, //"dcbt", OPTYPE_DCACHE, 0, 1}}, + {470, &JitArm::Default}, //"dcbi", OPTYPE_DCACHE, 0, 4}}, + {758, &JitArm::Default}, //"dcba", OPTYPE_DCACHE, 0, 4}}, + {1014, &JitArm::Default}, //"dcbz", OPTYPE_DCACHE, 0, 4}}, + + //load word + {23, &JitArm::lwzx}, //"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + {55, &JitArm::Default}, //"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //load halfword + {279, &JitArm::Default}, //"lhzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + {311, &JitArm::Default}, //"lhzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //load halfword signextend + {343, &JitArm::Default}, //"lhax", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + {375, &JitArm::Default}, //"lhaux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //load byte + {87, &JitArm::Default}, //"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + {119, &JitArm::Default}, //"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //load byte reverse + {534, &JitArm::Default}, //"lwbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + {790, &JitArm::Default}, //"lhbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + + // Conditional load/store (Wii SMP) + {150, &JitArm::Default}, //"stwcxd", OPTYPE_STORE, FL_EVIL | FL_SET_CR0}}, + {20, &JitArm::Default}, //"lwarx", OPTYPE_LOAD, FL_EVIL | FL_OUT_D | FL_IN_A0B | FL_SET_CR0}}, + + //load string (interpret these) + {533, &JitArm::Default}, //"lswx", OPTYPE_LOAD, FL_EVIL | FL_IN_A | FL_OUT_D}}, + {597, &JitArm::Default}, //"lswi", OPTYPE_LOAD, FL_EVIL | FL_IN_AB | FL_OUT_D}}, + + //store word + {151, &JitArm::Default}, //"stwx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, + {183, &JitArm::Default}, //"stwux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //store halfword + {407, &JitArm::Default}, //"sthx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, + {439, &JitArm::Default}, //"sthux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //store byte + {215, &JitArm::Default}, //"stbx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, + {247, &JitArm::Default}, //"stbux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //store bytereverse + {662, &JitArm::Default}, //"stwbrx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, + {918, &JitArm::Default}, //"sthbrx", OPTYPE_STORE, FL_IN_A | FL_IN_B}}, + + {661, &JitArm::Default}, //"stswx", OPTYPE_STORE, FL_EVIL}}, + {725, &JitArm::Default}, //"stswi", OPTYPE_STORE, FL_EVIL}}, + + // fp load/store + {535, &JitArm::Default}, //"lfsx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}}, + {567, &JitArm::Default}, //"lfsux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}}, + {599, &JitArm::Default}, //"lfdx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}}, + {631, &JitArm::Default}, //"lfdux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}}, + + {663, &JitArm::Default}, //"stfsx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}}, + {695, &JitArm::Default}, //"stfsux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}}, + {727, &JitArm::Default}, //"stfdx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}}, + {759, &JitArm::Default}, //"stfdux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}}, + {983, &JitArm::Default}, //"stfiwx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}}, + + {19, &JitArm::Default}, //"mfcr", OPTYPE_SYSTEM, FL_OUT_D}}, + {83, &JitArm::Default}, //"mfmsr", OPTYPE_SYSTEM, FL_OUT_D}}, + {144, &JitArm::Default}, //"mtcrf", OPTYPE_SYSTEM, 0}}, + {146, &JitArm::mtmsr}, //"mtmsr", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + {210, &JitArm::Default}, //"mtsr", OPTYPE_SYSTEM, 0}}, + {242, &JitArm::Default}, //"mtsrin", OPTYPE_SYSTEM, 0}}, + {339, &JitArm::mfspr}, //"mfspr", OPTYPE_SPR, FL_OUT_D}}, + {467, &JitArm::mtspr}, //"mtspr", OPTYPE_SPR, 0, 2}}, + {371, &JitArm::Default}, //"mftb", OPTYPE_SYSTEM, FL_OUT_D | FL_TIMER}}, + {512, &JitArm::Default}, //"mcrxr", OPTYPE_SYSTEM, 0}}, + {595, &JitArm::Default}, //"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 2}}, + {659, &JitArm::Default}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}}, + + {4, &JitArm::Break}, //"tw", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}}, + {598, &JitArm::Default}, //"sync", OPTYPE_SYSTEM, 0, 2}}, + {982, &JitArm::icbi}, //"icbi", OPTYPE_SYSTEM, FL_ENDBLOCK, 3}}, + + // Unused instructions on GC + {310, &JitArm::Default}, //"eciwx", OPTYPE_INTEGER, FL_RC_BIT}}, + {438, &JitArm::Default}, //"ecowx", OPTYPE_INTEGER, FL_RC_BIT}}, + {854, &JitArm::Default}, //"eieio", OPTYPE_INTEGER, FL_RC_BIT}}, + {306, &JitArm::Default}, //"tlbie", OPTYPE_SYSTEM, 0}}, + {370, &JitArm::Default}, //"tlbia", OPTYPE_SYSTEM, 0}}, + {566, &JitArm::Default}, //"tlbsync", OPTYPE_SYSTEM, 0}}, +}; + +static GekkoOPTemplate table31_2[] = +{ + {266, &JitArm::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, + {778, &JitArm::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, + {10, &JitArm::Default}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}}, + {138, &JitArm::Default}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {234, &JitArm::Default}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {202, &JitArm::Default}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {491, &JitArm::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, + {1003, &JitArm::Default}, //"divwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, + {459, &JitArm::Default}, //"divwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, + {971, &JitArm::Default}, //"divwuox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, + {75, &JitArm::Default}, //"mulhwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}}, + {11, &JitArm::Default}, //"mulhwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}}, + {235, &JitArm::Default}, //"mullwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}}, + {747, &JitArm::Default}, //"mullwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}}, + {104, &JitArm::negx}, //"negx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, + {40, &JitArm::Default}, //"subfx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, + {552, &JitArm::Default}, //"subox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, + {8, &JitArm::Default}, //"subfcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}}, + {136, &JitArm::Default}, //"subfex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {232, &JitArm::Default}, //"subfmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {200, &JitArm::Default}, //"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, +}; + +static GekkoOPTemplate table59[] = +{ + {18, &JitArm::Default}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}}, + {20, &JitArm::Default}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {21, &JitArm::Default}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}}, +// {22, &JitArm::Default}, //"fsqrtsx", OPTYPE_FPU, FL_RC_BIT_F}}, // Not implemented on gekko + {24, &JitArm::Default}, //"fresx", OPTYPE_FPU, FL_RC_BIT_F}}, + {25, &JitArm::Default}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {28, &JitArm::Default}, //"fmsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {29, &JitArm::Default}, //"fmaddsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {30, &JitArm::Default}, //"fnmsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {31, &JitArm::Default}, //"fnmaddsx", OPTYPE_FPU, FL_RC_BIT_F}}, +}; + +static GekkoOPTemplate table63[] = +{ + {264, &JitArm::fabsx}, //"fabsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {32, &JitArm::Default}, //"fcmpo", OPTYPE_FPU, FL_RC_BIT_F}}, + {0, &JitArm::Default}, //"fcmpu", OPTYPE_FPU, FL_RC_BIT_F}}, + {14, &JitArm::Default}, //"fctiwx", OPTYPE_FPU, FL_RC_BIT_F}}, + {15, &JitArm::Default}, //"fctiwzx", OPTYPE_FPU, FL_RC_BIT_F}}, + {72, &JitArm::fmrx}, //"fmrx", OPTYPE_FPU, FL_RC_BIT_F}}, + {136, &JitArm::Default}, //"fnabsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {40, &JitArm::Default}, //"fnegx", OPTYPE_FPU, FL_RC_BIT_F}}, + {12, &JitArm::Default}, //"frspx", OPTYPE_FPU, FL_RC_BIT_F}}, + + {64, &JitArm::Default}, //"mcrfs", OPTYPE_SYSTEMFP, 0}}, + {583, &JitArm::Default}, //"mffsx", OPTYPE_SYSTEMFP, 0}}, + {70, &JitArm::Default}, //"mtfsb0x", OPTYPE_SYSTEMFP, 0, 2}}, + {38, &JitArm::Default}, //"mtfsb1x", OPTYPE_SYSTEMFP, 0, 2}}, + {134, &JitArm::Default}, //"mtfsfix", OPTYPE_SYSTEMFP, 0, 2}}, + {711, &JitArm::Default}, //"mtfsfx", OPTYPE_SYSTEMFP, 0, 2}}, +}; + +static GekkoOPTemplate table63_2[] = +{ + {18, &JitArm::Default}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}}, + {20, &JitArm::Default}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}}, + {21, &JitArm::faddx}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}}, + {22, &JitArm::Default}, //"fsqrtx", OPTYPE_FPU, FL_RC_BIT_F}}, + {23, &JitArm::Default}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}}, + {25, &JitArm::Default}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}}, + {26, &JitArm::Default}, //"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}}, + {28, &JitArm::Default}, //"fmsubx", OPTYPE_FPU, FL_RC_BIT_F}}, + {29, &JitArm::Default}, //"fmaddx", OPTYPE_FPU, FL_RC_BIT_F}}, + {30, &JitArm::Default}, //"fnmsubx", OPTYPE_FPU, FL_RC_BIT_F}}, + {31, &JitArm::Default}, //"fnmaddx", OPTYPE_FPU, FL_RC_BIT_F}}, +}; + + +namespace JitArmTables +{ + +void CompileInstruction(PPCAnalyst::CodeOp & op) +{ + JitArm *jitarm = (JitArm *)jit; + (jitarm->*dynaOpTable[op.inst.OPCD])(op.inst); + GekkoOPInfo *info = op.opinfo; + if (info) { +#ifdef OPLOG + if (!strcmp(info->opname, OP_TO_LOG)){ ///"mcrfs" + rsplocations.push_back(jit.js.compilerPC); + } +#endif + info->compileCount++; + info->lastUse = jit->js.compilerPC; + } +} + +void InitTables() +{ + // once initialized, tables are read-only + static bool initialized = false; + if (initialized) + return; + + //clear + for (int i = 0; i < 32; i++) + { + dynaOpTable59[i] = &JitArm::unknown_instruction; + } + + for (int i = 0; i < 1024; i++) + { + dynaOpTable4 [i] = &JitArm::unknown_instruction; + dynaOpTable19[i] = &JitArm::unknown_instruction; + dynaOpTable31[i] = &JitArm::unknown_instruction; + dynaOpTable63[i] = &JitArm::unknown_instruction; + } + + for (int i = 0; i < (int)(sizeof(primarytable) / sizeof(GekkoOPTemplate)); i++) + { + dynaOpTable[primarytable[i].opcode] = primarytable[i].Inst; + } + + for (int i = 0; i < 32; i++) + { + int fill = i << 5; + for (int j = 0; j < (int)(sizeof(table4_2) / sizeof(GekkoOPTemplate)); j++) + { + int op = fill+table4_2[j].opcode; + dynaOpTable4[op] = table4_2[j].Inst; + } + } + + for (int i = 0; i < 16; i++) + { + int fill = i << 6; + for (int j = 0; j < (int)(sizeof(table4_3) / sizeof(GekkoOPTemplate)); j++) + { + int op = fill+table4_3[j].opcode; + dynaOpTable4[op] = table4_3[j].Inst; + } + } + + for (int i = 0; i < (int)(sizeof(table4) / sizeof(GekkoOPTemplate)); i++) + { + int op = table4[i].opcode; + dynaOpTable4[op] = table4[i].Inst; + } + + for (int i = 0; i < (int)(sizeof(table31) / sizeof(GekkoOPTemplate)); i++) + { + int op = table31[i].opcode; + dynaOpTable31[op] = table31[i].Inst; + } + + for (int i = 0; i < 1; i++) + { + int fill = i << 9; + for (int j = 0; j < (int)(sizeof(table31_2) / sizeof(GekkoOPTemplate)); j++) + { + int op = fill + table31_2[j].opcode; + dynaOpTable31[op] = table31_2[j].Inst; + } + } + + for (int i = 0; i < (int)(sizeof(table19) / sizeof(GekkoOPTemplate)); i++) + { + int op = table19[i].opcode; + dynaOpTable19[op] = table19[i].Inst; + } + + for (int i = 0; i < (int)(sizeof(table59) / sizeof(GekkoOPTemplate)); i++) + { + int op = table59[i].opcode; + dynaOpTable59[op] = table59[i].Inst; + } + + for (int i = 0; i < (int)(sizeof(table63) / sizeof(GekkoOPTemplate)); i++) + { + int op = table63[i].opcode; + dynaOpTable63[op] = table63[i].Inst; + } + + for (int i = 0; i < 32; i++) + { + int fill = i << 5; + for (int j = 0; j < (int)(sizeof(table63_2) / sizeof(GekkoOPTemplate)); j++) + { + int op = fill + table63_2[j].opcode; + dynaOpTable63[op] = table63_2[j].Inst; + } + } + + initialized = true; + +} + +} // namespace diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.h new file mode 100644 index 0000000000..4904ce3984 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.h @@ -0,0 +1,29 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef JITARM_TABLES_H +#define JITARM_TABLES_H + +#include "../Gekko.h" +#include "../PPCTables.h" + +namespace JitArmTables +{ + void CompileInstruction(PPCAnalyst::CodeOp & op); + void InitTables(); +} +#endif diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp new file mode 100644 index 0000000000..e45058b57b --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp @@ -0,0 +1,174 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include "../../HW/Memmap.h" + +#include "../PowerPC.h" +#include "../../CoreTiming.h" +#include "MemoryUtil.h" + +#include "Jit.h" +#include "../JitCommon/JitCache.h" + +#include "../../HW/GPFifo.h" +#include "../../Core.h" +#include "JitAsm.h" +#include "ArmEmitter.h" + +using namespace ArmGen; + +//TODO - make an option +//#if _DEBUG +// bool enableDebug = false; +//#else +// bool enableDebug = false; +//#endif + +JitArmAsmRoutineManager asm_routines; + +void JitArmAsmRoutineManager::Generate() +{ + enterCode = GetCodePtr(); + PUSH(2, R11, _LR); // R11 is frame pointer in Debug. + + MOVI2R(R0, (u32)&CoreTiming::downcount); + MOVI2R(R9, (u32)&PowerPC::ppcState); + + FixupBranch skipToRealDispatcher = B(); + dispatcher = GetCodePtr(); + printf("Dispatcher is %p\n", dispatcher); + + // Downcount Check + // The result of slice decrementation should be in flags if somebody jumped here + // IMPORTANT - We jump on negative, not carry!!! + FixupBranch bail = B_CC(CC_MI); + + SetJumpTarget(skipToRealDispatcher); + dispatcherNoCheck = GetCodePtr(); + + // This block of code gets the address of the compiled block of code + // It runs though to the compiling portion if it isn't found + LDR(R12, R9, STRUCT_OFF(PowerPC::ppcState, pc));// Load the current PC into R12 + + MOVI2R(R14, JIT_ICACHE_MASK); // Potential for optimization + AND(R12, R12, R14); // R12 contains PC & JIT_ICACHE_MASK here. + // Confirmed good to this point 08-03-12 + + MOVI2R(R14, (u32)jit->GetBlockCache()->GetICache()); + // Confirmed That this loads the base iCache Location correctly 08-04-12 + + LDR(R12, R14, R12, true, true); // R12 contains iCache[PC & JIT_ICACHE_MASK] here + // R12 Confirmed this is the correct iCache Location loaded. + TST(R12, 0xFC); // Test to see if it is a JIT block. + + SetCC(CC_EQ); // Only run next part if R12 is zero + // Success, it is our Jitblock. + MOVI2R(R14, (u32)jit->GetBlockCache()->GetCodePointers()); + // LDR R14 right here to get CodePointers()[0] pointer. + REV(R12, R12); // Reversing this gives us our JITblock. + LSL(R12, R12, 2); // Multiply by four because address locations are u32 in size + LDR(R14, R14, R12, true, true); // Load the block address in to R14 + + B(R14); + + FixupBranch NextBlock = B(); // Jump to end so we can start a new block + SetCC(); // Return to always executing codes + + // If we get to this point, that means that we don't have the block cached to execute + // So call ArmJit to compile the block and then execute it. + MOVI2R(R14, (u32)&Jit); + LDR(R0, R9, STRUCT_OFF(PowerPC::ppcState, pc)); + BL(R14); + + B(dispatcherNoCheck); + + // fpException() + // Floating Point Exception Check, Jumped to if false + fpException = GetCodePtr(); + LDR(R0, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions)); + ORR(R0, R0, EXCEPTION_FPU_UNAVAILABLE); + STR(R9, R0, STRUCT_OFF(PowerPC::ppcState, Exceptions)); + QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions); + LDR(R0, R9, STRUCT_OFF(PowerPC::ppcState, npc)); + STR(R9, R0, STRUCT_OFF(PowerPC::ppcState, pc)); + B(dispatcher); + + SetJumpTarget(bail); + doTiming = GetCodePtr(); + // XXX: In JIT64, Advance() gets called /after/ the exception checking + // once it jumps back to the start of outerLoop + QuickCallFunction(R14, (void*)&CoreTiming::Advance); + + // Does exception checking + testExceptions = GetCodePtr(); + LDR(R0, R9, STRUCT_OFF(PowerPC::ppcState, pc)); + STR(R9, R0, STRUCT_OFF(PowerPC::ppcState, npc)); + QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions); + LDR(R0, R9, STRUCT_OFF(PowerPC::ppcState, npc)); + STR(R9, R0, STRUCT_OFF(PowerPC::ppcState, pc)); + // Check the state pointer to see if we are exiting + // Gets checked on every exception check + MOVI2R(R0, (u32)PowerPC::GetStatePtr()); + MVN(R1, 0); + LDR(R0, R0); + TST(R0, R1); + FixupBranch Exit = B_CC(CC_NEQ); + + SetJumpTarget(NextBlock); + B(dispatcher); + + SetJumpTarget(Exit); + + POP(2, R11, _PC); + FlushIcache(); +} + +void JitArmAsmRoutineManager::GenerateCommon() +{ +/* fifoDirectWrite8 = AlignCode4(); + GenFifoWrite(8); + fifoDirectWrite16 = AlignCode4(); + GenFifoWrite(16); + fifoDirectWrite32 = AlignCode4(); + GenFifoWrite(32); + fifoDirectWriteFloat = AlignCode4(); + GenFifoFloatWrite(); + fifoDirectWriteXmm64 = AlignCode4(); + GenFifoXmm64Write(); + + GenQuantizedLoads(); + GenQuantizedStores(); + GenQuantizedSingleStores(); +*/ + //CMPSD(R(XMM0), M(&zero), + // TODO + + // Fast write routines - special case the most common hardware write + // TODO: use this. + // Even in x86, the param values will be in the right registers. + /* + const u8 *fastMemWrite8 = AlignCode16(); + CMP(32, R(ABI_PARAM2), Imm32(0xCC008000)); + FixupBranch skip_fast_write = J_CC(CC_NE, false); + MOV(32, EAX, M(&m_gatherPipeCount)); + MOV(8, MDisp(EAX, (u32)&m_gatherPipe), ABI_PARAM1); + ADD(32, 1, M(&m_gatherPipeCount)); + RET(); + SetJumpTarget(skip_fast_write); + CALL((void *)&Memory::Write_U8);*/ +} diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.h new file mode 100644 index 0000000000..9a61e9e653 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.h @@ -0,0 +1,43 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _JITARMASM_H +#define _JITARMASM_H +#include "ArmEmitter.h" +#include "../JitCommon/JitAsmCommon.h" +using namespace ArmGen; +class JitArmAsmRoutineManager : public CommonAsmRoutinesBase, public ARMXCodeBlock +{ +private: + void Generate(); + void GenerateCommon(); + +public: + void Init() { + AllocCodeSpace(8192); + Generate(); + WriteProtect(); + } + + void Shutdown() { + FreeCodeSpace(); + } +}; + +extern JitArmAsmRoutineManager asm_routines; + +#endif // _JIT64ASM_H diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.cpp new file mode 100644 index 0000000000..9c6ffdbac4 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.cpp @@ -0,0 +1,167 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "JitRegCache.h" + +ArmRegCache::ArmRegCache() +{ + emit = 0; +} + +void ArmRegCache::Init(ARMXEmitter *emitter) +{ + emit = emitter; + ARMReg *PPCRegs = GetPPCAllocationOrder(NUMPPCREG); + ARMReg *Regs = GetAllocationOrder(NUMARMREG); + for(u8 a = 0; a < 32; ++a) + { + // This gives us the memory locations of the gpr registers so we can + // load them. + regs[a].location = (u8*)&PowerPC::ppcState.gpr[a]; + regs[a].UsesLeft = 0; + } + for(u8 a = 0; a < NUMPPCREG; ++a) + { + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].Reg = PPCRegs[a]; + ArmCRegs[a].LastLoad = 0; + } + for(u8 a = 0; a < NUMARMREG; ++a) + { + ArmRegs[a].Reg = Regs[a]; + ArmRegs[a].free = true; + } +} +void ArmRegCache::Start(PPCAnalyst::BlockRegStats &stats) +{ + for(u8 a = 0; a < NUMPPCREG; ++a) + { + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].LastLoad = 0; + } + for(u8 a = 0; a < 32; ++a) + regs[a].UsesLeft = stats.GetTotalNumAccesses(a); +} +ARMReg *ArmRegCache::GetPPCAllocationOrder(int &count) +{ + // This will return us the allocation order of the registers we can use on + // the ppc side. + static ARMReg allocationOrder[] = + { + R0, R1, R2, R3, R4, R5, R6, R7, R8 + }; + count = sizeof(allocationOrder) / sizeof(const int); + return allocationOrder; +} +ARMReg *ArmRegCache::GetAllocationOrder(int &count) +{ + // This will return us the allocation order of the registers we can use on + // the host side. + static ARMReg allocationOrder[] = + { + R14, R12, R11, R10 + }; + count = sizeof(allocationOrder) / sizeof(const int); + return allocationOrder; +} + +ARMReg ArmRegCache::GetReg(bool AutoLock) +{ + for(u8 a = 0; a < NUMARMREG; ++a) + if(ArmRegs[a].free) + { + // Alright, this one is free + if (AutoLock) + ArmRegs[a].free = false; + return ArmRegs[a].Reg; + } + // Uh Oh, we have all them locked.... + _assert_msg_(_DYNA_REC_, false, "All available registers are locked dumb dumb"); + return R0; +} +void ArmRegCache::Lock(ARMReg Reg) +{ + for(u8 RegNum = 0; RegNum < NUMARMREG; ++RegNum) + if(ArmRegs[RegNum].Reg == Reg) + { + _assert_msg_(_DYNA_REC, ArmRegs[RegNum].free, "This register is already locked"); + ArmRegs[RegNum].free = false; + } + _assert_msg_(_DYNA_REC, false, "Register %d can't be used with lock", Reg); +} +void ArmRegCache::Unlock(ARMReg R0, ARMReg R1, ARMReg R2, ARMReg R3) +{ + for(u8 RegNum = 0; RegNum < NUMARMREG; ++RegNum) + { + if(ArmRegs[RegNum].Reg == R0) + { + _assert_msg_(_DYNA_REC, !ArmRegs[RegNum].free, "This register is already unlocked"); + ArmRegs[RegNum].free = true; + } + if( R1 != INVALID_REG && ArmRegs[RegNum].Reg == R1) ArmRegs[RegNum].free = true; + if( R2 != INVALID_REG && ArmRegs[RegNum].Reg == R2) ArmRegs[RegNum].free = true; + if( R3 != INVALID_REG && ArmRegs[RegNum].Reg == R3) ArmRegs[RegNum].free = true; + } +} + +ARMReg ArmRegCache::R(u32 preg) +{ + u32 HighestUsed = 0; + u8 Num = 0; + for(u8 a = 0; a < NUMPPCREG; ++a){ + ++ArmCRegs[a].LastLoad; + if (ArmCRegs[a].LastLoad > HighestUsed) + { + HighestUsed = ArmCRegs[a].LastLoad; + Num = a; + } + } + // Check if already Loaded + for(u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg == preg) + { + ArmCRegs[a].LastLoad = 0; + return ArmCRegs[a].Reg; + } + // Check if we have a free register + for (u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg == 33) + { + emit->LDR(ArmCRegs[a].Reg, R9, STRUCT_OFF(PowerPC::ppcState, gpr) + preg * 4); + ArmCRegs[a].PPCReg = preg; + ArmCRegs[a].LastLoad = 0; + return ArmCRegs[a].Reg; + } + // Alright, we couldn't get a free space, dump that least used register + emit->STR(R9, ArmCRegs[Num].Reg, STRUCT_OFF(PowerPC::ppcState, gpr) + ArmCRegs[Num].PPCReg * 4); + emit->LDR(ArmCRegs[Num].Reg, R9, STRUCT_OFF(PowerPC::ppcState, gpr) + preg * 4); + ArmCRegs[Num].PPCReg = preg; + ArmCRegs[Num].LastLoad = 0; + return ArmCRegs[Num].Reg; +} + +void ArmRegCache::Flush() +{ + for(u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg != 33) + { + emit->STR(R9, ArmCRegs[a].Reg, STRUCT_OFF(PowerPC::ppcState, gpr) + ArmCRegs[a].PPCReg * 4); + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].LastLoad = 0; + } +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.h new file mode 100644 index 0000000000..7292ce1581 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.h @@ -0,0 +1,92 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _JITARMREGCACHE_H +#define _JITARMREGCACHE_H + +#include "ArmEmitter.h" +#include "../Gekko.h" +#include "../PPCAnalyst.h" + +using namespace ArmGen; +// This ARM Register cache actually pre loads the most used registers before +// the block to increase speed since every memory load requires two +// instructions to load it. We are going to use R0-RMAX as registers for the +// use of PPC Registers. +// Allocation order as follows +#define ARMREGS 16 +// Allocate R0 to R9 for PPC first. +// For General registers on the host side, start with R14 and go down as we go +// R13 is reserved for our stack pointer, don't ever use that. Unless you save +// it +// So we have R14, R12, R11, R10 to work with instructions + +struct PPCCachedReg +{ + const u8 *location; + u32 UsesLeft; +}; +struct JRCPPC +{ + u32 PPCReg; // Tied to which PPC Register + bool PS1; + ARMReg Reg; // Tied to which ARM Register + u32 LastLoad; +}; +struct JRCReg +{ + ARMReg Reg; // Which reg this is. + bool free; +}; +class ArmRegCache +{ +private: + PPCCachedReg regs[32]; + JRCPPC ArmCRegs[ARMREGS]; + JRCReg ArmRegs[ARMREGS]; // Four registers remaining + + int NUMPPCREG; + int NUMARMREG; + + ARMReg *GetAllocationOrder(int &count); + ARMReg *GetPPCAllocationOrder(int &count); + +protected: + ARMXEmitter *emit; + +public: + ArmRegCache(); + ~ArmRegCache() {} + + void Init(ARMXEmitter *emitter); + void Start(PPCAnalyst::BlockRegStats &stats); + + void SetEmitter(ARMXEmitter *emitter) {emit = emitter;} + + ARMReg GetReg(bool AutoLock = true); // Return a ARM register we can use. + void Lock(ARMReg reg); + void Unlock(ARMReg R0, ARMReg R1 = INVALID_REG, ARMReg R2 = INVALID_REG, ARMReg R3 = + INVALID_REG); + void Flush(); + ARMReg R(u32 preg); // Returns a cached register + +}; + + + + +#endif diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp index 34b9a681e9..7f509dbf0e 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp @@ -15,7 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "CPUDetect.h" #include "x64Emitter.h" @@ -26,7 +26,7 @@ #include "../../CoreTiming.h" #include "MemoryUtil.h" -#include "ABI.h" +#include "x64ABI.h" #include "../JitCommon/JitCache.h" #include "../../HW/GPFifo.h" diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h index cbec27d2aa..a610a03326 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h @@ -21,16 +21,8 @@ #include "../JitCommon/Jit_Util.h" #include "Thunk.h" -class CommonAsmRoutines : public EmuCodeBlock { -protected: - void GenQuantizedLoads(); - void GenQuantizedStores(); - void GenQuantizedSingleStores(); - +class CommonAsmRoutinesBase { public: - void GenFifoWrite(int size); - void GenFifoXmm64Write(); - void GenFifoFloatWrite(); const u8 *fifoDirectWrite8; const u8 *fifoDirectWrite16; @@ -72,8 +64,23 @@ public: // In: XMM0: Bottom 32-bit slot holds the float to be written. const u8 **singleStoreQuantized; +}; + +class CommonAsmRoutines : public CommonAsmRoutinesBase, public EmuCodeBlock +{ +protected: + void GenQuantizedLoads(); + void GenQuantizedStores(); + void GenQuantizedSingleStores(); + +public: + void GenFifoWrite(int size); + void GenFifoXmm64Write(); + void GenFifoFloatWrite(); + private: ThunkManager thunks; + }; #endif diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp index 3042cfedba..76e791a94c 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp @@ -25,7 +25,7 @@ #include "../../HW/Memmap.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "x64Analyzer.h" @@ -160,7 +160,7 @@ const u8 *TrampolineCache::GetWriteTrampoline(const InstructionInfo &info) // 1) It's really necessary. We don't know anything about the context. // 2) It doesn't really hurt. Only instructions that access I/O will get these, and there won't be // that many of them in a typical program/game. -const u8 *JitBase::BackPatch(u8 *codePtr, int accessType, u32 emAddress, void *ctx_void) +const u8 *Jitx86Base::BackPatch(u8 *codePtr, int accessType, u32 emAddress, void *ctx_void) { #ifdef _M_X64 CONTEXT *ctx = (CONTEXT *)ctx_void; diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h index 4b880eb86d..871a112c6c 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h @@ -34,6 +34,9 @@ // from the real context. struct CONTEXT { + #ifdef _M_ARM + u32 reg_pc; + #else #ifdef _M_X64 u64 Rip; u64 Rax; @@ -41,6 +44,7 @@ u32 Eip; u32 Eax; #endif + #endif }; #endif diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h index 5352c06d04..158171be0f 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h @@ -32,12 +32,9 @@ #define JIT_OPCODE 0 -class JitBase : public CPUCoreBase, public EmuCodeBlock +class JitBase : public CPUCoreBase { protected: - JitBlockCache blocks; - TrampolineCache trampolines; - struct JitOptions { bool optimizeStack; @@ -85,14 +82,29 @@ public: // This should probably be removed from public: JitOptions jo; JitState js; - - JitBlockCache *GetBlockCache() { return &blocks; } + + virtual JitBaseBlockCache *GetBlockCache() = 0; virtual void Jit(u32 em_address) = 0; + virtual const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx) = 0; + + virtual const CommonAsmRoutinesBase *GetAsmRoutines() = 0; + + virtual bool IsInCodeSpace(u8 *ptr) = 0; +}; + +class Jitx86Base : public JitBase, public EmuCodeBlock +{ +protected: + JitBlockCache blocks; + TrampolineCache trampolines; +public: + JitBlockCache *GetBlockCache() { return &blocks; } + const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx); - virtual const CommonAsmRoutines *GetAsmRoutines() = 0; + bool IsInCodeSpace(u8 *ptr) { return IsInSpace(ptr); } }; extern JitBase *jit; diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp index d409518bf9..415b37ca61 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp @@ -32,15 +32,13 @@ #include "MemoryUtil.h" #include "../../HW/Memmap.h" +#include "../JitInterface.h" #include "../../CoreTiming.h" #include "../PowerPC.h" #include "../PPCTables.h" #include "../PPCAnalyst.h" -#include "x64Emitter.h" -#include "x64Analyzer.h" - #include "JitCache.h" #include "JitBase.h" @@ -68,12 +66,12 @@ bool JitBlock::ContainsAddress(u32 em_address) return (em_address >= originalAddress && em_address < originalAddress + 4 * originalSize); } - bool JitBlockCache::IsFull() const + bool JitBaseBlockCache::IsFull() const { return GetNumBlocks() >= MAX_NUM_BLOCKS - 1; } - void JitBlockCache::Init() + void JitBaseBlockCache::Init() { MAX_NUM_BLOCKS = 65536*2; @@ -91,11 +89,11 @@ bool JitBlock::ContainsAddress(u32 em_address) } else { - PanicAlert("JitBlockCache::Init() - iCache is already initialized"); + PanicAlert("JitBaseBlockCache::Init() - iCache is already initialized"); } if (iCache == 0 || iCacheEx == 0 || iCacheVMEM == 0) { - PanicAlert("JitBlockCache::Init() - unable to allocate iCache"); + PanicAlert("JitBaseBlockCache::Init() - unable to allocate iCache"); } memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE); memset(iCacheEx, JIT_ICACHE_INVALID_BYTE, JIT_ICACHEEX_SIZE); @@ -104,7 +102,7 @@ bool JitBlock::ContainsAddress(u32 em_address) Clear(); } - void JitBlockCache::Shutdown() + void JitBaseBlockCache::Shutdown() { delete[] blocks; delete[] blockCodePointers; @@ -133,7 +131,7 @@ bool JitBlock::ContainsAddress(u32 em_address) // This clears the JIT cache. It's called from JitCache.cpp when the JIT cache // is full and when saving and loading states. - void JitBlockCache::Clear() + void JitBaseBlockCache::Clear() { if (IsFull()) Core::DisplayMessage("Clearing block cache.", 3000); @@ -151,7 +149,7 @@ bool JitBlock::ContainsAddress(u32 em_address) memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS); } - void JitBlockCache::ClearSafe() + void JitBaseBlockCache::ClearSafe() { #ifdef JIT_UNLIMITED_ICACHE memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE); @@ -160,7 +158,7 @@ bool JitBlock::ContainsAddress(u32 em_address) #endif } - /*void JitBlockCache::DestroyBlocksWithFlag(BlockFlag death_flag) + /*void JitBaseBlockCache::DestroyBlocksWithFlag(BlockFlag death_flag) { for (int i = 0; i < num_blocks; i++) { @@ -171,23 +169,23 @@ bool JitBlock::ContainsAddress(u32 em_address) } }*/ - void JitBlockCache::Reset() + void JitBaseBlockCache::Reset() { Shutdown(); Init(); } - JitBlock *JitBlockCache::GetBlock(int no) + JitBlock *JitBaseBlockCache::GetBlock(int no) { return &blocks[no]; } - int JitBlockCache::GetNumBlocks() const + int JitBaseBlockCache::GetNumBlocks() const { return num_blocks; } - bool JitBlockCache::RangeIntersect(int s1, int e1, int s2, int e2) const + bool JitBaseBlockCache::RangeIntersect(int s1, int e1, int s2, int e2) const { // check if any endpoint is inside the other range if ((s1 >= s2 && s1 <= e2) || @@ -199,7 +197,7 @@ bool JitBlock::ContainsAddress(u32 em_address) return false; } - int JitBlockCache::AllocateBlock(u32 em_address) + int JitBaseBlockCache::AllocateBlock(u32 em_address) { JitBlock &b = blocks[num_blocks]; b.invalid = false; @@ -215,12 +213,12 @@ bool JitBlock::ContainsAddress(u32 em_address) return num_blocks - 1; } - void JitBlockCache::FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr) + void JitBaseBlockCache::FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr) { blockCodePointers[block_num] = code_ptr; JitBlock &b = blocks[block_num]; - b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress); - Memory::Write_Opcode_JIT(b.originalAddress, (JIT_OPCODE << 26) | block_num); + b.originalFirstOpcode = JitInterface::Read_Opcode_JIT(b.originalAddress); + JitInterface::Write_Opcode_JIT(b.originalAddress, (JIT_OPCODE << 26) | block_num); // Convert the logical address to a physical address for the block map u32 pAddr = b.originalAddress & 0x1FFFFFFF; @@ -264,29 +262,29 @@ bool JitBlock::ContainsAddress(u32 em_address) #endif } - const u8 **JitBlockCache::GetCodePointers() + const u8 **JitBaseBlockCache::GetCodePointers() { return blockCodePointers; } #ifdef JIT_UNLIMITED_ICACHE - u8* JitBlockCache::GetICache() + u8* JitBaseBlockCache::GetICache() { return iCache; } - u8* JitBlockCache::GetICacheEx() + u8* JitBaseBlockCache::GetICacheEx() { return iCacheEx; } - u8* JitBlockCache::GetICacheVMEM() + u8* JitBaseBlockCache::GetICacheVMEM() { return iCacheVMEM; } #endif - int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr) + int JitBaseBlockCache::GetBlockNumberFromStartAddress(u32 addr) { if (!blocks) return -1; @@ -317,24 +315,24 @@ bool JitBlock::ContainsAddress(u32 em_address) return inst; } - void JitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector *block_numbers) + void JitBaseBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector *block_numbers) { for (int i = 0; i < num_blocks; i++) if (blocks[i].ContainsAddress(em_address)) block_numbers->push_back(i); } - u32 JitBlockCache::GetOriginalFirstOp(int block_num) + u32 JitBaseBlockCache::GetOriginalFirstOp(int block_num) { if (block_num >= num_blocks) { - //PanicAlert("JitBlockCache::GetOriginalFirstOp - block_num = %u is out of range", block_num); + //PanicAlert("JitBaseBlockCache::GetOriginalFirstOp - block_num = %u is out of range", block_num); return block_num; } return blocks[block_num].originalFirstOpcode; } - CompiledCode JitBlockCache::GetCompiledCodeFromBlock(int block_num) + CompiledCode JitBaseBlockCache::GetCompiledCodeFromBlock(int block_num) { return (CompiledCode)blockCodePointers[block_num]; } @@ -345,7 +343,7 @@ bool JitBlock::ContainsAddress(u32 em_address) //Can be faster by doing a queue for blocks to link up, and only process those //Should probably be done - void JitBlockCache::LinkBlockExits(int i) + void JitBaseBlockCache::LinkBlockExits(int i) { JitBlock &b = blocks[i]; if (b.invalid) @@ -360,8 +358,7 @@ bool JitBlock::ContainsAddress(u32 em_address) int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]); if (destinationBlock != -1) { - XEmitter emit(b.exitPtrs[e]); - emit.JMP(blocks[destinationBlock].checkedEntry, true); + WriteLinkBlock(b.exitPtrs[e], blocks[destinationBlock].checkedEntry); b.linkStatus[e] = true; } } @@ -370,7 +367,7 @@ bool JitBlock::ContainsAddress(u32 em_address) using namespace std; - void JitBlockCache::LinkBlock(int i) + void JitBaseBlockCache::LinkBlock(int i) { LinkBlockExits(i); JitBlock &b = blocks[i]; @@ -386,7 +383,7 @@ bool JitBlock::ContainsAddress(u32 em_address) } } - void JitBlockCache::UnlinkBlock(int i) + void JitBaseBlockCache::UnlinkBlock(int i) { JitBlock &b = blocks[i]; pair::iterator, multimap::iterator> ppp; @@ -403,7 +400,7 @@ bool JitBlock::ContainsAddress(u32 em_address) } } - void JitBlockCache::DestroyBlock(int block_num, bool invalidate) + void JitBaseBlockCache::DestroyBlock(int block_num, bool invalidate) { if (block_num < 0 || block_num >= num_blocks) { @@ -419,7 +416,7 @@ bool JitBlock::ContainsAddress(u32 em_address) } b.invalid = true; #ifdef JIT_UNLIMITED_ICACHE - Memory::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode?b.originalFirstOpcode:JIT_ICACHE_INVALID_WORD); + JitInterface::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode?b.originalFirstOpcode:JIT_ICACHE_INVALID_WORD); #else if (Memory::ReadFast32(b.originalAddress) == block_num) Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress); @@ -430,18 +427,10 @@ bool JitBlock::ContainsAddress(u32 em_address) // Send anyone who tries to run this block back to the dispatcher. // Not entirely ideal, but .. pretty good. // Spurious entrances from previously linked blocks can only come through checkedEntry - XEmitter emit((u8 *)b.checkedEntry); - emit.MOV(32, M(&PC), Imm32(b.originalAddress)); - emit.JMP(jit->GetAsmRoutines()->dispatcher, true); - // this is not needed really - /* - emit.SetCodePtr((u8 *)blockCodePointers[blocknum]); - emit.MOV(32, M(&PC), Imm32(b.originalAddress)); - emit.JMP(asm_routines.dispatcher, true); - */ + WriteDestroyBlock(b.checkedEntry, b.originalAddress); } - void JitBlockCache::InvalidateICache(u32 address, const u32 length) + void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length) { // Convert the logical address to a physical address for the block map u32 pAddr = address & 0x1FFFFFFF; @@ -449,7 +438,7 @@ bool JitBlock::ContainsAddress(u32 em_address) // Optimize the common case of length == 32 which is used by Interpreter::dcb* bool destroy_block = true; if (length == 32) - { + { if (!valid_block[pAddr / 32]) destroy_block = false; else @@ -462,7 +451,7 @@ bool JitBlock::ContainsAddress(u32 em_address) { std::map, u32>::iterator it1 = block_map.lower_bound(std::make_pair(pAddr, 0)), it2 = it1; while (it2 != block_map.end() && it2->first.second < pAddr + length) - { + { #ifdef JIT_UNLIMITED_ICACHE JitBlock &b = blocks[it2->second]; if (b.originalAddress & JIT_ICACHE_VMEM_BIT) @@ -516,3 +505,14 @@ bool JitBlock::ContainsAddress(u32 em_address) } #endif } + void JitBlockCache::WriteLinkBlock(u8* location, const u8* address) + { + XEmitter emit(location); + emit.JMP(address, true); + } + void JitBlockCache::WriteDestroyBlock(const u8* location, u32 address) + { + XEmitter emit((u8 *)location); + emit.MOV(32, M(&PC), Imm32(address)); + emit.JMP(jit->GetAsmRoutines()->dispatcher, true); + } diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h index 4214f33875..b148cb8090 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h @@ -78,7 +78,8 @@ struct JitBlock typedef void (*CompiledCode)(); -class JitBlockCache + +class JitBaseBlockCache { const u8 **blockCodePointers; JitBlock *blocks; @@ -97,9 +98,13 @@ class JitBlockCache void LinkBlockExits(int i); void LinkBlock(int i); void UnlinkBlock(int i); + + // Virtual for overloaded + virtual void WriteLinkBlock(u8* location, const u8* address) = 0; + virtual void WriteDestroyBlock(const u8* location, u32 address) = 0; public: - JitBlockCache() : + JitBaseBlockCache() : blockCodePointers(0), blocks(0), num_blocks(0), #ifdef JIT_UNLIMITED_ICACHE iCache(0), iCacheEx(0), iCacheVMEM(0), @@ -146,4 +151,11 @@ public: //void DestroyBlocksWithFlag(BlockFlag death_flag); }; +// x86 BlockCache +class JitBlockCache : public JitBaseBlockCache +{ +private: + void WriteLinkBlock(u8* location, const u8* address); + void WriteDestroyBlock(const u8* location, u32 address); +}; #endif diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp index cc1327c695..f5c4cb022b 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp @@ -25,7 +25,7 @@ #include "../../HW/Memmap.h" #include "../PPCTables.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "JitBase.h" #include "Jit_Util.h" diff --git a/Source/Core/Core/Src/PowerPC/JitInterface.cpp b/Source/Core/Core/Src/PowerPC/JitInterface.cpp new file mode 100644 index 0000000000..8fcdd9837f --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitInterface.cpp @@ -0,0 +1,350 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#ifdef _WIN32 +#include +#endif + +#include "JitInterface.h" +#include "JitCommon/JitBase.h" + +#ifndef _M_GENERIC +#include "Jit64IL/JitIL.h" +#include "Jit64/Jit.h" +#include "Jit64/Jit64_Tables.h" +#include "Jit64IL/JitIL_Tables.h" +#endif + +#ifdef _M_ARM +#include "JitArm32/Jit.h" +#include "JitArm32/JitArm_Tables.h" +#endif + +#include "Profiler.h" +#include "PPCSymbolDB.h" +#include "HW/Memmap.h" +#include "ConfigManager.h" + +bool bFakeVMEM = false; +bool bMMU = false; + +namespace JitInterface +{ + void DoState(PointerWrap &p) + { + if (jit && p.GetMode() == PointerWrap::MODE_READ) + jit->GetBlockCache()->ClearSafe(); + } + CPUCoreBase *InitJitCore(int core) + { + bFakeVMEM = SConfig::GetInstance().m_LocalCoreStartupParameter.iTLBHack == 1; + bMMU = SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU; + + CPUCoreBase *ptr = NULL; + switch(core) + { + #ifndef _M_GENERIC + case 1: + { + ptr = new Jit64(); + break; + } + case 2: + { + ptr = new JitIL(); + break; + } + #endif + #ifdef _M_ARM + case 3: + { + ptr = new JitArm(); + break; + } + #endif + default: + { + PanicAlert("Unrecognizable cpu_core: %d", core); + return NULL; + break; + } + } + jit = static_cast(ptr); + jit->Init(); + return ptr; + } + void InitTables(int core) + { + switch(core) + { + #ifndef _M_GENERIC + case 1: + { + Jit64Tables::InitTables(); + break; + } + case 2: + { + JitILTables::InitTables(); + break; + } + #endif + #ifdef _M_ARM + case 3: + { + JitArmTables::InitTables(); + break; + } + #endif + default: + { + PanicAlert("Unrecognizable cpu_core: %d", core); + break; + } + } + } + CPUCoreBase *GetCore() + { + return jit; + } + + void WriteProfileResults(const char *filename) + { + // Can't really do this with no jit core available + #ifndef _M_GENERIC + + std::vector stats; + stats.reserve(jit->GetBlockCache()->GetNumBlocks()); + u64 cost_sum = 0; + #ifdef _WIN32 + u64 timecost_sum = 0; + u64 countsPerSec; + QueryPerformanceFrequency((LARGE_INTEGER *)&countsPerSec); + #endif + for (int i = 0; i < jit->GetBlockCache()->GetNumBlocks(); i++) + { + const JitBlock *block = jit->GetBlockCache()->GetBlock(i); + // Rough heuristic. Mem instructions should cost more. + u64 cost = block->originalSize * (block->runCount / 4); + #ifdef _WIN32 + u64 timecost = block->ticCounter; + #endif + // Todo: tweak. + if (block->runCount >= 1) + stats.push_back(BlockStat(i, cost)); + cost_sum += cost; + #ifdef _WIN32 + timecost_sum += timecost; + #endif + } + + sort(stats.begin(), stats.end()); + File::IOFile f(filename, "w"); + if (!f) + { + PanicAlert("failed to open %s", filename); + return; + } + fprintf(f.GetHandle(), "origAddr\tblkName\tcost\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n"); + for (unsigned int i = 0; i < stats.size(); i++) + { + const JitBlock *block = jit->GetBlockCache()->GetBlock(stats[i].blockNum); + if (block) + { + std::string name = g_symbolDB.GetDescription(block->originalAddress); + double percent = 100.0 * (double)stats[i].cost / (double)cost_sum; + #ifdef _WIN32 + double timePercent = 100.0 * (double)block->ticCounter / (double)timecost_sum; + fprintf(f.GetHandle(), "%08x\t%s\t%llu\t%llu\t%.2lf\t%llf\t%lf\t%i\n", + block->originalAddress, name.c_str(), stats[i].cost, + block->ticCounter, percent, timePercent, + (double)block->ticCounter*1000.0/(double)countsPerSec, block->codeSize); + #else + fprintf(f.GetHandle(), "%08x\t%s\t%llu\t???\t%.2lf\t???\t???\t%i\n", + block->originalAddress, name.c_str(), stats[i].cost, percent, block->codeSize); + #endif + } + } + #endif + } + bool IsInCodeSpace(u8 *ptr) + { + return jit->IsInCodeSpace(ptr); + } + const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx) + { + return jit->BackPatch(codePtr, accessType, em_address, ctx); + } + + void ClearCache() + { + if (jit) + jit->ClearCache(); + } + void ClearSafe() + { + if (jit) + jit->GetBlockCache()->ClearSafe(); + } + + void InvalidateICache(u32 address, u32 size) + { + if (jit) + jit->GetBlockCache()->InvalidateICache(address, size); + } + + + // Memory functions + u32 Read_Opcode_JIT_Uncached(const u32 _Address) + { + u8* iCache; + u32 addr; + if (_Address & JIT_ICACHE_VMEM_BIT) + { + iCache = jit->GetBlockCache()->GetICacheVMEM(); + addr = _Address & JIT_ICACHE_MASK; + } + else if (_Address & JIT_ICACHE_EXRAM_BIT) + { + iCache = jit->GetBlockCache()->GetICacheEx(); + addr = _Address & JIT_ICACHEEX_MASK; + } + else + { + iCache = jit->GetBlockCache()->GetICache(); + addr = _Address & JIT_ICACHE_MASK; + } + u32 inst = *(u32*)(iCache + addr); + if (inst == JIT_ICACHE_INVALID_WORD) + { + u32 cache_block_start = addr & ~0x1f; + u32 mem_block_start = _Address & ~0x1f; + u8 *pMem = Memory::GetPointer(mem_block_start); + memcpy(iCache + cache_block_start, pMem, 32); + inst = *(u32*)(iCache + addr); + } + inst = Common::swap32(inst); + + if ((inst & 0xfc000000) == 0) + { + inst = jit->GetBlockCache()->GetOriginalFirstOp(inst); + } + + return inst; + } + + u32 Read_Opcode_JIT(u32 _Address) + { + #ifdef FAST_ICACHE + if (bMMU && !bFakeVMEM && (_Address & Memory::ADDR_MASK_MEM1)) + { + _Address = Memory::TranslateAddress(_Address, Memory::FLAG_OPCODE); + if (_Address == 0) + { + return 0; + } + } + u32 inst = 0; + + // Bypass the icache for the external interrupt exception handler + if ( (_Address & 0x0FFFFF00) == 0x00000500 ) + inst = Read_Opcode_JIT_Uncached(_Address); + else + inst = PowerPC::ppcState.iCache.ReadInstruction(_Address); + #else + u32 inst = Memory::ReadUnchecked_U32(_Address); + #endif + return inst; + } + + // The following function is deprecated in favour of FAST_ICACHE + u32 Read_Opcode_JIT_LC(const u32 _Address) + { + #ifdef JIT_UNLIMITED_ICACHE + if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 && + (_Address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area + (_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000) + { + PanicAlertT("iCacheJIT: Reading Opcode from %x. Please report.", _Address); + ERROR_LOG(MEMMAP, "iCacheJIT: Reading Opcode from %x. Please report.", _Address); + return 0; + } + u8* iCache; + u32 addr; + if (_Address & JIT_ICACHE_VMEM_BIT) + { + iCache = jit->GetBlockCache()->GetICacheVMEM(); + addr = _Address & JIT_ICACHE_MASK; + } + else if (_Address & JIT_ICACHE_EXRAM_BIT) + { + iCache = jit->GetBlockCache()->GetICacheEx(); + addr = _Address & JIT_ICACHEEX_MASK; + } + else + { + iCache = jit->GetBlockCache()->GetICache(); + addr = _Address & JIT_ICACHE_MASK; + } + u32 inst = *(u32*)(iCache + addr); + if (inst == JIT_ICACHE_INVALID_WORD) + inst = Memory::ReadUnchecked_U32(_Address); + else + inst = Common::swap32(inst); + #else + u32 inst = Memory::ReadUnchecked_U32(_Address); + #endif + if ((inst & 0xfc000000) == 0) + { + inst = jit->GetBlockCache()->GetOriginalFirstOp(inst); + } + return inst; + } + + // WARNING! No checks! + // We assume that _Address is cached + void Write_Opcode_JIT(const u32 _Address, const u32 _Value) + { + #ifdef JIT_UNLIMITED_ICACHE + if (_Address & JIT_ICACHE_VMEM_BIT) + { + *(u32*)(jit->GetBlockCache()->GetICacheVMEM() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value); + } + else if (_Address & JIT_ICACHE_EXRAM_BIT) + { + *(u32*)(jit->GetBlockCache()->GetICacheEx() + (_Address & JIT_ICACHEEX_MASK)) = Common::swap32(_Value); + } + else + *(u32*)(jit->GetBlockCache()->GetICache() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value); + #else + Memory::WriteUnchecked_U32(_Value, _Address); + #endif + } + + + void Shutdown() + { + if (jit) + { + jit->Shutdown(); + delete jit; + jit = NULL; + } + } +} diff --git a/Source/Core/Core/Src/PowerPC/JitInterface.h b/Source/Core/Core/Src/PowerPC/JitInterface.h new file mode 100644 index 0000000000..a01c3dfa6e --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitInterface.h @@ -0,0 +1,56 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "ChunkFile.h" +#include "CPUCoreBase.h" + +namespace JitInterface +{ + void DoState(PointerWrap &p); + + CPUCoreBase *InitJitCore(int core); + void InitTables(int core); + CPUCoreBase *GetCore(); + + // Debugging + void WriteProfileResults(const char *filename); + + // Memory Utilities + bool IsInCodeSpace(u8 *ptr); + const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx); + + // used by JIT to read instructions + u32 Read_Opcode_JIT(const u32 _Address); + // used by JIT. uses iCacheJIT. Reads in the "Locked cache" mode + u32 Read_Opcode_JIT_LC(const u32 _Address); + void Write_Opcode_JIT(const u32 _Address, const u32 _Value); + + // Clearing CodeCache + void ClearCache(); + + void ClearSafe(); + + void InvalidateICache(u32 address, u32 size); + + void Shutdown(); +} +extern bool bFakeVMEM; +extern bool bMMU; + +#ifdef _M_ARM +#include "JitArm32/Jit.h" +#endif diff --git a/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp index fa9f278c29..15a85568de 100644 --- a/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp @@ -21,6 +21,7 @@ #include "StringUtil.h" #include "Interpreter/Interpreter.h" #include "../HW/Memmap.h" +#include "JitInterface.h" #include "PPCTables.h" #include "PPCSymbolDB.h" #include "SignatureDB.h" @@ -368,7 +369,7 @@ u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa, } else { - inst = Memory::Read_Opcode_JIT(address); + inst = JitInterface::Read_Opcode_JIT(address); } } diff --git a/Source/Core/Core/Src/PowerPC/PPCCache.cpp b/Source/Core/Core/Src/PowerPC/PPCCache.cpp index 6956e9db1c..a0e4c666a4 100644 --- a/Source/Core/Core/Src/PowerPC/PPCCache.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCCache.cpp @@ -20,6 +20,7 @@ #include "PowerPC.h" #include "JitCommon/JitBase.h" #include "JitCommon/JitCache.h" +#include "JitInterface.h" namespace PowerPC { @@ -76,8 +77,7 @@ namespace PowerPC memset(lookup_table_ex, 0xff, sizeof(lookup_table_ex)); memset(lookup_table_vmem, 0xff, sizeof(lookup_table_vmem)); #endif - if (jit) - jit->GetBlockCache()->ClearSafe(); + JitInterface::ClearSafe(); } void InstructionCache::Init() @@ -109,8 +109,7 @@ namespace PowerPC } #endif valid[set] = 0; - if (jit) - jit->GetBlockCache()->InvalidateICache(addr & ~0x1f, 32); + JitInterface::InvalidateICache(addr & ~0x1f, 32); } u32 InstructionCache::ReadInstruction(u32 addr) diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.cpp b/Source/Core/Core/Src/PowerPC/PPCTables.cpp index d96089cebb..a6975f5860 100644 --- a/Source/Core/Core/Src/PowerPC/PPCTables.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCTables.cpp @@ -24,11 +24,7 @@ #include "FileUtil.h" #include "Interpreter/Interpreter.h" #include "Interpreter/Interpreter_Tables.h" -#include "Jit64IL/JitIL_Tables.h" -#include "Jit64/Jit64_Tables.h" - -#include "Jit64IL/JitIL.h" -#include "Jit64/Jit.h" +#include "JitInterface.h" struct op_inf { @@ -165,19 +161,9 @@ void InitTables(int cpu_core) // Interpreter break; } - case 1: - { - Jit64Tables::InitTables(); - break; - } - case 2: - { - JitILTables::InitTables(); - break; - } default: { - PanicAlert("Unrecognizable cpu_core: %d", cpu_core); + JitInterface::InitTables(cpu_core); break; } } diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.cpp b/Source/Core/Core/Src/PowerPC/PowerPC.cpp index 8a7b817212..d4447331e7 100644 --- a/Source/Core/Core/Src/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/Src/PowerPC/PowerPC.cpp @@ -29,12 +29,10 @@ #include "../HW/SystemTimers.h" #include "Interpreter/Interpreter.h" -#include "JitCommon/JitBase.h" -#include "Jit64IL/JitIL.h" -#include "Jit64/Jit.h" #include "PowerPC.h" #include "PPCTables.h" #include "CPUCoreBase.h" +#include "JitInterface.h" #include "../Host.h" #include "HW/EXI.h" @@ -87,8 +85,7 @@ void DoState(PointerWrap &p) // SystemTimers::DecrementerSet(); // SystemTimers::TimeBaseSet(); - if (jit && p.GetMode() == PointerWrap::MODE_READ) - jit->GetBlockCache()->ClearSafe(); + JitInterface::DoState(p); } void ResetRegisters() @@ -131,28 +128,18 @@ void ResetRegisters() void Init(int cpu_core) { - enum { - FPU_PREC_24 = 0 << 8, - FPU_PREC_53 = 2 << 8, - FPU_PREC_64 = 3 << 8, - FPU_PREC_MASK = 3 << 8, - }; -#ifdef _M_IX86 - // sets the floating-point lib to 53-bit - // PowerPC has a 53bit floating pipeline only - // eg: sscanf is very sensitive -#ifdef _WIN32 - _control87(_PC_53, MCW_PC); -#else - unsigned short _mode; - asm ("fstcw %0" : : "m" (_mode)); - _mode = (_mode & ~FPU_PREC_MASK) | FPU_PREC_53; - asm ("fldcw %0" : : "m" (_mode)); -#endif -#else - //x64 doesn't need this - fpu is done with SSE - //but still - set any useful sse options here -#endif + FPURoundMode::SetPrecisionMode(FPURoundMode::PREC_53); + + memset(ppcState.mojs, 0, sizeof(ppcState.mojs)); + memset(ppcState.sr, 0, sizeof(ppcState.sr)); + ppcState.DebugCount = 0; + ppcState.dtlb_last = 0; + ppcState.dtlb_last = 0; + memset(ppcState.dtlb_va, 0, sizeof(ppcState.dtlb_va)); + memset(ppcState.dtlb_pa, 0, sizeof(ppcState.dtlb_pa)); + ppcState.itlb_last = 0; + memset(ppcState.itlb_va, 0, sizeof(ppcState.itlb_va)); + memset(ppcState.itlb_pa, 0, sizeof(ppcState.itlb_pa)); memset(ppcState.mojs, 0, sizeof(ppcState.mojs)); memset(ppcState.sr, 0, sizeof(ppcState.sr)); @@ -179,27 +166,13 @@ void Init(int cpu_core) cpu_core_base = interpreter; break; } - case 1: - { - cpu_core_base = new Jit64(); - break; - } - case 2: - { - cpu_core_base = new JitIL(); - break; - } - default: - { - PanicAlert("Unrecognizable cpu_core: %d", cpu_core); - break; - } + default: + cpu_core_base = JitInterface::InitJitCore(cpu_core); + break; } if (cpu_core_base != interpreter) { - jit = static_cast(cpu_core_base); - jit->Init(); mode = MODE_JIT; } else @@ -213,12 +186,7 @@ void Init(int cpu_core) void Shutdown() { - if (jit) - { - jit->Shutdown(); - delete jit; - jit = NULL; - } + JitInterface::Shutdown(); interpreter->Shutdown(); cpu_core_base = NULL; state = CPU_POWERDOWN; @@ -244,7 +212,7 @@ void SetMode(CoreMode new_mode) case MODE_JIT: // Switching from interpreter to JIT. // Don't really need to do much. It'll work, the cache will refill itself. - cpu_core_base = jit; + cpu_core_base = JitInterface::GetCore(); break; } } diff --git a/Source/Core/Core/Src/PowerPC/Profiler.cpp b/Source/Core/Core/Src/PowerPC/Profiler.cpp index 3636b00717..fc8942f09b 100644 --- a/Source/Core/Core/Src/PowerPC/Profiler.cpp +++ b/Source/Core/Core/Src/PowerPC/Profiler.cpp @@ -15,17 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include "JitCommon/JitBase.h" - -#include -#include - -#ifdef _WIN32 -#include -#endif - -#include "PPCSymbolDB.h" -#include "FileUtil.h" +#include "JitInterface.h" namespace Profiler { @@ -33,73 +23,9 @@ namespace Profiler bool g_ProfileBlocks; bool g_ProfileInstructions; -struct BlockStat -{ - BlockStat(int bn, u64 c) : blockNum(bn), cost(c) {} - int blockNum; - u64 cost; - - bool operator <(const BlockStat &other) const - { return cost > other.cost; } -}; - void WriteProfileResults(const char *filename) { - std::vector stats; - stats.reserve(jit->GetBlockCache()->GetNumBlocks()); - u64 cost_sum = 0; -#ifdef _WIN32 - u64 timecost_sum = 0; - u64 countsPerSec; - QueryPerformanceFrequency((LARGE_INTEGER *)&countsPerSec); -#endif - for (int i = 0; i < jit->GetBlockCache()->GetNumBlocks(); i++) - { - const JitBlock *block = jit->GetBlockCache()->GetBlock(i); - if (block && !block->invalid) - { - // Rough heuristic. Mem instructions should cost more. - u64 cost = block->originalSize * (block->runCount / 4); -#ifdef _WIN32 - u64 timecost = block->ticCounter; -#endif - // Todo: tweak. - if (block->runCount >= 1) - stats.push_back(BlockStat(i, cost)); - cost_sum += cost; -#ifdef _WIN32 - timecost_sum += timecost; -#endif - } - } - - sort(stats.begin(), stats.end()); - File::IOFile f(filename, "w"); - if (!f) - { - PanicAlert("failed to open %s", filename); - return; - } - fprintf(f.GetHandle(), "origAddr\tblkName\tcost\trunCount\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n"); - for (unsigned int i = 0; i < stats.size(); i++) - { - const JitBlock *block = jit->GetBlockCache()->GetBlock(stats[i].blockNum); - if (block && !block->invalid) - { - std::string name = g_symbolDB.GetDescription(block->originalAddress); - double percent = 100.0 * (double)stats[i].cost / (double)cost_sum; -#ifdef _WIN32 - double timePercent = 100.0 * (double)block->ticCounter / (double)timecost_sum; - fprintf(f.GetHandle(), "%08x\t%s\t%llu\t%llu\t%llu\t%.2lf\t%llf\t%lf\t%i\n", - block->originalAddress, name.c_str(), stats[i].cost, block->runCount, - block->ticCounter, percent, timePercent, - (double)block->ticCounter*1000.0/(double)countsPerSec, block->codeSize); -#else - fprintf(f.GetHandle(), "%08x\t%s\t%llu\t???\t%.2lf\t???\t???\t%i\n", - block->originalAddress, name.c_str(), stats[i].cost, percent, block->codeSize); -#endif - } - } + JitInterface::WriteProfileResults(filename); } } // namespace diff --git a/Source/Core/Core/Src/PowerPC/Profiler.h b/Source/Core/Core/Src/PowerPC/Profiler.h index ada130e90f..b8beeaae72 100644 --- a/Source/Core/Core/Src/PowerPC/Profiler.h +++ b/Source/Core/Core/Src/PowerPC/Profiler.h @@ -57,6 +57,15 @@ #define PROFILER_VPOP #endif +struct BlockStat +{ + BlockStat(int bn, u64 c) : blockNum(bn), cost(c) {} + int blockNum; + u64 cost; + + bool operator <(const BlockStat &other) const + { return cost > other.cost; } +}; namespace Profiler { diff --git a/Source/Core/Core/Src/MemTools.cpp b/Source/Core/Core/Src/x64MemTools.cpp similarity index 96% rename from Source/Core/Core/Src/MemTools.cpp rename to Source/Core/Core/Src/x64MemTools.cpp index bb6fef6439..fff26b3cb3 100644 --- a/Source/Core/Core/Src/MemTools.cpp +++ b/Source/Core/Core/Src/x64MemTools.cpp @@ -52,8 +52,10 @@ #include "MemTools.h" #include "HW/Memmap.h" #include "PowerPC/PowerPC.h" +#include "PowerPC/JitInterface.h" +#ifndef _M_GENERIC #include "PowerPC/JitCommon/JitBase.h" -#include "PowerPC/JitCommon/JitBackpatch.h" +#endif #include "x64Analyzer.h" namespace EMM @@ -77,7 +79,7 @@ LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs) PVOID codeAddr = pPtrs->ExceptionRecord->ExceptionAddress; unsigned char *codePtr = (unsigned char*)codeAddr; - if (!jit->IsInCodeSpace(codePtr)) { + if (!JitInterface::IsInCodeSpace(codePtr)) { // Let's not prevent debugging. return (DWORD)EXCEPTION_CONTINUE_SEARCH; } @@ -107,7 +109,7 @@ LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs) //We could emulate the memory accesses here, but then they would still be around to take up //execution resources. Instead, we backpatch into a generic memory call and retry. - const u8 *new_rip = jit->BackPatch(codePtr, accessType, emAddress, ctx); + const u8 *new_rip = JitInterface::BackPatch(codePtr, accessType, emAddress, ctx); // Rip/Eip needs to be updated. if (new_rip) @@ -182,6 +184,7 @@ void print_trace(const char * msg) void sigsegv_handler(int signal, siginfo_t *info, void *raw_context) { +#ifndef _M_GENERIC if (signal != SIGSEGV) { // We are not interested in other signals - handle it as usual. @@ -203,7 +206,7 @@ void sigsegv_handler(int signal, siginfo_t *info, void *raw_context) #else u8 *fault_instruction_ptr = (u8 *)CREG_EIP(ctx); #endif - if (!jit->IsInCodeSpace(fault_instruction_ptr)) { + if (!JitInterface::IsInCodeSpace(fault_instruction_ptr)) { // Let's not prevent debugging. return; } @@ -240,6 +243,7 @@ void sigsegv_handler(int signal, siginfo_t *info, void *raw_context) CREG_EIP(ctx) = fake_ctx.Eip; #endif } +#endif } void InstallExceptionHandler() diff --git a/Source/Core/DiscIO/Src/BannerLoader.cpp b/Source/Core/DiscIO/Src/BannerLoader.cpp index 6451c73670..2350896c9c 100644 --- a/Source/Core/DiscIO/Src/BannerLoader.cpp +++ b/Source/Core/DiscIO/Src/BannerLoader.cpp @@ -27,7 +27,9 @@ #include #else #include +#ifndef ANDROID #include +#endif #include #endif @@ -131,6 +133,9 @@ bool IBannerLoader::CopyBeUnicodeToString( std::string& _rDestination, const u16 delete[] buffer; } } +#else +#ifdef ANDROID + return false; #else if (_src) { @@ -193,6 +198,7 @@ bool IBannerLoader::CopyBeUnicodeToString( std::string& _rDestination, const u16 delete[] src_buffer_start; iconv_close(conv_desc); } +#endif #endif return returnCode; } diff --git a/Source/Core/DolphinWX/CMakeLists.txt b/Source/Core/DolphinWX/CMakeLists.txt index 858e05bbfd..c3cdccccfc 100644 --- a/Source/Core/DolphinWX/CMakeLists.txt +++ b/Source/Core/DolphinWX/CMakeLists.txt @@ -10,21 +10,21 @@ set(LIBS core ${GTK2_LIBRARIES} ${XRANDR_LIBRARIES} ${X11_LIBRARIES}) - -if(SDL2_FOUND) - # Using shared SDL2 - set(LIBS ${LIBS} ${SDL2_LIBRARY}) -else(SDL2_FOUND) - if(SDL_FOUND) - # Using shared SDL - set(LIBS ${LIBS} ${SDL_LIBRARY}) - else(SDL_FOUND) - # Using static SDL from Externals - set(LIBS ${LIBS} SDL) +if(NOT ANDROID) + if(SDL2_FOUND) + # Using shared SDL2 + set(LIBS ${LIBS} ${SDL2_LIBRARY}) + else(SDL2_FOUND) + if(SDL_FOUND) + # Using shared SDL + set(LIBS ${LIBS} ${SDL_LIBRARY}) + else(SDL_FOUND) + # Using static SDL from Externals + set(LIBS ${LIBS} SDL) + endif() endif() endif() - if(LIBAV_FOUND) set(LIBS ${LIBS} ${LIBAV_LIBRARIES}) endif() @@ -79,13 +79,18 @@ if(wxWidgets_FOUND) set(WXLIBS ${wxWidgets_LIBRARIES}) else() - set(SRCS - Src/MainNoGUI.cpp) + if(ANDROID) + set(SRCS Src/MainAndroid.cpp) + else() + set(SRCS Src/MainNoGUI.cpp) + endif() endif() if(USE_EGL) - set(SRCS ${SRCS} Src/GLInterface/EGL.cpp - Src/GLInterface/X11_Util.cpp) + if(NOT ANDROID) + set(SRCS ${SRCS} Src/GLInterface/EGL_X11.cpp + Src/GLInterface/X11_Util.cpp) + endif() else() if(WIN32) set(SRCS ${SRCS} Src/GLInterface/GLW.cpp) @@ -127,7 +132,9 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_source_files_properties(${RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) else() - set(SRCS ${SRCS} Src/X11Utils.cpp) + if(NOT ANDROID) + set(SRCS ${SRCS} Src/X11Utils.cpp) + endif() endif() if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" OR @@ -146,75 +153,85 @@ else() set(DOLPHIN_EXE ${DOLPHIN_EXE_BASE}-nogui) endif() -add_executable(${DOLPHIN_EXE} ${SRCS}) -target_link_libraries(${DOLPHIN_EXE} ${LIBS} ${WXLIBS}) - -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - include(BundleUtilities) - set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${DOLPHIN_EXE}.app) - - # Ask for an application bundle. - set_target_properties(${DOLPHIN_EXE} PROPERTIES - MACOSX_BUNDLE true - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in - ) - - # Install Cg framework into application bundle. - copy_resolved_framework_into_bundle( - # Our framework in "Externals" does not have "Versions/Current/" in - # its path; work around the missing directory levels using "././". - "${CMAKE_SOURCE_DIR}/Externals/Cg/Cg.framework/././Cg" - "${BUNDLE_PATH}/Contents/Frameworks/Cg.framework/././Cg" - ) - - # Fix up the bundle after it is finished. - # There does not seem to be an easy way to run CMake commands post-build, - # so we invoke CMake again on a generated script. - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/postprocess_bundle.cmake " - include(BundleUtilities) - message(\"Fixing up application bundle: ${BUNDLE_PATH}\") - set(BU_CHMOD_BUNDLE_ITEMS ON) - fixup_bundle(\"${BUNDLE_PATH}\" \"\" \"\") - ") - add_custom_command(TARGET ${DOLPHIN_EXE} POST_BUILD - COMMAND ${CMAKE_COMMAND} -P postprocess_bundle.cmake - ) - - # Copy data files into application bundle. - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/copy_data_into_bundle.cmake " - file(INSTALL ${CMAKE_SOURCE_DIR}/Data/Sys ${CMAKE_SOURCE_DIR}/Data/User - DESTINATION ${BUNDLE_PATH}/Contents/Resources - ) - file(GLOB TRANSLATION_FILES RELATIVE ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}/*.gmo - ) - foreach(TRANSLATION_FILE \${TRANSLATION_FILES}) - string(REPLACE \".gmo\" \".lproj\" TRANSLATION_DIR - \${TRANSLATION_FILE} - ) - # It would be better to copy to the new name as a single action, - # but I can't figure out a way to let CMake do that. - file(COPY ${CMAKE_BINARY_DIR}/\${TRANSLATION_FILE} - DESTINATION ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR} - NO_SOURCE_PERMISSIONS - ) - file(RENAME - ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/\${TRANSLATION_FILE} - ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/dolphin-emu.mo - ) - endforeach(TRANSLATION_FILE) - ") - add_custom_target(CopyDataIntoBundle ALL - COMMAND ${CMAKE_COMMAND} -P copy_data_into_bundle.cmake - VERBATIM - ) - - # Install bundle into systemwide /Applications directory. - install(DIRECTORY ${BUNDLE_PATH} DESTINATION /Applications - USE_SOURCE_PERMISSIONS - ) +if(ANDROID) + add_library(${DOLPHIN_EXE} SHARED ${SRCS}) + target_link_libraries(${DOLPHIN_EXE} + log + android + "-Wl,--whole-archive" + ${LIBS} + "-Wl,--no-whole-archive" + ) else() - install(TARGETS ${DOLPHIN_EXE} RUNTIME DESTINATION ${bindir}) + add_executable(${DOLPHIN_EXE} ${SRCS}) + target_link_libraries(${DOLPHIN_EXE} ${LIBS} ${WXLIBS}) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + include(BundleUtilities) + set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${DOLPHIN_EXE}.app) + + # Ask for an application bundle. + set_target_properties(${DOLPHIN_EXE} PROPERTIES + MACOSX_BUNDLE true + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in + ) + + # Install Cg framework into application bundle. + copy_resolved_framework_into_bundle( + # Our framework in "Externals" does not have "Versions/Current/" in + # its path; work around the missing directory levels using "././". + "${CMAKE_SOURCE_DIR}/Externals/Cg/Cg.framework/././Cg" + "${BUNDLE_PATH}/Contents/Frameworks/Cg.framework/././Cg" + ) + + # Fix up the bundle after it is finished. + # There does not seem to be an easy way to run CMake commands post-build, + # so we invoke CMake again on a generated script. + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/postprocess_bundle.cmake " + include(BundleUtilities) + message(\"Fixing up application bundle: ${BUNDLE_PATH}\") + set(BU_CHMOD_BUNDLE_ITEMS ON) + fixup_bundle(\"${BUNDLE_PATH}\" \"\" \"\") + ") + add_custom_command(TARGET ${DOLPHIN_EXE} POST_BUILD + COMMAND ${CMAKE_COMMAND} -P postprocess_bundle.cmake + ) + + # Copy data files into application bundle. + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/copy_data_into_bundle.cmake " + file(INSTALL ${CMAKE_SOURCE_DIR}/Data/Sys ${CMAKE_SOURCE_DIR}/Data/User + DESTINATION ${BUNDLE_PATH}/Contents/Resources + ) + file(GLOB TRANSLATION_FILES RELATIVE ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}/*.gmo + ) + foreach(TRANSLATION_FILE \${TRANSLATION_FILES}) + string(REPLACE \".gmo\" \".lproj\" TRANSLATION_DIR + \${TRANSLATION_FILE} + ) + # It would be better to copy to the new name as a single action, + # but I can't figure out a way to let CMake do that. + file(COPY ${CMAKE_BINARY_DIR}/\${TRANSLATION_FILE} + DESTINATION ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR} + NO_SOURCE_PERMISSIONS + ) + file(RENAME + ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/\${TRANSLATION_FILE} + ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/dolphin-emu.mo + ) + endforeach(TRANSLATION_FILE) + ") + add_custom_target(CopyDataIntoBundle ALL + COMMAND ${CMAKE_COMMAND} -P copy_data_into_bundle.cmake + VERBATIM + ) + + # Install bundle into systemwide /Applications directory. + install(DIRECTORY ${BUNDLE_PATH} DESTINATION /Applications + USE_SOURCE_PERMISSIONS + ) + else() + install(TARGETS ${DOLPHIN_EXE} RUNTIME DESTINATION ${bindir}) + endif() endif() set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} ${DOLPHIN_EXE}) diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp index 1c0776862c..601faeaec6 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp @@ -38,6 +38,7 @@ #include "LogManager.h" #include "HW/CPU.h" #include "PowerPC/PowerPC.h" +#include "PowerPC/JitInterface.h" #include "Debugger/PPCDebugInterface.h" #include "Debugger/Debugger_SymbolMap.h" #include "PowerPC/PPCAnalyst.h" @@ -45,8 +46,6 @@ #include "PowerPC/PPCSymbolDB.h" #include "PowerPC/SignatureDB.h" #include "PowerPC/PPCTables.h" -#include "PowerPC/JitCommon/JitBase.h" -#include "PowerPC/JitCommon/JitCache.h" // for ClearCache() #include "ConfigManager.h" @@ -260,8 +259,7 @@ void CCodeWindow::SingleStep() { if (CCPU::IsStepping()) { - if (jit) - jit->GetBlockCache()->InvalidateICache(PC, 4); + JitInterface::InvalidateICache(PC, 4); CCPU::StepOpcode(&sync_event); wxThread::Sleep(20); // need a short wait here @@ -492,10 +490,8 @@ void CCodeWindow::OnCPUMode(wxCommandEvent& event) } // Clear the JIT cache to enable these changes - if (jit) - { - jit->ClearCache(); - } + JitInterface::ClearCache(); + // Update UpdateButtonStates(); } @@ -509,7 +505,7 @@ void CCodeWindow::OnJitMenu(wxCommandEvent& event) break; case IDM_CLEARCODECACHE: - jit->ClearCache(); + JitInterface::ClearCache(); break; case IDM_SEARCHINSTRUCTION: diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index 46b3a1e8e5..b0b53cc5ea 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -704,7 +704,7 @@ bool IsHotkey(wxKeyEvent &event, int Id) { return (event.GetKeyCode() != WXK_NONE && event.GetKeyCode() == SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkey[Id] && - event.GetModifiers() == SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkeyModifier[Id]); + event.GetModifiers() == SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkeyModifier[Id]); } int GetCmdForHotkey(unsigned int key) diff --git a/Source/Core/DolphinWX/Src/GLInterface.h b/Source/Core/DolphinWX/Src/GLInterface.h index a81f17104c..70b4942e94 100644 --- a/Source/Core/DolphinWX/Src/GLInterface.h +++ b/Source/Core/DolphinWX/Src/GLInterface.h @@ -18,9 +18,11 @@ #define _GLINTERFACE_H_ #include "Thread.h" - -#if defined(USE_EGL) && USE_EGL -#include "GLInterface/EGL.h" +#ifdef ANDROID +#include +#include +#elif defined(USE_EGL) && USE_EGL +#include "GLInterface/EGL_X11.h" #elif defined(USE_WX) && USE_WX #include "GLInterface/WX.h" #elif defined(__APPLE__) @@ -29,10 +31,13 @@ #include "GLInterface/WGL.h" #elif defined(HAVE_X11) && HAVE_X11 #include "GLInterface/GLX.h" +#else +#error Platform doesnt have a GLInterface #endif typedef struct { -#if defined(USE_EGL) && USE_EGL // This is currently a X11/EGL implementation for desktop +#ifdef ANDROID +#elif defined(USE_EGL) && USE_EGL // This is currently a X11/EGL implementation for desktop int screen; Display *dpy; Display *evdpy; diff --git a/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp b/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.cpp similarity index 99% rename from Source/Core/DolphinWX/Src/GLInterface/EGL.cpp rename to Source/Core/DolphinWX/Src/GLInterface/EGL_X11.cpp index 304eb92059..c092aced64 100644 --- a/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp +++ b/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.cpp @@ -19,7 +19,7 @@ #include "RenderBase.h" #include "../GLInterface.h" -#include "EGL.h" +#include "EGL_X11.h" // Show the current FPS void cInterfaceEGL::UpdateFPSDisplay(const char *text) diff --git a/Source/Core/DolphinWX/Src/GLInterface/EGL.h b/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.h similarity index 100% rename from Source/Core/DolphinWX/Src/GLInterface/EGL.h rename to Source/Core/DolphinWX/Src/GLInterface/EGL_X11.h diff --git a/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h b/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h index c2d1ffc54b..1c00a1fd89 100644 --- a/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h +++ b/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h @@ -23,11 +23,11 @@ protected: u32 s_backbuffer_width; u32 s_backbuffer_height; public: - virtual void Swap() = 0; - virtual void UpdateFPSDisplay(const char *Text) = 0; - virtual bool Create(void *&window_handle) = 0; - virtual bool MakeCurrent() = 0; - virtual void Shutdown() = 0; + virtual void Swap() {} + virtual void UpdateFPSDisplay(const char *Text) {} + virtual bool Create(void *&window_handle) { return true; } + virtual bool MakeCurrent() { return true; } + virtual void Shutdown() {} virtual void SwapInterval(int Interval) { } virtual u32 GetBackBufferWidth() { return s_backbuffer_width; } diff --git a/Source/Core/DolphinWX/Src/MainAndroid.cpp b/Source/Core/DolphinWX/Src/MainAndroid.cpp new file mode 100644 index 0000000000..ca2119921d --- /dev/null +++ b/Source/Core/DolphinWX/Src/MainAndroid.cpp @@ -0,0 +1,149 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#include +#include +#include + +#include "Common.h" +#include "FileUtil.h" + +#include "Core.h" +#include "Host.h" +#include "CPUDetect.h" +#include "Thread.h" + +#include "PowerPC/PowerPC.h" +#include "HW/Wiimote.h" + +#include "VideoBackendBase.h" +#include "ConfigManager.h" +#include "LogManager.h" +#include "BootManager.h" + +#include +#include +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "Dolphinemu", __VA_ARGS__)) + +bool rendererHasFocus = true; +bool running = true; + +void Host_NotifyMapLoaded() {} +void Host_RefreshDSPDebuggerWindow() {} + +void Host_ShowJitResults(unsigned int address){} + +Common::Event updateMainFrameEvent; +void Host_Message(int Id) +{ +} + +void* Host_GetRenderHandle() +{ + return NULL; +} + +void* Host_GetInstance() { return NULL; } + +void Host_UpdateTitle(const char* title){}; + +void Host_UpdateLogDisplay(){} + +void Host_UpdateDisasmDialog(){} + +void Host_UpdateMainFrame() +{ +} + +void Host_UpdateBreakPointView(){} + +bool Host_GetKeyState(int keycode) +{ + return false; +} + +void Host_GetRenderWindowSize(int& x, int& y, int& width, int& height) +{ + x = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowXPos; + y = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowYPos; + width = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowWidth; + height = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowHeight; +} + +void Host_RequestRenderWindowSize(int width, int height) {} +void Host_SetStartupDebuggingParameters() +{ +} + +bool Host_RendererHasFocus() +{ + return true; +} + +void Host_ConnectWiimote(int wm_idx, bool connect) {} + +void Host_SetWaitCursor(bool enable){} + +void Host_UpdateStatusBar(const char* _pText, int Filed){} + +void Host_SysMessage(const char *fmt, ...) +{ + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + size_t len = strlen(msg); + if (msg[len - 1] != '\n') { + msg[len - 1] = '\n'; + msg[len] = '\0'; + } + LOGI(msg); +} + +void Host_SetWiiMoteConnectionState(int _State) {} + +#ifdef __cplusplus +extern "C" +{ +#endif +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_dolphinemuactivity_main(JNIEnv *env, jobject obj) +{ + LogManager::Init(); + SConfig::Init(); + VideoBackend::PopulateList(); + VideoBackend::ActivateBackend(SConfig::GetInstance(). + m_LocalCoreStartupParameter.m_strVideoBackend); + WiimoteReal::LoadSettings(); + + // No use running the loop when booting fails + if (BootManager::BootCore("")) + { + while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN) + updateMainFrameEvent.Wait(); + } + + WiimoteReal::Shutdown(); + VideoBackend::ClearList(); + SConfig::Shutdown(); + LogManager::Shutdown(); +} + +#ifdef __cplusplus +} +#endif diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index 6ed8e29c6b..cba3666399 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -3,7 +3,6 @@ set(SRCS Src/BPFunctions.cpp Src/BPStructs.cpp Src/CPMemory.cpp Src/CommandProcessor.cpp - Src/DLCache.cpp Src/Debugger.cpp Src/Fifo.cpp Src/FPSCounter.cpp @@ -24,7 +23,6 @@ set(SRCS Src/BPFunctions.cpp Src/Statistics.cpp Src/TextureCacheBase.cpp Src/TextureConversionShader.cpp - Src/TextureDecoder.cpp Src/VertexLoader.cpp Src/VertexLoaderManager.cpp Src/VertexLoader_Color.cpp @@ -41,6 +39,14 @@ set(SRCS Src/BPFunctions.cpp Src/memcpy_amd.cpp) set(LIBS core) + +if(NOT _M_GENERIC) + set(SRCS ${SRCS} Src/x64TextureDecoder.cpp + Src/x64DLCache.cpp) +else() + set(SRCS ${SRCS} Src/GenericTextureDecoder.cpp + Src/GenericDLCache.cpp) +endif() if(NOT ${CL} STREQUAL CL-NOTFOUND) list(APPEND LIBS ${CL}) endif() diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index 50aa21ebbf..413b163ced 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -222,11 +222,11 @@ void RunGpu() { u8 *uData = Memory::GetPointer(fifo.CPReadPointer); - SaveSSEState(); - LoadDefaultSSEState(); + FPURoundMode::SaveSIMDState(); + FPURoundMode::LoadDefaultSIMDState(); ReadDataFromFifo(uData, 32); OpcodeDecoder_Run(g_bSkipCurrentFrame); - LoadSSEState(); + FPURoundMode::LoadSIMDState(); //DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base"); diff --git a/Source/Core/VideoCommon/Src/GenericDLCache.cpp b/Source/Core/VideoCommon/Src/GenericDLCache.cpp new file mode 100644 index 0000000000..5e27deb469 --- /dev/null +++ b/Source/Core/VideoCommon/Src/GenericDLCache.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// TODO: Handle cache-is-full condition :p + + +#include "Common.h" +#include "DLCache.h" + +namespace DLCache +{ + +void Init() +{ +} + +void Shutdown() +{ +} + +void Clear() +{ +} + +void ProgressiveCleanup() +{ +} +} // namespace + +// NOTE - outside the namespace on purpose. +bool HandleDisplayList(u32 address, u32 size) +{ + return false; +} + +void IncrementCheckContextId() +{ +} diff --git a/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp b/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp new file mode 100644 index 0000000000..ad7cfeebf9 --- /dev/null +++ b/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp @@ -0,0 +1,2182 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +//#include "VideoCommon.h" // to get debug logs + +#include "CPUDetect.h" +#include "TextureDecoder.h" +#include "OpenCL.h" +#include "OpenCL/OCLTextureDecoder.h" +#include "VideoConfig.h" + +#include "LookUpTables.h" + +#include + + + +bool TexFmt_Overlay_Enable=false; +bool TexFmt_Overlay_Center=false; + +extern const char* texfmt[]; +extern const unsigned char sfont_map[]; +extern const unsigned char sfont_raw[][9*10]; + +// TRAM +// STATE_TO_SAVE + GC_ALIGNED16(u8 texMem[TMEM_SIZE]); + + +// Gamecube/Wii texture decoder + +// Decodes all known Gamecube/Wii texture formats. +// by ector + +int TexDecoder_GetTexelSizeInNibbles(int format) +{ + switch (format & 0x3f) { + case GX_TF_I4: return 1; + case GX_TF_I8: return 2; + case GX_TF_IA4: return 2; + case GX_TF_IA8: return 4; + case GX_TF_RGB565: return 4; + case GX_TF_RGB5A3: return 4; + case GX_TF_RGBA8: return 8; + case GX_TF_C4: return 1; + case GX_TF_C8: return 2; + case GX_TF_C14X2: return 4; + case GX_TF_CMPR: return 1; + case GX_CTF_R4: return 1; + case GX_CTF_RA4: return 2; + case GX_CTF_RA8: return 4; + case GX_CTF_YUVA8: return 8; + case GX_CTF_A8: return 2; + case GX_CTF_R8: return 2; + case GX_CTF_G8: return 2; + case GX_CTF_B8: return 2; + case GX_CTF_RG8: return 4; + case GX_CTF_GB8: return 4; + + case GX_TF_Z8: return 2; + case GX_TF_Z16: return 4; + case GX_TF_Z24X8: return 8; + + case GX_CTF_Z4: return 1; + case GX_CTF_Z8M: return 2; + case GX_CTF_Z8L: return 2; + case GX_CTF_Z16L: return 4; + default: return 1; + } +} + +int TexDecoder_GetTextureSizeInBytes(int width, int height, int format) +{ + return (width * height * TexDecoder_GetTexelSizeInNibbles(format)) / 2; +} + +int TexDecoder_GetBlockWidthInTexels(u32 format) +{ + switch (format) + { + case GX_TF_I4: return 8; + case GX_TF_I8: return 8; + case GX_TF_IA4: return 8; + case GX_TF_IA8: return 4; + case GX_TF_RGB565: return 4; + case GX_TF_RGB5A3: return 4; + case GX_TF_RGBA8: return 4; + case GX_TF_C4: return 8; + case GX_TF_C8: return 8; + case GX_TF_C14X2: return 4; + case GX_TF_CMPR: return 8; + case GX_CTF_R4: return 8; + case GX_CTF_RA4: return 8; + case GX_CTF_RA8: return 4; + case GX_CTF_A8: return 8; + case GX_CTF_R8: return 8; + case GX_CTF_G8: return 8; + case GX_CTF_B8: return 8; + case GX_CTF_RG8: return 4; + case GX_CTF_GB8: return 4; + case GX_TF_Z8: return 8; + case GX_TF_Z16: return 4; + case GX_TF_Z24X8: return 4; + case GX_CTF_Z4: return 8; + case GX_CTF_Z8M: return 8; + case GX_CTF_Z8L: return 8; + case GX_CTF_Z16L: return 4; + default: + ERROR_LOG(VIDEO, "Unsupported Texture Format (%08x)! (GetBlockWidthInTexels)", format); + return 8; + } +} + +int TexDecoder_GetBlockHeightInTexels(u32 format) +{ + switch (format) + { + case GX_TF_I4: return 8; + case GX_TF_I8: return 4; + case GX_TF_IA4: return 4; + case GX_TF_IA8: return 4; + case GX_TF_RGB565: return 4; + case GX_TF_RGB5A3: return 4; + case GX_TF_RGBA8: return 4; + case GX_TF_C4: return 8; + case GX_TF_C8: return 4; + case GX_TF_C14X2: return 4; + case GX_TF_CMPR: return 8; + case GX_CTF_R4: return 8; + case GX_CTF_RA4: return 4; + case GX_CTF_RA8: return 4; + case GX_CTF_A8: return 4; + case GX_CTF_R8: return 4; + case GX_CTF_G8: return 4; + case GX_CTF_B8: return 4; + case GX_CTF_RG8: return 4; + case GX_CTF_GB8: return 4; + case GX_TF_Z8: return 4; + case GX_TF_Z16: return 4; + case GX_TF_Z24X8: return 4; + case GX_CTF_Z4: return 8; + case GX_CTF_Z8M: return 4; + case GX_CTF_Z8L: return 4; + case GX_CTF_Z16L: return 4; + default: + ERROR_LOG(VIDEO, "Unsupported Texture Format (%08x)! (GetBlockHeightInTexels)", format); + return 4; + } +} + +//returns bytes +int TexDecoder_GetPaletteSize(int format) +{ + switch (format) + { + case GX_TF_C4: return 16 * 2; + case GX_TF_C8: return 256 * 2; + case GX_TF_C14X2: return 16384 * 2; + default: + return 0; + } +} + +static inline u32 decodeIA8(u16 val) +{ + int a = val >> 8; + int i = val & 0xFF; + return (a << 24) | (i << 16) | (i << 8) | i; +} + +static inline u32 decode5A3(u16 val) +{ + int r,g,b,a; + if ((val & 0x8000)) + { + a = 0xFF; + r = Convert5To8((val >> 10) & 0x1F); + g = Convert5To8((val >> 5) & 0x1F); + b = Convert5To8(val & 0x1F); + } + else + { + a = Convert3To8((val >> 12) & 0x7); + r = Convert4To8((val >> 8) & 0xF); + g = Convert4To8((val >> 4) & 0xF); + b = Convert4To8(val & 0xF); + } + return (a << 24) | (r << 16) | (g << 8) | b; +} + +static inline u32 decode5A3RGBA(u16 val) +{ + int r,g,b,a; + if ((val&0x8000)) + { + r=Convert5To8((val>>10) & 0x1f); + g=Convert5To8((val>>5 ) & 0x1f); + b=Convert5To8((val ) & 0x1f); + a=0xFF; + } + else + { + a=Convert3To8((val>>12) & 0x7); + r=Convert4To8((val>>8 ) & 0xf); + g=Convert4To8((val>>4 ) & 0xf); + b=Convert4To8((val ) & 0xf); + } + return r | (g<<8) | (b << 16) | (a << 24); +} + +static inline u32 decode565RGBA(u16 val) +{ + int r,g,b,a; + r=Convert5To8((val>>11) & 0x1f); + g=Convert6To8((val>>5 ) & 0x3f); + b=Convert5To8((val ) & 0x1f); + a=0xFF; + return r | (g<<8) | (b << 16) | (a << 24); +} + +static inline u32 decodeIA8Swapped(u16 val) +{ + int a = val & 0xFF; + int i = val >> 8; + return i | (i<<8) | (i<<16) | (a<<24); +} + + + +struct DXTBlock +{ + u16 color1; + u16 color2; + u8 lines[4]; +}; + +//inline void decodebytesC4(u32 *dst, const u8 *src, int numbytes, int tlutaddr, int tlutfmt) +inline void decodebytesC4_5A3_To_BGRA32(u32 *dst, const u8 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u8 val = src[x]; + *dst++ = decode5A3(Common::swap16(tlut[val >> 4])); + *dst++ = decode5A3(Common::swap16(tlut[val & 0xF])); + } +} + +inline void decodebytesC4_5A3_To_rgba32(u32 *dst, const u8 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u8 val = src[x]; + *dst++ = decode5A3RGBA(Common::swap16(tlut[val >> 4])); + *dst++ = decode5A3RGBA(Common::swap16(tlut[val & 0xF])); + } +} + +inline void decodebytesC4_To_Raw16(u16* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem+tlutaddr); + for (int x = 0; x < 4; x++) + { + u8 val = src[x]; + *dst++ = Common::swap16(tlut[val >> 4]); + *dst++ = Common::swap16(tlut[val & 0xF]); + } +} + +inline void decodebytesC4IA8_To_RGBA(u32* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem+tlutaddr); + for (int x = 0; x < 4; x++) + { + u8 val = src[x]; + *dst++ = decodeIA8Swapped(tlut[val >> 4]); + *dst++ = decodeIA8Swapped(tlut[val & 0xF]); + } +} + +inline void decodebytesC4RGB565_To_RGBA(u32* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem+tlutaddr); + for (int x = 0; x < 4; x++) + { + u8 val = src[x]; + *dst++ = decode565RGBA(Common::swap16(tlut[val >> 4])); + *dst++ = decode565RGBA(Common::swap16(tlut[val & 0xF])); + } +} + +//inline void decodebytesC8(u32 *dst, const u8 *src, int numbytes, int tlutaddr, int tlutfmt) +inline void decodebytesC8_5A3_To_BGRA32(u32 *dst, const u8 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 8; x++) + { + u8 val = src[x]; + *dst++ = decode5A3(Common::swap16(tlut[val])); + } +} + +inline void decodebytesC8_5A3_To_RGBA32(u32 *dst, const u8 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 8; x++) + { + u8 val = src[x]; + *dst++ = decode5A3RGBA(Common::swap16(tlut[val])); + } +} + +inline void decodebytesC8_To_Raw16(u16* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 8; x++) + { + u8 val = src[x]; + *dst++ = Common::swap16(tlut[val]); + } +} + +inline void decodebytesC8IA8_To_RGBA(u32* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 8; x++) + { + *dst++ = decodeIA8Swapped(tlut[src[x]]); + } +} + +inline void decodebytesC8RGB565_To_RGBA(u32* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 8; x++) + { + *dst++ = decode565RGBA(Common::swap16(tlut[src[x]])); + } +} + +inline void decodebytesC14X2_5A3_To_BGRA32(u32 *dst, const u16 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u16 val = Common::swap16(src[x]); + *dst++ = decode5A3(Common::swap16(tlut[(val & 0x3FFF)])); + } +} + +inline void decodebytesC14X2_5A3_To_RGBA(u32 *dst, const u16 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u16 val = Common::swap16(src[x]); + *dst++ = decode5A3RGBA(Common::swap16(tlut[(val & 0x3FFF)])); + } +} + +inline void decodebytesC14X2_To_Raw16(u16* dst, const u16* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u16 val = Common::swap16(src[x]); + *dst++ = Common::swap16(tlut[(val & 0x3FFF)]); + } +} + +inline void decodebytesC14X2IA8_To_RGBA(u32* dst, const u16* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u16 val = Common::swap16(src[x]); + *dst++ = decodeIA8Swapped(tlut[(val & 0x3FFF)]); + } +} + +inline void decodebytesC14X2rgb565_To_RGBA(u32* dst, const u16* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u16 val = Common::swap16(src[x]); + *dst++ = decode565RGBA(Common::swap16(tlut[(val & 0x3FFF)])); + } +} + +// Needs more speed. +inline void decodebytesIA4(u16 *dst, const u8 *src) +{ + for (int x = 0; x < 8; x++) + { + const u8 val = src[x]; + u8 a = Convert4To8(val >> 4); + u8 l = Convert4To8(val & 0xF); + dst[x] = (a << 8) | l; + } +} + +inline void decodebytesIA4RGBA(u32 *dst, const u8 *src) +{ + for (int x = 0; x < 8; x++) + { + const u8 val = src[x]; + u8 a = Convert4To8(val >> 4); + u8 l = Convert4To8(val & 0xF); + dst[x] = (a << 24) | l << 16 | l << 8 | l; + } +} + +inline void decodebytesRGB5A3(u32 *dst, const u16 *src) +{ +#if 0 + for (int x = 0; x < 4; x++) + dst[x] = decode5A3(Common::swap16(src[x])); +#else + dst[0] = decode5A3(Common::swap16(src[0])); + dst[1] = decode5A3(Common::swap16(src[1])); + dst[2] = decode5A3(Common::swap16(src[2])); + dst[3] = decode5A3(Common::swap16(src[3])); +#endif +} + +inline void decodebytesRGB5A3rgba(u32 *dst, const u16 *src) +{ +#if 0 + for (int x = 0; x < 4; x++) + dst[x] = decode5A3RGBA(Common::swap16(src[x])); +#else + dst[0] = decode5A3RGBA(Common::swap16(src[0])); + dst[1] = decode5A3RGBA(Common::swap16(src[1])); + dst[2] = decode5A3RGBA(Common::swap16(src[2])); + dst[3] = decode5A3RGBA(Common::swap16(src[3])); +#endif +} + +// This one is used by many video formats. It'd therefore be good if it was fast. +// Needs more speed. +inline void decodebytesARGB8_4(u32 *dst, const u16 *src, const u16 *src2) +{ +#if 0 + for (int x = 0; x < 4; x++) + dst[x] = Common::swap32((src2[x] << 16) | src[x]); +#else + dst[0] = Common::swap32((src2[0] << 16) | src[0]); + dst[1] = Common::swap32((src2[1] << 16) | src[1]); + dst[2] = Common::swap32((src2[2] << 16) | src[2]); + dst[3] = Common::swap32((src2[3] << 16) | src[3]); +#endif + + // This can probably be done in a few SSE pack/unpack instructions + pshufb + // some unpack instruction x2: + // ABABABABABABABAB 1212121212121212 -> + // AB12AB12AB12AB12 AB12AB12AB12AB12 + // 2x pshufb-> + // 21BA21BA21BA21BA 21BA21BA21BA21BA + // and we are done. +} + +inline void decodebytesARGB8_4ToRgba(u32 *dst, const u16 *src, const u16 * src2) +{ +#if 0 + for (int x = 0; x < 4; x++) { + dst[x] = ((src[x] & 0xFF) << 24) | ((src[x] & 0xFF00)>>8) | (src2[x] << 8); + } +#else + dst[0] = ((src[0] & 0xFF) << 24) | ((src[0] & 0xFF00)>>8) | (src2[0] << 8); + dst[1] = ((src[1] & 0xFF) << 24) | ((src[1] & 0xFF00)>>8) | (src2[1] << 8); + dst[2] = ((src[2] & 0xFF) << 24) | ((src[2] & 0xFF00)>>8) | (src2[2] << 8); + dst[3] = ((src[3] & 0xFF) << 24) | ((src[3] & 0xFF00)>>8) | (src2[3] << 8); +#endif +} + +inline u32 makecol(int r, int g, int b, int a) +{ + return (a << 24)|(r << 16)|(g << 8)|b; +} + +inline u32 makeRGBA(int r, int g, int b, int a) +{ + return (a<<24)|(b<<16)|(g<<8)|r; +} + +void decodeDXTBlock(u32 *dst, const DXTBlock *src, int pitch) +{ + // S3TC Decoder (Note: GCN decodes differently from PC so we can't use native support) + // Needs more speed. + u16 c1 = Common::swap16(src->color1); + u16 c2 = Common::swap16(src->color2); + int blue1 = Convert5To8(c1 & 0x1F); + int blue2 = Convert5To8(c2 & 0x1F); + int green1 = Convert6To8((c1 >> 5) & 0x3F); + int green2 = Convert6To8((c2 >> 5) & 0x3F); + int red1 = Convert5To8((c1 >> 11) & 0x1F); + int red2 = Convert5To8((c2 >> 11) & 0x1F); + int colors[4]; + colors[0] = makecol(red1, green1, blue1, 255); + colors[1] = makecol(red2, green2, blue2, 255); + if (c1 > c2) + { + int blue3 = ((blue2 - blue1) >> 1) - ((blue2 - blue1) >> 3); + int green3 = ((green2 - green1) >> 1) - ((green2 - green1) >> 3); + int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3); + colors[2] = makecol(red1 + red3, green1 + green3, blue1 + blue3, 255); + colors[3] = makecol(red2 - red3, green2 - green3, blue2 - blue3, 255); + } + else + { + colors[2] = makecol((red1 + red2 + 1) / 2, // Average + (green1 + green2 + 1) / 2, + (blue1 + blue2 + 1) / 2, 255); + colors[3] = makecol(red2, green2, blue2, 0); // Color2 but transparent + } + + for (int y = 0; y < 4; y++) + { + int val = src->lines[y]; + for (int x = 0; x < 4; x++) + { + dst[x] = colors[(val >> 6) & 3]; + val <<= 2; + } + dst += pitch; + } +} + +void decodeDXTBlockRGBA(u32 *dst, const DXTBlock *src, int pitch) +{ + // S3TC Decoder (Note: GCN decodes differently from PC so we can't use native support) + // Needs more speed. + u16 c1 = Common::swap16(src->color1); + u16 c2 = Common::swap16(src->color2); + int blue1 = Convert5To8(c1 & 0x1F); + int blue2 = Convert5To8(c2 & 0x1F); + int green1 = Convert6To8((c1 >> 5) & 0x3F); + int green2 = Convert6To8((c2 >> 5) & 0x3F); + int red1 = Convert5To8((c1 >> 11) & 0x1F); + int red2 = Convert5To8((c2 >> 11) & 0x1F); + int colors[4]; + colors[0] = makeRGBA(red1, green1, blue1, 255); + colors[1] = makeRGBA(red2, green2, blue2, 255); + if (c1 > c2) + { + int blue3 = ((blue2 - blue1) >> 1) - ((blue2 - blue1) >> 3); + int green3 = ((green2 - green1) >> 1) - ((green2 - green1) >> 3); + int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3); + colors[2] = makeRGBA(red1 + red3, green1 + green3, blue1 + blue3, 255); + colors[3] = makeRGBA(red2 - red3, green2 - green3, blue2 - blue3, 255); + } + else + { + colors[2] = makeRGBA((red1 + red2 + 1) / 2, // Average + (green1 + green2 + 1) / 2, + (blue1 + blue2 + 1) / 2, 255); + colors[3] = makeRGBA(red2, green2, blue2, 0); // Color2 but transparent + } + + for (int y = 0; y < 4; y++) + { + int val = src->lines[y]; + for (int x = 0; x < 4; x++) + { + dst[x] = colors[(val >> 6) & 3]; + val <<= 2; + } + dst += pitch; + } +} + +#if 0 // TODO - currently does not handle transparency correctly and causes problems when texture dimensions are not multiples of 8 +static void copyDXTBlock(u8* dst, const u8* src) +{ + ((u16*)dst)[0] = Common::swap16(((u16*)src)[0]); + ((u16*)dst)[1] = Common::swap16(((u16*)src)[1]); + u32 pixels = ((u32*)src)[1]; + // A bit of trickiness here: the row are in the same order + // between the two formats, but the ordering within the rows + // is reversed. + pixels = ((pixels >> 4) & 0x0F0F0F0F) | ((pixels << 4) & 0xF0F0F0F0); + pixels = ((pixels >> 2) & 0x33333333) | ((pixels << 2) & 0xCCCCCCCC); + ((u32*)dst)[1] = pixels; +} +#endif + +static PC_TexFormat GetPCFormatFromTLUTFormat(int tlutfmt) +{ + switch (tlutfmt) + { + case 0: return PC_TEX_FMT_IA8; // IA8 + case 1: return PC_TEX_FMT_RGB565; // RGB565 + case 2: return PC_TEX_FMT_BGRA32; // RGB5A3: This TLUT format requires + // extra work to decode. + } + return PC_TEX_FMT_NONE; // Error +} + +PC_TexFormat GetPC_TexFormat(int texformat, int tlutfmt) +{ + switch (texformat) + { + case GX_TF_C4: + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_I4: + return PC_TEX_FMT_IA8; + case GX_TF_I8: // speed critical + return PC_TEX_FMT_IA8; + case GX_TF_C8: + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_IA4: + return PC_TEX_FMT_IA4_AS_IA8; + case GX_TF_IA8: + return PC_TEX_FMT_IA8; + case GX_TF_C14X2: + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_RGB565: + return PC_TEX_FMT_RGB565; + case GX_TF_RGB5A3: + return PC_TEX_FMT_BGRA32; + case GX_TF_RGBA8: // speed critical + return PC_TEX_FMT_BGRA32; + case GX_TF_CMPR: // speed critical + // The metroid games use this format almost exclusively. + { + return PC_TEX_FMT_BGRA32; + } + } + + // The "copy" texture formats, too? + return PC_TEX_FMT_NONE; +} + + +//switch endianness, unswizzle +//TODO: to save memory, don't blindly convert everything to argb8888 +//also ARGB order needs to be swapped later, to accommodate modern hardware better +//need to add DXT support too +PC_TexFormat TexDecoder_Decode_real(u8 *dst, const u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt) +{ + const int Wsteps4 = (width + 3) / 4; + const int Wsteps8 = (width + 7) / 8; + + switch (texformat) + { + case GX_TF_C4: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = yStep * 8; iy < 8; iy++, xStep++) + decodebytesC4_5A3_To_BGRA32((u32*)dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr); + } + else + { + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = yStep * 8; iy < 8; iy++, xStep++) + decodebytesC4_To_Raw16((u16*)dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr); + } + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_I4: + { + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = yStep * 8 ; iy < 8; iy++,xStep++) + for (int ix = 0; ix < 4; ix++) + { + int val = src[4 * xStep + ix]; + dst[(y + iy) * width + x + ix * 2] = Convert4To8(val >> 4); + dst[(y + iy) * width + x + ix * 2 + 1] = Convert4To8(val & 0xF); + } + } + return PC_TEX_FMT_I4_AS_I8; + case GX_TF_I8: // speed critical + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + { + ((u64*)(dst + (y + iy) * width + x))[0] = ((u64*)(src + 8 * xStep))[0]; + } + } + return PC_TEX_FMT_I8; + case GX_TF_C8: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC8_5A3_To_BGRA32((u32*)dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr); + } + else + { + + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC8_To_Raw16((u16*)dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr); + } + } + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_IA4: + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesIA4((u16*)dst + (y + iy) * width + x, src + 8 * xStep); + } + return PC_TEX_FMT_IA4_AS_IA8; + case GX_TF_IA8: + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = yStep * 4; iy < 4; iy++, xStep++) + { + u16 *ptr = (u16 *)dst + (y + iy) * width + x; + u16 *s = (u16 *)(src + 8 * xStep); + for(int j = 0; j < 4; j++) + *ptr++ = Common::swap16(*s++); + } + + } + return PC_TEX_FMT_IA8; + case GX_TF_C14X2: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC14X2_5A3_To_BGRA32((u32*)dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr); + } + else + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC14X2_To_Raw16((u16*)dst + (y + iy) * width + x,(u16*)(src + 8 * xStep), tlutaddr); + } + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_RGB565: + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + { + u16 *ptr = (u16 *)dst + (y + iy) * width + x; + u16 *s = (u16 *)(src + 8 * xStep); + for(int j = 0; j < 4; j++) + *ptr++ = Common::swap16(*s++); + } + } + return PC_TEX_FMT_RGB565; + case GX_TF_RGB5A3: + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + //decodebytesRGB5A3((u32*)dst+(y+iy)*width+x, (u16*)src, 4); + decodebytesRGB5A3((u32*)dst+(y+iy)*width+x, (u16*)(src + 8 * xStep)); + } + return PC_TEX_FMT_BGRA32; + case GX_TF_RGBA8: // speed critical + { + + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + { + const u8* src2 = src + 64 * yStep; + for (int iy = 0; iy < 4; iy++) + decodebytesARGB8_4((u32*)dst + (y+iy)*width + x, (u16*)src2 + 4 * iy, (u16*)src2 + 4 * iy + 16); + } + } + } + return PC_TEX_FMT_BGRA32; + case GX_TF_CMPR: // speed critical + // The metroid games use this format almost exclusively. + { +#if 0 // TODO - currently does not handle transparency correctly and causes problems when texture dimensions are not multiples of 8 + // 11111111 22222222 55555555 66666666 + // 33333333 44444444 77777777 88888888 + for (int y = 0; y < height; y += 8) + { + for (int x = 0; x < width; x += 8) + { + copyDXTBlock(dst+(y/2)*width+x*2, src); + src += 8; + copyDXTBlock(dst+(y/2)*width+x*2+8, src); + src += 8; + copyDXTBlock(dst+(y/2+2)*width+x*2, src); + src += 8; + copyDXTBlock(dst+(y/2+2)*width+x*2+8, src); + src += 8; + } + } + return PC_TEX_FMT_DXT1; +#else + for (int y = 0; y < height; y += 8) + { + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++) + { + const u8* src2 = src + 4 * sizeof(DXTBlock) * yStep; + decodeDXTBlock((u32*)dst + y * width + x, (DXTBlock*)src2, width); + src2 += sizeof(DXTBlock); + decodeDXTBlock((u32*)dst + y * width + x + 4, (DXTBlock*)src2, width); + src2 += sizeof(DXTBlock); + decodeDXTBlock((u32*)dst + (y + 4) * width + x, (DXTBlock*)src2, width); + src2 += sizeof(DXTBlock); + decodeDXTBlock((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src2, width); + } + } +#endif + return PC_TEX_FMT_BGRA32; + } + } + + // The "copy" texture formats, too? + return PC_TEX_FMT_NONE; +} + + + +// JSD 01/06/11: +// TODO: we really should ensure BOTH the source and destination addresses are aligned to 16-byte boundaries to +// squeeze out a little more performance. _mm_loadu_si128/_mm_storeu_si128 is slower than _mm_load_si128/_mm_store_si128 +// because they work on unaligned addresses. The processor is free to make the assumption that addresses are multiples +// of 16 in the aligned case. +// TODO: complete SSE2 optimization of less often used texture formats. +// TODO: refactor algorithms using _mm_loadl_epi64 unaligned loads to prefer 128-bit aligned loads. + +PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int height, int texformat, int tlutaddr, int tlutfmt) +{ + + const int Wsteps4 = (width + 3) / 4; + const int Wsteps8 = (width + 7) / 8; + + switch (texformat) + { + case GX_TF_C4: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8,yStep++) + for (int iy = 0, xStep = 8 * yStep; iy < 8; iy++,xStep++) + decodebytesC4_5A3_To_rgba32(dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr); + } + else if(tlutfmt == 0) + { + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8,yStep++) + for (int iy = 0, xStep = 8 * yStep; iy < 8; iy++,xStep++) + decodebytesC4IA8_To_RGBA(dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr); + + } + else + { + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8,yStep++) + for (int iy = 0, xStep = 8 * yStep; iy < 8; iy++,xStep++) + decodebytesC4RGB565_To_RGBA(dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr); + } + break; + case GX_TF_I4: + { + // Reference C implementation: + for (int y = 0; y < height; y += 8) + for (int x = 0; x < width; x += 8) + for (int iy = 0; iy < 8; iy++, src += 4) + for (int ix = 0; ix < 4; ix++) + { + int val = src[ix]; + u8 i1 = Convert4To8(val >> 4); + u8 i2 = Convert4To8(val & 0xF); + memset(dst+(y + iy) * width + x + ix * 2 , i1,4); + memset(dst+(y + iy) * width + x + ix * 2 + 1 , i2,4); + } + } + break; + case GX_TF_I8: // speed critical + { + // Reference C implementation + for (int y = 0; y < height; y += 4) + for (int x = 0; x < width; x += 8) + for (int iy = 0; iy < 4; ++iy, src += 8) + { + u32 * newdst = dst + (y + iy)*width+x; + const u8 * newsrc = src; + u8 srcval; + + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = newsrc[0]; newdst[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + } + } + break; + case GX_TF_C8: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC8_5A3_To_RGBA32((u32*)dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr); + } + else if(tlutfmt == 0) + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC8IA8_To_RGBA(dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr); + + } + else + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC8RGB565_To_RGBA(dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr); + + } + break; + case GX_TF_IA4: + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesIA4RGBA(dst + (y + iy) * width + x, src + 8 * xStep); + } + break; + case GX_TF_IA8: + { + // Reference C implementation: + for (int y = 0; y < height; y += 4) + for (int x = 0; x < width; x += 4) + for (int iy = 0; iy < 4; iy++, src += 8) + { + u32 *ptr = dst + (y + iy) * width + x; + u16 *s = (u16 *)src; + ptr[0] = decodeIA8Swapped(s[0]); + ptr[1] = decodeIA8Swapped(s[1]); + ptr[2] = decodeIA8Swapped(s[2]); + ptr[3] = decodeIA8Swapped(s[3]); + } + } + break; + case GX_TF_C14X2: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC14X2_5A3_To_BGRA32(dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr); + } + else if (tlutfmt == 0) + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC14X2IA8_To_RGBA(dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr); + } + else + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC14X2rgb565_To_RGBA(dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr); + } + break; + case GX_TF_RGB565: + { + // Reference C implementation. + for (int y = 0; y < height; y += 4) + for (int x = 0; x < width; x += 4) + for (int iy = 0; iy < 4; iy++, src += 8) + { + u32 *ptr = dst + (y + iy) * width + x; + u16 *s = (u16 *)src; + for(int j = 0; j < 4; j++) + *ptr++ = decode565RGBA(Common::swap16(*s++)); + } + } + break; + case GX_TF_RGB5A3: + { + // Reference C implementation: + for (int y = 0; y < height; y += 4) + for (int x = 0; x < width; x += 4) + for (int iy = 0; iy < 4; iy++, src += 8) + decodebytesRGB5A3rgba(dst+(y+iy)*width+x, (u16*)src); + } + break; + case GX_TF_RGBA8: // speed critical + { + // Reference C implementation. + for (int y = 0; y < height; y += 4) + for (int x = 0; x < width; x += 4) + { + for (int iy = 0; iy < 4; iy++) + decodebytesARGB8_4ToRgba(dst + (y+iy)*width + x, (u16*)src + 4 * iy, (u16*)src + 4 * iy + 16); + src += 64; + } + } + break; + case GX_TF_CMPR: // speed critical + // The metroid games use this format almost exclusively. + { + for (int y = 0; y < height; y += 8) + { + for (int x = 0; x < width; x += 8) + { + decodeDXTBlockRGBA((u32*)dst + y * width + x, (DXTBlock*)src, width); + src += sizeof(DXTBlock); + decodeDXTBlockRGBA((u32*)dst + y * width + x + 4, (DXTBlock*)src, width); + src += sizeof(DXTBlock); + decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x, (DXTBlock*)src, width); + src += sizeof(DXTBlock); + decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src, width); + src += sizeof(DXTBlock); + } + } + break; + } + } + + // The "copy" texture formats, too? + return PC_TEX_FMT_RGBA32; +} + + + + +void TexDecoder_SetTexFmtOverlayOptions(bool enable, bool center) +{ + TexFmt_Overlay_Enable = enable; + TexFmt_Overlay_Center = center; +} + +PC_TexFormat TexDecoder_Decode(u8 *dst, const u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt,bool rgbaOnly) +{ + PC_TexFormat retval = TexDecoder_Decode_OpenCL(dst, src, + width, height, texformat, tlutaddr, tlutfmt, rgbaOnly); + if (retval == PC_TEX_FMT_NONE) + retval = rgbaOnly ? TexDecoder_Decode_RGBA((u32*)dst, src, + width, height, texformat, tlutaddr, tlutfmt) + : TexDecoder_Decode_real(dst, src, + width, height, texformat, tlutaddr, tlutfmt); + + if ((!TexFmt_Overlay_Enable)|| (retval == PC_TEX_FMT_NONE)) + return retval; + + int w = min(width, 40); + int h = min(height, 10); + + int xoff = (width - w) >> 1; + int yoff = (height - h) >> 1; + + if (!TexFmt_Overlay_Center) + { + xoff=0; + yoff=0; + } + + const char* fmt = texfmt[texformat&15]; + while (*fmt) + { + int xcnt = 0; + int nchar = sfont_map[(int)*fmt]; + + const unsigned char *ptr = sfont_raw[nchar]; // each char is up to 9x10 + + for (int x = 0; x < 9;x++) + { + if (ptr[x] == 0x78) + break; + xcnt++; + } + + for (int y=0; y < 10; y++) + { + for (int x=0; x < xcnt; x++) + { + switch(retval) + { + case PC_TEX_FMT_I8: + { + // TODO: Is this an acceptable way to draw in I8? + u8 *dtp = (u8*)dst; + dtp[(y + yoff) * width + x + xoff] = ptr[x] ? 0xFF : 0x88; + break; + } + case PC_TEX_FMT_IA8: + case PC_TEX_FMT_IA4_AS_IA8: + { + u16 *dtp = (u16*)dst; + dtp[(y + yoff) * width + x + xoff] = ptr[x] ? 0xFFFF : 0xFF00; + break; + } + case PC_TEX_FMT_RGB565: + { + u16 *dtp = (u16*)dst; + dtp[(y + yoff)*width + x + xoff] = ptr[x] ? 0xFFFF : 0x0000; + break; + } + default: + case PC_TEX_FMT_BGRA32: + { + int *dtp = (int*)dst; + dtp[(y + yoff) * width + x + xoff] = ptr[x] ? 0xFFFFFFFF : 0xFF000000; + break; + } + } + } + ptr += 9; + } + xoff += xcnt; + fmt++; + } + + return retval; +} + + + +void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth, int texformat, int tlutaddr, int tlutfmt) +{ + /* General formula for computing texture offset + // + u16 sBlk = s / blockWidth; + u16 tBlk = t / blockHeight; + u16 widthBlks = (width / blockWidth) + 1; + u32 base = (tBlk * widthBlks + sBlk) * blockWidth * blockHeight; + u16 blkS = s & (blockWidth - 1); + u16 blkT = t & (blockHeight - 1); + u32 blkOff = blkT * blockWidth + blkS; + */ + + switch (texformat) + { + case GX_TF_C4: + { + u16 sBlk = s >> 3; + u16 tBlk = t >> 3; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; + u16 blkS = s & 7; + u16 blkT = t & 7; + u32 blkOff = (blkT << 3) + blkS; + + int rs = (blkOff & 1)?0:4; + u32 offset = base + (blkOff >> 1); + + u8 val = (*(src + offset) >> rs) & 0xF; + u16 *tlut = (u16*)(texMem + tlutaddr); + + switch (tlutfmt) + { + case 0: + *((u32*)dst) = decodeIA8Swapped(tlut[val]); + break; + case 1: + *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val])); + break; + case 2: + *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val])); + break; + } + } + break; + case GX_TF_I4: + { + u16 sBlk = s >> 3; + u16 tBlk = t >> 3; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; + u16 blkS = s & 7; + u16 blkT = t & 7; + u32 blkOff = (blkT << 3) + blkS; + + int rs = (blkOff & 1)?0:4; + u32 offset = base + (blkOff >> 1); + + u8 val = (*(src + offset) >> rs) & 0xF; + val = Convert4To8(val); + dst[0] = val; + dst[1] = val; + dst[2] = val; + dst[3] = val; + } + break; + case GX_TF_I8: + { + u16 sBlk = s >> 3; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; + u16 blkS = s & 7; + u16 blkT = t & 3; + u32 blkOff = (blkT << 3) + blkS; + + u8 val = *(src + base + blkOff); + dst[0] = val; + dst[1] = val; + dst[2] = val; + dst[3] = val; + } + break; + case GX_TF_C8: + { + u16 sBlk = s >> 3; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; + u16 blkS = s & 7; + u16 blkT = t & 3; + u32 blkOff = (blkT << 3) + blkS; + + u8 val = *(src + base + blkOff); + u16 *tlut = (u16*)(texMem + tlutaddr); + + switch (tlutfmt) + { + case 0: + *((u32*)dst) = decodeIA8Swapped(tlut[val]); + break; + case 1: + *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val])); + break; + case 2: + *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val])); + break; + } + } + break; + case GX_TF_IA4: + { + u16 sBlk = s >> 3; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; + u16 blkS = s & 7; + u16 blkT = t & 3; + u32 blkOff = (blkT << 3) + blkS; + + u8 val = *(src + base + blkOff); + const u8 a = Convert4To8(val>>4); + const u8 l = Convert4To8(val&0xF); + dst[0] = l; + dst[1] = l; + dst[2] = l; + dst[3] = a; + } + break; + case GX_TF_IA8: + { + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 4; + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blkOff = (blkT << 2) + blkS; + + u32 offset = (base + blkOff) << 1; + const u16* valAddr = (u16*)(src + offset); + + *((u32*)dst) = decodeIA8Swapped(*valAddr); + } + break; + case GX_TF_C14X2: + { + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 4; + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blkOff = (blkT << 2) + blkS; + + u32 offset = (base + blkOff) << 1; + const u16* valAddr = (u16*)(src + offset); + + u16 val = Common::swap16(*valAddr) & 0x3FFF; + u16 *tlut = (u16*)(texMem + tlutaddr); + + switch (tlutfmt) + { + case 0: + *((u32*)dst) = decodeIA8Swapped(tlut[val]); + break; + case 1: + *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val])); + break; + case 2: + *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val])); + break; + } + } + break; + case GX_TF_RGB565: + { + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 4; + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blkOff = (blkT << 2) + blkS; + + u32 offset = (base + blkOff) << 1; + const u16* valAddr = (u16*)(src + offset); + + *((u32*)dst) = decode565RGBA(Common::swap16(*valAddr)); + } + break; + case GX_TF_RGB5A3: + { + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 4; + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blkOff = (blkT << 2) + blkS; + + u32 offset = (base + blkOff) << 1; + const u16* valAddr = (u16*)(src + offset); + + *((u32*)dst) = decode5A3RGBA(Common::swap16(*valAddr)); + } + break; + case GX_TF_RGBA8: + { + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; // shift by 5 is correct + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blkOff = (blkT << 2) + blkS; + + u32 offset = (base + blkOff) << 1 ; + const u8* valAddr = src + offset; + + dst[3] = valAddr[0]; + dst[0] = valAddr[1]; + dst[1] = valAddr[32]; + dst[2] = valAddr[33]; + } + break; + case GX_TF_CMPR: + { + u16 sDxt = s >> 2; + u16 tDxt = t >> 2; + + u16 sBlk = sDxt >> 1; + u16 tBlk = tDxt >> 1; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 2; + u16 blkS = sDxt & 1; + u16 blkT = tDxt & 1; + u32 blkOff = (blkT << 1) + blkS; + + u32 offset = (base + blkOff) << 3; + + const DXTBlock* dxtBlock = (const DXTBlock*)(src + offset); + + u16 c1 = Common::swap16(dxtBlock->color1); + u16 c2 = Common::swap16(dxtBlock->color2); + int blue1 = Convert5To8(c1 & 0x1F); + int blue2 = Convert5To8(c2 & 0x1F); + int green1 = Convert6To8((c1 >> 5) & 0x3F); + int green2 = Convert6To8((c2 >> 5) & 0x3F); + int red1 = Convert5To8((c1 >> 11) & 0x1F); + int red2 = Convert5To8((c2 >> 11) & 0x1F); + + u16 ss = s & 3; + u16 tt = t & 3; + + int colorSel = dxtBlock->lines[tt]; + int rs = 6 - (ss << 1); + colorSel = (colorSel >> rs) & 3; + colorSel |= c1 > c2?0:4; + + u32 color = 0; + + switch (colorSel) + { + case 0: + case 4: + color = makeRGBA(red1, green1, blue1, 255); + break; + case 1: + case 5: + color = makeRGBA(red2, green2, blue2, 255); + break; + case 2: + color = makeRGBA(red1+(red2-red1)/3, green1+(green2-green1)/3, blue1+(blue2-blue1)/3, 255); + break; + case 3: + color = makeRGBA(red2+(red1-red2)/3, green2+(green1-green2)/3, blue2+(blue1-blue2)/3, 255); + break; + case 6: + color = makeRGBA((int)ceil((float)(red1+red2)/2), (int)ceil((float)(green1+green2)/2), (int)ceil((float)(blue1+blue2)/2), 255); + break; + case 7: + color = makeRGBA(red2, green2, blue2, 0); + break; + } + + *((u32*)dst) = color; + } + break; + } +} + + +const char* texfmt[] = { + // pixel + "I4", "I8", "IA4", "IA8", + "RGB565", "RGB5A3", "RGBA8", "0x07", + "C4", "C8", "C14X2", "0x0B", + "0x0C", "0x0D", "CMPR", "0x0F", + // Z-buffer + "0x10", "Z8", "0x12", "Z16", + "0x14", "0x15", "Z24X8", "0x17", + "0x18", "0x19", "0x1A", "0x1B", + "0x1C", "0x1D", "0x1E", "0x1F", + // pixel + copy + "CR4", "0x21", "CRA4", "CRA8", + "0x24", "0x25", "CYUVA8", "CA8", + "CR8", "CG8", "CB8", "CRG8", + "CGB8", "0x2D", "0x2E", "0x2F", + // Z + copy + "CZ4", "0x31", "0x32", "0x33", + "0x34", "0x35", "0x36", "0x37", + "0x38", "CZ8M", "CZ8L", "0x3B", + "CZ16L", "0x3D", "0x3E", "0x3F", +}; + +const unsigned char sfont_map[] = { + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,10,10,10,10, + 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25, + 26,27,28,29,30,31,32,33,34,35,36,10,10,10,10,10, + 10,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51, + 52,53,54,55,56,57,58,59,60,61,62,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, +}; + +const unsigned char sfont_raw[][9*10] = { + { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + }, +}; diff --git a/Source/Core/VideoCommon/Src/VertexLoader.cpp b/Source/Core/VideoCommon/Src/VertexLoader.cpp index 5bffab8ee7..526cbe7e49 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader.cpp @@ -23,7 +23,7 @@ #include "MemoryUtil.h" #include "StringUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "PixelEngine.h" #include "Host.h" @@ -43,8 +43,9 @@ //BBox #include "XFMemory.h" extern float GC_ALIGNED16(g_fProjectionMatrix[16]); - +#ifndef _M_GENERIC #define USE_JIT +#endif #define COMPILED_CODE_SIZE 4096 @@ -82,8 +83,9 @@ static const float fractionTable[32] = { 1.0f / (1U << 24), 1.0f / (1U << 25), 1.0f / (1U << 26), 1.0f / (1U << 27), 1.0f / (1U << 28), 1.0f / (1U << 29), 1.0f / (1U << 30), 1.0f / (1U << 31), }; - +#ifdef USE_JIT using namespace Gen; +#endif void LOADERDECL PosMtx_ReadDirect_UByte() { @@ -182,14 +184,19 @@ VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr) m_VtxDesc = vtx_desc; SetVAT(vtx_attr.g0.Hex, vtx_attr.g1.Hex, vtx_attr.g2.Hex); + #ifdef USE_JIT AllocCodeSpace(COMPILED_CODE_SIZE); CompileVertexTranslator(); WriteProtect(); + #endif + } VertexLoader::~VertexLoader() { + #ifdef USE_JIT FreeCodeSpace(); + #endif delete m_NativeFmt; } @@ -474,7 +481,8 @@ void VertexLoader::WriteCall(TPipelineFunction func) m_PipelineStages[m_numPipelineStages++] = func; #endif } - +// ARMTODO: This should be done in a better way +#ifndef _M_GENERIC void VertexLoader::WriteGetVariable(int bits, OpArg dest, void *address) { #ifdef USE_JIT @@ -498,7 +506,7 @@ void VertexLoader::WriteSetVariable(int bits, void *address, OpArg value) #endif #endif } - +#endif void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) { m_numLoadedVertices += count; diff --git a/Source/Core/VideoCommon/Src/VertexLoader.h b/Source/Core/VideoCommon/Src/VertexLoader.h index 98a57cb9ff..0f321cd14f 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader.h +++ b/Source/Core/VideoCommon/Src/VertexLoader.h @@ -76,7 +76,12 @@ private: } }; +// ARMTODO: This should be done in a better way +#ifndef _M_GENERIC class VertexLoader : public Gen::XCodeBlock, NonCopyable +#else +class VertexLoader +#endif { public: VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr); @@ -122,8 +127,10 @@ private: void WriteCall(TPipelineFunction); +#ifndef _M_GENERIC void WriteGetVariable(int bits, Gen::OpArg dest, void *address); void WriteSetVariable(int bits, void *address, Gen::OpArg dest); +#endif }; #endif diff --git a/Source/Core/VideoCommon/Src/DLCache.cpp b/Source/Core/VideoCommon/Src/x64DLCache.cpp similarity index 99% rename from Source/Core/VideoCommon/Src/DLCache.cpp rename to Source/Core/VideoCommon/Src/x64DLCache.cpp index c828ea3a03..559593a08c 100644 --- a/Source/Core/VideoCommon/Src/DLCache.cpp +++ b/Source/Core/VideoCommon/Src/x64DLCache.cpp @@ -35,7 +35,7 @@ #include "VertexLoaderManager.h" #include "VertexManagerBase.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "DLCache.h" #include "VideoConfig.h" diff --git a/Source/Core/VideoCommon/Src/TextureDecoder.cpp b/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp similarity index 97% rename from Source/Core/VideoCommon/Src/TextureDecoder.cpp rename to Source/Core/VideoCommon/Src/x64TextureDecoder.cpp index 30df817902..6c474920cd 100644 --- a/Source/Core/VideoCommon/Src/TextureDecoder.cpp +++ b/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp @@ -1119,20 +1119,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he _mm_storeu_si128( (__m128i*)( dst+(y + iy+1) * width + x + 4 ), o4 ); } } -#if 0 - // Reference C implementation: - for (int y = 0; y < height; y += 8) - for (int x = 0; x < width; x += 8) - for (int iy = 0; iy < 8; iy++, src += 4) - for (int ix = 0; ix < 4; ix++) - { - int val = src[ix]; - u8 i1 = Convert4To8(val >> 4); - u8 i2 = Convert4To8(val & 0xF); - memset(dst+(y + iy) * width + x + ix * 2 , i1,4); - memset(dst+(y + iy) * width + x + ix * 2 + 1 , i2,4); - } -#endif } break; case GX_TF_I8: // speed critical @@ -1248,26 +1234,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he } } -#if 0 - // Reference C implementation - for (int y = 0; y < height; y += 4) - for (int x = 0; x < width; x += 8) - for (int iy = 0; iy < 4; ++iy, src += 8) - { - u32 * newdst = dst + (y + iy)*width+x; - const u8 * newsrc = src; - u8 srcval; - - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = newsrc[0]; newdst[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - } -#endif } break; case GX_TF_C8: @@ -1380,20 +1346,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he _mm_storeu_si128( (__m128i*)(dst + (y + iy) * width + x), r1 ); } } -#if 0 - // Reference C implementation: - for (int y = 0; y < height; y += 4) - for (int x = 0; x < width; x += 4) - for (int iy = 0; iy < 4; iy++, src += 8) - { - u32 *ptr = dst + (y + iy) * width + x; - u16 *s = (u16 *)src; - ptr[0] = decodeIA8Swapped(s[0]); - ptr[1] = decodeIA8Swapped(s[1]); - ptr[2] = decodeIA8Swapped(s[2]); - ptr[3] = decodeIA8Swapped(s[3]); - } -#endif } break; case GX_TF_C14X2: @@ -1493,18 +1445,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he __m128i *ptr = (__m128i *)(dst + (y + iy) * width + x); _mm_storeu_si128(ptr, abgr888x4); } -#if 0 - // Reference C implementation. - for (int y = 0; y < height; y += 4) - for (int x = 0; x < width; x += 4) - for (int iy = 0; iy < 4; iy++, src += 8) - { - u32 *ptr = dst + (y + iy) * width + x; - u16 *s = (u16 *)src; - for(int j = 0; j < 4; j++) - *ptr++ = decode565RGBA(Common::swap16(*s++)); - } -#endif } break; case GX_TF_RGB5A3: @@ -1718,13 +1658,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he } } } -#if 0 - // Reference C implementation: - for (int y = 0; y < height; y += 4) - for (int x = 0; x < width; x += 4) - for (int iy = 0; iy < 4; iy++, src += 8) - decodebytesRGB5A3rgba(dst+(y+iy)*width+x, (u16*)src); -#endif } break; case GX_TF_RGBA8: // speed critical @@ -1860,16 +1793,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he _mm_storeu_si128(dst128, rgba11); } } -#if 0 - // Reference C implementation. - for (int y = 0; y < height; y += 4) - for (int x = 0; x < width; x += 4) - { - for (int iy = 0; iy < 4; iy++) - decodebytesARGB8_4ToRgba(dst + (y+iy)*width + x, (u16*)src + 4 * iy, (u16*)src + 4 * iy + 16); - src += 64; - } -#endif } break; case GX_TF_CMPR: // speed critical @@ -2104,22 +2027,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he } } } -#if 0 - for (int y = 0; y < height; y += 8) - { - for (int x = 0; x < width; x += 8) - { - decodeDXTBlockRGBA((u32*)dst + y * width + x, (DXTBlock*)src, width); - src += sizeof(DXTBlock); - decodeDXTBlockRGBA((u32*)dst + y * width + x + 4, (DXTBlock*)src, width); - src += sizeof(DXTBlock); - decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x, (DXTBlock*)src, width); - src += sizeof(DXTBlock); - decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src, width); - src += sizeof(DXTBlock); - } - } -#endif break; } } diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index bf9122e6b5..0c1b13f301 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -111,8 +111,8 @@ ..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories) - false - + false + true @@ -143,7 +143,7 @@ ..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories) false - + true true @@ -182,7 +182,6 @@ - @@ -204,7 +203,6 @@ - @@ -216,6 +214,8 @@ + + diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters index e7019f17ed..6038d5e9e2 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters @@ -5,9 +5,6 @@ - - Vertex Loading - Vertex Loading @@ -92,9 +89,6 @@ Decoding - - Decoding - Base @@ -122,6 +116,12 @@ Util + + Decoding + + + Vertex Loading + diff --git a/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp b/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp index bfaf21ec7e..d68228273c 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp @@ -19,7 +19,7 @@ #include "D3DBase.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "MemoryUtil.h" #include "VertexShaderGen.h" diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp index 29a1b6a662..01ea415263 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp @@ -51,7 +51,9 @@ void VideoBackend::UpdateFPSDisplay(const char *text) } void InitInterface() { - #if defined(USE_EGL) && USE_EGL + #ifdef ANDROID + GLInterface = new cInterfaceBase; + #elif defined(USE_EGL) && USE_EGL GLInterface = new cInterfaceEGL; #elif defined(USE_WX) && USE_WX GLInterface = new cInterfaceWX; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp index ae20649433..0528bd1878 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp @@ -17,7 +17,7 @@ #include "GLUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "MemoryUtil.h" #include "VertexShaderGen.h" diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index 05f21beed1..99e01bfb3d 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -204,7 +204,9 @@ void VideoBackend::Video_Prepare() GL_REPORT_ERRORD(); VertexLoaderManager::Init(); TextureConverter::Init(); +#ifndef _M_GENERIC DLCache::Init(); +#endif // Notify the core that the video backend is ready Host_Message(WM_USER_CREATE); @@ -219,7 +221,9 @@ void VideoBackend::Shutdown() s_efbAccessRequested = false; s_FifoShuttingDown = false; s_swapRequested = false; +#ifndef _M_GENERIC DLCache::Shutdown(); +#endif Fifo_Shutdown(); PostProcessing::Shutdown(); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp index 0091e4eaca..032ff9d74a 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp @@ -125,7 +125,9 @@ void DecodeStandard(u32 bufferSize) if (Cmd == GX_NOP) return; - + // Causes a SIGBUS error on Android + // XXX: Investigate +#ifndef ANDROID // check if switching in or out of an object // only used for debuggging if (inObjectStream && (Cmd & 0x87) != lastPrimCmd) @@ -139,7 +141,7 @@ void DecodeStandard(u32 bufferSize) lastPrimCmd = Cmd & 0x87; DebugUtil::OnObjectBegin(); } - +#endif switch(Cmd) { case GX_NOP: diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp index b9afc1abb5..72b26338b5 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp @@ -115,15 +115,15 @@ void RunGpu() if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread) { // We are going to do FP math on the main thread so have to save the current state - SaveSSEState(); - LoadDefaultSSEState(); + FPURoundMode::SaveSIMDState(); + FPURoundMode::LoadDefaultSIMDState(); // run the opcode decoder do { RunBuffer(); } while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr); - LoadSSEState(); + FPURoundMode::LoadSIMDState(); } } From 08fe3c213ad71e903fed83edfada5a79c75f11f9 Mon Sep 17 00:00:00 2001 From: Rachel Bryk Date: Tue, 26 Feb 2013 18:28:56 -0500 Subject: [PATCH 16/70] Abort loading states from incompatible graphics backends. --- Source/Core/Core/Src/State.cpp | 2 +- Source/Core/VideoCommon/Src/MainBase.cpp | 5 +++++ Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index 0facf2f387..773d757337 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 14; +static const u32 STATE_VERSION = 15; struct StateHeader { diff --git a/Source/Core/VideoCommon/Src/MainBase.cpp b/Source/Core/VideoCommon/Src/MainBase.cpp index 726ef71b38..a881bebfb2 100644 --- a/Source/Core/VideoCommon/Src/MainBase.cpp +++ b/Source/Core/VideoCommon/Src/MainBase.cpp @@ -186,6 +186,11 @@ void VideoBackendHardware::InitializeShared() // Run from the CPU thread void VideoBackendHardware::DoState(PointerWrap& p) { + bool software = false; + p.Do(software); + if (p.GetMode() == PointerWrap::MODE_READ && software == true) + // change mode to abort load of incompatible save state. + p.SetMode(PointerWrap::MODE_VERIFY); VideoCommon_DoState(p); p.DoMarker("VideoCommon"); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp index d78b8ba13b..6976b18690 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp @@ -41,6 +41,7 @@ #include "Core.h" #include "OpcodeDecoder.h" #include "SWVertexLoader.h" +#include "SWStatistics.h" #define VSYNC_ENABLED 0 @@ -97,6 +98,11 @@ bool VideoSoftware::Initialize(void *&window_handle) void VideoSoftware::DoState(PointerWrap& p) { + bool software = true; + p.Do(software); + if (p.GetMode() == PointerWrap::MODE_READ && software == false) + // change mode to abort load of incompatible save state. + p.SetMode(PointerWrap::MODE_VERIFY); // TODO: incomplete SWCommandProcessor::DoState(p); SWPixelEngine::DoState(p); @@ -105,6 +111,7 @@ void VideoSoftware::DoState(PointerWrap& p) Clipper::DoState(p); p.Do(swxfregs); p.Do(bpmem); + p.Do(swstats); // CP Memory p.DoArray(arraybases, 16); From 46f5c19c6d2fbd3318e9a6de3c3c2e313c669cf0 Mon Sep 17 00:00:00 2001 From: Rachel Bryk Date: Tue, 26 Feb 2013 18:43:37 -0500 Subject: [PATCH 17/70] Not sure if this is the right way to handle this, but it makes the save states perfectly stable. That's all that really matters, right? --- Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp | 5 ++--- Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp index 4401916e1f..8e3f0c2925 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp @@ -55,9 +55,8 @@ void DoState(PointerWrap &p) p.Do(lastPrimCmd); p.Do(streamSize); p.Do(streamAddress); - // not sure how to save this... It seems to be the only thing left that is really important. - // uncommenting this will prevent all error messages, and any crashes/hangs on load, but then obviously it'll segfault once you restart dolphin. - //p.Do(currentFunction); + if (p.GetMode() == PointerWrap::MODE_READ) + ResetDecoding(); } void DecodePrimitiveStream(u32 iBufferSize) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp index 6976b18690..0e2d6afa72 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp @@ -103,7 +103,8 @@ void VideoSoftware::DoState(PointerWrap& p) if (p.GetMode() == PointerWrap::MODE_READ && software == false) // change mode to abort load of incompatible save state. p.SetMode(PointerWrap::MODE_VERIFY); - // TODO: incomplete + + // TODO: incomplete? SWCommandProcessor::DoState(p); SWPixelEngine::DoState(p); EfbInterface::DoState(p); From f1c990069c8d0e54f7aa079e6e2c7b785a0d56db Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 26 Feb 2013 20:47:48 -0500 Subject: [PATCH 18/70] Yell at the user if they change window size while dumping frames, and some other avi dumping stuff. --- Source/Core/VideoCommon/Src/AVIDump.cpp | 18 ++++- Source/Core/VideoCommon/Src/AVIDump.h | 6 +- Source/Core/VideoCommon/Src/RenderBase.cpp | 5 +- Source/Core/VideoCommon/Src/RenderBase.h | 2 +- .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 25 ++++--- Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 29 ++++---- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 66 ++++++++----------- 7 files changed, 73 insertions(+), 78 deletions(-) diff --git a/Source/Core/VideoCommon/Src/AVIDump.cpp b/Source/Core/VideoCommon/Src/AVIDump.cpp index c172903b5d..8514e8bd03 100644 --- a/Source/Core/VideoCommon/Src/AVIDump.cpp +++ b/Source/Core/VideoCommon/Src/AVIDump.cpp @@ -157,9 +157,21 @@ void AVIDump::Stop() NOTICE_LOG(VIDEO, "Stop"); } -void AVIDump::AddFrame(char *data) +void AVIDump::AddFrame(const u8* data, int w, int h) { - AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer); + static bool bShownError = false; + if ((w != m_bitmap.biWidth || h != m_bitmap.biHeight) && !bShownError) + { + PanicAlert("You have resized the window while dumping frames.\n" + "Nothing sane can be done to handle this.\n" + "Your video will likely be broken."); + bShownError=true; + + m_bitmap.biWidth = w; + m_bitmap.biHeight = h; + } + + AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, const_cast(data), m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer); m_totalBytes += m_byteBuffer; // Close the recording if the file is more than 2gb // VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb. @@ -298,7 +310,7 @@ bool AVIDump::CreateFile() return true; } -void AVIDump::AddFrame(uint8_t *data, int width, int height) +void AVIDump::AddFrame(const u8* data, int width, int height) { avpicture_fill((AVPicture *)s_BGRFrame, data, PIX_FMT_BGR24, width, height); diff --git a/Source/Core/VideoCommon/Src/AVIDump.h b/Source/Core/VideoCommon/Src/AVIDump.h index e74df05db4..08ab6be254 100644 --- a/Source/Core/VideoCommon/Src/AVIDump.h +++ b/Source/Core/VideoCommon/Src/AVIDump.h @@ -24,6 +24,8 @@ #include #endif +#include "CommonTypes.h" + class AVIDump { private: @@ -36,11 +38,11 @@ class AVIDump public: #ifdef _WIN32 static bool Start(HWND hWnd, int w, int h); - static void AddFrame(char *data); #else static bool Start(int w, int h); - static void AddFrame(uint8_t *data, int width, int height); #endif + static void AddFrame(const u8* data, int width, int height); + static void Stop(); }; diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp index 8e1d012fa2..90a09aec43 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.cpp +++ b/Source/Core/VideoCommon/Src/RenderBase.cpp @@ -83,7 +83,9 @@ unsigned int Renderer::efb_scale_denominatorY = 1; unsigned int Renderer::ssaa_multiplier = 1; -Renderer::Renderer() : frame_data(NULL), bLastFrameDumped(false) +Renderer::Renderer() + : frame_data() + , bLastFrameDumped(false) { UpdateActiveConfig(); TextureCache::OnConfigChanged(g_ActiveConfig); @@ -110,7 +112,6 @@ Renderer::~Renderer() if (pFrameDump.IsOpen()) pFrameDump.Close(); #endif - delete[] frame_data; } void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index 5376577cbd..8b5505e082 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -147,7 +147,7 @@ protected: #else File::IOFile pFrameDump; #endif - char* frame_data; + std::vector frame_data; bool bLastFrameDumped; // The framebuffer size diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index a6cb52c40f..44f4f1b15b 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -761,11 +761,11 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle return SUCCEEDED(hr); } -void formatBufferDump(const char *in, char *out, int w, int h, int p) +void formatBufferDump(const u8* in, u8* out, int w, int h, int p) { for (int y = 0; y < h; ++y) { - const u8 *line = (u8*)(in + (h - y - 1) * p); + auto line = (in + (h - y - 1) * p); for (int x = 0; x < w; ++x) { out[0] = line[2]; @@ -782,8 +782,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) { - if (g_ActiveConfig.bDumpFrames && frame_data) - AVIDump::AddFrame(frame_data); + if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); Core::Callback_VideoCopiedToXFB(false); return; @@ -794,8 +794,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { - if (g_ActiveConfig.bDumpFrames && frame_data) - AVIDump::AddFrame(frame_data); + if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); Core::Callback_VideoCopiedToXFB(false); return; @@ -934,16 +934,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map); - if (!frame_data || w != s_recordWidth || h != s_recordHeight) + if (frame_data.empty() || w != s_recordWidth || h != s_recordHeight) { - delete[] frame_data; - frame_data = new char[3 * s_recordWidth * s_recordHeight]; + frame_data.resize(3 * s_recordWidth * s_recordHeight); w = s_recordWidth; h = s_recordHeight; } - char* source_ptr = (char*)map.pData + GetTargetRectangle().left*4 + GetTargetRectangle().top*map.RowPitch; - formatBufferDump(source_ptr, frame_data, s_recordWidth, s_recordHeight, map.RowPitch); - AVIDump::AddFrame(frame_data); + auto source_ptr = (const u8*)map.pData + GetTargetRectangle().left*4 + GetTargetRectangle().top*map.RowPitch; + formatBufferDump(source_ptr, &frame_data[0], s_recordWidth, s_recordHeight, map.RowPitch); + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); D3D::context->Unmap(s_screenshot_texture, 0); } bLastFrameDumped = true; @@ -952,7 +951,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (bLastFrameDumped && bAVIDumping) { - SAFE_DELETE_ARRAY(frame_data); + std::vector().swap(frame_data); w = h = 0; AVIDump::Stop(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 0657309801..151d80b16f 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -216,11 +216,11 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) } -void formatBufferDump(const char *in, char *out, int w, int h, int p) +void formatBufferDump(const u8* in, u8* out, int w, int h, int p) { for (int y = 0; y < h; y++) { - const char *line = in + (h - y - 1) * p; + auto line = in + (h - y - 1) * p; for (int x = 0; x < w; x++) { memcpy(out, line, 3); @@ -725,8 +725,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) { - if (g_ActiveConfig.bDumpFrames && frame_data) - AVIDump::AddFrame(frame_data); + if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); Core::Callback_VideoCopiedToXFB(false); return; @@ -737,8 +737,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { - if (g_ActiveConfig.bDumpFrames && frame_data) - AVIDump::AddFrame(frame_data); + if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); Core::Callback_VideoCopiedToXFB(false); return; @@ -935,15 +935,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons D3DLOCKED_RECT rect; if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, GetTargetRectangle().AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY))) { - if (!frame_data || w != s_recordWidth || h != s_recordHeight) + if (frame_data.empty() || w != s_recordWidth || h != s_recordHeight) { - delete[] frame_data; - frame_data = new char[3 * s_recordWidth * s_recordHeight]; + frame_data.resize(3 * s_recordWidth * s_recordHeight); w = s_recordWidth; h = s_recordHeight; } - formatBufferDump((const char*)rect.pBits, frame_data, s_recordWidth, s_recordHeight, rect.Pitch); - AVIDump::AddFrame(frame_data); + formatBufferDump((const u8*)rect.pBits, &frame_data[0], s_recordWidth, s_recordHeight, rect.Pitch); + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); ScreenShootMEMSurface->UnlockRect(); } } @@ -953,12 +952,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (bLastFrameDumped && bAVIDumping) { - if (frame_data) - { - delete[] frame_data; - frame_data = 0; - w = h = 0; - } + std::vector().swap(frame_data); + w = h = 0; AVIDump::Stop(); bAVIDumping = false; OSD::AddMessage("Stop dumping frames to AVI", 2000); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 3ff8b834ce..3cb4426513 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -956,20 +956,23 @@ void Renderer::SetBlendMode(bool forceUpdate) s_blendMode = newval; } +void DumpFrame(const std::vector& data, int w, int h) +{ +#if defined(HAVE_LIBAV) || defined(_WIN32) + if (g_ActiveConfig.bDumpFrames && !data.empty()) + { + AVIDump::AddFrame(&data[0], w, h); + } +#endif +} + // This function has the final picture. We adjust the aspect ratio here. void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { static int w = 0, h = 0; if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) { - if (g_ActiveConfig.bDumpFrames && frame_data) - { -#ifdef _WIN32 - AVIDump::AddFrame(frame_data); -#elif defined HAVE_LIBAV - AVIDump::AddFrame((u8*)frame_data, w, h); -#endif - } + DumpFrame(frame_data, w, h); Core::Callback_VideoCopiedToXFB(false); return; } @@ -979,14 +982,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if (g_ActiveConfig.VirtualXFBEnabled() && (!xfbSourceList || xfbCount == 0)) { - if (g_ActiveConfig.bDumpFrames && frame_data) - { -#ifdef _WIN32 - AVIDump::AddFrame(frame_data); -#elif defined HAVE_LIBAV - AVIDump::AddFrame((u8*)frame_data, w, h); -#endif - } + DumpFrame(frame_data, w, h); Core::Callback_VideoCopiedToXFB(false); return; } @@ -1149,16 +1145,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons if (g_ActiveConfig.bDumpFrames) { std::lock_guard lk(s_criticalScreenshot); - if (!frame_data || w != flipped_trc.GetWidth() || + if (frame_data.empty() || w != flipped_trc.GetWidth() || h != flipped_trc.GetHeight()) { - if (frame_data) delete[] frame_data; w = flipped_trc.GetWidth(); h = flipped_trc.GetHeight(); - frame_data = new char[3 * w * h]; + frame_data.resize(3 * w * h); } glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(flipped_trc.left, flipped_trc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data); + glReadPixels(flipped_trc.left, flipped_trc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]); if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0) { if (!bLastFrameDumped) @@ -1179,12 +1174,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons } if (bAVIDumping) { - #ifdef _WIN32 - AVIDump::AddFrame(frame_data); - #else - FlipImageData((u8*)frame_data, w, h); - AVIDump::AddFrame((u8*)frame_data, w, h); + #ifndef _WIN32 + FlipImageData(&frame_data[0], w, h); #endif + + AVIDump::AddFrame(&frame_data[0], w, h); } bLastFrameDumped = true; @@ -1196,12 +1190,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (bLastFrameDumped && bAVIDumping) { - if (frame_data) - { - delete[] frame_data; - frame_data = NULL; - w = h = 0; - } + std::vector().swap(frame_data); + w = h = 0; AVIDump::Stop(); bAVIDumping = false; OSD::AddMessage("Stop dumping frames", 2000); @@ -1215,9 +1205,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons std::string movie_file_name; w = GetTargetRectangle().GetWidth(); h = GetTargetRectangle().GetHeight(); - frame_data = new char[3 * w * h]; + frame_data.resize(3 * w * h); glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(GetTargetRectangle().left, GetTargetRectangle().bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data); + glReadPixels(GetTargetRectangle().left, GetTargetRectangle().bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]); if (GL_REPORT_ERROR() == GL_NO_ERROR) { if (!bLastFrameDumped) @@ -1228,21 +1218,17 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons OSD::AddMessage("Error opening framedump.raw for writing.", 2000); else { - char msg [255]; - sprintf(msg, "Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h); - OSD::AddMessage(msg, 2000); + OSD::AddMessage(StromFromFormat("Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h), 2000); } } if (pFrameDump) { - FlipImageData((u8*)frame_data, w, h); - pFrameDump.WriteBytes(frame_data, w * 3 * h); + FlipImageData(&frame_data[0], w, h); + pFrameDump.WriteBytes(&frame_data[0], w * 3 * h); pFrameDump.Flush(); } bLastFrameDumped = true; } - - delete[] frame_data; } else { From a680d17eef88646b8cd6018c1c5e8f0e39d056ee Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 26 Feb 2013 19:59:33 -0600 Subject: [PATCH 19/70] Buildfix. --- Source/Core/VideoCommon/Src/AVIDump.cpp | 8 ++++---- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Core/VideoCommon/Src/AVIDump.cpp b/Source/Core/VideoCommon/Src/AVIDump.cpp index 8514e8bd03..fefb09fecb 100644 --- a/Source/Core/VideoCommon/Src/AVIDump.cpp +++ b/Source/Core/VideoCommon/Src/AVIDump.cpp @@ -159,13 +159,13 @@ void AVIDump::Stop() void AVIDump::AddFrame(const u8* data, int w, int h) { - static bool bShownError = false; - if ((w != m_bitmap.biWidth || h != m_bitmap.biHeight) && !bShownError) + static bool shown_error = false; + if ((w != m_bitmap.biWidth || h != m_bitmap.biHeight) && !shown_error) { PanicAlert("You have resized the window while dumping frames.\n" "Nothing sane can be done to handle this.\n" "Your video will likely be broken."); - bShownError=true; + shown_error = true; m_bitmap.biWidth = w; m_bitmap.biHeight = h; @@ -312,7 +312,7 @@ bool AVIDump::CreateFile() void AVIDump::AddFrame(const u8* data, int width, int height) { - avpicture_fill((AVPicture *)s_BGRFrame, data, PIX_FMT_BGR24, width, height); + avpicture_fill((AVPicture *)s_BGRFrame, const_cast(data), PIX_FMT_BGR24, width, height); // Convert image from BGR24 to desired pixel format, and scale to initial // width and height diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 3cb4426513..b5393cdbde 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -1218,7 +1218,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons OSD::AddMessage("Error opening framedump.raw for writing.", 2000); else { - OSD::AddMessage(StromFromFormat("Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h), 2000); + OSD::AddMessage(StringFromFormat("Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h).c_str(), 2000); } } if (pFrameDump) From be7643cd2d1a27324070550ad82eca2c3bd59f19 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 27 Feb 2013 02:15:32 +0000 Subject: [PATCH 20/70] Add the missing FPR cache --- .../Core/Src/PowerPC/JitArm32/JitFPRCache.cpp | 168 ++++++++++++++++++ .../Core/Src/PowerPC/JitArm32/JitFPRCache.h | 62 +++++++ 2 files changed, 230 insertions(+) create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.cpp create mode 100644 Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.h diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.cpp new file mode 100644 index 0000000000..08f10df826 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.cpp @@ -0,0 +1,168 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "JitFPRCache.h" + +ArmFPRCache::ArmFPRCache() +{ + emit = 0; +} + +void ArmFPRCache::Init(ARMXEmitter *emitter) +{ + emit = emitter; + ARMReg *PPCRegs = GetPPCAllocationOrder(NUMPPCREG); + ARMReg *Regs = GetAllocationOrder(NUMARMREG); + + for(u8 a = 0; a < NUMPPCREG; ++a) + { + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].Reg = PPCRegs[a]; + ArmCRegs[a].LastLoad = 0; + ArmCRegs[a].PS1 = false; + } + for(u8 a = 0; a < NUMARMREG; ++a) + { + ArmRegs[a].Reg = Regs[a]; + ArmRegs[a].free = true; + } +} +void ArmFPRCache::Start(PPCAnalyst::BlockRegStats &stats) +{ + for(u8 a = 0; a < NUMPPCREG; ++a) + { + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].LastLoad = 0; + } +} +ARMReg *ArmFPRCache::GetPPCAllocationOrder(int &count) +{ + // This will return us the allocation order of the registers we can use on + // the ppc side. + static ARMReg allocationOrder[] = + { + D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, + D11, D12, D13, D14, D15, D16, D17, D18, D19, + D20, D21, D22, D23, D24, D25, D26, D27 + }; + count = sizeof(allocationOrder) / sizeof(const int); + return allocationOrder; +} +ARMReg *ArmFPRCache::GetAllocationOrder(int &count) +{ + // This will return us the allocation order of the registers we can use on + // the host side. + static ARMReg allocationOrder[] = + { + D31, D30, D29, D28 + }; + count = sizeof(allocationOrder) / sizeof(const int); + return allocationOrder; +} + +ARMReg ArmFPRCache::GetReg(bool AutoLock) +{ + for(u8 a = 0; a < NUMARMREG; ++a) + if(ArmRegs[a].free) + { + // Alright, this one is free + if (AutoLock) + ArmRegs[a].free = false; + return ArmRegs[a].Reg; + } + // Uh Oh, we have all them locked.... + _assert_msg_(_DYNA_REC_, false, "All available registers are locked dumb dumb"); + return D31; +} +void ArmFPRCache::Unlock(ARMReg V0) +{ + for(u8 RegNum = 0; RegNum < NUMARMREG; ++RegNum) + { + if(ArmRegs[RegNum].Reg == V0) + { + _assert_msg_(_DYNA_REC, !ArmRegs[RegNum].free, "This register is already unlocked"); + ArmRegs[RegNum].free = true; + } + } +} +ARMReg ArmFPRCache::GetPPCReg(u32 preg, bool PS1, bool preLoad) +{ + u32 HighestUsed = 0; + u8 Num = 0; + for(u8 a = 0; a < NUMPPCREG; ++a){ + ++ArmCRegs[a].LastLoad; + if (ArmCRegs[a].LastLoad > HighestUsed) + { + HighestUsed = ArmCRegs[a].LastLoad; + Num = a; + } + } + // Check if already Loaded + for(u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg == preg && ArmCRegs[a].PS1 == PS1) + { + ArmCRegs[a].LastLoad = 0; + return ArmCRegs[a].Reg; + } + // Check if we have a free register + for (u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg == 33) + { + u16 offset = STRUCT_OFF(PowerPC::ppcState, ps) + (preg * 16) + (PS1 ? 8 : 0); + if (preLoad) + emit->VLDR(ArmCRegs[a].Reg, R9, offset); + ArmCRegs[a].PPCReg = preg; + ArmCRegs[a].LastLoad = 0; + ArmCRegs[a].PS1 = PS1; + return ArmCRegs[a].Reg; + } + // Alright, we couldn't get a free space, dump that least used register + u16 offsetOld = STRUCT_OFF(PowerPC::ppcState, ps) + (ArmCRegs[Num].PPCReg * 16) + (ArmCRegs[Num].PS1 ? 8 : 0); + emit->VSTR(ArmCRegs[Num].Reg, R9, offsetOld); + + u16 offsetNew = STRUCT_OFF(PowerPC::ppcState, ps) + (preg * 16) + (PS1 ? 8 : 0); + if (preLoad) + emit->VLDR(ArmCRegs[Num].Reg, R9, offsetNew); + ArmCRegs[Num].PPCReg = preg; + ArmCRegs[Num].LastLoad = 0; + ArmCRegs[Num].PS1 = PS1; + return ArmCRegs[Num].Reg; + +} + +ARMReg ArmFPRCache::R0(u32 preg, bool preLoad) +{ + return GetPPCReg(preg, false, preLoad); +} + +ARMReg ArmFPRCache::R1(u32 preg, bool preLoad) +{ + return GetPPCReg(preg, true, preLoad); +} + +void ArmFPRCache::Flush() +{ + for(u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg != 33) + { + u16 offset = STRUCT_OFF(PowerPC::ppcState, ps) + (ArmCRegs[a].PPCReg * 16) + (ArmCRegs[a].PS1 ? 8 : 0); + emit->VSTR(ArmCRegs[a].Reg, R9, offset); + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].LastLoad = 0; + } +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.h new file mode 100644 index 0000000000..6b4f056409 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.h @@ -0,0 +1,62 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _JITARMFPRCACHE_H +#define _JITARMFPRCACHE_H + +#include "ArmEmitter.h" +#include "../Gekko.h" +#include "../PPCAnalyst.h" +#include "JitRegCache.h" + +#define ARMFPUREGS 32 +using namespace ArmGen; + +class ArmFPRCache +{ +private: + PPCCachedReg regs[32]; + JRCPPC ArmCRegs[ARMFPUREGS]; + JRCReg ArmRegs[ARMFPUREGS]; + + int NUMPPCREG; + int NUMARMREG; + + ARMReg *GetAllocationOrder(int &count); + ARMReg *GetPPCAllocationOrder(int &count); + + ARMReg GetPPCReg(u32 preg, bool PS1, bool preLoad); + +protected: + ARMXEmitter *emit; + +public: + ArmFPRCache(); + ~ArmFPRCache() {} + + void Init(ARMXEmitter *emitter); + void Start(PPCAnalyst::BlockRegStats &stats); + + void SetEmitter(ARMXEmitter *emitter) {emit = emitter;} + + ARMReg GetReg(bool AutoLock = true); // Return a ARM register we can use. + void Unlock(ARMReg V0); + void Flush(); + ARMReg R0(u32 preg, bool preLoad = true); // Returns a cached register + ARMReg R1(u32 preg, bool preLoad = true); +}; +#endif From e435851e7a8dd56c94bb9bdc30f4c60c5b561163 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 25 Feb 2013 00:28:25 -0600 Subject: [PATCH 21/70] Add disabled code for authenticating wiimotes on Windows. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 93 ++++++++++++------- 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 61abeffa2d..2ae34a7ca5 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -35,6 +35,8 @@ #include #include +//#define AUTHENTICATE_WIIMOTES + typedef struct _HIDD_ATTRIBUTES { ULONG Size; @@ -56,6 +58,7 @@ typedef BOOL (__stdcall *PBth_BluetoothFindRadioClose)(HBLUETOOTH_RADIO_FIND); typedef DWORD (__stdcall *PBth_BluetoothGetRadioInfo)(HANDLE, PBLUETOOTH_RADIO_INFO); typedef DWORD (__stdcall *PBth_BluetoothRemoveDevice)(const BLUETOOTH_ADDRESS*); typedef DWORD (__stdcall *PBth_BluetoothSetServiceState)(HANDLE, const BLUETOOTH_DEVICE_INFO*, const GUID*, DWORD); +typedef DWORD (__stdcall *PBth_BluetoothAuthenticateDevice)(HWND, HANDLE, BLUETOOTH_DEVICE_INFO*, PWCHAR, ULONG); PHidD_GetHidGuid HidD_GetHidGuid = NULL; PHidD_GetAttributes HidD_GetAttributes = NULL; @@ -70,6 +73,7 @@ PBth_BluetoothFindRadioClose Bth_BluetoothFindRadioClose = NULL; PBth_BluetoothGetRadioInfo Bth_BluetoothGetRadioInfo = NULL; PBth_BluetoothRemoveDevice Bth_BluetoothRemoveDevice = NULL; PBth_BluetoothSetServiceState Bth_BluetoothSetServiceState = NULL; +PBth_BluetoothAuthenticateDevice Bth_BluetoothAuthenticateDevice = NULL; HINSTANCE hid_lib = NULL; HINSTANCE bthprops_lib = NULL; @@ -114,12 +118,13 @@ inline void init_lib() Bth_BluetoothGetRadioInfo = (PBth_BluetoothGetRadioInfo)GetProcAddress(bthprops_lib, "BluetoothGetRadioInfo"); Bth_BluetoothRemoveDevice = (PBth_BluetoothRemoveDevice)GetProcAddress(bthprops_lib, "BluetoothRemoveDevice"); Bth_BluetoothSetServiceState = (PBth_BluetoothSetServiceState)GetProcAddress(bthprops_lib, "BluetoothSetServiceState"); + Bth_BluetoothAuthenticateDevice = (PBth_BluetoothAuthenticateDevice)GetProcAddress(bthprops_lib, "BluetoothAuthenticateDevice"); if (!Bth_BluetoothFindDeviceClose || !Bth_BluetoothFindFirstDevice || !Bth_BluetoothFindFirstRadio || !Bth_BluetoothFindNextDevice || !Bth_BluetoothFindNextRadio || !Bth_BluetoothFindRadioClose || !Bth_BluetoothGetRadioInfo || !Bth_BluetoothRemoveDevice || - !Bth_BluetoothSetServiceState) + !Bth_BluetoothSetServiceState || !Bth_BluetoothAuthenticateDevice) { PanicAlertT("Failed to load bthprops.cpl"); exit(EXIT_FAILURE); @@ -135,9 +140,9 @@ namespace WiimoteReal template void ProcessWiimotes(bool new_scan, T& callback); -bool AttachWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi); -void RemoveWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi); -bool ForgetWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi); +bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT&); +void RemoveWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&); +bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&); WiimoteScanner::WiimoteScanner() : m_run_thread() @@ -149,16 +154,19 @@ WiimoteScanner::WiimoteScanner() WiimoteScanner::~WiimoteScanner() { // TODO: what do we want here? - ProcessWiimotes(false, RemoveWiimote); + ProcessWiimotes(false, [](HANDLE, BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) + { + RemoveWiimote(btdi); + }); } void WiimoteScanner::Update() { bool forgot_some = false; - ProcessWiimotes(false, [&](HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) + ProcessWiimotes(false, [&](HANDLE, BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) { - forgot_some |= ForgetWiimote(hRadio, btdi); + forgot_some |= ForgetWiimote(btdi); }); // Some hacks that allows disconnects to be detected before connections are handled @@ -173,10 +181,10 @@ void WiimoteScanner::Update() // Returns the total number of found and connected wiimotes. std::vector WiimoteScanner::FindWiimotes() { - ProcessWiimotes(true, [](HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) + ProcessWiimotes(true, [](HANDLE hRadio, const BLUETOOTH_RADIO_INFO& rinfo, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) { - ForgetWiimote(hRadio, btdi); - AttachWiimote(hRadio, btdi); + ForgetWiimote(btdi); + AttachWiimote(hRadio, rinfo, btdi); }); // Get the device id @@ -485,31 +493,32 @@ void ProcessWiimotes(bool new_scan, T& callback) BLUETOOTH_RADIO_INFO radioInfo; radioInfo.dwSize = sizeof(radioInfo); - // TODO: check for SUCCEEDED() - Bth_BluetoothGetRadioInfo(hRadio, &radioInfo); - - srch.hRadio = hRadio; - - BLUETOOTH_DEVICE_INFO btdi; - btdi.dwSize = sizeof(btdi); - - // Enumerate BT devices - HBLUETOOTH_DEVICE_FIND hFindDevice = Bth_BluetoothFindFirstDevice(&srch, &btdi); - while (hFindDevice) + auto const rinfo_result = Bth_BluetoothGetRadioInfo(hRadio, &radioInfo); + if (ERROR_SUCCESS == rinfo_result) { - // btdi.szName is sometimes missings it's content - it's a bt feature.. - DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ", - btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered); + srch.hRadio = hRadio; - if (std::regex_match(btdi.szName, wiimote_device_name)) - { - callback(hRadio, btdi); - } + BLUETOOTH_DEVICE_INFO btdi; + btdi.dwSize = sizeof(btdi); - if (false == Bth_BluetoothFindNextDevice(hFindDevice, &btdi)) + // Enumerate BT devices + HBLUETOOTH_DEVICE_FIND hFindDevice = Bth_BluetoothFindFirstDevice(&srch, &btdi); + while (hFindDevice) { - Bth_BluetoothFindDeviceClose(hFindDevice); - hFindDevice = NULL; + // btdi.szName is sometimes missings it's content - it's a bt feature.. + DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ", + btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered); + + if (std::regex_match(btdi.szName, wiimote_device_name)) + { + callback(hRadio, radioInfo, btdi); + } + + if (false == Bth_BluetoothFindNextDevice(hFindDevice, &btdi)) + { + Bth_BluetoothFindDeviceClose(hFindDevice); + hFindDevice = NULL; + } } } @@ -521,7 +530,7 @@ void ProcessWiimotes(bool new_scan, T& callback) } } -void RemoveWiimote(HANDLE, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) +void RemoveWiimote(BLUETOOTH_DEVICE_INFO_STRUCT& btdi) { //if (btdi.fConnected) { @@ -532,14 +541,26 @@ void RemoveWiimote(HANDLE, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) } } -bool AttachWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) +bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO& radio_info, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) { // We don't want "remembered" devices. // SetServiceState will just fail with them.. if (!btdi.fConnected && !btdi.fRemembered) { - NOTICE_LOG(WIIMOTE, "Found wiimote. Enabling HID service."); + auto const& wm_addr = btdi.Address.rgBytes; + NOTICE_LOG(WIIMOTE, "Found wiimote (%02x:%02x:%02x:%02x:%02x:%02x). Enabling HID service.", + wm_addr[0], wm_addr[1], wm_addr[2], wm_addr[3], wm_addr[4], wm_addr[5]); + +#if defined(AUTHENTICATE_WIIMOTES) + // Authenticate + auto const& radio_addr = radio_info.address.rgBytes; + const DWORD auth_result = Bth_BluetoothAuthenticateDevice(NULL, hRadio, &btdi, + std::vector(radio_addr, radio_addr + 6).data(), 6); + + if (ERROR_SUCCESS != auth_result) + ERROR_LOG(WIIMOTE, "AttachWiimote: BluetoothAuthenticateDevice returned %08x", auth_result); +#endif // Activate service const DWORD hr = Bth_BluetoothSetServiceState(hRadio, &btdi, &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE); @@ -547,7 +568,7 @@ bool AttachWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) g_connect_times[btdi.Address.ullLong] = std::time(nullptr); if (FAILED(hr)) - ERROR_LOG(WIIMOTE, "Pair-Up: BluetoothSetServiceState() returned %08x", hr); + ERROR_LOG(WIIMOTE, "AttachWiimote: BluetoothSetServiceState returned %08x", hr); else return true; } @@ -556,7 +577,7 @@ bool AttachWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) } // Removes remembered non-connected devices -bool ForgetWiimote(HANDLE, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) +bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT& btdi) { if (!btdi.fConnected && btdi.fRemembered) { From 8c779bb2426a5eae7fbf0e5048ae18bdf3d34a3c Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 27 Feb 2013 10:26:32 -0600 Subject: [PATCH 22/70] Ah. I blame vim on this typo entirely. --- Source/Core/Common/Src/ArmEmitter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp index 6463dbe2ef..f24ffbb07f 100644 --- a/Source/Core/Common/Src/ArmEmitter.cpp +++ b/Source/Core/Common/Src/ArmEmitter.cpp @@ -791,7 +791,7 @@ void ARMXEmitter::VABS(ARMReg Vd, ARMReg Vm) if (single_reg) { - Write32(NO_COND | (0xEB << 20) | ((Vd & 0x1) << 6) | ((Vd & 0x1E) << 11) \ + Write32(NO_COND | (0xEB << 20) | ((Vd & 0x1) << 22) | ((Vd & 0x1E) << 11) \ | (0xAC << 4) | ((Vm & 0x1) << 5) | (Vm >> 1)); } else From f1d727cf1376efebf434abcaa31c63abd2894dad Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 27 Feb 2013 11:53:24 -0600 Subject: [PATCH 23/70] Merge latest ArmEmitter changes from ppsspp while we're at it. --- Source/Core/Common/Src/ArmEmitter.cpp | 137 +++++++++++++++++++++----- Source/Core/Common/Src/ArmEmitter.h | 16 +-- 2 files changed, 123 insertions(+), 30 deletions(-) diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp index f24ffbb07f..3b3bf7c550 100644 --- a/Source/Core/Common/Src/ArmEmitter.cpp +++ b/Source/Core/Common/Src/ArmEmitter.cpp @@ -22,11 +22,16 @@ #include #include -// For cache flushing on Symbian/Blackberry +// For cache flushing on Symbian/iOS/Blackberry #ifdef __SYMBIAN32__ #include #endif +#ifdef IOS +#include +#include +#endif + #ifdef BLACKBERRY #include #endif @@ -185,18 +190,16 @@ void ARMXEmitter::FlushIcache() void ARMXEmitter::FlushIcacheSection(u8 *start, u8 *end) { #ifdef __SYMBIAN32__ - User::IMB_Range( start, end); + User::IMB_Range(start, end); #elif defined(BLACKBERRY) msync(start, end - start, MS_SYNC | MS_INVALIDATE_ICACHE); -#else -#ifndef _WIN32 -#ifdef ANDROID - __builtin___clear_cache (start, end); -#else - // If on Linux, we HAVE to clear from start addr or else everything gets /really/ unstable - __builtin___clear_cache (startcode, end); -#endif +#elif defined(IOS) + sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start); +#elif !defined(_WIN32) +#ifndef ANDROID + start = startcode; #endif + __builtin___clear_cache(start, end); #endif } @@ -493,6 +496,7 @@ void ARMXEmitter::SMULL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn) { Write4OpMultiply(0xC, destLo, destHi, rn, rm); } + void ARMXEmitter::SXTB (ARMReg dest, ARMReg op2) { Write32(condition | (0x6AF << 16) | (dest << 12) | (7 << 4) | op2); @@ -528,9 +532,10 @@ void ARMXEmitter::MRS (ARMReg dest) { Write32(condition | (16 << 20) | (15 << 16) | (dest << 12)); } + void ARMXEmitter::WriteStoreOp(u32 op, ARMReg dest, ARMReg src, Operand2 op2) { - if (op2.GetData() == 0) // Don't index + if (op2.GetData() == 0) // set the preindex bit, but not the W bit! Write32(condition | 0x01800000 | (op << 20) | (dest << 16) | (src << 12) | op2.Imm12()); else Write32(condition | (op << 20) | (3 << 23) | (dest << 16) | (src << 12) | op2.Imm12()); @@ -620,6 +625,7 @@ ARMReg ARMXEmitter::SubBase(ARMReg Reg) } return Reg; } + // NEON Specific void ARMXEmitter::VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { @@ -627,7 +633,7 @@ void ARMXEmitter::VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) _assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VADD(integer) when CPU doesn't support it"); bool register_quad = Vd >= Q0; - + // Gets encoded as a double register Vd = SubBase(Vd); Vn = SubBase(Vn); @@ -651,16 +657,20 @@ void ARMXEmitter::VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg 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, u16 op) +void ARMXEmitter::VLDR(ARMReg Dest, ARMReg Base, u16 offset) { _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 & 3), "Offset needs to be word aligned"); + _assert_msg_(DYNA_REC, (offset & 0xC03) == 0, "VLDR: Offset needs to be word aligned and small enough"); + + if (offset & 0xC03) { + ERROR_LOG(DYNA_REC, "VLDR: Bad offset %08x", offset); + } + bool single_reg = Dest < D0; Dest = SubBase(Dest); @@ -668,20 +678,25 @@ void ARMXEmitter::VLDR(ARMReg Dest, ARMReg Base, u16 op) if (single_reg) { Write32(NO_COND | (0x1B << 23) | ((Dest & 0x1) << 22) | (1 << 20) | (Base << 16) \ - | ((Dest & 0x1E) << 11) | (10 << 8) | (op >> 2)); + | ((Dest & 0x1E) << 11) | (10 << 8) | (offset >> 2)); } else { Write32(NO_COND | (0x1B << 23) | ((Dest & 0x10) << 18) | (1 << 20) | (Base << 16) \ - | ((Dest & 0xF) << 12) | (11 << 8) | (op >> 2)); + | ((Dest & 0xF) << 12) | (11 << 8) | (offset >> 2)); } } -void ARMXEmitter::VSTR(ARMReg Src, ARMReg Base, u16 op) +void ARMXEmitter::VSTR(ARMReg Src, ARMReg Base, u16 offset) { _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 & 3), "Offset needs to be word aligned"); + _assert_msg_(DYNA_REC, (offset & 0xC03) == 0, "VSTR: Offset needs to be word aligned"); + + if (offset & 0xC03) { + ERROR_LOG(DYNA_REC, "VSTR: Bad offset %08x", offset); + } + bool single_reg = Src < D0; Src = SubBase(Src); @@ -689,13 +704,13 @@ void ARMXEmitter::VSTR(ARMReg Src, ARMReg Base, u16 op) if (single_reg) { Write32(NO_COND | (0x1B << 23) | ((Src & 0x1) << 22) | (Base << 16) \ - | ((Src & 0x1E) << 11) | (10 << 8) | (op >> 2)); + | ((Src & 0x1E) << 11) | (10 << 8) | (offset >> 2)); } else { Write32(NO_COND | (0x1B << 23) | ((Src & 0x10) << 18) | (Base << 16) \ - | ((Src & 0xF) << 12) | (11 << 8) | (op >> 2)); + | ((Src & 0xF) << 12) | (11 << 8) | (offset >> 2)); } } void ARMXEmitter::VCMP(ARMReg Vd, ARMReg Vm) @@ -779,12 +794,14 @@ void ARMXEmitter::VSQRT(ARMReg Vd, ARMReg Vm) | ((Vd & 0xF) << 12) | (0x2F << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF)); } } + // VFP and ASIMD void ARMXEmitter::VABS(ARMReg Vd, ARMReg Vm) { _assert_msg_(DYNA_REC, Vd < Q0, "VABS doesn't currently support Quad reg"); _assert_msg_(DYNA_REC, Vd >= S0, "VABS doesn't support ARM Regs"); bool single_reg = Vd < D0; + bool double_reg = Vd < Q0; Vd = SubBase(Vd); Vm = SubBase(Vm); @@ -796,10 +813,19 @@ void ARMXEmitter::VABS(ARMReg Vd, ARMReg Vm) } else { - Write32(NO_COND | (0xEB << 20) | ((Vd & 0x10) << 18) | ((Vd & 0xF) << 12) \ - | (0xBC << 4) | ((Vm & 0x10) << 1) | (Vm & 0xF)); + if (double_reg) + { + Write32(NO_COND | (0xEB << 20) | ((Vd & 0x10) << 18) | ((Vd & 0xF) << 12) \ + | (0xBC << 4) | ((Vm & 0x10) << 1) | (Vm & 0xF)); + } + else + { + _assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use VADD with Quad Reg without support!"); + // XXX: TODO + } } } + void ARMXEmitter::VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm) { _assert_msg_(DYNA_REC, Vd >= S0, "Passed invalid dest register to VADD"); @@ -870,6 +896,70 @@ void ARMXEmitter::VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm) } } } +void ARMXEmitter::VMUL(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) | (0x2 << 20) \ + | ((Vn & 0x1E) << 15) | ((Vd & 0x1E) << 11) | (0x5 << 9) \ + | ((Vn & 0x1) << 7) | ((Vm & 0x1) << 5) | (Vm >> 1)); + } + else + { + if (double_reg) + { + Write32(NO_COND | (0x1C << 23) | ((Vd & 0x10) << 18) | (0x2 << 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 VMUL with Quad Reg without support!"); + // XXX: TODO + } + } +} + +void ARMXEmitter::VNEG(ARMReg Vd, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd < Q0, "VNEG doesn't currently support Quad reg"); + _assert_msg_(DYNA_REC, Vd >= S0, "VNEG doesn't support ARM Regs"); + bool single_reg = Vd < D0; + bool double_reg = Vd < Q0; + + Vd = SubBase(Vd); + Vm = SubBase(Vm); + + if (single_reg) + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x1) << 22) | (0x31 << 16) \ + | ((Vd & 0x1E) << 11) | (0x29 << 6) | ((Vm & 0x1) << 5) | (Vm >> 1)); + } + else + { + if (double_reg) + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x10) << 18) | (0x31 << 16) \ + | ((Vd & 0xF) << 12) | (0x2D << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF)); + } + else + { + _assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use VNEG with Quad Reg without support!"); + // XXX: TODO + + } + } +} void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src, bool high) { @@ -881,6 +971,7 @@ void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src, bool high) Write32(NO_COND | (0xE << 24) | (high << 21) | ((Dest & 0xF) << 16) | (Src << 12) \ | (11 << 8) | ((Dest & 0x10) << 3) | (1 << 4)); } + void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src) { if (Dest > R15) diff --git a/Source/Core/Common/Src/ArmEmitter.h b/Source/Core/Common/Src/ArmEmitter.h index 13635867a9..a3ff7d25ae 100644 --- a/Source/Core/Common/Src/ArmEmitter.h +++ b/Source/Core/Common/Src/ArmEmitter.h @@ -227,7 +227,7 @@ public: } const u32 IMMSR() // IMM shifted register { - _assert_msg_(DYNA_REC, Type = TYPE_IMMSREG, "IMMSR must be imm shifted register"); + _assert_msg_(DYNA_REC, Type == TYPE_IMMSREG, "IMMSR must be imm shifted register"); return ((IndexOrShift & 0x1f) << 7 | (Shift << 5) | Value); } const u32 RSR() // Register shifted register @@ -343,8 +343,9 @@ private: void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2); void WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2); + void Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm); - + // New Ops void WriteInstruction(u32 op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags = false); @@ -452,7 +453,7 @@ public: void MUL (ARMReg dest, ARMReg src, ARMReg op2); void MULS(ARMReg dest, ARMReg src, ARMReg op2); - + void UMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm); void SMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm); @@ -498,8 +499,8 @@ public: void VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); // VFP Only - void VLDR(ARMReg Dest, ARMReg Base, u16 op); - void VSTR(ARMReg Src, ARMReg Base, u16 op); + void VLDR(ARMReg Dest, ARMReg Base, u16 offset); + void VSTR(ARMReg Src, ARMReg Base, u16 offset); void VCMP(ARMReg Vd, ARMReg Vm); // Compares against zero void VCMP(ARMReg Vd); @@ -507,10 +508,11 @@ public: void VSQRT(ARMReg Vd, ARMReg Vm); // NEON and VFP - void VABS(ARMReg Vd, ARMReg Vm); void VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm); - + void VABS(ARMReg Vd, ARMReg Vm); + void VNEG(ARMReg Vd, ARMReg Vm); + void VMUL(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VMOV(ARMReg Dest, ARMReg Src, bool high); void VMOV(ARMReg Dest, ARMReg Src); From 9ff704f202cf4d31e00476c08d27327f12478b8a Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 27 Feb 2013 15:17:23 -0600 Subject: [PATCH 24/70] Small improvement to cmpli/cmpi in ARMJit. --- .../Src/PowerPC/JitArm32/JitArm_Integer.cpp | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp index 63c96b21fd..753568c9d3 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp @@ -193,11 +193,18 @@ void JitArm::cmpi(UGeckoInstruction inst) JITDISABLE(Integer) ARMReg RA = gpr.R(inst.RA); - ARMReg rA = gpr.GetReg(); int crf = inst.CRFD; - MOVI2R(rA, inst.SIMM_16); - CMP(RA, rA); - gpr.Unlock(rA); + if (inst.SIMM_16 >= 0 && inst.SIMM_16 < 256) + { + CMP(RA, inst.SIMM_16); + } + else + { + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, inst.SIMM_16); + CMP(RA, rA); + gpr.Unlock(rA); + } ComputeRC(crf); } void JitArm::cmpli(UGeckoInstruction inst) @@ -208,9 +215,16 @@ void JitArm::cmpli(UGeckoInstruction inst) ARMReg RA = gpr.R(inst.RA); ARMReg rA = gpr.GetReg(); int crf = inst.CRFD; - MOVI2R(rA, (u32)inst.UIMM); - CMP(RA, rA); - + u32 uimm = (u32)inst.UIMM; + if (uimm < 256) + { + CMP(RA, uimm); + } + else + { + MOVI2R(rA, (u32)inst.UIMM); + CMP(RA, rA); + } // Unsigned GenerateRC() MOV(rA, 0x2); // Result == 0 From 0ea458b4dc9241a59fd18456c846be44694fdb7d Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 27 Feb 2013 18:00:42 -0600 Subject: [PATCH 25/70] Add functions for converting between UTF-8/16. --- Source/Core/Common/Src/StringUtil.cpp | 34 +++++++++++++++++++++++++++ Source/Core/Common/Src/StringUtil.h | 7 ++++++ 2 files changed, 41 insertions(+) diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index 6ef3d91a73..503c2810c3 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -22,6 +22,10 @@ #include "CommonPaths.h" #include "StringUtil.h" +#ifdef _WIN32 +#include +#endif + // faster than sscanf bool AsciiToHex(const char* _szValue, u32& result) { @@ -375,3 +379,33 @@ std::string UriEncode(const std::string & sSrc) delete [] pStart; return sResult; } + +#ifdef _WIN32 + +std::string UTF16ToUTF8(const std::wstring& input) +{ + auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr); + + std::string output; + output.resize(size); + + if (size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr)) + output.clear(); + + return output; +} + +std::wstring UTF8ToUTF16(const std::string& input) +{ + auto const size = MultiByteToWideChar(CP_UTF8, 0, input.data(), input.size(), nullptr, 0); + + std::wstring output; + output.resize(size); + + if (size != MultiByteToWideChar(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size())) + output.clear(); + + return output; +} + +#endif diff --git a/Source/Core/Common/Src/StringUtil.h b/Source/Core/Common/Src/StringUtil.h index 102ae2d5fb..4e02ce4506 100644 --- a/Source/Core/Common/Src/StringUtil.h +++ b/Source/Core/Common/Src/StringUtil.h @@ -97,4 +97,11 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st std::string UriDecode(const std::string & sSrc); std::string UriEncode(const std::string & sSrc); +#ifdef _WIN32 + +std::string UTF16ToUTF8(const std::wstring& str); +std::wstring UTF8ToUTF16(const std::string& str); + +#endif + #endif // _STRINGUTIL_H_ From ea75577278d818e4d3cb3b6db329017df69df00f Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 27 Feb 2013 18:01:48 -0600 Subject: [PATCH 26/70] Use the new UTF-16 conversion function in two places. --- .../Src/ControllerInterface/DInput/DInput.cpp | 16 +++++----------- Source/Plugins/Plugin_VideoDX11/Src/main.cpp | 6 ++---- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp index c23e9df17e..01baf9cf1a 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp @@ -4,7 +4,7 @@ #include "DInput.h" -#include +#include "StringUtil.h" #ifdef CIFACE_USE_DINPUT_JOYSTICK #include "DInputJoystick.h" @@ -41,24 +41,18 @@ BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) std::string GetDeviceName(const LPDIRECTINPUTDEVICE8 device) { - std::string out; - - DIPROPSTRING str; - ZeroMemory(&str, sizeof(str)); + DIPROPSTRING str = {}; str.diph.dwSize = sizeof(str); str.diph.dwHeaderSize = sizeof(str.diph); str.diph.dwHow = DIPH_DEVICE; + std::string result; if (SUCCEEDED(device->GetProperty(DIPROP_PRODUCTNAME, &str.diph))) { - const int size = WideCharToMultiByte(CP_UTF8, 0, str.wsz, -1, NULL, 0, NULL, NULL); - char* const data = new char[size]; - if (size == WideCharToMultiByte(CP_UTF8, 0, str.wsz, -1, data, size, NULL, NULL)) - out.assign(data); - delete[] data; + result = StripSpaces(UTF16ToUTF8(str.wsz)); } - return StripSpaces(out); + return result; } void Init(std::vector& devices, HWND hwnd) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index b7dd9101d3..512f70eaa7 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -102,15 +102,13 @@ void InitBackendInfo() if (FAILED(hr)) PanicAlert("Failed to create IDXGIFactory object"); - char tmpstr[512] = {}; - DXGI_ADAPTER_DESC desc; // adapters g_Config.backend_info.Adapters.clear(); g_Config.backend_info.AAModes.clear(); while (factory->EnumAdapters((UINT)g_Config.backend_info.Adapters.size(), &ad) != DXGI_ERROR_NOT_FOUND) { + DXGI_ADAPTER_DESC desc; ad->GetDesc(&desc); - WideCharToMultiByte(/*CP_UTF8*/CP_ACP, 0, desc.Description, -1, tmpstr, 512, 0, false); // TODO: These don't get updated on adapter change, yet if (g_Config.backend_info.Adapters.size() == g_Config.iAdapter) @@ -127,7 +125,7 @@ void InitBackendInfo() } } - g_Config.backend_info.Adapters.push_back(tmpstr); + g_Config.backend_info.Adapters.push_back(UTF16ToUTF8(desc.Description)); ad->Release(); } From 69f7671ee8184b109d801243707116eb1a5cba56 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 27 Feb 2013 18:51:02 -0600 Subject: [PATCH 27/70] Fix "Common" to build with "Unicode" project setting. --- Source/Core/Common/Common.vcxproj | 4 +- Source/Core/Common/Src/CDUtils.cpp | 11 ++--- Source/Core/Common/Src/ConsoleListener.cpp | 4 +- Source/Core/Common/Src/ExtendedTrace.cpp | 52 +++++++++------------- Source/Core/Common/Src/ExtendedTrace.h | 9 ++-- Source/Core/Common/Src/FileSearch.cpp | 5 +-- Source/Core/Common/Src/FileUtil.cpp | 19 ++++---- Source/Core/Common/Src/Misc.cpp | 2 +- Source/Core/Common/Src/MsgHandler.cpp | 2 +- Source/Core/Common/Src/StringUtil.h | 14 ++++++ 10 files changed, 63 insertions(+), 59 deletions(-) diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 626a4df909..822fafe74b 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -44,7 +44,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary @@ -54,7 +54,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary diff --git a/Source/Core/Common/Src/CDUtils.cpp b/Source/Core/Common/Src/CDUtils.cpp index 42aa9bfe34..9a302b9189 100644 --- a/Source/Core/Common/Src/CDUtils.cpp +++ b/Source/Core/Common/Src/CDUtils.cpp @@ -6,6 +6,7 @@ #include // for std::unique_ptr #ifdef _WIN32 #include +#include "StringUtil.h" #elif __APPLE__ #include #include @@ -25,7 +26,7 @@ #ifdef _WIN32 // takes a root drive path, returns true if it is a cdrom drive -bool is_cdrom(const char drive[]) +bool is_cdrom(const TCHAR* drive) { return (DRIVE_CDROM == GetDriveType(drive)); } @@ -36,15 +37,15 @@ std::vector cdio_get_devices() std::vector drives; const DWORD buffsize = GetLogicalDriveStrings(0, NULL); - std::unique_ptr buff(new char[buffsize]); - if (GetLogicalDriveStrings(buffsize, buff.get()) == buffsize - 1) + std::vector buff(buffsize); + if (GetLogicalDriveStrings(buffsize, buff.data()) == buffsize - 1) { - const char* drive = buff.get(); + auto drive = buff.data(); while (*drive) { if (is_cdrom(drive)) { - std::string str(drive); + std::string str(TStrToUTF8(drive)); str.pop_back(); // we don't want the final backslash drives.push_back(std::move(str)); } diff --git a/Source/Core/Common/Src/ConsoleListener.cpp b/Source/Core/Common/Src/ConsoleListener.cpp index cf03581431..5a4ff126bf 100644 --- a/Source/Core/Common/Src/ConsoleListener.cpp +++ b/Source/Core/Common/Src/ConsoleListener.cpp @@ -61,7 +61,7 @@ void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title // Save the window handle that AllocConsole() created hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // Set the console window title - SetConsoleTitle(Title); + SetConsoleTitle(UTF8ToTStr(Title).c_str()); // Set letter space LetterSpace(80, 4000); //MoveWindow(GetConsoleWindow(), 200,200, 800,800, true); @@ -195,7 +195,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool static const int MAX_BYTES = 1024 * 16; - std::vector> Str; + std::vector> Str; std::vector> Attr; // ReadConsoleOutputAttribute seems to have a limit at this level diff --git a/Source/Core/Common/Src/ExtendedTrace.cpp b/Source/Core/Common/Src/ExtendedTrace.cpp index 3fe661f2e4..85057639a5 100644 --- a/Source/Core/Common/Src/ExtendedTrace.cpp +++ b/Source/Core/Common/Src/ExtendedTrace.cpp @@ -17,6 +17,7 @@ #include #include #include "ExtendedTrace.h" +#include "StringUtil.h" using namespace std; #include @@ -274,13 +275,21 @@ static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo ) return ret; } -void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file ) +void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack) +{ + TCHAR symInfo[BUFFERSIZE] = _T("?"); + TCHAR srcInfo[BUFFERSIZE] = _T("?"); + + GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo); + GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo); + etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n"); +} + +void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file ) { STACKFRAME callStack; BOOL bResult; CONTEXT context; - TCHAR symInfo[BUFFERSIZE] = _T("?"); - TCHAR srcInfo[BUFFERSIZE] = _T("?"); HANDLE hProcess = GetCurrentProcess(); // If it's not this thread, let's suspend it, and resume it at the end @@ -318,9 +327,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file ) etfprint(file, "Call stack info: \n"); etfprint(file, lpszMessage); - GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo ); - GetSourceInfoFromAddress( (ULONG)callStack.AddrPC.Offset, srcInfo ); - etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n")); + PrintFunctionAndSourceInfo(file, callStack); for( ULONG index = 0; ; index++ ) { @@ -341,9 +348,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file ) if( !bResult || callStack.AddrFrame.Offset == 0 ) break; - GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo ); - GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo ); - etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n")); + PrintFunctionAndSourceInfo(file, callStack); } @@ -351,19 +356,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file ) ResumeThread( hThread ); } -void StackTrace( HANDLE hThread, wchar_t const*lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp ) -{ - // TODO: remove when Common builds as unicode - size_t origsize = wcslen(lpszMessage) + 1; - const size_t newsize = 100; - size_t convertedChars = 0; - char nstring[newsize]; - wcstombs_s(&convertedChars, nstring, origsize, lpszMessage, _TRUNCATE); - - StackTrace(hThread, nstring, file, eip, esp, ebp ); -} - -void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp ) +void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp ) { STACKFRAME callStack; BOOL bResult; @@ -391,9 +384,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO etfprint(file, "Call stack info: \n"); etfprint(file, lpszMessage); - GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo ); - GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo ); - etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n")); + PrintFunctionAndSourceInfo(file, callStack); for( ULONG index = 0; ; index++ ) { @@ -414,10 +405,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO if( !bResult || callStack.AddrFrame.Offset == 0 ) break; - GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo ); - GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo ); - etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n")); - + PrintFunctionAndSourceInfo(file, callStack); } if ( hThread != GetCurrentThread() ) @@ -426,7 +414,8 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO char g_uefbuf[2048]; -void etfprintf(FILE *file, const char *format, ...) { +void etfprintf(FILE *file, const char *format, ...) +{ va_list ap; va_start(ap, format); int len = vsprintf(g_uefbuf, format, ap); @@ -434,7 +423,8 @@ void etfprintf(FILE *file, const char *format, ...) { va_end(ap); } -void etfprint(FILE *file, const std::string &text) { +void etfprint(FILE *file, const std::string &text) +{ size_t len = text.length(); fwrite(text.data(), 1, len, file); } diff --git a/Source/Core/Common/Src/ExtendedTrace.h b/Source/Core/Common/Src/ExtendedTrace.h index 12e7ed41fa..003c8a68e3 100644 --- a/Source/Core/Common/Src/ExtendedTrace.h +++ b/Source/Core/Common/Src/ExtendedTrace.h @@ -26,15 +26,14 @@ #define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) InitSymInfo( IniSymbolPath ) #define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo() -#define STACKTRACE(file) StackTrace( GetCurrentThread(), _T(""), file) -#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), _T(""), file, eip, esp, ebp) +#define STACKTRACE(file) StackTrace( GetCurrentThread(), "", file) +#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp) // class File; BOOL InitSymInfo( PCSTR ); BOOL UninitSymInfo(); -void StackTrace( HANDLE, LPCTSTR, FILE *file); -void StackTrace( HANDLE, LPCTSTR, FILE *file, DWORD eip, DWORD esp, DWORD ebp); -void StackTrace( HANDLE hThread, wchar_t const* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp); +void StackTrace(HANDLE, char const* msg, FILE *file); +void StackTrace(HANDLE, char const* msg, FILE *file, DWORD eip, DWORD esp, DWORD ebp); // functions by Masken void etfprintf(FILE *file, const char *format, ...); diff --git a/Source/Core/Common/Src/FileSearch.cpp b/Source/Core/Common/Src/FileSearch.cpp index 595dfe7000..674cf0e1d5 100644 --- a/Source/Core/Common/Src/FileSearch.cpp +++ b/Source/Core/Common/Src/FileSearch.cpp @@ -51,7 +51,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string& BuildCompleteFilename(GCMSearchPath, _strPath, _searchString); #ifdef _WIN32 WIN32_FIND_DATA findData; - HANDLE FindFirst = FindFirstFile(GCMSearchPath.c_str(), &findData); + HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData); if (FindFirst != INVALID_HANDLE_VALUE) { @@ -62,7 +62,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string& if (findData.cFileName[0] != '.') { std::string strFilename; - BuildCompleteFilename(strFilename, _strPath, findData.cFileName); + BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName)); m_FileNames.push_back(strFilename); } @@ -112,7 +112,6 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string& #endif } - const CFileSearch::XStringVector& CFileSearch::GetFileNames() const { return m_FileNames; diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp index f42c204396..b3c2d7c161 100644 --- a/Source/Core/Common/Src/FileUtil.cpp +++ b/Source/Core/Common/Src/FileUtil.cpp @@ -41,10 +41,11 @@ #include #endif -#include #include #include +#include "StringUtil.h" + #ifndef S_ISDIR #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) #endif @@ -127,7 +128,7 @@ bool Delete(const std::string &filename) } #ifdef _WIN32 - if (!DeleteFile(filename.c_str())) + if (!DeleteFile(UTF8ToTStr(filename).c_str())) { WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s", filename.c_str(), GetLastErrorMsg()); @@ -149,7 +150,7 @@ bool CreateDir(const std::string &path) { INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str()); #ifdef _WIN32 - if (::CreateDirectory(path.c_str(), NULL)) + if (::CreateDirectory(UTF8ToTStr(path).c_str(), NULL)) return true; DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) @@ -228,7 +229,7 @@ bool DeleteDir(const std::string &filename) } #ifdef _WIN32 - if (::RemoveDirectory(filename.c_str())) + if (::RemoveDirectory(UTF8ToTStr(filename).c_str())) return true; #else if (rmdir(filename.c_str()) == 0) @@ -257,7 +258,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename) INFO_LOG(COMMON, "Copy: %s --> %s", srcFilename.c_str(), destFilename.c_str()); #ifdef _WIN32 - if (CopyFile(srcFilename.c_str(), destFilename.c_str(), FALSE)) + if (CopyFile(UTF8ToTStr(srcFilename).c_str(), UTF8ToTStr(destFilename).c_str(), FALSE)) return true; ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s", @@ -413,7 +414,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry) // Find the first file in the directory. WIN32_FIND_DATA ffd; - HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd); + HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); @@ -423,7 +424,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry) do { FSTEntry entry; - const std::string virtualName(ffd.cFileName); + const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else struct dirent dirent, *result = NULL; @@ -480,7 +481,7 @@ bool DeleteDirRecursively(const std::string &directory) #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; - HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd); + HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { @@ -491,7 +492,7 @@ bool DeleteDirRecursively(const std::string &directory) // windows loop do { - const std::string virtualName = ffd.cFileName; + const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else struct dirent dirent, *result = NULL; DIR *dirp = opendir(directory.c_str()); diff --git a/Source/Core/Common/Src/Misc.cpp b/Source/Core/Common/Src/Misc.cpp index aafe37886f..8364bda48d 100644 --- a/Source/Core/Common/Src/Misc.cpp +++ b/Source/Core/Common/Src/Misc.cpp @@ -31,7 +31,7 @@ const char* GetLastErrorMsg() #ifdef _WIN32 static __declspec(thread) char err_str[buff_size] = {}; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err_str, buff_size, NULL); #else diff --git a/Source/Core/Common/Src/MsgHandler.cpp b/Source/Core/Common/Src/MsgHandler.cpp index 7c666227aa..283dc72ef1 100644 --- a/Source/Core/Common/Src/MsgHandler.cpp +++ b/Source/Core/Common/Src/MsgHandler.cpp @@ -106,7 +106,7 @@ bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int S if (Style == QUESTION) STYLE = MB_ICONQUESTION; if (Style == WARNING) STYLE = MB_ICONWARNING; - return IDYES == MessageBox(0, text, caption, STYLE | (yes_no ? MB_YESNO : MB_OK)); + return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK)); #else printf("%s\n", text); diff --git a/Source/Core/Common/Src/StringUtil.h b/Source/Core/Common/Src/StringUtil.h index 4e02ce4506..5177bc8ed8 100644 --- a/Source/Core/Common/Src/StringUtil.h +++ b/Source/Core/Common/Src/StringUtil.h @@ -102,6 +102,20 @@ std::string UriEncode(const std::string & sSrc); std::string UTF16ToUTF8(const std::wstring& str); std::wstring UTF8ToUTF16(const std::string& str); +#ifdef _UNICODE +inline std::string TStrToUTF8(const std::wstring& str) +{ return UTF16ToUTF8(str); } + +inline std::wstring UTF8ToTStr(const std::string& str) +{ return UTF8ToUTF16(str); } +#else +inline std::string TStrToUTF8(const std::string& str) +{ return str; } + +inline std::string UTF8ToTStr(const std::string& str) +{ return str; } +#endif + #endif #endif // _STRINGUTIL_H_ From 65683ebc6494623a7bf0e297522b6912319e3e8c Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 27 Feb 2013 19:43:29 -0600 Subject: [PATCH 28/70] Hopefully fix all filename handling to support Unicode. --- Source/Core/Common/Src/FileUtil.cpp | 48 ++++++++++----------------- Source/Core/Common/Src/SDCardUtil.cpp | 7 ++-- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp index b3c2d7c161..78685bbe70 100644 --- a/Source/Core/Common/Src/FileUtil.cpp +++ b/Source/Core/Common/Src/FileUtil.cpp @@ -82,7 +82,7 @@ bool Exists(const std::string &filename) std::string copy(filename); StripTailDirSlashes(copy); - int result = stat64(copy.c_str(), &file_info); + int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info); return (result == 0); } @@ -95,7 +95,7 @@ bool IsDirectory(const std::string &filename) std::string copy(filename); StripTailDirSlashes(copy); - int result = stat64(copy.c_str(), &file_info); + int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info); if (result < 0) { WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s", @@ -344,7 +344,7 @@ u64 GetSize(const std::string &filename) return 0; } struct stat64 buf; - if (stat64(filename.c_str(), &buf) == 0) + if (_tstat64(UTF8ToTStr(filename).c_str(), &buf) == 0) { DEBUG_LOG(COMMON, "GetSize: %s: %lld", filename.c_str(), (long long)buf.st_size); @@ -392,13 +392,13 @@ bool CreateEmptyFile(const std::string &filename) { INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str()); - FILE *pFile = fopen(filename.c_str(), "wb"); - if (!pFile) { + if (!File::IOFile(filename, "wb")) + { ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s", filename.c_str(), GetLastErrorMsg()); return false; } - fclose(pFile); + return true; } @@ -623,14 +623,14 @@ std::string GetBundleDirectory() #endif #ifdef _WIN32 -std::string &GetExeDirectory() +std::string& GetExeDirectory() { static std::string DolphinPath; if (DolphinPath.empty()) { - char Dolphin_exe_Path[2048]; - GetModuleFileNameA(NULL, Dolphin_exe_Path, 2048); - DolphinPath = Dolphin_exe_Path; + TCHAR Dolphin_exe_Path[2048]; + GetModuleFileName(NULL, Dolphin_exe_Path, 2048); + DolphinPath = TStrToUTF8(Dolphin_exe_Path); DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\')); } return DolphinPath; @@ -731,31 +731,19 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath) bool WriteStringToFile(bool text_file, const std::string &str, const char *filename) { - FILE *f = fopen(filename, text_file ? "w" : "wb"); - if (!f) - return false; - size_t len = str.size(); - if (len != fwrite(str.data(), 1, str.size(), f)) // TODO: string::data() may not be contiguous - { - fclose(f); - return false; - } - fclose(f); - return true; + return File::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size()); } bool ReadFileToString(bool text_file, const char *filename, std::string &str) { - FILE *f = fopen(filename, text_file ? "r" : "rb"); + File::IOFile file(filename, text_file ? "r" : "rb"); + auto const f = file.GetHandle(); + if (!f) return false; - size_t len = (size_t)GetSize(f); - char *buf = new char[len + 1]; - buf[fread(buf, 1, len, f)] = 0; - str = std::string(buf, len); - fclose(f); - delete [] buf; - return true; + + str.resize(GetSize(f)); + return file.ReadArray(&str[0], str.size()); } IOFile::IOFile() @@ -799,7 +787,7 @@ bool IOFile::Open(const std::string& filename, const char openmode[]) { Close(); #ifdef _WIN32 - fopen_s(&m_file, filename.c_str(), openmode); + _tfopen_s(&m_file, UTF8ToTStr(filename).c_str(), UTF8ToTStr(openmode).c_str()); #else m_file = fopen(filename.c_str(), openmode); #endif diff --git a/Source/Core/Common/Src/SDCardUtil.cpp b/Source/Core/Common/Src/SDCardUtil.cpp index 0f2ad08607..cf37ffff3e 100644 --- a/Source/Core/Common/Src/SDCardUtil.cpp +++ b/Source/Core/Common/Src/SDCardUtil.cpp @@ -29,6 +29,7 @@ // Modified for Dolphin. #include "SDCardUtil.h" +#include "FileUtil.h" #include #include @@ -190,7 +191,6 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename) { u32 sectors_per_fat; u32 sectors_per_disk; - FILE* f; // Convert MB to bytes disk_size *= 1024 * 1024; @@ -207,7 +207,8 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename) boot_sector_init(s_boot_sector, s_fsinfo_sector, disk_size, nullptr); fat_init(s_fat_head); - f = fopen(filename, "wb"); + File::IOFile file(filename, "wb"); + FILE* const f = file.GetHandle(); if (!f) { ERROR_LOG(COMMON, "Could not create file '%s', aborting...\n", filename); @@ -247,13 +248,11 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename) if (write_empty(f, sectors_per_disk - RESERVED_SECTORS - 2*sectors_per_fat)) goto FailWrite; - fclose(f); return true; FailWrite: ERROR_LOG(COMMON, "Could not write to '%s', aborting...\n", filename); if (unlink(filename) < 0) ERROR_LOG(COMMON, "unlink(%s) failed\n%s", filename, GetLastErrorMsg()); - fclose(f); return false; } From 536c110b31339eab5437c5f023494a9ec5c9364b Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 27 Feb 2013 20:04:07 -0600 Subject: [PATCH 29/70] Fix "DiscIO" to build with "Unicode". --- Source/Core/DiscIO/DiscIO.vcxproj | 4 ++-- Source/Core/DiscIO/Src/DriveBlob.cpp | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Source/Core/DiscIO/DiscIO.vcxproj b/Source/Core/DiscIO/DiscIO.vcxproj index 6dd24ddd44..722aae2040 100644 --- a/Source/Core/DiscIO/DiscIO.vcxproj +++ b/Source/Core/DiscIO/DiscIO.vcxproj @@ -44,7 +44,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary @@ -54,7 +54,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary diff --git a/Source/Core/DiscIO/Src/DriveBlob.cpp b/Source/Core/DiscIO/Src/DriveBlob.cpp index e69f8ff34c..2638f3fac4 100644 --- a/Source/Core/DiscIO/Src/DriveBlob.cpp +++ b/Source/Core/DiscIO/Src/DriveBlob.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include "DriveBlob.h" +#include "StringUtil.h" namespace DiscIO { @@ -23,12 +24,9 @@ namespace DiscIO DriveReader::DriveReader(const char *drive) { #ifdef _WIN32 - char path[MAX_PATH]; - strncpy(path, drive, 3); - path[2] = 0; - sprintf(path, "\\\\.\\%s", drive); SectorReader::SetSectorSize(2048); - hDisc = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + auto const path = UTF8ToTStr(std::string("\\\\.\\") + drive); + hDisc = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); if (hDisc != INVALID_HANDLE_VALUE) { From 6f87611767ea9072a2680154b26dd8d3f2dd0222 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 27 Feb 2013 20:27:22 -0600 Subject: [PATCH 30/70] Fix "Core" to build with "Unicode". --- Source/Core/Core/Core.vcxproj | 6 +-- Source/Core/Core/Src/ConfigManager.cpp | 6 +-- Source/Core/Core/Src/Console.cpp | 4 +- Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp | 46 +++++++++---------- Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h | 14 +++--- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 6 +-- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 2 +- .../Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp | 5 +- 8 files changed, 41 insertions(+), 48 deletions(-) diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 1dd547b2ea..17495de740 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -44,7 +44,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary @@ -54,7 +54,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary @@ -602,4 +602,4 @@ - + \ No newline at end of file diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index 85ecc7143f..8c7872119e 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -137,7 +137,7 @@ void SConfig::SaveSettings() ini.Get("General", "GCMPathes", &oldPaths, 0); for (int i = numPaths; i < oldPaths; i++) { - TCHAR tmp[16]; + char tmp[16]; sprintf(tmp, "GCMPath%i", i); ini.DeleteKey("General", tmp); } @@ -146,7 +146,7 @@ void SConfig::SaveSettings() for (int i = 0; i < numPaths; i++) { - TCHAR tmp[16]; + char tmp[16]; sprintf(tmp, "GCMPath%i", i); ini.Set("General", tmp, m_ISOFolder[i]); } @@ -284,7 +284,7 @@ void SConfig::LoadSettings() { for (int i = 0; i < numGCMPaths; i++) { - TCHAR tmp[16]; + char tmp[16]; sprintf(tmp, "GCMPath%i", i); std::string tmpPath; ini.Get("General", tmp, &tmpPath, ""); diff --git a/Source/Core/Core/Src/Console.cpp b/Source/Core/Core/Src/Console.cpp index 759dc46bc5..b0ef416a84 100644 --- a/Source/Core/Core/Src/Console.cpp +++ b/Source/Core/Core/Src/Console.cpp @@ -98,8 +98,8 @@ void Console_Submit(const char *cmd) } CASE("dump") { - TCHAR temp[256]; - TCHAR filename[256]; + char temp[256]; + char filename[256]; u32 start; u32 end; sscanf(cmd, "%s %08x %08x %s", temp, &start, &end, filename); diff --git a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp index 87ebd90344..03332d3012 100644 --- a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp +++ b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp @@ -25,7 +25,7 @@ namespace Win32TAPHelper { -bool IsTAPDevice(const char *guid) +bool IsTAPDevice(const TCHAR *guid) { HKEY netcard_key; LONG status; @@ -39,13 +39,13 @@ bool IsTAPDevice(const char *guid) for (;;) { - char enum_name[256]; - char unit_string[256]; + TCHAR enum_name[256]; + TCHAR unit_string[256]; HKEY unit_key; - char component_id_string[] = "ComponentId"; - char component_id[256]; - char net_cfg_instance_id_string[] = "NetCfgInstanceId"; - char net_cfg_instance_id[256]; + TCHAR component_id_string[] = _T("ComponentId"); + TCHAR component_id[256]; + TCHAR net_cfg_instance_id_string[] = _T("NetCfgInstanceId"); + TCHAR net_cfg_instance_id[256]; DWORD data_type; len = sizeof(enum_name); @@ -56,7 +56,7 @@ bool IsTAPDevice(const char *guid) else if (status != ERROR_SUCCESS) return false; - snprintf(unit_string, sizeof(unit_string), "%s\\%s", ADAPTER_KEY, enum_name); + _sntprintf(unit_string, sizeof(unit_string), _T("%s\\%s"), ADAPTER_KEY, enum_name); status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit_string, 0, KEY_READ, &unit_key); @@ -78,8 +78,8 @@ bool IsTAPDevice(const char *guid) if (status == ERROR_SUCCESS && data_type == REG_SZ) { - if (!strcmp(component_id, TAP_COMPONENT_ID) && - !strcmp(net_cfg_instance_id, guid)) + if (!_tcscmp(component_id, TAP_COMPONENT_ID) && + !_tcscmp(net_cfg_instance_id, guid)) { RegCloseKey(unit_key); RegCloseKey(netcard_key); @@ -96,7 +96,7 @@ bool IsTAPDevice(const char *guid) return false; } -bool GetGUIDs(std::vector& guids) +bool GetGUIDs(std::vector>& guids) { LONG status; HKEY control_net_key; @@ -111,12 +111,12 @@ bool GetGUIDs(std::vector& guids) while (!found_all) { - char enum_name[256]; - char connection_string[256]; + TCHAR enum_name[256]; + TCHAR connection_string[256]; HKEY connection_key; - char name_data[256]; + TCHAR name_data[256]; DWORD name_type; - const char name_string[] = "Name"; + const TCHAR name_string[] = _T("Name"); len = sizeof(enum_name); status = RegEnumKeyEx(control_net_key, i, enum_name, @@ -127,8 +127,8 @@ bool GetGUIDs(std::vector& guids) else if (status != ERROR_SUCCESS) return false; - snprintf(connection_string, sizeof(connection_string), - "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, enum_name); + _sntprintf(connection_string, sizeof(connection_string), + _T("%s\\%s\\Connection"), NETWORK_CONNECTIONS_KEY, enum_name); status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, connection_string, 0, KEY_READ, &connection_key); @@ -165,15 +165,11 @@ bool GetGUIDs(std::vector& guids) return true; } -bool OpenTAP(HANDLE& adapter, const std::string device_guid) +bool OpenTAP(HANDLE& adapter, const std::basic_string& device_guid) { - char device_path[256]; + auto const device_path = USERMODEDEVICEDIR + device_guid + TAPSUFFIX; - /* Open Windows TAP-Win32 adapter */ - snprintf(device_path, sizeof(device_path), "%s%s%s", - USERMODEDEVICEDIR, device_guid.c_str(), TAPSUFFIX); - - adapter = CreateFile(device_path, GENERIC_READ | GENERIC_WRITE, 0, 0, + adapter = CreateFile(device_path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); if (adapter == INVALID_HANDLE_VALUE) @@ -192,7 +188,7 @@ bool CEXIETHERNET::Activate() return true; DWORD len; - std::vector device_guids; + std::vector> device_guids; if (!Win32TAPHelper::GetGUIDs(device_guids)) { diff --git a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h index 2676a3fc7e..2a5bc52ffa 100644 --- a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h +++ b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h @@ -65,18 +65,18 @@ // Registry keys //================= -#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" +#define ADAPTER_KEY _T("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}") -#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" +#define NETWORK_CONNECTIONS_KEY _T("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}") //====================== // Filesystem prefixes //====================== -#define USERMODEDEVICEDIR "\\\\.\\Global\\" -#define SYSDEVICEDIR "\\Device\\" -#define USERDEVICEDIR "\\DosDevices\\Global\\" -#define TAPSUFFIX ".tap" +#define USERMODEDEVICEDIR _T("\\\\.\\Global\\") +#define SYSDEVICEDIR _T("\\Device\\") +#define USERDEVICEDIR _T("\\DosDevices\\Global\\") +#define TAPSUFFIX _T(".tap") //========================================================= // TAP_COMPONENT_ID -- This string defines the TAP driver @@ -84,4 +84,4 @@ // simultaneously. //========================================================= -#define TAP_COMPONENT_ID "tap0901" +#define TAP_COMPONENT_ID _T("tap0901") diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 2ae34a7ca5..2407d697a4 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -464,9 +463,6 @@ int Wiimote::IOWrite(const u8* buf, int len) template void ProcessWiimotes(bool new_scan, T& callback) { - // match strings like "Nintendo RVL-WBC-01", "Nintendo RVL-CNT-01", "Nintendo RVL-CNT-01-TR" - const std::wregex wiimote_device_name(L"Nintendo RVL-.*"); - BLUETOOTH_DEVICE_SEARCH_PARAMS srch; srch.dwSize = sizeof(srch); srch.fReturnAuthenticated = true; @@ -509,7 +505,7 @@ void ProcessWiimotes(bool new_scan, T& callback) DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ", btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered); - if (std::regex_match(btdi.szName, wiimote_device_name)) + if (IsValidBluetoothName(UTF16ToUTF8(btdi.szName))) { callback(hRadio, radioInfo, btdi); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index 793a13ceb0..cfc66106b4 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -91,7 +91,7 @@ public: int int_sock; // Interrupt socket #elif defined(_WIN32) - std::string devicepath; // Unique wiimote reference + std::basic_string devicepath; // Unique wiimote reference //ULONGLONG btaddr; // Bluetooth address HANDLE dev_handle; // HID handle OVERLAPPED hid_overlap_read, hid_overlap_write; // Overlap handle diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp index 3eb0096929..363176e18a 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -58,6 +58,7 @@ #include "CommonPaths.h" #include "IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "../Movie.h" +#include "StringUtil.h" #ifdef _WIN32 #include @@ -926,7 +927,7 @@ u32 CWII_IPC_HLE_Device_es::ES_DIVerify(u8* _pTMD, u32 _sz) else { #ifdef _WIN32 - MoveFile(savePath.c_str(), (savePath + "../backup/").c_str()); + MoveFile(UTF8ToTStr(savePath).c_str(), UTF8ToTStr(savePath + "../backup/").c_str()); #else File::CopyDir(savePath.c_str(),(savePath + "../backup/").c_str()); File::DeleteDirRecursively(savePath.c_str()); @@ -940,7 +941,7 @@ u32 CWII_IPC_HLE_Device_es::ES_DIVerify(u8* _pTMD, u32 _sz) if (File::Exists((savePath + "banner.bin").c_str())) File::DeleteDirRecursively(savePath); #ifdef _WIN32 - MoveFile((savePath + "../backup/").c_str(), savePath.c_str()); + MoveFile(UTF8ToTStr(savePath + "../backup/").c_str(), UTF8ToTStr(savePath).c_str()); #else File::CopyDir((savePath + "../backup/").c_str(), savePath.c_str()); File::DeleteDirRecursively((savePath + "../backup/").c_str()); From e82d976d2f2e2f026ecdcdbe978ce7eaeb0da804 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 27 Feb 2013 20:55:19 -0600 Subject: [PATCH 31/70] Buildfix for non-legacy OSes. --- Source/Core/Common/Src/FileUtil.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp index 78685bbe70..7b9ab2e464 100644 --- a/Source/Core/Common/Src/FileUtil.cpp +++ b/Source/Core/Common/Src/FileUtil.cpp @@ -82,7 +82,11 @@ bool Exists(const std::string &filename) std::string copy(filename); StripTailDirSlashes(copy); +#ifdef _WIN32 int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info); +#else + int result = stat64(copy.c_str(), &file_info); +#endif return (result == 0); } @@ -95,7 +99,11 @@ bool IsDirectory(const std::string &filename) std::string copy(filename); StripTailDirSlashes(copy); +#ifdef _WIN32 int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info); +#else + int result = stat64(copy.c_str(), &file_info); +#endif if (result < 0) { WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s", @@ -343,8 +351,13 @@ u64 GetSize(const std::string &filename) WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str()); return 0; } + struct stat64 buf; +#ifdef _WIN32 if (_tstat64(UTF8ToTStr(filename).c_str(), &buf) == 0) +#else + if (stat64(filename.c_str(), &buf) == 0) +#endif { DEBUG_LOG(COMMON, "GetSize: %s: %lld", filename.c_str(), (long long)buf.st_size); From 56f09d3b91479deb0f3ae3c7ce623c7a4724e087 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 27 Feb 2013 22:37:38 -0600 Subject: [PATCH 32/70] Attempt to be consistent with conversions between std::string and wxString. --- Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp | 11 +-- Source/Core/DolphinWX/Src/AboutDolphin.cpp | 3 +- Source/Core/DolphinWX/Src/CheatsWindow.cpp | 13 ++-- Source/Core/DolphinWX/Src/ConfigMain.cpp | 42 +++++------ .../DolphinWX/Src/Debugger/BreakpointDlg.cpp | 5 +- .../DolphinWX/Src/Debugger/BreakpointView.cpp | 19 ++--- .../Core/DolphinWX/Src/Debugger/CodeView.cpp | 39 +++++----- .../DolphinWX/Src/Debugger/CodeWindow.cpp | 21 +++--- .../Src/Debugger/CodeWindowFunctions.cpp | 20 ++--- .../DolphinWX/Src/Debugger/DSPDebugWindow.cpp | 6 +- .../Src/Debugger/DSPRegisterView.cpp | 4 +- .../Core/DolphinWX/Src/Debugger/JitWindow.cpp | 1 + .../DolphinWX/Src/Debugger/MemoryCheckDlg.cpp | 5 +- .../DolphinWX/Src/Debugger/MemoryView.cpp | 26 ++++--- .../DolphinWX/Src/Debugger/MemoryWindow.cpp | 17 ++--- .../DolphinWX/Src/Debugger/RegisterView.cpp | 9 ++- Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp | 7 +- Source/Core/DolphinWX/Src/FrameAui.cpp | 11 +-- Source/Core/DolphinWX/Src/FrameTools.cpp | 27 ++++--- Source/Core/DolphinWX/Src/GameListCtrl.cpp | 34 ++++----- Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp | 9 ++- Source/Core/DolphinWX/Src/ISOFile.cpp | 3 +- Source/Core/DolphinWX/Src/ISOProperties.cpp | 36 ++++----- Source/Core/DolphinWX/Src/InputConfigDiag.cpp | 75 +++++++++---------- .../DolphinWX/Src/InputConfigDiagBitmaps.cpp | 11 +-- Source/Core/DolphinWX/Src/LogConfigWindow.cpp | 3 +- Source/Core/DolphinWX/Src/Main.cpp | 24 +++--- Source/Core/DolphinWX/Src/MemcardManager.cpp | 28 +++---- Source/Core/DolphinWX/Src/NetWindow.cpp | 45 +++++------ Source/Core/DolphinWX/Src/PHackSettings.cpp | 13 ++-- Source/Core/DolphinWX/Src/PatchAddEdit.cpp | 9 ++- Source/Core/DolphinWX/Src/UDPConfigDiag.cpp | 8 +- Source/Core/DolphinWX/Src/VideoConfigDiag.cpp | 18 ++--- Source/Core/DolphinWX/Src/VideoConfigDiag.h | 5 +- Source/Core/DolphinWX/Src/WxUtils.cpp | 16 +++- Source/Core/DolphinWX/Src/WxUtils.h | 9 ++- Source/Core/DolphinWX/Src/X11Utils.cpp | 3 +- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 3 +- .../Src/VideoConfigDialog.cpp | 6 +- 39 files changed, 344 insertions(+), 300 deletions(-) diff --git a/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp b/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp index c3ed12bbea..e08753f40f 100644 --- a/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp +++ b/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp @@ -17,6 +17,7 @@ #include "ARCodeAddEdit.h" #include "ARDecrypt.h" +#include "WxUtils.h" extern std::vector arCodes; @@ -38,7 +39,7 @@ CARCodeAddEdit::CARCodeAddEdit(int _selection, wxWindow* parent, wxWindowID id, } else { - currentName = wxString(arCodes.at(selection).name.c_str(), *wxConvCurrent); + currentName = StrToWxStr(arCodes.at(selection).name); tempEntries = arCodes.at(selection); } @@ -73,7 +74,7 @@ CARCodeAddEdit::CARCodeAddEdit(int _selection, wxWindow* parent, wxWindowID id, void CARCodeAddEdit::ChangeEntry(wxSpinEvent& event) { ActionReplay::ARCode currentCode = arCodes.at((int)arCodes.size() - event.GetPosition()); - EditCheatName->SetValue(wxString(currentCode.name.c_str(), *wxConvCurrent)); + EditCheatName->SetValue(StrToWxStr(currentCode.name)); UpdateTextCtrl(currentCode); } @@ -84,7 +85,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event)) // Split the entered cheat into lines. std::vector userInputLines; - SplitString(std::string(EditCheatCode->GetValue().mb_str()), '\n', userInputLines); + SplitString(WxStrToStr(EditCheatCode->GetValue()), '\n', userInputLines); for (size_t i = 0; i < userInputLines.size(); i++) { @@ -148,7 +149,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event)) // Add a new AR cheat code. ActionReplay::ARCode newCheat; - newCheat.name = std::string(EditCheatName->GetValue().mb_str()); + newCheat.name = WxStrToStr(EditCheatName->GetValue()); newCheat.ops = decryptedLines; newCheat.active = true; @@ -157,7 +158,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event)) else { // Update the currently-selected AR cheat code. - arCodes.at(selection).name = std::string(EditCheatName->GetValue().mb_str()); + arCodes.at(selection).name = WxStrToStr(EditCheatName->GetValue()); arCodes.at(selection).ops = decryptedLines; } diff --git a/Source/Core/DolphinWX/Src/AboutDolphin.cpp b/Source/Core/DolphinWX/Src/AboutDolphin.cpp index 5e1825b6ae..eeecf18d48 100644 --- a/Source/Core/DolphinWX/Src/AboutDolphin.cpp +++ b/Source/Core/DolphinWX/Src/AboutDolphin.cpp @@ -17,6 +17,7 @@ #include "Common.h" #include "AboutDolphin.h" +#include "WxUtils.h" #include "../resources/dolphin_logo.cpp" #include "scmrev.h" @@ -62,7 +63,7 @@ AboutDolphin::AboutDolphin(wxWindow *parent, wxWindowID id, "and should not be used to play games you do\n" "not legally own."; wxStaticText* const Message = new wxStaticText(this, wxID_ANY, - wxString::FromAscii(Text.c_str())); + StrToWxStr(Text.c_str())); Message->Wrap(GetSize().GetWidth()); wxBoxSizer* const sInfo = new wxBoxSizer(wxVERTICAL); diff --git a/Source/Core/DolphinWX/Src/CheatsWindow.cpp b/Source/Core/DolphinWX/Src/CheatsWindow.cpp index 63ddced86b..1e0f714467 100644 --- a/Source/Core/DolphinWX/Src/CheatsWindow.cpp +++ b/Source/Core/DolphinWX/Src/CheatsWindow.cpp @@ -24,6 +24,7 @@ #include "ISOProperties.h" #include "HW/Memmap.h" #include "Frame.h" +#include "WxUtils.h" #define MAX_CHEAT_SEARCH_RESULTS_DISPLAY 256 @@ -273,7 +274,7 @@ void wxCheatsWindow::Load_ARCodes() { ARCode code = GetARCode(i); ARCodeIndex ind; - u32 index = m_CheckListBox_CheatsList->Append(wxString(code.name.c_str(), *wxConvCurrent)); + u32 index = m_CheckListBox_CheatsList->Append(StrToWxStr(code.name)); m_CheckListBox_CheatsList->Check(index, code.active); ind.index = i; ind.uiIndex = index; @@ -291,18 +292,18 @@ void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& WXUNUSED (e if ((int)indexList[i].uiIndex == index) { ARCode code = GetARCode(i); - m_Label_Codename->SetLabel(_("Name: ") + wxString(code.name.c_str(), *wxConvCurrent)); + m_Label_Codename->SetLabel(_("Name: ") + StrToWxStr(code.name)); char text[CHAR_MAX]; char* numcodes = text; sprintf(numcodes, "Number of Codes: %lu", (unsigned long)code.ops.size()); - m_Label_NumCodes->SetLabel(wxString::FromAscii(numcodes)); + m_Label_NumCodes->SetLabel(StrToWxStr(numcodes)); m_ListBox_CodesList->Clear(); for (size_t j = 0; j < code.ops.size(); j++) { char text2[CHAR_MAX]; char* ops = text2; sprintf(ops, "%08x %08x", code.ops[j].cmd_addr, code.ops[j].value); - m_ListBox_CodesList->Append(wxString::FromAscii(ops)); + m_ListBox_CodesList->Append(StrToWxStr(ops)); } } } @@ -347,7 +348,7 @@ void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED (eve const std::vector &arLog = ActionReplay::GetSelfLog(); for (u32 i = 0; i < arLog.size(); i++) { - m_TextCtrl_Log->AppendText(wxString::FromAscii(arLog[i].c_str())); + m_TextCtrl_Log->AppendText(StrToWxStr(arLog[i].c_str())); } } @@ -619,7 +620,7 @@ void CreateCodeDialog::PressOK(wxCommandEvent& ev) // create the new code ActionReplay::ARCode new_cheat; new_cheat.active = false; - new_cheat.name = std::string(code_name.ToAscii()); + new_cheat.name = WxStrToStr(code_name); const ActionReplay::AREntry new_entry(code_address, code_value); new_cheat.ops.push_back(new_entry); diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index dc044afe09..bdb4cdc7fe 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -33,6 +33,7 @@ #include "IPC_HLE/WII_IPC_HLE.h" #include "NANDContentLoader.h" +#include "WxUtils.h" #include "Globals.h" // Local #include "ConfigMain.h" #include "ConfigManager.h" @@ -100,7 +101,6 @@ static const wxLanguage langIds[] = #define EXIDEV_AM_BB_STR _trans("AM-Baseboard") #define EXIDEV_GECKO_STR "USBGecko" -#define CSTR_TRANS(a) wxString(wxGetTranslation(wxT(a))).mb_str() #define WXSTR_TRANS(a) wxString(wxGetTranslation(wxT(a))) #ifdef WIN32 //only used with xgettext to be picked up as translatable string. @@ -188,7 +188,7 @@ CConfigMain::CConfigMain(wxWindow* parent, wxWindowID id, const wxString& title, // Update selected ISO paths for(u32 i = 0; i < SConfig::GetInstance().m_ISOFolder.size(); i++) { - ISOPaths->Append(wxString(SConfig::GetInstance().m_ISOFolder[i].c_str(), *wxConvCurrent)); + ISOPaths->Append(StrToWxStr(SConfig::GetInstance().m_ISOFolder[i])); } } @@ -477,10 +477,10 @@ void CConfigMain::InitializeGUIValues() // Paths RecursiveISOPath->SetValue(SConfig::GetInstance().m_RecursiveISOFolder); - DefaultISO->SetPath(wxString(startup_params.m_strDefaultGCM.c_str(), *wxConvCurrent)); - DVDRoot->SetPath(wxString(startup_params.m_strDVDRoot.c_str(), *wxConvCurrent)); - ApploaderPath->SetPath(wxString(startup_params.m_strApploader.c_str(), *wxConvCurrent)); - NANDRoot->SetPath(wxString(SConfig::GetInstance().m_NANDPath.c_str(), *wxConvCurrent)); + DefaultISO->SetPath(StrToWxStr(startup_params.m_strDefaultGCM)); + DVDRoot->SetPath(StrToWxStr(startup_params.m_strDVDRoot)); + ApploaderPath->SetPath(StrToWxStr(startup_params.m_strApploader)); + NANDRoot->SetPath(StrToWxStr(SConfig::GetInstance().m_NANDPath)); } void CConfigMain::InitializeGUITooltips() @@ -958,10 +958,10 @@ void CConfigMain::AudioSettingsChanged(wxCommandEvent& event) break; case ID_BACKEND: - VolumeSlider->Enable(SupportsVolumeChanges(std::string(BackendSelection->GetStringSelection().mb_str()))); - Latency->Enable(std::string(BackendSelection->GetStringSelection().mb_str()) == BACKEND_OPENAL); - DPL2Decoder->Enable(std::string(BackendSelection->GetStringSelection().mb_str()) == BACKEND_OPENAL); - SConfig::GetInstance().sBackend = BackendSelection->GetStringSelection().mb_str(); + VolumeSlider->Enable(SupportsVolumeChanges(WxStrToStr(BackendSelection->GetStringSelection()))); + Latency->Enable(WxStrToStr(BackendSelection->GetStringSelection()) == BACKEND_OPENAL); + DPL2Decoder->Enable(WxStrToStr(BackendSelection->GetStringSelection()) == BACKEND_OPENAL); + SConfig::GetInstance().sBackend = WxStrToStr(BackendSelection->GetStringSelection()); AudioCommon::UpdateSoundStream(); break; @@ -982,9 +982,9 @@ void CConfigMain::AddAudioBackends() for (std::vector::const_iterator iter = backends.begin(); iter != backends.end(); ++iter) { - BackendSelection->Append(wxString::FromAscii((*iter).c_str())); + BackendSelection->Append(StrToWxStr((*iter).c_str())); int num = BackendSelection->\ - FindString(wxString::FromAscii(SConfig::GetInstance().sBackend.c_str())); + FindString(StrToWxStr(SConfig::GetInstance().sBackend.c_str())); BackendSelection->SetSelection(num); } } @@ -1046,12 +1046,12 @@ void CConfigMain::GCSettingsChanged(wxCommandEvent& event) void CConfigMain::ChooseMemcardPath(std::string& strMemcard, bool isSlotA) { - std::string filename = std::string(wxFileSelector( + std::string filename = WxStrToStr(wxFileSelector( _("Choose a file to open"), - wxString::FromUTF8(File::GetUserPath(D_GCUSER_IDX).c_str()), + StrToWxStr(File::GetUserPath(D_GCUSER_IDX)), isSlotA ? wxT(GC_MEMCARDA) : wxT(GC_MEMCARDB), wxEmptyString, - _("Gamecube Memory Cards (*.raw,*.gcp)") + wxString(wxT("|*.raw;*.gcp"))).mb_str()); + _("Gamecube Memory Cards (*.raw,*.gcp)") + wxString(wxT("|*.raw;*.gcp")))); if (!filename.empty()) { @@ -1242,7 +1242,7 @@ void CConfigMain::AddRemoveISOPaths(wxCommandEvent& event) SConfig::GetInstance().m_ISOFolder.clear(); for (unsigned int i = 0; i < ISOPaths->GetCount(); i++) - SConfig::GetInstance().m_ISOFolder.push_back(std::string(ISOPaths->GetStrings()[i].mb_str())); + SConfig::GetInstance().m_ISOFolder.push_back(WxStrToStr(ISOPaths->GetStrings()[i])); } void CConfigMain::RecursiveDirectoryChanged(wxCommandEvent& WXUNUSED (event)) @@ -1253,24 +1253,24 @@ void CConfigMain::RecursiveDirectoryChanged(wxCommandEvent& WXUNUSED (event)) void CConfigMain::DefaultISOChanged(wxFileDirPickerEvent& WXUNUSED (event)) { - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = DefaultISO->GetPath().mb_str(); + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = WxStrToStr(DefaultISO->GetPath()); } void CConfigMain::DVDRootChanged(wxFileDirPickerEvent& WXUNUSED (event)) { - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDVDRoot = DVDRoot->GetPath().mb_str(); + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDVDRoot = WxStrToStr(DVDRoot->GetPath()); } void CConfigMain::ApploaderPathChanged(wxFileDirPickerEvent& WXUNUSED (event)) { - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strApploader = ApploaderPath->GetPath().mb_str(); + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strApploader = WxStrToStr(ApploaderPath->GetPath()); } void CConfigMain::NANDRootChanged(wxFileDirPickerEvent& WXUNUSED (event)) { std::string NANDPath = - SConfig::GetInstance().m_NANDPath = File::GetUserPath(D_WIIROOT_IDX, std::string(NANDRoot->GetPath().mb_str())); - NANDRoot->SetPath(wxString(NANDPath.c_str(), *wxConvCurrent)); + SConfig::GetInstance().m_NANDPath = File::GetUserPath(D_WIIROOT_IDX, WxStrToStr(NANDRoot->GetPath())); + NANDRoot->SetPath(wxString(NANDPath)); SConfig::GetInstance().m_SYSCONF->UpdateLocation(); DiscIO::cUIDsys::AccessInstance().UpdateLocation(); DiscIO::CSharedContent::AccessInstance().UpdateLocation(); diff --git a/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp b/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp index 58e73b167e..96dbac8ff8 100644 --- a/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp @@ -19,6 +19,7 @@ #include "StringUtil.h" #include "PowerPC/PowerPC.h" #include "BreakpointWindow.h" +#include "../WxUtils.h" BEGIN_EVENT_TABLE(BreakPointDlg, wxDialog) EVT_BUTTON(wxID_OK, BreakPointDlg::OnOK) @@ -42,14 +43,14 @@ void BreakPointDlg::OnOK(wxCommandEvent& event) { wxString AddressString = m_pEditAddress->GetLineText(0); u32 Address = 0; - if (AsciiToHex(AddressString.mb_str(), Address)) + if (AsciiToHex(WxStrToStr(AddressString).c_str(), Address)) { PowerPC::breakpoints.Add(Address); Parent->NotifyUpdate(); Close(); } else - PanicAlert("The address %s is invalid.", (const char *)AddressString.ToUTF8()); + PanicAlert("The address %s is invalid.", WxStrToStr(AddressString).c_str()); event.Skip(); } diff --git a/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp b/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp index 496cb8fe5d..a23e9194fd 100644 --- a/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp @@ -23,6 +23,7 @@ #include "PowerPC/PPCSymbolDB.h" #include "PowerPC/PowerPC.h" #include "HW/Memmap.h" +#include "../WxUtils.h" CBreakPointView::CBreakPointView(wxWindow* parent, const wxWindowID id) : wxListCtrl(parent, id, wxDefaultPosition, wxDefaultSize, @@ -50,20 +51,20 @@ void CBreakPointView::Update() if (!rBP.bTemporary) { wxString temp; - temp = wxString::FromAscii(rBP.bOn ? "on" : " "); + temp = StrToWxStr(rBP.bOn ? "on" : " "); int Item = InsertItem(0, temp); - temp = wxString::FromAscii("BP"); + temp = StrToWxStr("BP"); SetItem(Item, 1, temp); Symbol *symbol = g_symbolDB.GetSymbolFromAddr(rBP.iAddress); if (symbol) { - temp = wxString::FromAscii(g_symbolDB.GetDescription(rBP.iAddress)); + temp = StrToWxStr(g_symbolDB.GetDescription(rBP.iAddress)); SetItem(Item, 2, temp); } sprintf(szBuffer, "%08x", rBP.iAddress); - temp = wxString::FromAscii(szBuffer); + temp = StrToWxStr(szBuffer); SetItem(Item, 3, temp); SetItemData(Item, rBP.iAddress); @@ -76,27 +77,27 @@ void CBreakPointView::Update() const TMemCheck& rMemCheck = rMemChecks[i]; wxString temp; - temp = wxString::FromAscii((rMemCheck.Break || rMemCheck.Log) ? "on" : " "); + temp = StrToWxStr((rMemCheck.Break || rMemCheck.Log) ? "on" : " "); int Item = InsertItem(0, temp); - temp = wxString::FromAscii("MC"); + temp = StrToWxStr("MC"); SetItem(Item, 1, temp); Symbol *symbol = g_symbolDB.GetSymbolFromAddr(rMemCheck.StartAddress); if (symbol) { - temp = wxString::FromAscii(g_symbolDB.GetDescription(rMemCheck.StartAddress)); + temp = StrToWxStr(g_symbolDB.GetDescription(rMemCheck.StartAddress)); SetItem(Item, 2, temp); } sprintf(szBuffer, "%08x to %08x", rMemCheck.StartAddress, rMemCheck.EndAddress); - temp = wxString::FromAscii(szBuffer); + temp = StrToWxStr(szBuffer); SetItem(Item, 3, temp); size_t c = 0; if (rMemCheck.OnRead) szBuffer[c++] = 'r'; if (rMemCheck.OnWrite) szBuffer[c++] = 'w'; szBuffer[c] = 0x00; - temp = wxString::FromAscii(szBuffer); + temp = StrToWxStr(szBuffer); SetItem(Item, 4, temp); SetItemData(Item, rMemCheck.StartAddress); diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp index f696aaab64..3b22ca339d 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp @@ -23,6 +23,7 @@ #include "Host.h" #include "CodeView.h" #include "SymbolDB.h" +#include "../WxUtils.h" #include #include @@ -223,7 +224,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) { char disasm[256]; debugger->disasm(selection, disasm, 256); - wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(disasm))); + wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(disasm))); } break; @@ -231,7 +232,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) { char temp[24]; sprintf(temp, "%08x", debugger->readInstruction(selection)); - wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(temp))); + wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp))); } break; @@ -252,7 +253,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) debugger->disasm(addr, disasm, 256); text = text + StringFromFormat("%08x: ", addr) + disasm + "\r\n"; } - wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(text.c_str()))); + wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text.c_str()))); } } break; @@ -297,12 +298,12 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) Symbol *symbol = symbol_db->GetSymbolFromAddr(selection); if (symbol) { - wxTextEntryDialog input_symbol(this, wxString::FromAscii("Rename symbol:"), + wxTextEntryDialog input_symbol(this, StrToWxStr("Rename symbol:"), wxGetTextFromUserPromptStr, - wxString::FromAscii(symbol->name.c_str())); + StrToWxStr(symbol->name.c_str())); if (input_symbol.ShowModal() == wxID_OK) { - symbol->name = input_symbol.GetValue().mb_str(); + symbol->name = WxStrToStr(input_symbol.GetValue()); Refresh(); // Redraw to show the renamed symbol } Host_NotifyMapLoaded(); @@ -327,23 +328,23 @@ void CCodeView::OnMouseUpR(wxMouseEvent& event) wxMenu* menu = new wxMenu; //menu->Append(IDM_GOTOINMEMVIEW, "&Goto in mem view"); menu->Append(IDM_FOLLOWBRANCH, - wxString::FromAscii("&Follow branch"))->Enable(AddrToBranch(selection) ? true : false); + StrToWxStr("&Follow branch"))->Enable(AddrToBranch(selection) ? true : false); menu->AppendSeparator(); #if wxUSE_CLIPBOARD - menu->Append(IDM_COPYADDRESS, wxString::FromAscii("Copy &address")); - menu->Append(IDM_COPYFUNCTION, wxString::FromAscii("Copy &function"))->Enable(isSymbol); - menu->Append(IDM_COPYCODE, wxString::FromAscii("Copy &code line")); - menu->Append(IDM_COPYHEX, wxString::FromAscii("Copy &hex")); + menu->Append(IDM_COPYADDRESS, StrToWxStr("Copy &address")); + menu->Append(IDM_COPYFUNCTION, StrToWxStr("Copy &function"))->Enable(isSymbol); + menu->Append(IDM_COPYCODE, StrToWxStr("Copy &code line")); + menu->Append(IDM_COPYHEX, StrToWxStr("Copy &hex")); menu->AppendSeparator(); #endif - menu->Append(IDM_RENAMESYMBOL, wxString::FromAscii("Rename &symbol"))->Enable(isSymbol); + menu->Append(IDM_RENAMESYMBOL, StrToWxStr("Rename &symbol"))->Enable(isSymbol); menu->AppendSeparator(); menu->Append(IDM_RUNTOHERE, _("&Run To Here")); menu->Append(IDM_ADDFUNCTION, _("&Add function")); - menu->Append(IDM_JITRESULTS, wxString::FromAscii("PPC vs X86")); - menu->Append(IDM_INSERTBLR, wxString::FromAscii("Insert &blr")); - menu->Append(IDM_INSERTNOP, wxString::FromAscii("Insert &nop")); - menu->Append(IDM_PATCHALERT, wxString::FromAscii("Patch alert")); + menu->Append(IDM_JITRESULTS, StrToWxStr("PPC vs X86")); + menu->Append(IDM_INSERTBLR, StrToWxStr("Insert &blr")); + menu->Append(IDM_INSERTNOP, StrToWxStr("Insert &nop")); + menu->Append(IDM_PATCHALERT, StrToWxStr("Patch alert")); PopupMenu(menu); event.Skip(true); } @@ -489,7 +490,7 @@ void CCodeView::OnPaint(wxPaintEvent& event) dc.SetTextForeground(_T("#000000")); } - dc.DrawText(wxString::FromAscii(dis2), 17 + 17*charWidth, rowY1); + dc.DrawText(StrToWxStr(dis2), 17 + 17*charWidth, rowY1); // ------------ } @@ -499,7 +500,7 @@ void CCodeView::OnPaint(wxPaintEvent& event) else dc.SetTextForeground(_T("#8000FF")); // purple - dc.DrawText(wxString::FromAscii(dis), 17 + (plain ? 1*charWidth : 9*charWidth), rowY1); + dc.DrawText(StrToWxStr(dis), 17 + (plain ? 1*charWidth : 9*charWidth), rowY1); if (desc[0] == 0) { @@ -513,7 +514,7 @@ void CCodeView::OnPaint(wxPaintEvent& event) //UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE); if (strlen(desc)) { - dc.DrawText(wxString::FromAscii(desc), 17 + 35 * charWidth, rowY1); + dc.DrawText(StrToWxStr(desc), 17 + 35 * charWidth, rowY1); } } diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp index 601faeaec6..1cff07c0f4 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp @@ -30,6 +30,7 @@ #include "CodeWindow.h" #include "CodeView.h" +#include "../WxUtils.h" #include "FileUtil.h" #include "Core.h" #include "HW/Memmap.h" @@ -210,7 +211,7 @@ void CCodeWindow::OnAddrBoxChange(wxCommandEvent& event) wxTextCtrl* pAddrCtrl = (wxTextCtrl*)GetToolBar()->FindControl(IDM_ADDRBOX); wxString txt = pAddrCtrl->GetValue(); - std::string text(txt.mb_str()); + std::string text(WxStrToStr(txt)); text = StripSpaces(text); if (text.size() == 8) { @@ -312,7 +313,7 @@ void CCodeWindow::UpdateLists() Symbol *caller_symbol = g_symbolDB.GetSymbolFromAddr(caller_addr); if (caller_symbol) { - int idx = callers->Append(wxString::FromAscii(StringFromFormat + int idx = callers->Append(StrToWxStr(StringFromFormat ("< %s (%08x)", caller_symbol->name.c_str(), caller_addr).c_str())); callers->SetClientData(idx, (void*)(u64)caller_addr); } @@ -325,7 +326,7 @@ void CCodeWindow::UpdateLists() Symbol *call_symbol = g_symbolDB.GetSymbolFromAddr(call_addr); if (call_symbol) { - int idx = calls->Append(wxString::FromAscii(StringFromFormat + int idx = calls->Append(StrToWxStr(StringFromFormat ("> %s (%08x)", call_symbol->name.c_str(), call_addr).c_str())); calls->SetClientData(idx, (void*)(u64)call_addr); } @@ -344,12 +345,12 @@ void CCodeWindow::UpdateCallstack() for (size_t i = 0; i < stack.size(); i++) { - int idx = callstack->Append(wxString::FromAscii(stack[i].Name.c_str())); + int idx = callstack->Append(StrToWxStr(stack[i].Name.c_str())); callstack->SetClientData(idx, (void*)(u64)stack[i].vAddress); } if (!ret) - callstack->Append(wxString::FromAscii("invalid callstack")); + callstack->Append(StrToWxStr("invalid callstack")); } // Create CPU Mode menus @@ -360,7 +361,7 @@ void CCodeWindow::CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParam wxMenu* pCoreMenu = new wxMenu; wxMenuItem* interpreter = pCoreMenu->Append(IDM_INTERPRETER, _("&Interpreter core"), - wxString::FromAscii("This is necessary to get break points" + StrToWxStr("This is necessary to get break points" " and stepping to work as explained in the Developer Documentation. But it can be very" " slow, perhaps slower than 1 fps."), wxITEM_CHECK); @@ -428,7 +429,7 @@ void CCodeWindow::CreateMenuOptions(wxMenu* pMenu) boottopause->Check(bBootToPause); wxMenuItem* automaticstart = pMenu->Append(IDM_AUTOMATICSTART, _("&Automatic start"), - wxString::FromAscii( + StrToWxStr( "Automatically load the Default ISO when Dolphin starts, or the last game you loaded," " if you have not given it an elf file with the --elf command line. [This can be" " convenient if you are bug-testing with a certain game and want to rebuild" @@ -515,10 +516,10 @@ void CCodeWindow::OnJitMenu(wxCommandEvent& event) for (u32 addr = 0x80000000; addr < 0x80100000; addr += 4) { const char *name = PPCTables::GetInstructionName(Memory::ReadUnchecked_U32(addr)); - if (name && !strcmp((const char *)str.mb_str(), name)) + auto const wx_name = WxStrToStr(str); + if (name && (wx_name == name)) { - std::string mb_str(str.mb_str()); - NOTICE_LOG(POWERPC, "Found %s at %08x", mb_str.c_str(), addr); + NOTICE_LOG(POWERPC, "Found %s at %08x", wx_name.c_str(), addr); } } break; diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp index 706b398dce..a11783c010 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp @@ -25,6 +25,7 @@ #include "DebuggerUIUtil.h" +#include "../WxUtils.h" #include "RegisterWindow.h" #include "BreakpointWindow.h" #include "MemoryWindow.h" @@ -65,7 +66,7 @@ void CCodeWindow::Load() std::string fontDesc; ini.Get("General", "DebuggerFont", &fontDesc); if (!fontDesc.empty()) - DebuggerFont.SetNativeFontInfoUserDesc(wxString::FromAscii(fontDesc.c_str())); + DebuggerFont.SetNativeFontInfoUserDesc(StrToWxStr(fontDesc.c_str())); // Boot to pause or not ini.Get("General", "AutomaticStart", &bAutomaticStart, false); @@ -107,7 +108,7 @@ void CCodeWindow::Save() ini.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX)); ini.Set("General", "DebuggerFont", - std::string(DebuggerFont.GetNativeFontInfoUserDesc().mb_str())); + WxStrToStr(DebuggerFont.GetNativeFontInfoUserDesc())); // Boot to pause or not ini.Set("General", "AutomaticStart", GetMenuBar()->IsChecked(IDM_AUTOMATICSTART)); @@ -154,7 +155,7 @@ void CCodeWindow::CreateMenuSymbols(wxMenuBar *pMenuBar) pSymbolsMenu->Append(IDM_SAVEMAPFILE, _("&Save symbol map")); pSymbolsMenu->AppendSeparator(); pSymbolsMenu->Append(IDM_SAVEMAPFILEWITHCODES, _("Save code"), - wxString::FromAscii("Save the entire disassembled code. This may take a several seconds" + StrToWxStr("Save the entire disassembled code. This may take a several seconds" " and may require between 50 and 100 MB of hard drive space. It will only save code" " that are in the first 4 MB of memory, if you are debugging a game that load .rel" " files with code to memory you may want to increase that to perhaps 8 MB, you can do" @@ -284,7 +285,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) if (!path.IsEmpty()) { - std::ifstream f(path.mb_str()); + std::ifstream f(WxStrToStr(path)); std::string line; while (std::getline(f, line)) @@ -312,13 +313,13 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) { wxTextEntryDialog input_prefix( this, - wxString::FromAscii("Only export symbols with prefix:\n(Blank for all symbols)"), + StrToWxStr("Only export symbols with prefix:\n(Blank for all symbols)"), wxGetTextFromUserPromptStr, wxEmptyString); if (input_prefix.ShowModal() == wxID_OK) { - std::string prefix(input_prefix.GetValue().mb_str()); + std::string prefix(WxStrToStr(input_prefix.GetValue())); wxString path = wxFileSelector( _T("Save signature as"), wxEmptyString, wxEmptyString, wxEmptyString, @@ -328,8 +329,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) { SignatureDB db; db.Initialize(&g_symbolDB, prefix.c_str()); - std::string filename(path.mb_str()); - db.Save(path.mb_str()); + db.Save(WxStrToStr(path).c_str()); } } } @@ -343,7 +343,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) if (!path.IsEmpty()) { SignatureDB db; - db.Load(path.mb_str()); + db.Load(WxStrToStr(path).c_str()); db.Apply(&g_symbolDB); } } @@ -366,7 +366,7 @@ void CCodeWindow::NotifyMapLoaded() symbols->Clear(); for (PPCSymbolDB::XFuncMap::iterator iter = g_symbolDB.GetIterator(); iter != g_symbolDB.End(); ++iter) { - int idx = symbols->Append(wxString::FromAscii(iter->second.name.c_str())); + int idx = symbols->Append(StrToWxStr(iter->second.name.c_str())); symbols->SetClientData(idx, (void*)&iter->second); } symbols->Thaw(); diff --git a/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp index a4591d3994..27da055990 100644 --- a/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp @@ -22,6 +22,7 @@ #include +#include "../WxUtils.h" #include "StringUtil.h" #include "DSPDebugWindow.h" #include "DSPRegisterView.h" @@ -220,7 +221,7 @@ void DSPDebuggerLLE::UpdateSymbolMap() for (SymbolDB::XFuncMap::iterator iter = DSPSymbols::g_dsp_symbol_db.GetIterator(); iter != DSPSymbols::g_dsp_symbol_db.End(); ++iter) { - int idx = m_SymbolList->Append(wxString::FromAscii(iter->second.name.c_str())); + int idx = m_SymbolList->Append(StrToWxStr(iter->second.name.c_str())); m_SymbolList->SetClientData(idx, (void*)&iter->second); } m_SymbolList->Thaw(); @@ -250,8 +251,7 @@ void DSPDebuggerLLE::OnAddrBoxChange(wxCommandEvent& event) wxTextCtrl* pAddrCtrl = (wxTextCtrl*)m_Toolbar->FindControl(ID_ADDRBOX); wxString txt = pAddrCtrl->GetValue(); - std::string text(txt.mb_str()); - text = StripSpaces(text); + auto text = StripSpaces(WxStrToStr(txt)); if (text.size()) { u32 addr; diff --git a/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp b/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp index ca275ba66a..b8634e14dc 100644 --- a/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp @@ -17,7 +17,7 @@ #include "DSPDebugWindow.h" #include "DSPRegisterView.h" - +#include "../WxUtils.h" wxString CDSPRegTable::GetValue(int row, int col) { @@ -25,7 +25,7 @@ wxString CDSPRegTable::GetValue(int row, int col) { switch (col) { - case 0: return wxString::FromAscii(pdregname(row)); + case 0: return StrToWxStr(pdregname(row)); case 1: return wxString::Format(wxT("0x%04x"), DSPCore_ReadRegister(row)); default: return wxEmptyString; } diff --git a/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp index 69cee04db5..e80d206112 100644 --- a/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp @@ -37,6 +37,7 @@ #include "Core.h" #include "StringUtil.h" #include "LogManager.h" +#include "../WxUtils.h" #include "../Globals.h" diff --git a/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp b/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp index f66e781ca3..41e09a7451 100644 --- a/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp @@ -15,6 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ +#include "../WxUtils.h" #include "MemoryCheckDlg.h" #include "Common.h" #include "StringUtil.h" @@ -79,9 +80,9 @@ void MemoryCheckDlg::OnOK(wxCommandEvent& event) u32 StartAddress, EndAddress; bool EndAddressOK = EndAddressString.Len() && - AsciiToHex(EndAddressString.mb_str(), EndAddress); + AsciiToHex(WxStrToStr(EndAddressString).c_str(), EndAddress); - if (AsciiToHex(StartAddressString.mb_str(), StartAddress) && + if (AsciiToHex(WxStrToStr(StartAddressString).c_str(), StartAddress) && (OnRead || OnWrite) && (Log || Break)) { TMemCheck MemCheck; diff --git a/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp b/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp index c6244fb7de..14d1aed8c0 100644 --- a/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp @@ -22,6 +22,8 @@ #include "HW/Memmap.h" #include "MemoryView.h" +#include "../WxUtils.h" + #include #include @@ -149,7 +151,7 @@ void CMemoryView::OnPopupMenu(wxCommandEvent& event) { char temp[24]; sprintf(temp, "%08x", debugger->readExtraMemory(memory, selection)); - wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(temp))); + wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp))); } break; #endif @@ -186,16 +188,16 @@ void CMemoryView::OnMouseDownR(wxMouseEvent& event) wxMenu* menu = new wxMenu; //menu.Append(IDM_GOTOINMEMVIEW, "&Goto in mem view"); #if wxUSE_CLIPBOARD - menu->Append(IDM_COPYADDRESS, wxString::FromAscii("Copy &address")); - menu->Append(IDM_COPYHEX, wxString::FromAscii("Copy &hex")); + menu->Append(IDM_COPYADDRESS, StrToWxStr("Copy &address")); + menu->Append(IDM_COPYHEX, StrToWxStr("Copy &hex")); #endif - menu->Append(IDM_TOGGLEMEMORY, wxString::FromAscii("Toggle &memory")); + menu->Append(IDM_TOGGLEMEMORY, StrToWxStr("Toggle &memory")); wxMenu* viewAsSubMenu = new wxMenu; - viewAsSubMenu->Append(IDM_VIEWASFP, wxString::FromAscii("FP value")); - viewAsSubMenu->Append(IDM_VIEWASASCII, wxString::FromAscii("ASCII")); - viewAsSubMenu->Append(IDM_VIEWASHEX, wxString::FromAscii("Hex")); - menu->AppendSubMenu(viewAsSubMenu, wxString::FromAscii("View As:")); + viewAsSubMenu->Append(IDM_VIEWASFP, StrToWxStr("FP value")); + viewAsSubMenu->Append(IDM_VIEWASASCII, StrToWxStr("ASCII")); + viewAsSubMenu->Append(IDM_VIEWASHEX, StrToWxStr("Hex")); + menu->AppendSubMenu(viewAsSubMenu, StrToWxStr("View As:")); PopupMenu(menu); } @@ -285,7 +287,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event) char mem[256]; debugger->getRawMemoryString(memory, address, mem, 256); dc.SetTextForeground(_T("#000080")); - dc.DrawText(wxString::FromAscii(mem), 17+fontSize*(8), rowY1); + dc.DrawText(StrToWxStr(mem), 17+fontSize*(8), rowY1); dc.SetTextForeground(_T("#000000")); } @@ -361,9 +363,9 @@ void CMemoryView::OnPaint(wxPaintEvent& event) char desc[256] = ""; if (viewAsType != VIEWAS_HEX) - dc.DrawText(wxString::FromAscii(dis), textPlacement + fontSize*(8 + 8), rowY1); + dc.DrawText(StrToWxStr(dis), textPlacement + fontSize*(8 + 8), rowY1); else - dc.DrawText(wxString::FromAscii(dis), textPlacement, rowY1); + dc.DrawText(StrToWxStr(dis), textPlacement, rowY1); if (desc[0] == 0) strcpy(desc, debugger->getDescription(address).c_str()); @@ -371,7 +373,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event) dc.SetTextForeground(_T("#0000FF")); if (strlen(desc)) - dc.DrawText(wxString::FromAscii(desc), 17+fontSize*((8+8+8+30)*2), rowY1); + dc.DrawText(StrToWxStr(desc), 17+fontSize*((8+8+8+30)*2), rowY1); // Show blue memory check dot if (debugger->isMemCheck(address)) diff --git a/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp index 5673d7b7c1..4b87cfa154 100644 --- a/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp @@ -20,6 +20,8 @@ #include #include #include + +#include "../WxUtils.h" #include "MemoryWindow.h" #include "HW/CPU.h" #include "PowerPC/PowerPC.h" @@ -152,8 +154,8 @@ void CMemoryWindow::JumpToAddress(u32 _Address) void CMemoryWindow::SetMemoryValue(wxCommandEvent& event) { - std::string str_addr = std::string(addrbox->GetValue().mb_str()); - std::string str_val = std::string(valbox->GetValue().mb_str()); + std::string str_addr = WxStrToStr(addrbox->GetValue()); + std::string str_val = WxStrToStr(valbox->GetValue()); u32 addr; u32 val; @@ -179,7 +181,7 @@ void CMemoryWindow::OnAddrBoxChange(wxCommandEvent& event) if (txt.size()) { u32 addr; - sscanf(txt.mb_str(), "%08x", &addr); + sscanf(WxStrToStr(txt).c_str(), "%08x", &addr); memview->Center(addr & ~3); } @@ -349,10 +351,7 @@ void CMemoryWindow::onSearch(wxCommandEvent& event) tmpstr = new char[newsize + 1]; memset(tmpstr, 0, newsize + 1); } - //sprintf(tmpstr, "%s%s", tmpstr, rawData.c_str()); - //strcpy(&tmpstr[1], rawData.ToAscii()); - //memcpy(&tmpstr[1], &rawData.c_str()[0], rawData.size()); - sprintf(tmpstr, "%s%s", tmpstr, (const char *)rawData.mb_str()); + sprintf(tmpstr, "%s%s", tmpstr, WxStrToStr(rawData).c_str()); tmp2 = &Dest.front(); count = 0; for(i = 0; i < strlen(tmpstr); i++) @@ -376,7 +375,7 @@ void CMemoryWindow::onSearch(wxCommandEvent& event) tmpstr = new char[size+1]; tmp2 = &Dest.front(); - sprintf(tmpstr, "%s", (const char *)rawData.mb_str()); + sprintf(tmpstr, "%s", WxStrToStr(rawData).c_str()); for(i = 0; i < size; i++) tmp2[i] = tmpstr[i]; @@ -393,7 +392,7 @@ void CMemoryWindow::onSearch(wxCommandEvent& event) u32 addr = 0; if (txt.size()) { - sscanf(txt.mb_str(), "%08x", &addr); + sscanf(WxStrToStr(txt).c_str(), "%08x", &addr); } i = addr+4; for( ; i < szRAM; i++) diff --git a/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp b/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp index c4a30fd522..0c414cb522 100644 --- a/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp @@ -20,6 +20,7 @@ #include "PowerPC/PowerPC.h" #include "HW/ProcessorInterface.h" #include "IniFile.h" +#include "../WxUtils.h" // F-zero 80005e60 wtf?? @@ -51,9 +52,9 @@ wxString CRegTable::GetValue(int row, int col) { if (row < 32) { switch (col) { - case 0: return wxString::FromAscii(GetGPRName(row)); + case 0: return StrToWxStr(GetGPRName(row)); case 1: return wxString::Format(wxT("%08x"), GPR(row)); - case 2: return wxString::FromAscii(GetFPRName(row)); + case 2: return StrToWxStr(GetFPRName(row)); case 3: return wxString::Format(wxT("%016llx"), riPS0(row)); case 4: return wxString::Format(wxT("%016llx"), riPS1(row)); default: return wxEmptyString; @@ -61,7 +62,7 @@ wxString CRegTable::GetValue(int row, int col) } else { if (row - 32 < NUM_SPECIALS) { switch (col) { - case 0: return wxString::FromAscii(special_reg_names[row - 32]); + case 0: return StrToWxStr(special_reg_names[row - 32]); case 1: return wxString::Format(wxT("%08x"), GetSpecialRegValue(row - 32)); default: return wxEmptyString; } @@ -91,7 +92,7 @@ static void SetSpecialRegValue(int reg, u32 value) { void CRegTable::SetValue(int row, int col, const wxString& strNewVal) { u32 newVal = 0; - if (TryParse(std::string(strNewVal.mb_str()), &newVal)) + if (TryParse(WxStrToStr(strNewVal), &newVal)) { if (row < 32) { if (col == 1) diff --git a/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp b/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp index 81268e3467..6e18c192eb 100644 --- a/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp +++ b/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp @@ -22,6 +22,7 @@ #include "FifoPlayer/FifoPlayer.h" #include "FifoPlayer/FifoRecorder.h" #include "OpcodeDecoding.h" +#include "WxUtils.h" #include #include @@ -395,7 +396,7 @@ void FifoPlayerDlg::OnSaveFile(wxCommandEvent& WXUNUSED(event)) if (!path.empty()) { wxBeginBusyCursor(); - bool result = file->Save(path.mb_str()); + bool result = file->Save(WxStrToStr(path).c_str()); wxEndBusyCursor(); if (!result) @@ -752,10 +753,10 @@ void FifoPlayerDlg::OnObjectCmdListSelectionChanged(wxCommandEvent& event) char name[64]="\0", desc[512]="\0"; GetBPRegInfo(cmddata+1, name, sizeof(name), desc, sizeof(desc)); newLabel = _("BP register "); - newLabel += (name[0] != '\0') ? wxString(name, *wxConvCurrent) : wxString::Format(_("UNKNOWN_%02X"), *(cmddata+1)); + newLabel += (name[0] != '\0') ? StrToWxStr(name) : wxString::Format(_("UNKNOWN_%02X"), *(cmddata+1)); newLabel += wxT(":\n"); if (desc[0] != '\0') - newLabel += wxString(desc, *wxConvCurrent); + newLabel += StrToWxStr(desc); else newLabel += _("No description available"); } diff --git a/Source/Core/DolphinWX/Src/FrameAui.cpp b/Source/Core/DolphinWX/Src/FrameAui.cpp index 0550c5cd39..fd3cbb662b 100644 --- a/Source/Core/DolphinWX/Src/FrameAui.cpp +++ b/Source/Core/DolphinWX/Src/FrameAui.cpp @@ -21,6 +21,7 @@ #include "Globals.h" // Local #include "Frame.h" #include "LogWindow.h" +#include "WxUtils.h" #include "ConfigManager.h" // Core @@ -548,7 +549,7 @@ void CFrame::OnDropDownToolbarItem(wxAuiToolBarEvent& event) for (u32 i = 0; i < Perspectives.size(); i++) { wxMenuItem* mItem = new wxMenuItem(menuPopup, IDM_PERSPECTIVES_0 + i, - wxString::FromAscii(Perspectives[i].Name.c_str()), + StrToWxStr(Perspectives[i].Name.c_str()), wxT(""), wxITEM_CHECK); menuPopup->Append(mItem); if (i == ActivePerspective) mItem->Check(true); @@ -580,7 +581,7 @@ void CFrame::OnToolBar(wxCommandEvent& event) return; } SaveIniPerspectives(); - GetStatusBar()->SetStatusText(wxString::FromAscii(std::string + GetStatusBar()->SetStatusText(StrToWxStr(std::string ("Saved " + Perspectives[ActivePerspective].Name).c_str()), 0); break; case IDM_PERSPECTIVES_ADD_PANE: @@ -633,7 +634,7 @@ void CFrame::OnDropDownToolbarSelect(wxCommandEvent& event) } SPerspectives Tmp; - Tmp.Name = dlg.GetValue().mb_str(); + Tmp.Name = WxStrToStr(dlg.GetValue()); Tmp.Perspective = m_Mgr->SavePerspective(); ActivePerspective = (u32)Perspectives.size(); @@ -870,7 +871,7 @@ void CFrame::LoadIniPerspectives() ini.Get(_Section.c_str(), "Width", &_Width, "70,25"); ini.Get(_Section.c_str(), "Height", &_Height, "80,80"); - Tmp.Perspective = wxString::FromAscii(_Perspective.c_str()); + Tmp.Perspective = StrToWxStr(_Perspective.c_str()); SplitString(_Width, ',', _SWidth); SplitString(_Height, ',', _SHeight); @@ -940,7 +941,7 @@ void CFrame::SaveIniPerspectives() for (u32 i = 0; i < Perspectives.size(); i++) { std::string _Section = "P - " + Perspectives[i].Name; - ini.Set(_Section.c_str(), "Perspective", Perspectives[i].Perspective.mb_str()); + ini.Set(_Section.c_str(), "Perspective", WxStrToStr(Perspectives[i].Perspective)); std::string SWidth = "", SHeight = ""; for (u32 j = 0; j < Perspectives[i].Width.size(); j++) diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index cb2750ade4..a1dcd959fe 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -101,7 +101,7 @@ void CFrame::CreateMenu() drives = cdio_get_devices(); // Windows Limitation of 24 character drives for (unsigned int i = 0; i < drives.size() && i < 24; i++) { - externalDrive->Append(IDM_DRIVE1 + i, wxString::FromAscii(drives[i].c_str())); + externalDrive->Append(IDM_DRIVE1 + i, StrToWxStr(drives[i].c_str())); } fileMenu->AppendSeparator(); @@ -601,12 +601,10 @@ void CFrame::DoOpen(bool Boot) // Should we boot a new game or just change the disc? if (Boot && !path.IsEmpty()) - BootGame(std::string(path.mb_str())); + BootGame(WxStrToStr(path)); else { - char newDiscpath[2048]; - strncpy(newDiscpath, path.mb_str(), strlen(path.mb_str())+1); - DVDInterface::ChangeDisc(newDiscpath); + DVDInterface::ChangeDisc(WxStrToStr(path).c_str()); } } @@ -693,7 +691,7 @@ void CFrame::OnPlayRecording(wxCommandEvent& WXUNUSED (event)) GetMenuBar()->FindItem(IDM_RECORDREADONLY)->Check(true); } - if(Movie::PlayInput(path.mb_str())) + if (Movie::PlayInput(WxStrToStr(path).c_str())) BootGame(std::string("")); } @@ -1015,7 +1013,7 @@ void CFrame::DoStop() X11Utils::InhibitScreensaver(X11Utils::XDisplayFromHandle(GetHandle()), X11Utils::XWindowFromHandle(GetHandle()), false); #endif - m_RenderFrame->SetTitle(wxString::FromAscii(scm_rev_str)); + m_RenderFrame->SetTitle(StrToWxStr(scm_rev_str)); // Destroy the renderer frame when not rendering to main m_RenderParent->Unbind(wxEVT_SIZE, &CFrame::OnRenderParentResize, this); @@ -1081,7 +1079,7 @@ void CFrame::DoRecordingSave() if(path.IsEmpty()) return; - Movie::SaveRecording(path.mb_str()); + Movie::SaveRecording(WxStrToStr(path).c_str()); if (!paused) DoPause(); @@ -1212,7 +1210,7 @@ void CFrame::StatusBarMessage(const char * Text, ...) vsnprintf(Str, MAX_BYTES, Text, ArgPtr); va_end(ArgPtr); - if (this->GetStatusBar()->IsEnabled()) this->GetStatusBar()->SetStatusText(wxString::FromAscii(Str),0); + if (this->GetStatusBar()->IsEnabled()) this->GetStatusBar()->SetStatusText(StrToWxStr(Str),0); } @@ -1248,7 +1246,8 @@ void CFrame::OnImportSave(wxCommandEvent& WXUNUSED (event)) if (!path.IsEmpty()) { - CWiiSaveCrypted* saveFile = new CWiiSaveCrypted(path.mb_str()); + // TODO: Does this actually need to be dynamically allocated for some reason? + CWiiSaveCrypted* saveFile = new CWiiSaveCrypted(WxStrToStr(path).c_str()); delete saveFile; } } @@ -1288,7 +1287,7 @@ void CFrame::OnInstallWAD(wxCommandEvent& event) _T("Wii WAD file (*.wad)|*.wad"), wxFD_OPEN | wxFD_PREVIEW | wxFD_FILE_MUST_EXIST, this); - fileName = path.mb_str(); + fileName = WxStrToStr(path); break; } default: @@ -1354,7 +1353,7 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect) GetUsbPointer()->AccessWiiMote(wm_idx | 0x100)->Activate(connect); wxString msg(wxString::Format(wxT("Wiimote %i %s"), wm_idx + 1, connect ? wxT("Connected") : wxT("Disconnected"))); - Core::DisplayMessage(msg.ToAscii(), 3000); + Core::DisplayMessage(WxStrToStr(msg), 3000); Host_UpdateMainFrame(); } } @@ -1394,7 +1393,7 @@ void CFrame::OnLoadStateFromFile(wxCommandEvent& WXUNUSED (event)) this); if (!path.IsEmpty()) - State::LoadAs((const char*)path.mb_str()); + State::LoadAs(WxStrToStr(path)); } void CFrame::OnSaveStateToFile(wxCommandEvent& WXUNUSED (event)) @@ -1408,7 +1407,7 @@ void CFrame::OnSaveStateToFile(wxCommandEvent& WXUNUSED (event)) this); if (!path.IsEmpty()) - State::SaveAs((const char*)path.mb_str()); + State::SaveAs(WxStrToStr(path)); } void CFrame::OnLoadLastState(wxCommandEvent& WXUNUSED (event)) diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index 6fd298ad81..d385b947e5 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -257,7 +257,7 @@ void CGameListCtrl::BrowseForDirectory() if (dialog.ShowModal() == wxID_OK) { - std::string sPath(dialog.GetPath().mb_str()); + std::string sPath(WxStrToStr(dialog.GetPath())); std::vector::iterator itResult = std::find( SConfig::GetInstance().m_ISOFolder.begin(), SConfig::GetInstance().m_ISOFolder.end(), sPath); @@ -402,7 +402,7 @@ wxString NiceSizeFormat(s64 _size) wxString NiceString; char tempstr[32]; sprintf(tempstr,"%3.1f %s", f, sizes[s]); - NiceString = wxString::FromAscii(tempstr); + NiceString = StrToWxStr(tempstr); return(NiceString); } @@ -614,7 +614,7 @@ void CGameListCtrl::ScanForISOs() // Update with the progress (i) and the message dialog.Update(i, wxString::Format(_("Scanning %s"), - wxString(FileName.c_str(), *wxConvCurrent).c_str())); + StrToWxStr(FileName).c_str())); if (dialog.WasCancelled()) break; @@ -858,7 +858,7 @@ void CGameListCtrl::OnMouseMotion(wxMouseEvent& event) char temp[2048]; sprintf(temp, "^ %s%s%s", emuState[emu_state - 1], issues.size() > 0 ? " :\n" : "", issues.c_str()); - toolTip = new wxEmuStateTip(this, wxString(temp, *wxConvCurrent), &toolTip); + toolTip = new wxEmuStateTip(this, StrToWxStr(temp), &toolTip); } else toolTip = new wxEmuStateTip(this, _("Not Set"), &toolTip); @@ -1115,9 +1115,9 @@ void CGameListCtrl::OnWiki(wxCommandEvent& WXUNUSED (event)) void CGameListCtrl::MultiCompressCB(const char* text, float percent, void* arg) { percent = (((float)m_currentItem) + percent) / (float)m_numberItem; - wxString textString(StringFromFormat("%s (%i/%i) - %s", + wxString textString(StrToWxStr(StringFromFormat("%s (%i/%i) - %s", m_currentFilename.c_str(), (int)m_currentItem+1, - (int)m_numberItem, text).c_str(), *wxConvCurrent); + (int)m_numberItem, text))); ((wxProgressDialog*)arg)->Update((int)(percent*1000), textString); } @@ -1170,13 +1170,13 @@ void CGameListCtrl::CompressSelection(bool _compress) std::string OutputFileName; BuildCompleteFilename(OutputFileName, - (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), + WxStrToStr(browseDialog.GetPath()), FileName); - if (wxFileExists(wxString::FromAscii(OutputFileName.c_str())) && + if (wxFileExists(StrToWxStr(OutputFileName.c_str())) && wxMessageBox( wxString::Format(_("The file %s already exists.\nDo you wish to replace it?"), - wxString(OutputFileName.c_str(), *wxConvCurrent).c_str()), + StrToWxStr(OutputFileName).c_str()), _("Confirm File Overwrite"), wxYES_NO) == wxNO) continue; @@ -1198,13 +1198,13 @@ void CGameListCtrl::CompressSelection(bool _compress) std::string OutputFileName; BuildCompleteFilename(OutputFileName, - (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), + WxStrToStr(browseDialog.GetPath()), FileName); - if (wxFileExists(wxString::FromAscii(OutputFileName.c_str())) && + if (wxFileExists(StrToWxStr(OutputFileName.c_str())) && wxMessageBox( wxString::Format(_("The file %s already exists.\nDo you wish to replace it?"), - wxString(OutputFileName.c_str(), *wxConvCurrent).c_str()), + StrToWxStr(OutputFileName).c_str()), _("Confirm File Overwrite"), wxYES_NO) == wxNO) continue; @@ -1225,7 +1225,7 @@ void CGameListCtrl::CompressSelection(bool _compress) void CGameListCtrl::CompressCB(const char* text, float percent, void* arg) { ((wxProgressDialog*)arg)-> - Update((int)(percent*1000), wxString(text, *wxConvCurrent)); + Update((int)(percent*1000), StrToWxStr(text)); } void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event)) @@ -1251,8 +1251,8 @@ void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event)) path = wxFileSelector( _("Save decompressed GCM/ISO"), - wxString(FilePath.c_str(), *wxConvCurrent), - wxString(FileName.c_str(), *wxConvCurrent) + FileType.After('*'), + StrToWxStr(FilePath), + StrToWxStr(FileName) + FileType.After('*'), wxEmptyString, FileType + wxT("|") + wxGetTranslation(wxALL_FILES), wxFD_SAVE, @@ -1262,8 +1262,8 @@ void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event)) { path = wxFileSelector( _("Save compressed GCM/ISO"), - wxString(FilePath.c_str(), *wxConvCurrent), - wxString(FileName.c_str(), *wxConvCurrent) + _T(".gcz"), + StrToWxStr(FilePath), + StrToWxStr(FileName) + _T(".gcz"), wxEmptyString, _("All compressed GC/Wii ISO files (gcz)") + wxString::Format(wxT("|*.gcz|%s"), wxGetTranslation(wxALL_FILES)), diff --git a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp index e015c55ae8..76d4833c0b 100644 --- a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp +++ b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp @@ -13,6 +13,7 @@ // If not, see http://www.gnu.org/licenses/ #include "GeckoCodeDiag.h" +#include "WxUtils.h" #include @@ -76,7 +77,7 @@ void CodeConfigPanel::UpdateCodeList() gcodes_end = m_gcodes.end(); for (; gcodes_iter!=gcodes_end; ++gcodes_iter) { - m_listbox_gcodes->Append(wxString(gcodes_iter->name.c_str(), *wxConvCurrent)); + m_listbox_gcodes->Append(StrToWxStr(gcodes_iter->name)); if (gcodes_iter->enabled) m_listbox_gcodes->Check(m_listbox_gcodes->GetCount()-1, true); } @@ -109,7 +110,7 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&) if (sel > -1) { - m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name) + wxString(m_gcodes[sel].name.c_str(), *wxConvCurrent)); + m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name) + StrToWxStr(m_gcodes[sel].name)); // notes textctrl m_infobox.textctrl_notes->Clear(); @@ -117,10 +118,10 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&) notes_iter = m_gcodes[sel].notes.begin(), notes_end = m_gcodes[sel].notes.end(); for (; notes_iter!=notes_end; ++notes_iter) - m_infobox.textctrl_notes->AppendText(wxString(notes_iter->c_str(), *wxConvCurrent)); + m_infobox.textctrl_notes->AppendText(StrToWxStr(*notes_iter)); m_infobox.textctrl_notes->ScrollLines(-99); // silly - m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator) + wxString(m_gcodes[sel].creator.c_str(), *wxConvCurrent)); + m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator) + StrToWxStr(m_gcodes[sel].creator)); // add codes to info listbox std::vector::const_iterator diff --git a/Source/Core/DolphinWX/Src/ISOFile.cpp b/Source/Core/DolphinWX/Src/ISOFile.cpp index 833268ad63..639190fa0e 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.cpp +++ b/Source/Core/DolphinWX/Src/ISOFile.cpp @@ -28,6 +28,7 @@ #include "StringUtil.h" #include "Hash.h" #include "IniFile.h" +#include "WxUtils.h" #include "Filesystem.h" #include "BannerLoader.h" @@ -331,7 +332,7 @@ const std::string GameListItem::GetWiiFSPath() const File::CreateFullPath(Path); if (Path[0] == '.') - ret = std::string(wxGetCwd().mb_str()) + std::string(Path).substr(strlen(ROOT_DIR)); + ret = WxStrToStr(wxGetCwd()) + std::string(Path).substr(strlen(ROOT_DIR)); else ret = std::string(Path); } diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index c44aad5d5b..e739ff043b 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -23,6 +23,7 @@ #include "CommonPaths.h" #include "Globals.h" +#include "WxUtils.h" #include "VolumeCreator.h" #include "Filesystem.h" #include "ISOProperties.h" @@ -663,10 +664,10 @@ void CISOProperties::OnExtractFile(wxCommandEvent& WXUNUSED (event)) { int partitionNum = wxAtoi(File.SubString(10, 11)); File.Remove(0, 12); // Remove "Partition x/" - WiiDisc.at(partitionNum).FileSystem->ExportFile(File.mb_str(), Path.mb_str()); + WiiDisc.at(partitionNum).FileSystem->ExportFile(WxStrToStr(File).c_str(), WxStrToStr(Path).c_str()); } else - pFileSystem->ExportFile(File.mb_str(), Path.mb_str()); + pFileSystem->ExportFile(WxStrToStr(File).c_str(), WxStrToStr(Path).c_str()); } void CISOProperties::ExportDir(const char* _rFullPath, const char* _rExportFolder, const int partitionNum) @@ -727,7 +728,7 @@ void CISOProperties::ExportDir(const char* _rFullPath, const char* _rExportFolde (u32)(((float)(i - index[0]) / (float)(index[1] - index[0])) * 100))); dialog.Update(i, wxString::Format(_("Extracting %s"), - wxString(fst[i]->m_FullPath, *wxConvCurrent).c_str())); + StrToWxStr(fst[i]->m_FullPath).c_str())); if (dialog.WasCancelled()) break; @@ -778,9 +779,9 @@ void CISOProperties::OnExtractDir(wxCommandEvent& event) { if (DiscIO::IsVolumeWiiDisc(OpenISO)) for (u32 i = 0; i < WiiDisc.size(); i++) - ExportDir(NULL, Path.mb_str(), i); + ExportDir(NULL, WxStrToStr(Path).c_str(), i); else - ExportDir(NULL, Path.mb_str()); + ExportDir(NULL, WxStrToStr(Path).c_str()); return; } @@ -798,10 +799,10 @@ void CISOProperties::OnExtractDir(wxCommandEvent& event) { int partitionNum = wxAtoi(Directory.SubString(10, 11)); Directory.Remove(0, 12); // Remove "Partition x/" - ExportDir(Directory.mb_str(), Path.mb_str(), partitionNum); + ExportDir(WxStrToStr(Directory).c_str(), WxStrToStr(Path).c_str(), partitionNum); } else - ExportDir(Directory.mb_str(), Path.mb_str()); + ExportDir(WxStrToStr(Directory).c_str(), WxStrToStr(Path).c_str()); } void CISOProperties::OnExtractDataFromHeader(wxCommandEvent& event) @@ -821,15 +822,15 @@ void CISOProperties::OnExtractDataFromHeader(wxCommandEvent& event) bool ret = false; if (event.GetId() == IDM_EXTRACTAPPLOADER) { - ret = FS->ExportApploader(Path.mb_str()); + ret = FS->ExportApploader(WxStrToStr(Path).c_str()); } else if (event.GetId() == IDM_EXTRACTDOL) { - ret = FS->ExportDOL(Path.mb_str()); + ret = FS->ExportDOL(WxStrToStr(Path).c_str()); } if (!ret) - PanicAlertT("Failed to extract to %s!", (const char *)Path.mb_str()); + PanicAlertT("Failed to extract to %s!", WxStrToStr(Path).c_str()); } class IntegrityCheckThread : public wxThread @@ -989,7 +990,7 @@ void CISOProperties::LoadGameConfig() GameIni.Get("EmuState", "EmulationIssues", &sTemp); if (!sTemp.empty()) { - EmuIssues->SetValue(wxString(sTemp.c_str(), *wxConvCurrent)); + EmuIssues->SetValue(StrToWxStr(sTemp.c_str())); } EmuIssues->Enable(EmuState->GetSelection() != 0); @@ -1075,7 +1076,7 @@ bool CISOProperties::SaveGameConfig() GameIni.Get("EmuState","EmulationIssues", &sTemp); if (EmuIssues->GetValue() != sTemp) bRefreshList = true; - GameIni.Set("EmuState", "EmulationIssues", (const char*)EmuIssues->GetValue().mb_str(*wxConvCurrent)); + GameIni.Set("EmuState", "EmulationIssues", WxStrToStr(EmuIssues->GetValue())); PatchList_Save(); ActionReplayList_Save(); @@ -1156,7 +1157,7 @@ void CISOProperties::PatchList_Load() for (std::vector::const_iterator it = onFrame.begin(); it != onFrame.end(); ++it) { PatchEngine::Patch p = *it; - Patches->Append(wxString(p.name.c_str(), *wxConvCurrent)); + Patches->Append(StrToWxStr(p.name.c_str())); Patches->Check(index, p.active); ++index; } @@ -1209,7 +1210,7 @@ void CISOProperties::PatchButtonClicked(wxCommandEvent& event) CPatchAddEdit dlg(-1, this, 1, _("Add Patch")); if (dlg.ShowModal() == wxID_OK) { - Patches->Append(wxString(onFrame.back().name.c_str(), *wxConvCurrent)); + Patches->Append(StrToWxStr(onFrame.back().name)); Patches->Check((unsigned int)(onFrame.size() - 1), onFrame.back().active); } } @@ -1238,7 +1239,7 @@ void CISOProperties::ActionReplayList_Load() for (std::vector::const_iterator it = arCodes.begin(); it != arCodes.end(); ++it) { ActionReplay::ARCode arCode = *it; - Cheats->Append(wxString(arCode.name.c_str(), *wxConvCurrent)); + Cheats->Append(StrToWxStr(arCode.name)); Cheats->Check(index, arCode.active); ++index; } @@ -1256,7 +1257,7 @@ void CISOProperties::ActionReplayList_Save() for (std::vector::const_iterator iter2 = code.ops.begin(); iter2 != code.ops.end(); ++iter2) { - lines.push_back(std::string(wxString::Format(wxT("%08X %08X"), iter2->cmd_addr, iter2->value).mb_str())); + lines.push_back(WxStrToStr(wxString::Format(wxT("%08X %08X"), iter2->cmd_addr, iter2->value))); } ++index; } @@ -1364,5 +1365,6 @@ void CISOProperties::ChangeBannerDetails(int lang) std::string filename, extension; SplitPath(OpenGameListItem->GetFileName(), 0, &filename, &extension); // Also sets the window's title - SetTitle(wxString(StringFromFormat("%s%s: %s - ", filename.c_str(), extension.c_str(), OpenGameListItem->GetUniqueID().c_str()).c_str(), *wxConvCurrent)+shortName); + SetTitle(StrToWxStr(StringFromFormat("%s%s: %s - ", filename.c_str(), + extension.c_str(), OpenGameListItem->GetUniqueID().c_str()).c_str()) + shortName); } diff --git a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp index 1efcf98af6..d8a755aca6 100644 --- a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp @@ -17,10 +17,7 @@ #include "InputConfigDiag.h" #include "UDPConfigDiag.h" - -#define WXSTR_FROM_STR(s) (wxString::FromUTF8((s).c_str())) -#define WXTSTR_FROM_CSTR(s) (wxGetTranslation(wxString::FromUTF8(s))) -#define STR_FROM_WXSTR(w) (std::string((w).ToUTF8())) +#include "WxUtils.h" void GamepadPage::ConfigUDPWii(wxCommandEvent &event) { @@ -37,7 +34,7 @@ void GamepadPage::ConfigExtension(wxCommandEvent& event) if (ex->switch_extension) { wxDialog dlg(this, -1, - WXTSTR_FROM_CSTR(ex->attachments[ex->switch_extension]->GetName().c_str()), + StrToWxStr(ex->attachments[ex->switch_extension]->GetName().c_str()), wxDefaultPosition, wxDefaultSize); wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL); @@ -67,7 +64,7 @@ PadSettingExtension::PadSettingExtension(wxWindow* const parent, ControllerEmu:: e = extension->attachments.end(); for (; i!=e; ++i) - ((wxChoice*)wxcontrol)->Append(WXTSTR_FROM_CSTR((*i)->GetName().c_str())); + ((wxChoice*)wxcontrol)->Append(StrToWxStr((*i)->GetName().c_str())); UpdateGUI(); } @@ -83,7 +80,7 @@ void PadSettingExtension::UpdateValue() } PadSettingCheckBox::PadSettingCheckBox(wxWindow* const parent, ControlState& _value, const char* const label) - : PadSetting(new wxCheckBox(parent, -1, WXTSTR_FROM_CSTR(label), wxDefaultPosition)) + : PadSetting(new wxCheckBox(parent, -1, StrToWxStr(label), wxDefaultPosition)) , value(_value) { UpdateGUI(); @@ -119,8 +116,8 @@ ControlDialog::ControlDialog(GamepadPage* const parent, InputPlugin& plugin, Con m_devq = m_parent->controller->default_device; // GetStrings() sounds slow :/ - //device_cbox = new wxComboBox(this, -1, WXSTR_FROM_STR(ref->device_qualifier.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER); - device_cbox = new wxComboBox(this, -1, WXSTR_FROM_STR(m_devq.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER); + //device_cbox = new wxComboBox(this, -1, StrToWxStr(ref->device_qualifier.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER); + device_cbox = new wxComboBox(this, -1, StrToWxStr(m_devq.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER); device_cbox->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &ControlDialog::SetDevice, this); device_cbox->Bind(wxEVT_COMMAND_TEXT_ENTER, &ControlDialog::SetDevice, this); @@ -145,9 +142,9 @@ ControlButton::ControlButton(wxWindow* const parent, ControllerInterface::Contro , control_reference(_ref) { if (label.empty()) - SetLabel(WXSTR_FROM_STR(_ref->expression)); + SetLabel(StrToWxStr(_ref->expression)); else - SetLabel(WXSTR_FROM_STR(label)); + SetLabel(StrToWxStr(label)); } void InputConfigDialog::UpdateProfileComboBox() @@ -169,7 +166,7 @@ void InputConfigDialog::UpdateProfileComboBox() for (; si!=se; ++si) { std::string str(si->begin() + si->find_last_of('/') + 1 , si->end() - 4) ; - strs.push_back(WXSTR_FROM_STR(str)); + strs.push_back(StrToWxStr(str)); } std::vector< GamepadPage* >::iterator i = m_padpages.begin(), @@ -209,7 +206,7 @@ void ControlDialog::UpdateListContents() i = dev->Inputs().begin(), e = dev->Inputs().end(); for (; i!=e; ++i) - control_lbox->Append(WXSTR_FROM_STR((*i)->GetName())); + control_lbox->Append(StrToWxStr((*i)->GetName())); } else { @@ -218,7 +215,7 @@ void ControlDialog::UpdateListContents() i = dev->Outputs().begin(), e = dev->Outputs().end(); for (; i!=e; ++i) - control_lbox->Append(WXSTR_FROM_STR((*i)->GetName())); + control_lbox->Append(StrToWxStr((*i)->GetName())); } } } @@ -227,7 +224,7 @@ void ControlDialog::SelectControl(const std::string& name) { //UpdateGUI(); - const int f = control_lbox->FindString(WXSTR_FROM_STR(name)); + const int f = control_lbox->FindString(StrToWxStr(name)); if (f >= 0) control_lbox->Select(f); } @@ -235,7 +232,7 @@ void ControlDialog::SelectControl(const std::string& name) void ControlDialog::UpdateGUI() { // update textbox - textctrl->SetValue(WXSTR_FROM_STR(control_reference->expression)); + textctrl->SetValue(StrToWxStr(control_reference->expression)); // updates the "bound controls:" label m_bound_label->SetLabel(wxString::Format(_("Bound Controls: %lu"), @@ -244,7 +241,7 @@ void ControlDialog::UpdateGUI() void GamepadPage::UpdateGUI() { - device_cbox->SetValue(WXSTR_FROM_STR(controller->default_device.ToString())); + device_cbox->SetValue(StrToWxStr(controller->default_device.ToString())); std::vector< ControlGroupBox* >::const_iterator g = control_groups.begin(), ge = control_groups.end(); @@ -255,7 +252,7 @@ void GamepadPage::UpdateGUI() , e = (*g)->control_buttons.end(); for (; i!=e; ++i) //if (std::string::npos == (*i)->control_reference->expression.find_first_of("`|&!#")) - (*i)->SetLabel(WXSTR_FROM_STR((*i)->control_reference->expression)); + (*i)->SetLabel(StrToWxStr((*i)->control_reference->expression)); //else //(*i)->SetLabel(wxT("...")); @@ -294,7 +291,7 @@ void GamepadPage::LoadDefaults(wxCommandEvent&) void ControlDialog::SetControl(wxCommandEvent&) { - control_reference->expression = STR_FROM_WXSTR(textctrl->GetValue()); + control_reference->expression = WxStrToStr(textctrl->GetValue()); std::lock_guard lk(m_plugin.controls_lock); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); @@ -304,10 +301,10 @@ void ControlDialog::SetControl(wxCommandEvent&) void GamepadPage::SetDevice(wxCommandEvent&) { - controller->default_device.FromString(STR_FROM_WXSTR(device_cbox->GetValue())); + controller->default_device.FromString(WxStrToStr(device_cbox->GetValue())); // show user what it was validated as - device_cbox->SetValue(WXSTR_FROM_STR(controller->default_device.ToString())); + device_cbox->SetValue(StrToWxStr(controller->default_device.ToString())); // this will set all the controls to this default device controller->UpdateDefaultDevice(); @@ -319,10 +316,10 @@ void GamepadPage::SetDevice(wxCommandEvent&) void ControlDialog::SetDevice(wxCommandEvent&) { - m_devq.FromString(STR_FROM_WXSTR(device_cbox->GetValue())); + m_devq.FromString(WxStrToStr(device_cbox->GetValue())); // show user what it was validated as - device_cbox->SetValue(WXSTR_FROM_STR(m_devq.ToString())); + device_cbox->SetValue(StrToWxStr(m_devq.ToString())); // update gui UpdateListContents(); @@ -349,12 +346,12 @@ void ControlDialog::SetSelectedControl(wxCommandEvent&) // non-default device if (false == (m_devq == m_parent->controller->default_device)) - expr.append(wxT('`')).append(WXSTR_FROM_STR(m_devq.ToString())).append(wxT('`')); + expr.append(wxT('`')).append(StrToWxStr(m_devq.ToString())).append(wxT('`')); // append the control name expr += control_lbox->GetString(num); - control_reference->expression = STR_FROM_WXSTR(expr); + control_reference->expression = WxStrToStr(expr); std::lock_guard lk(m_plugin.controls_lock); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); @@ -380,12 +377,12 @@ void ControlDialog::AppendControl(wxCommandEvent& event) // non-default device if (false == (m_devq == m_parent->controller->default_device)) - expr.append(wxT('`')).append(WXSTR_FROM_STR(m_devq.ToString())).append(wxT('`')); + expr.append(wxT('`')).append(StrToWxStr(m_devq.ToString())).append(wxT('`')); // append the control name expr += control_lbox->GetString(num); - control_reference->expression = STR_FROM_WXSTR(expr); + control_reference->expression = WxStrToStr(expr); std::lock_guard lk(m_plugin.controls_lock); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); @@ -475,7 +472,7 @@ void GamepadPage::DetectControl(wxCommandEvent& event) g_controller_interface.UpdateReference(btn->control_reference, controller->default_device); } - btn->SetLabel(WXSTR_FROM_STR(btn->control_reference->expression)); + btn->SetLabel(StrToWxStr(btn->control_reference->expression)); } } @@ -565,7 +562,7 @@ void GamepadPage::GetProfilePath(std::string& path) path += PROFILES_PATH; path += m_plugin.profile_name; path += '/'; - path += STR_FROM_WXSTR(profile_cbox->GetValue()); + path += WxStrToStr(profile_cbox->GetValue()); path += ".ini"; } } @@ -615,7 +612,7 @@ void GamepadPage::DeleteProfile(wxCommandEvent&) if (File::Exists(fnamecstr) && AskYesNoT("Are you sure you want to delete \"%s\"?", - STR_FROM_WXSTR(profile_cbox->GetValue()).c_str())) + WxStrToStr(profile_cbox->GetValue()).c_str())) { File::Delete(fnamecstr); @@ -637,9 +634,9 @@ void InputConfigDialog::UpdateDeviceComboBox() for (; di!=de; ++di) { dq.FromDevice(*di); - (*i)->device_cbox->Append(WXSTR_FROM_STR(dq.ToString())); + (*i)->device_cbox->Append(StrToWxStr(dq.ToString())); } - (*i)->device_cbox->SetValue(WXSTR_FROM_STR((*i)->controller->default_device.ToString())); + (*i)->device_cbox->SetValue(StrToWxStr((*i)->controller->default_device.ToString())); } } @@ -680,7 +677,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin for (; ci != ce; ++ci) { - wxStaticText* const label = new wxStaticText(parent, -1, WXTSTR_FROM_CSTR((*ci)->name)); + wxStaticText* const label = new wxStaticText(parent, -1, StrToWxStr((*ci)->name)); ControlButton* const control_button = new ControlButton(parent, (*ci)->control_ref, 80); control_button->SetFont(m_SmallFont); @@ -734,7 +731,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin PadSettingSpin* setting = new PadSettingSpin(parent, *i); setting->wxcontrol->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &GamepadPage::AdjustSetting, eventsink); options.push_back(setting); - szr->Add(new wxStaticText(parent, -1, WXTSTR_FROM_CSTR((*i)->name))); + szr->Add(new wxStaticText(parent, -1, StrToWxStr((*i)->name))); szr->Add(setting->wxcontrol, 0, wxLEFT, 0); } @@ -760,7 +757,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin options.push_back(threshold_cbox); wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL); - szr->Add(new wxStaticText(parent, -1, WXTSTR_FROM_CSTR(group->settings[0]->name)), + szr->Add(new wxStaticText(parent, -1, StrToWxStr(group->settings[0]->name)), 0, wxCENTER|wxRIGHT, 3); szr->Add(threshold_cbox->wxcontrol, 0, wxRIGHT, 3); @@ -795,7 +792,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin setting->wxcontrol->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &GamepadPage::AdjustSetting, eventsink); options.push_back(setting); wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL); - szr->Add(new wxStaticText(parent, -1, WXTSTR_FROM_CSTR((*i)->name)), 0, wxCENTER|wxRIGHT, 3); + szr->Add(new wxStaticText(parent, -1, StrToWxStr((*i)->name)), 0, wxCENTER|wxRIGHT, 3); szr->Add(setting->wxcontrol, 0, wxRIGHT, 3); Add(szr, 0, wxALL|wxCENTER, 3); } @@ -859,7 +856,7 @@ ControlGroupsSizer::ControlGroupsSizer(ControllerEmu* const controller, wxWindow { ControlGroupBox* control_group_box = new ControlGroupBox(controller->groups[i], parent, eventsink); wxStaticBoxSizer *control_group = - new wxStaticBoxSizer(wxVERTICAL, parent, WXTSTR_FROM_CSTR(controller->groups[i]->name)); + new wxStaticBoxSizer(wxVERTICAL, parent, StrToWxStr(controller->groups[i]->name)); control_group->Add(control_group_box); const size_t grp_size = controller->groups[i]->controls.size() + controller->groups[i]->settings.size(); @@ -955,7 +952,7 @@ GamepadPage::GamepadPage(wxWindow* parent, InputPlugin& plugin, const unsigned i InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin, const std::string& name, const int tab_num) - : wxDialog(parent, wxID_ANY, WXTSTR_FROM_CSTR(name.c_str()), wxPoint(128,-1), wxDefaultSize) + : wxDialog(parent, wxID_ANY, StrToWxStr(name.c_str()), wxPoint(128,-1), wxDefaultSize) , m_plugin(plugin) { m_pad_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT); @@ -963,7 +960,7 @@ InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin { GamepadPage* gp = new GamepadPage(m_pad_notebook, m_plugin, i, this); m_padpages.push_back(gp); - m_pad_notebook->AddPage(gp, wxString::Format(wxT("%s %u"), WXTSTR_FROM_CSTR(m_plugin.gui_name), 1+i)); + m_pad_notebook->AddPage(gp, wxString::Format(wxT("%s %u"), StrToWxStr(m_plugin.gui_name), 1+i)); } m_pad_notebook->SetSelection(tab_num); diff --git a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp index ff5ed3b9cd..4e07ed990d 100644 --- a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp +++ b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include "InputConfigDiag.h" +#include "WxUtils.h" void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) { @@ -48,7 +49,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) // label for sticks and stuff if (64 == bitmap.GetHeight()) - dc.DrawText(wxString::FromAscii((*g)->control_group->name).Upper(), 4, 2); + dc.DrawText(StrToWxStr((*g)->control_group->name).Upper(), 4, 2); switch ( (*g)->control_group->type ) { @@ -227,7 +228,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) // text const char* const name = (*g)->control_group->controls[n]->name; // bit of hax so ZL, ZR show up as L, R - dc.DrawText(wxString::FromAscii((name[1] && name[1] < 'a') ? name[1] : name[0]), n*12 + 2, 1); + dc.DrawText(StrToWxStr((name[1] && name[1] < 'a') ? name[1] : name[0]), n*12 + 2, 1); } delete[] bitmasks; @@ -263,7 +264,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) dc.DrawRectangle(0, n*12, trigs[n], 14); // text - dc.DrawText(wxString::FromAscii((*g)->control_group->controls[n]->name), 3, n*12 + 1); + dc.DrawText(StrToWxStr((*g)->control_group->controls[n]->name), 3, n*12 + 1); } delete[] trigs; @@ -298,8 +299,8 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) dc.DrawRectangle(64, n*12, 32, 14); // text - dc.DrawText(wxString::FromAscii((*g)->control_group->controls[n+trigger_count]->name), 3, n*12 + 1); - dc.DrawText(wxString::FromAscii((*g)->control_group->controls[n]->name[0]), 64 + 3, n*12 + 1); + dc.DrawText(StrToWxStr((*g)->control_group->controls[n+trigger_count]->name), 3, n*12 + 1); + dc.DrawText(StrToWxStr((*g)->control_group->controls[n]->name[0]), 64 + 3, n*12 + 1); } // threshold box diff --git a/Source/Core/DolphinWX/Src/LogConfigWindow.cpp b/Source/Core/DolphinWX/Src/LogConfigWindow.cpp index 162647c64d..a4a5fa647a 100644 --- a/Source/Core/DolphinWX/Src/LogConfigWindow.cpp +++ b/Source/Core/DolphinWX/Src/LogConfigWindow.cpp @@ -20,6 +20,7 @@ #include "ConsoleListener.h" #include "LogWindow.h" #include "FileUtil.h" +#include "WxUtils.h" LogConfigWindow::LogConfigWindow(wxWindow* parent, CLogWindow *log_window, wxWindowID id) : wxPanel(parent, id, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _("Log Configuration")) @@ -74,7 +75,7 @@ void LogConfigWindow::CreateGUIControls() m_checks = new wxCheckListBox(this, wxID_ANY); m_checks->Bind(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, &LogConfigWindow::OnLogCheck, this); for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) - m_checks->Append(wxString::FromAscii(m_LogManager->GetFullName((LogTypes::LOG_TYPE)i))); + m_checks->Append(StrToWxStr(m_LogManager->GetFullName((LogTypes::LOG_TYPE)i))); // Sizers wxStaticBoxSizer* sbOutputs = new wxStaticBoxSizer(wxVERTICAL, this, _("Logger Outputs")); diff --git a/Source/Core/DolphinWX/Src/Main.cpp b/Source/Core/DolphinWX/Src/Main.cpp index d9d1908de3..60a8157c28 100644 --- a/Source/Core/DolphinWX/Src/Main.cpp +++ b/Source/Core/DolphinWX/Src/Main.cpp @@ -32,6 +32,7 @@ #include "Host.h" // Core #include "HW/Wiimote.h" +#include "WxUtils.h" #include "Globals.h" // Local #include "Main.h" #include "ConfigManager.h" @@ -211,7 +212,7 @@ bool DolphinApp::OnInit() } #ifdef _WIN32 - if (!wxSetWorkingDirectory(wxString(File::GetExeDirectory().c_str(), *wxConvCurrent))) + if (!wxSetWorkingDirectory(StrToWxStr(File::GetExeDirectory()))) { INFO_LOG(CONSOLE, "set working directory failed"); } @@ -246,7 +247,7 @@ bool DolphinApp::OnInit() if (selectVideoBackend && videoBackendName != wxEmptyString) SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoBackend = - std::string(videoBackendName.mb_str()); + WxStrToStr(videoBackendName); if (selectAudioEmulation) { @@ -296,7 +297,7 @@ bool DolphinApp::OnInit() #endif main_frame = new CFrame((wxFrame*)NULL, wxID_ANY, - wxString::FromAscii(scm_rev_str), + StrToWxStr(scm_rev_str), wxPoint(x, y), wxSize(w, h), UseDebugger, BatchMode, UseLogger); SetTopWindow(main_frame); @@ -317,7 +318,7 @@ void DolphinApp::MacOpenFile(const wxString &fileName) LoadFile = true; if (m_afterinit == NULL) - main_frame->BootGame(std::string(FileToLoad.mb_str())); + main_frame->BootGame(WxStrToStr(FileToLoad)); } void DolphinApp::AfterInit(wxTimerEvent& WXUNUSED(event)) @@ -331,7 +332,7 @@ void DolphinApp::AfterInit(wxTimerEvent& WXUNUSED(event)) // First check if we have an exec command line. if (LoadFile && FileToLoad != wxEmptyString) { - main_frame->BootGame(std::string(FileToLoad.mb_str())); + main_frame->BootGame(WxStrToStr(FileToLoad)); } // If we have selected Automatic Start, start the default ISO, // or if no default ISO exists, start the last loaded ISO @@ -418,7 +419,7 @@ void Host_SysMessage(const char *fmt, ...) va_end(list); if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; - //wxMessageBox(wxString::FromAscii(msg)); + //wxMessageBox(StrToWxStr(msg)); PanicAlert("%s", msg); } @@ -427,14 +428,13 @@ bool wxMsgAlert(const char* caption, const char* text, bool yes_no, int /*Style* #ifdef __WXGTK__ if (wxIsMainThread()) #endif - return wxYES == wxMessageBox(wxString::FromUTF8(text), - wxString::FromUTF8(caption), + return wxYES == wxMessageBox(StrToWxStr(text), StrToWxStr(caption), (yes_no) ? wxYES_NO : wxOK, wxGetActiveWindow()); #ifdef __WXGTK__ else { wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_PANIC); - event.SetString(wxString::FromUTF8(caption) + wxT(":") + wxString::FromUTF8(text)); + event.SetString(StrToWxStr(caption) + wxT(":") + StrToWxStr(text)); event.SetInt(yes_no); main_frame->GetEventHandler()->AddPendingEvent(event); main_frame->panic_event.Wait(); @@ -445,7 +445,7 @@ bool wxMsgAlert(const char* caption, const char* text, bool yes_no, int /*Style* std::string wxStringTranslator(const char *text) { - return (const char *)wxString(wxGetTranslation(wxString::From8BitData(text))).ToUTF8(); + return WxStrToStr(wxGetTranslation(wxString::From8BitData(text))); } // Accessor for the main window class @@ -536,7 +536,7 @@ void Host_UpdateMainFrame() void Host_UpdateTitle(const char* title) { wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_UPDATETITLE); - event.SetString(wxString::FromAscii(title)); + event.SetString(StrToWxStr(title)); main_frame->GetEventHandler()->AddPendingEvent(event); } @@ -603,7 +603,7 @@ void Host_UpdateStatusBar(const char* _pText, int Field) { wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_UPDATESTATUSBAR); // Set the event string - event.SetString(wxString::FromAscii(_pText)); + event.SetString(StrToWxStr(_pText)); // Update statusbar field event.SetInt(Field); // Post message diff --git a/Source/Core/DolphinWX/Src/MemcardManager.cpp b/Source/Core/DolphinWX/Src/MemcardManager.cpp index b3a7ab22b8..d9fd4d3ae6 100644 --- a/Source/Core/DolphinWX/Src/MemcardManager.cpp +++ b/Source/Core/DolphinWX/Src/MemcardManager.cpp @@ -17,6 +17,8 @@ #include "MemcardManager.h" #include "Common.h" + +#include "WxUtils.h" #include "wx/mstream.h" #define ARROWS slot ? _T("") : ARROW[slot], slot ? ARROW[slot] : _T("") @@ -290,7 +292,7 @@ void CMemcardManager::ChangePath(int slot) } else { - if (m_MemcardPath[slot]->GetPath().length() && ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot)) + if (m_MemcardPath[slot]->GetPath().length() && ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot)) { if (memoryCard[slot2]) { @@ -345,7 +347,7 @@ void CMemcardManager::OnPageChange(wxCommandEvent& event) m_NextPage[slot]->Disable(); m_MemcardList[slot]->nextPage = false; } - ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot); + ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot); break; case ID_PREVPAGE_A: slot = SLOT_A; @@ -361,7 +363,7 @@ void CMemcardManager::OnPageChange(wxCommandEvent& event) m_PrevPage[slot]->Disable(); m_MemcardList[slot]->prevPage = false; } - ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot); + ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot); break; } } @@ -373,7 +375,7 @@ void CMemcardManager::OnMenuChange(wxCommandEvent& event) { case ID_MEMCARDPATH_A: case ID_MEMCARDPATH_B: - DefaultMemcard[_id - ID_MEMCARDPATH_A] = m_MemcardPath[_id - ID_MEMCARDPATH_A]->GetPath().mb_str(); + DefaultMemcard[_id - ID_MEMCARDPATH_A] = WxStrToStr(m_MemcardPath[_id - ID_MEMCARDPATH_A]->GetPath()); return; case ID_USEPAGES: mcmSettings.usePages = !mcmSettings.usePages; @@ -400,8 +402,8 @@ void CMemcardManager::OnMenuChange(wxCommandEvent& event) break; } - if (memoryCard[SLOT_A]) ReloadMemcard(m_MemcardPath[SLOT_A]->GetPath().mb_str(), SLOT_A); - if (memoryCard[SLOT_B]) ReloadMemcard(m_MemcardPath[SLOT_B]->GetPath().mb_str(), SLOT_B); + if (memoryCard[SLOT_A]) ReloadMemcard(WxStrToStr(m_MemcardPath[SLOT_A]->GetPath()).c_str(), SLOT_A); + if (memoryCard[SLOT_B]) ReloadMemcard(WxStrToStr(m_MemcardPath[SLOT_B]->GetPath()).c_str(), SLOT_B); } bool CMemcardManager::CopyDeleteSwitch(u32 error, int slot) { @@ -416,7 +418,7 @@ bool CMemcardManager::CopyDeleteSwitch(u32 error, int slot) memoryCard[slot]->FixChecksums(); if (!memoryCard[slot]->Save()) PanicAlert(E_SAVEFAILED); page[slot] = FIRSTPAGE; - ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot); + ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot); } break; case NOMEMCARD: @@ -517,7 +519,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) wxString fileName = wxFileSelector( _("Select a save file to import"), (strcmp(DefaultIOPath.c_str(), "/Users/GC") == 0) - ? wxString::FromAscii("") + ? StrToWxStr("") : wxString::From8BitData(DefaultIOPath.c_str()), wxEmptyString, wxEmptyString, _("GameCube Savegame files(*.gci;*.gcs;*.sav)") + wxString(wxT("|*.gci;*.gcs;*.sav|")) + @@ -532,11 +534,11 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) _("GCI File(*.gci)") + wxString(_T("|*.gci")), wxFD_OVERWRITE_PROMPT|wxFD_SAVE, this); if (temp2.empty()) break; - fileName2 = temp2.mb_str(); + fileName2 = WxStrToStr(temp2); } if (fileName.length() > 0) { - CopyDeleteSwitch(memoryCard[slot]->ImportGci(fileName.mb_str(), fileName2), slot); + CopyDeleteSwitch(memoryCard[slot]->ImportGci(WxStrToStr(fileName).c_str(), fileName2), slot); } } break; @@ -564,9 +566,9 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) if (fileName.length() > 0) { - if (!CopyDeleteSwitch(memoryCard[slot]->ExportGci(index, fileName.mb_str(), ""), -1)) + if (!CopyDeleteSwitch(memoryCard[slot]->ExportGci(index, WxStrToStr(fileName).c_str(), ""), -1)) { - File::Delete(std::string(fileName.mb_str())); + File::Delete(WxStrToStr(fileName)); } } } @@ -576,7 +578,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) case ID_EXPORTALL_B: { std::string path1, path2, mpath; - mpath = m_MemcardPath[slot]->GetPath().mb_str(); + mpath = WxStrToStr(m_MemcardPath[slot]->GetPath()); SplitPath(mpath, &path1, &path2, NULL); path1 += path2; File::CreateDir(path1); diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index 142a7ea00c..d9fd5e6ca0 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -18,6 +18,7 @@ #include #include +#include "WxUtils.h" #include "NetPlay.h" #include "NetWindow.h" #include "Frame.h" @@ -72,7 +73,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* std::string address; netplay_section.Get("Address", &address, "localhost"); - m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, wxString::FromAscii(address.c_str())); + m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(address.c_str())); wxStaticText* const port_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Port :"), wxDefaultPosition, wxDefaultSize); @@ -80,7 +81,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* // string? w/e std::string port; netplay_section.Get("ConnectPort", &port, "2626"); - m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY, wxString::FromAscii(port.c_str())); + m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(port.c_str())); wxButton* const connect_btn = new wxButton(connect_tab, wxID_ANY, _("Connect")); connect_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &NetPlaySetupDiag::OnJoin, this); @@ -113,7 +114,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* // string? w/e std::string port; netplay_section.Get("HostPort", &port, "2626"); - m_host_port_text = new wxTextCtrl(host_tab, wxID_ANY, wxString::FromAscii(port.c_str())); + m_host_port_text = new wxTextCtrl(host_tab, wxID_ANY, StrToWxStr(port.c_str())); wxButton* const host_btn = new wxButton(host_tab, wxID_ANY, _("Host")); host_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &NetPlaySetupDiag::OnHost, this); @@ -124,7 +125,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* std::istringstream ss(game_list->GetGameNames()); std::string game; while (std::getline(ss,game)) - m_game_lbox->Append(wxString(game.c_str(), *wxConvCurrent)); + m_game_lbox->Append(StrToWxStr(game)); wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL); top_szr->Add(port_lbl, 0, wxCENTER | wxRIGHT, 5); @@ -167,10 +168,10 @@ NetPlaySetupDiag::~NetPlaySetupDiag() inifile.Load(dolphin_ini); IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay"); - netplay_section.Set("Nickname", m_nickname_text->GetValue().mb_str()); - netplay_section.Set("Address", m_connect_ip_text->GetValue().mb_str()); - netplay_section.Set("ConnectPort", m_connect_port_text->GetValue().mb_str()); - netplay_section.Set("HostPort", m_host_port_text->GetValue().mb_str()); + netplay_section.Set("Nickname", WxStrToStr(m_nickname_text->GetValue())); + netplay_section.Set("Address", WxStrToStr(m_connect_ip_text->GetValue())); + netplay_section.Set("ConnectPort", WxStrToStr(m_connect_port_text->GetValue())); + netplay_section.Set("HostPort", WxStrToStr(m_host_port_text->GetValue())); inifile.Save(dolphin_ini); main_frame->g_NetPlaySetupDiag = NULL; @@ -191,13 +192,13 @@ void NetPlaySetupDiag::OnHost(wxCommandEvent&) return; } - std::string game(m_game_lbox->GetStringSelection().mb_str()); + std::string game(WxStrToStr(m_game_lbox->GetStringSelection())); npd = new NetPlayDiag(m_parent, m_game_list, game, true); unsigned long port = 0; m_host_port_text->GetValue().ToULong(&port); netplay_ptr = new NetPlayServer(u16(port) - , std::string(m_nickname_text->GetValue().mb_str()), npd, game); + , WxStrToStr(m_nickname_text->GetValue()), npd, game); if (netplay_ptr->is_connected) { npd->Show(); @@ -222,8 +223,8 @@ void NetPlaySetupDiag::OnJoin(wxCommandEvent&) npd = new NetPlayDiag(m_parent, m_game_list, ""); unsigned long port = 0; m_connect_port_text->GetValue().ToULong(&port); - netplay_ptr = new NetPlayClient(std::string(m_connect_ip_text->GetValue().mb_str()) - , (u16)port, npd, std::string(m_nickname_text->GetValue().mb_str())); + netplay_ptr = new NetPlayClient(WxStrToStr(m_connect_ip_text->GetValue()) + , (u16)port, npd, WxStrToStr(m_nickname_text->GetValue())); if (netplay_ptr->is_connected) { npd->Show(); @@ -250,7 +251,7 @@ NetPlayDiag::NetPlayDiag(wxWindow* const parent, const CGameListCtrl* const game // top crap m_game_btn = new wxButton(panel, wxID_ANY, - wxString(m_selected_game.c_str(), *wxConvCurrent).Prepend(_(" Game : ")), + StrToWxStr(m_selected_game).Prepend(_(" Game : ")), wxDefaultPosition, wxDefaultSize, wxBU_LEFT); if (is_hosting) @@ -351,7 +352,7 @@ void NetPlayDiag::OnChat(wxCommandEvent&) if (s.Length()) { - netplay_ptr->SendChatMessage(std::string(s.mb_str())); + netplay_ptr->SendChatMessage(WxStrToStr(s)); m_chat_text->AppendText(s.Prepend(wxT(" >> ")).Append(wxT('\n'))); m_chat_msg_text->Clear(); } @@ -412,7 +413,7 @@ void NetPlayDiag::OnMsgChangeGame(const std::string& filename) { wxCommandEvent evt(wxEVT_THREAD, NP_GUI_EVT_CHANGE_GAME); // TODO: using a wxString in AddPendingEvent from another thread is unsafe i guess? - evt.SetString(wxString(filename.c_str(), *wxConvCurrent)); + evt.SetString(StrToWxStr(filename)); GetEventHandler()->AddPendingEvent(evt); } @@ -436,7 +437,7 @@ void NetPlayDiag::OnPadBuffHelp(wxCommandEvent&) << time * (60.0f/1000) << "(60fps) / " << time * (50.0f/1000) << "(50fps) >\n"; - m_chat_text->AppendText(wxString(ss.str().c_str(), *wxConvCurrent)); + m_chat_text->AppendText(StrToWxStr(ss.str())); } void NetPlayDiag::OnAdjustBuffer(wxCommandEvent& event) @@ -447,7 +448,7 @@ void NetPlayDiag::OnAdjustBuffer(wxCommandEvent& event) std::ostringstream ss; ss << "< Pad Buffer: " << val << " >"; netplay_ptr->SendChatMessage(ss.str()); - m_chat_text->AppendText(wxString(ss.str().c_str(), *wxConvCurrent).Append(wxT('\n'))); + m_chat_text->AppendText(StrToWxStr(ss.str()).Append(wxT('\n'))); } void NetPlayDiag::OnQuit(wxCommandEvent&) @@ -468,7 +469,7 @@ void NetPlayDiag::OnThread(wxCommandEvent& event) m_player_lbox->Clear(); std::istringstream ss(tmps); while (std::getline(ss, tmps)) - m_player_lbox->Append(wxString(tmps.c_str(), *wxConvCurrent)); + m_player_lbox->Append(StrToWxStr(tmps)); m_player_lbox->SetSelection(selection); @@ -477,7 +478,7 @@ void NetPlayDiag::OnThread(wxCommandEvent& event) case NP_GUI_EVT_CHANGE_GAME : // update selected game :/ { - m_selected_game.assign(event.GetString().mb_str()); + m_selected_game.assign(WxStrToStr(event.GetString())); m_game_btn->SetLabel(event.GetString().Prepend(_(" Game : "))); } break; @@ -503,7 +504,7 @@ void NetPlayDiag::OnThread(wxCommandEvent& event) std::string s; chat_msgs.Pop(s); //PanicAlert("message: %s", s.c_str()); - m_chat_text->AppendText(wxString(s.c_str(), *wxConvCurrent).Append(wxT('\n'))); + m_chat_text->AppendText(StrToWxStr(s).Append(wxT('\n'))); } } @@ -515,7 +516,7 @@ void NetPlayDiag::OnChangeGame(wxCommandEvent&) if (game_name.length()) { - m_selected_game = std::string(game_name.mb_str()); + m_selected_game = WxStrToStr(game_name); netplay_ptr->ChangeGame(m_selected_game); m_game_btn->SetLabel(game_name.Prepend(_(" Game : "))); } @@ -553,7 +554,7 @@ ChangeGameDiag::ChangeGameDiag(wxWindow* const parent, const CGameListCtrl* cons std::istringstream ss(game_list->GetGameNames()); std::string game; while (std::getline(ss,game)) - m_game_lbox->Append(wxString(game.c_str(), *wxConvCurrent)); + m_game_lbox->Append(StrToWxStr(game)); wxButton* const ok_btn = new wxButton(this, wxID_OK, _("Change")); ok_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &ChangeGameDiag::OnPick, this); diff --git a/Source/Core/DolphinWX/Src/PHackSettings.cpp b/Source/Core/DolphinWX/Src/PHackSettings.cpp index 83f08d9cb7..dcfa1a8501 100644 --- a/Source/Core/DolphinWX/Src/PHackSettings.cpp +++ b/Source/Core/DolphinWX/Src/PHackSettings.cpp @@ -17,6 +17,7 @@ #include "PHackSettings.h" #include "ConfigManager.h" +#include "WxUtils.h" extern PHackData PHack_Data; @@ -97,8 +98,8 @@ void CPHackSettings::LoadPHackData() if (sTemp.empty()) sTemp = wxString(_("(UNKNOWN)")).char_str(); if (i == 0) - PHackChoice->Append(wxString("-------------", *wxConvCurrent)); - PHackChoice->Append(wxString(sTemp.c_str(), *wxConvCurrent)); + PHackChoice->Append(StrToWxStr("-------------")); + PHackChoice->Append(StrToWxStr(sTemp)); } PHackChoice->Select(0); @@ -106,8 +107,8 @@ void CPHackSettings::LoadPHackData() PHackSZFar->Set3StateValue((wxCheckBoxState)PHack_Data.PHackSZFar); PHackExP->Set3StateValue((wxCheckBoxState)PHack_Data.PHackExP); - PHackZNear->SetValue(wxString(PHack_Data.PHZNear.c_str(), *wxConvCurrent)); - PHackZFar->SetValue(wxString(PHack_Data.PHZFar.c_str(), *wxConvCurrent)); + PHackZNear->SetValue(StrToWxStr(PHack_Data.PHZNear)); + PHackZFar->SetValue(StrToWxStr(PHack_Data.PHZFar)); } void CPHackSettings::SetRefresh(wxCommandEvent& event) @@ -128,9 +129,9 @@ void CPHackSettings::SetRefresh(wxCommandEvent& event) PHPresetsIni.Get(sIndex, "PH_ExtraParam", &bTemp); PHackExP->Set3StateValue((wxCheckBoxState)bTemp); PHPresetsIni.Get(sIndex, "PH_ZNear", &sTemp); - PHackZNear->SetValue(wxString(sTemp.c_str(), *wxConvCurrent)); + PHackZNear->SetValue(StrToWxStr(sTemp)); PHPresetsIni.Get(sIndex, "PH_ZFar", &sTemp); - PHackZFar->SetValue(wxString(sTemp.c_str(), *wxConvCurrent)); + PHackZFar->SetValue(StrToWxStr(sTemp)); } } diff --git a/Source/Core/DolphinWX/Src/PatchAddEdit.cpp b/Source/Core/DolphinWX/Src/PatchAddEdit.cpp index 7d521006d3..3199240d74 100644 --- a/Source/Core/DolphinWX/Src/PatchAddEdit.cpp +++ b/Source/Core/DolphinWX/Src/PatchAddEdit.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include "PatchAddEdit.h" +#include "WxUtils.h" extern std::vector onFrame; @@ -48,7 +49,7 @@ void CPatchAddEdit::CreateGUIControls(int _selection) } else { - currentName = wxString(onFrame.at(_selection).name.c_str(), *wxConvCurrent); + currentName = StrToWxStr(onFrame.at(_selection).name.c_str()); tempEntries = onFrame.at(_selection).entries; } @@ -66,7 +67,7 @@ void CPatchAddEdit::CreateGUIControls(int _selection) EntrySelection->SetValue((int)tempEntries.size()-1); wxArrayString wxArrayStringFor_EditPatchType; for (int i = 0; i < 3; ++i) - wxArrayStringFor_EditPatchType.Add(wxString::FromAscii(PatchEngine::PatchTypeStrings[i])); + wxArrayStringFor_EditPatchType.Add(StrToWxStr(PatchEngine::PatchTypeStrings[i])); EditPatchType = new wxRadioBox(this, ID_EDITPATCH_TYPE, _("Type"), wxDefaultPosition, wxDefaultSize, wxArrayStringFor_EditPatchType, 3, wxRA_SPECIFY_COLS); EditPatchType->SetSelection((int)tempEntries.at(0).type); wxStaticText* EditPatchValueText = new wxStaticText(this, ID_EDITPATCH_VALUE_TEXT, _("Value:")); @@ -121,7 +122,7 @@ void CPatchAddEdit::SavePatchData(wxCommandEvent& event) if (selection == -1) { PatchEngine::Patch newPatch; - newPatch.name = std::string(EditPatchName->GetValue().mb_str()); + newPatch.name = WxStrToStr(EditPatchName->GetValue()); newPatch.entries = tempEntries; newPatch.active = true; @@ -129,7 +130,7 @@ void CPatchAddEdit::SavePatchData(wxCommandEvent& event) } else { - onFrame.at(selection).name = std::string(EditPatchName->GetValue().mb_str()); + onFrame.at(selection).name = WxStrToStr(EditPatchName->GetValue()); onFrame.at(selection).entries = tempEntries; } diff --git a/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp b/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp index 2f31311495..9619f38dee 100644 --- a/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp @@ -4,6 +4,8 @@ #include "Common.h" #include "ControllerEmu.h" #include "IniFile.h" +#include "WxUtils.h" + #include UDPConfigDiag::UDPConfigDiag(wxWindow * const parent, UDPWrapper * _wrp) : @@ -26,7 +28,7 @@ UDPConfigDiag::UDPConfigDiag(wxWindow * const parent, UDPWrapper * _wrp) : wxBoxSizer *const port_sizer = new wxBoxSizer(wxHORIZONTAL); port_sizer->Add(new wxStaticText(this, wxID_ANY, _("UDP Port:")), 0, wxALIGN_CENTER); - port_tbox = new wxTextCtrl(this, wxID_ANY, wxString::FromUTF8(wrp->port.c_str())); + port_tbox = new wxTextCtrl(this, wxID_ANY, StrToWxStr(wrp->port)); port_sizer->Add(port_tbox, 1, wxLEFT | wxEXPAND, 5); enable->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &UDPConfigDiag::ChangeState, this); @@ -71,7 +73,7 @@ void UDPConfigDiag::ChangeUpdateFlags(wxCommandEvent & WXUNUSED(event)) void UDPConfigDiag::ChangeState(wxCommandEvent & WXUNUSED(event)) { - wrp->udpEn=enable->GetValue(); - wrp->port=port_tbox->GetValue().mb_str(wxConvUTF8); + wrp->udpEn = enable->GetValue(); + wrp->port = WxStrToStr(port_tbox->GetValue()); wrp->Refresh(); } diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp index 0ca4715c3d..7c8a3b7e04 100644 --- a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp @@ -141,7 +141,7 @@ wxArrayString GetListOfResolutions() if (std::find(resos.begin(), resos.end(), strRes) == resos.end()) { resos.push_back(strRes); - retlist.Add(wxString::FromAscii(res)); + retlist.Add(StrToWxStr(res)); } ZeroMemory(&dmi, sizeof(dmi)); } @@ -212,9 +212,9 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = g_available_video_backends.begin(), itend = g_available_video_backends.end(); for (; it != itend; ++it) - choice_backend->AppendString(wxGetTranslation(wxString::FromAscii((*it)->GetName().c_str()))); + choice_backend->AppendString(wxGetTranslation(StrToWxStr((*it)->GetName().c_str()))); - choice_backend->SetStringSelection(wxGetTranslation(wxString::FromAscii(g_video_backend->GetName().c_str()))); + choice_backend->SetStringSelection(wxGetTranslation(StrToWxStr(g_video_backend->GetName().c_str()))); choice_backend->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_Backend, this); szr_basic->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5); @@ -236,7 +236,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = vconfig.backend_info.Adapters.begin(), itend = vconfig.backend_info.Adapters.end(); for (; it != itend; ++it) - choice_adapter->AppendString(wxString::FromAscii(it->c_str())); + choice_adapter->AppendString(StrToWxStr(it->c_str())); choice_adapter->Select(vconfig.iAdapter); @@ -259,7 +259,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con RegisterControl(choice_display_resolution, wxGetTranslation(display_res_desc)); choice_display_resolution->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_DisplayResolution, this); - choice_display_resolution->SetStringSelection(wxString::FromAscii(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution.c_str())); + choice_display_resolution->SetStringSelection(StrToWxStr(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution.c_str())); szr_display->Add(label_display_resolution, 1, wxALIGN_CENTER_VERTICAL, 0); szr_display->Add(choice_display_resolution); @@ -355,7 +355,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = vconfig.backend_info.AAModes.begin(), itend = vconfig.backend_info.AAModes.end(); for (; it != itend; ++it) - choice_aamode->AppendString(wxGetTranslation(wxString::FromAscii(it->c_str()))); + choice_aamode->AppendString(wxGetTranslation(StrToWxStr(it->c_str()))); choice_aamode->Select(vconfig.iMultisampleMode); szr_enh->Add(text_aamode, 1, wxALIGN_CENTER_VERTICAL, 0); @@ -380,12 +380,12 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = vconfig.backend_info.PPShaders.begin(), itend = vconfig.backend_info.PPShaders.end(); for (; it != itend; ++it) - choice_ppshader->AppendString(wxString::FromAscii(it->c_str())); + choice_ppshader->AppendString(StrToWxStr(it->c_str())); if (vconfig.sPostProcessingShader.empty()) choice_ppshader->Select(0); else - choice_ppshader->SetStringSelection(wxString::FromAscii(vconfig.sPostProcessingShader.c_str())); + choice_ppshader->SetStringSelection(StrToWxStr(vconfig.sPostProcessingShader.c_str())); choice_ppshader->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_PPShader, this); @@ -595,7 +595,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con void VideoConfigDiag::Event_DisplayResolution(wxCommandEvent &ev) { SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution = - choice_display_resolution->GetStringSelection().mb_str(); + WxStrToStr(choice_display_resolution->GetStringSelection()); #if defined(HAVE_XRANDR) && HAVE_XRANDR main_frame->m_XRRConfig->Update(); #endif diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.h b/Source/Core/DolphinWX/Src/VideoConfigDiag.h index c7a19c6cb8..8507fffdc1 100644 --- a/Source/Core/DolphinWX/Src/VideoConfigDiag.h +++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.h @@ -20,6 +20,7 @@ #include #include "MsgHandler.h" +#include "WxUtils.h" template class BoolSetting : public W @@ -99,7 +100,7 @@ protected: else { // Select current backend again - choice_backend->SetStringSelection(wxString::FromAscii(g_video_backend->GetName().c_str())); + choice_backend->SetStringSelection(StrToWxStr(g_video_backend->GetName().c_str())); } } @@ -129,7 +130,7 @@ protected: { const int sel = ev.GetInt(); if (sel) - vconfig.sPostProcessingShader = ev.GetString().mb_str(); + vconfig.sPostProcessingShader = WxStrToStr(ev.GetString()); else vconfig.sPostProcessingShader.clear(); diff --git a/Source/Core/DolphinWX/Src/WxUtils.cpp b/Source/Core/DolphinWX/Src/WxUtils.cpp index 22fa10b84d..ee6f815648 100644 --- a/Source/Core/DolphinWX/Src/WxUtils.cpp +++ b/Source/Core/DolphinWX/Src/WxUtils.cpp @@ -20,12 +20,14 @@ #include #include +#include "WxUtils.h" + namespace WxUtils { // Launch a file according to its mime type void Launch(const char *filename) { - if (! ::wxLaunchDefaultBrowser(wxString(filename, *wxConvCurrent))) + if (! ::wxLaunchDefaultBrowser(StrToWxStr(filename))) { // WARN_LOG } @@ -34,7 +36,7 @@ void Launch(const char *filename) // Launch an file explorer window on a certain path void Explore(const char *path) { - wxString wxPath = wxString(path, *wxConvCurrent); + wxString wxPath = StrToWxStr(path); // Default to file if (! wxPath.Contains(wxT("://"))) { @@ -52,3 +54,13 @@ void Explore(const char *path) } } // namespace + +std::string WxStrToStr(const wxString& str) +{ + return str.ToUTF8(); +} + +wxString StrToWxStr(const std::string& str) +{ + return wxString::FromUTF8(str.c_str()); +} diff --git a/Source/Core/DolphinWX/Src/WxUtils.h b/Source/Core/DolphinWX/Src/WxUtils.h index 8e837e9e96..61a16b298e 100644 --- a/Source/Core/DolphinWX/Src/WxUtils.h +++ b/Source/Core/DolphinWX/Src/WxUtils.h @@ -18,7 +18,11 @@ #ifndef WXUTILS_H #define WXUTILS_H -namespace WxUtils { +#include +#include + +namespace WxUtils +{ // Launch a file according to its mime type void Launch(const char *filename); @@ -28,4 +32,7 @@ void Explore(const char *path); } // namespace +std::string WxStrToStr(const wxString& str); +wxString StrToWxStr(const std::string& str); + #endif // WXUTILS diff --git a/Source/Core/DolphinWX/Src/X11Utils.cpp b/Source/Core/DolphinWX/Src/X11Utils.cpp index f032f81e96..3582b9b576 100644 --- a/Source/Core/DolphinWX/Src/X11Utils.cpp +++ b/Source/Core/DolphinWX/Src/X11Utils.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include "X11Utils.h" +#include "WxUtils.h" #include #include @@ -350,7 +351,7 @@ void XRRConfiguration::AddResolutions(wxArrayString& arrayStringFor_FullscreenRe if (std::find(resos.begin(), resos.end(), strRes) == resos.end()) { resos.push_back(strRes); - arrayStringFor_FullscreenResolution.Add(wxString::FromUTF8(strRes.c_str())); + arrayStringFor_FullscreenResolution.Add(StrToWxStr(strRes)); } } } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index b5393cdbde..d0bb94a39a 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -24,6 +24,7 @@ #include #include "GLUtil.h" +#include "WxUtils.h" #include "FileUtil.h" @@ -1538,7 +1539,7 @@ void TakeScreenshot(ScrStrct* threadStruct) // Save the screenshot and finally kill the wxImage object // This is really expensive when saving to PNG, but not at all when using BMP - threadStruct->img->SaveFile(wxString::FromAscii(threadStruct->filename.c_str()), + threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename.c_str()), wxBITMAP_TYPE_PNG); threadStruct->img->Destroy(); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp index bd085a3edf..670c3f9c6d 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp @@ -34,7 +34,7 @@ IntegerSetting::IntegerSetting(wxWindow* parent, const wxString& label, T& se VideoConfigDialog::VideoConfigDialog(wxWindow* parent, const std::string& title, const std::string& _ininame) : wxDialog(parent, -1, - wxString(wxT("Dolphin ")).append(wxString::FromAscii(title.c_str())).append(wxT(" Graphics Configuration")), + wxString(wxT("Dolphin ")).append(StrToWxStr(title.c_str())).append(wxT(" Graphics Configuration")), wxDefaultPosition, wxDefaultSize), vconfig(g_SWVideoConfig), ininame(_ininame) @@ -64,10 +64,10 @@ VideoConfigDialog::VideoConfigDialog(wxWindow* parent, const std::string& title, it = g_available_video_backends.begin(), itend = g_available_video_backends.end(); for (; it != itend; ++it) - choice_backend->AppendString(wxString::FromAscii((*it)->GetName().c_str())); + choice_backend->AppendString(StrToWxStr((*it)->GetName())); // TODO: How to get the translated plugin name? - choice_backend->SetStringSelection(wxString::FromAscii(g_video_backend->GetName().c_str())); + choice_backend->SetStringSelection(StrToWxStr(g_video_backend->GetName())); choice_backend->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDialog::Event_Backend, this); szr_rendering->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5); From 03ec9a2e088b0818bf02a5bc2ffda4a512cba2b7 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 28 Feb 2013 02:39:06 -0600 Subject: [PATCH 33/70] Kill some unnecessary c_str and use StrToWxStr in a few places that I missed. --- Source/Core/DolphinWX/Src/AboutDolphin.cpp | 2 +- Source/Core/DolphinWX/Src/CheatsWindow.cpp | 2 +- Source/Core/DolphinWX/Src/ConfigMain.cpp | 9 +++++---- Source/Core/DolphinWX/Src/Debugger/CodeView.cpp | 4 ++-- .../Core/DolphinWX/Src/Debugger/CodeWindow.cpp | 2 +- .../Src/Debugger/CodeWindowFunctions.cpp | 4 ++-- .../DolphinWX/Src/Debugger/DSPDebugWindow.cpp | 2 +- Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp | 16 ++++++++-------- Source/Core/DolphinWX/Src/FrameAui.cpp | 4 ++-- Source/Core/DolphinWX/Src/FrameTools.cpp | 2 +- Source/Core/DolphinWX/Src/GameListCtrl.cpp | 10 +++++----- Source/Core/DolphinWX/Src/ISOProperties.cpp | 8 ++++---- Source/Core/DolphinWX/Src/InputConfigDiag.cpp | 8 ++++---- .../DolphinWX/Src/InputConfigDiagBitmaps.cpp | 4 ++-- Source/Core/DolphinWX/Src/NetWindow.cpp | 6 +++--- Source/Core/DolphinWX/Src/PatchAddEdit.cpp | 2 +- Source/Core/DolphinWX/Src/VideoConfigDiag.cpp | 14 +++++++------- Source/Core/DolphinWX/Src/VideoConfigDiag.h | 2 +- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 2 +- .../Src/VideoConfigDialog.cpp | 2 +- 20 files changed, 53 insertions(+), 52 deletions(-) diff --git a/Source/Core/DolphinWX/Src/AboutDolphin.cpp b/Source/Core/DolphinWX/Src/AboutDolphin.cpp index eeecf18d48..5126274601 100644 --- a/Source/Core/DolphinWX/Src/AboutDolphin.cpp +++ b/Source/Core/DolphinWX/Src/AboutDolphin.cpp @@ -63,7 +63,7 @@ AboutDolphin::AboutDolphin(wxWindow *parent, wxWindowID id, "and should not be used to play games you do\n" "not legally own."; wxStaticText* const Message = new wxStaticText(this, wxID_ANY, - StrToWxStr(Text.c_str())); + StrToWxStr(Text)); Message->Wrap(GetSize().GetWidth()); wxBoxSizer* const sInfo = new wxBoxSizer(wxVERTICAL); diff --git a/Source/Core/DolphinWX/Src/CheatsWindow.cpp b/Source/Core/DolphinWX/Src/CheatsWindow.cpp index 1e0f714467..fb3c3cbb23 100644 --- a/Source/Core/DolphinWX/Src/CheatsWindow.cpp +++ b/Source/Core/DolphinWX/Src/CheatsWindow.cpp @@ -348,7 +348,7 @@ void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED (eve const std::vector &arLog = ActionReplay::GetSelfLog(); for (u32 i = 0; i < arLog.size(); i++) { - m_TextCtrl_Log->AppendText(StrToWxStr(arLog[i].c_str())); + m_TextCtrl_Log->AppendText(StrToWxStr(arLog[i])); } } diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index bdb4cdc7fe..068501c432 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -982,9 +982,9 @@ void CConfigMain::AddAudioBackends() for (std::vector::const_iterator iter = backends.begin(); iter != backends.end(); ++iter) { - BackendSelection->Append(StrToWxStr((*iter).c_str())); + BackendSelection->Append(StrToWxStr(*iter)); int num = BackendSelection->\ - FindString(StrToWxStr(SConfig::GetInstance().sBackend.c_str())); + FindString(StrToWxStr(SConfig::GetInstance().sBackend)); BackendSelection->SetSelection(num); } } @@ -1269,8 +1269,9 @@ void CConfigMain::ApploaderPathChanged(wxFileDirPickerEvent& WXUNUSED (event)) void CConfigMain::NANDRootChanged(wxFileDirPickerEvent& WXUNUSED (event)) { std::string NANDPath = - SConfig::GetInstance().m_NANDPath = File::GetUserPath(D_WIIROOT_IDX, WxStrToStr(NANDRoot->GetPath())); - NANDRoot->SetPath(wxString(NANDPath)); + SConfig::GetInstance().m_NANDPath = + File::GetUserPath(D_WIIROOT_IDX, WxStrToStr(NANDRoot->GetPath())); + NANDRoot->SetPath(StrToWxStr(NANDPath)); SConfig::GetInstance().m_SYSCONF->UpdateLocation(); DiscIO::cUIDsys::AccessInstance().UpdateLocation(); DiscIO::CSharedContent::AccessInstance().UpdateLocation(); diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp index 3b22ca339d..31ad19d6da 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp @@ -253,7 +253,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) debugger->disasm(addr, disasm, 256); text = text + StringFromFormat("%08x: ", addr) + disasm + "\r\n"; } - wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text.c_str()))); + wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text))); } } break; @@ -300,7 +300,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) { wxTextEntryDialog input_symbol(this, StrToWxStr("Rename symbol:"), wxGetTextFromUserPromptStr, - StrToWxStr(symbol->name.c_str())); + StrToWxStr(symbol->name)); if (input_symbol.ShowModal() == wxID_OK) { symbol->name = WxStrToStr(input_symbol.GetValue()); diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp index 1cff07c0f4..9172a3af9a 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp @@ -345,7 +345,7 @@ void CCodeWindow::UpdateCallstack() for (size_t i = 0; i < stack.size(); i++) { - int idx = callstack->Append(StrToWxStr(stack[i].Name.c_str())); + int idx = callstack->Append(StrToWxStr(stack[i].Name)); callstack->SetClientData(idx, (void*)(u64)stack[i].vAddress); } diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp index a11783c010..7ec36131ff 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp @@ -66,7 +66,7 @@ void CCodeWindow::Load() std::string fontDesc; ini.Get("General", "DebuggerFont", &fontDesc); if (!fontDesc.empty()) - DebuggerFont.SetNativeFontInfoUserDesc(StrToWxStr(fontDesc.c_str())); + DebuggerFont.SetNativeFontInfoUserDesc(StrToWxStr(fontDesc)); // Boot to pause or not ini.Get("General", "AutomaticStart", &bAutomaticStart, false); @@ -366,7 +366,7 @@ void CCodeWindow::NotifyMapLoaded() symbols->Clear(); for (PPCSymbolDB::XFuncMap::iterator iter = g_symbolDB.GetIterator(); iter != g_symbolDB.End(); ++iter) { - int idx = symbols->Append(StrToWxStr(iter->second.name.c_str())); + int idx = symbols->Append(StrToWxStr(iter->second.name)); symbols->SetClientData(idx, (void*)&iter->second); } symbols->Thaw(); diff --git a/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp index 27da055990..e77b57399e 100644 --- a/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp @@ -221,7 +221,7 @@ void DSPDebuggerLLE::UpdateSymbolMap() for (SymbolDB::XFuncMap::iterator iter = DSPSymbols::g_dsp_symbol_db.GetIterator(); iter != DSPSymbols::g_dsp_symbol_db.End(); ++iter) { - int idx = m_SymbolList->Append(StrToWxStr(iter->second.name.c_str())); + int idx = m_SymbolList->Append(StrToWxStr(iter->second.name)); m_SymbolList->SetClientData(idx, (void*)&iter->second); } m_SymbolList->Thaw(); diff --git a/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp index e80d206112..7f98af6c57 100644 --- a/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp @@ -120,9 +120,9 @@ void CJitWindow::Compare(u32 em_address) } // Do not merge this "if" with the above - block_num changes inside it. if (block_num < 0) { - ppc_box->SetValue(wxString::FromAscii(StringFromFormat("(non-code address: %08x)", - em_address).c_str())); - x86_box->SetValue(wxString::FromAscii(StringFromFormat("(no translation)").c_str())); + ppc_box->SetValue(StrToWxStr(StringFromFormat("(non-code address: %08x)", + em_address))); + x86_box->SetValue(StrToWxStr(StringFromFormat("(no translation)"))); delete[] xDis; return; } @@ -151,7 +151,7 @@ void CJitWindow::Compare(u32 em_address) *sptr++ = 10; num_x86_instructions++; } - x86_box->SetValue(wxString::FromAscii((char*)xDis)); + x86_box->SetValue(StrToWxStr((char*)xDis)); // == Fill in ppc box u32 ppc_addr = block->originalAddress; @@ -190,11 +190,11 @@ void CJitWindow::Compare(u32 em_address) sptr += sprintf(sptr, "Num bytes: PPC: %i x86: %i (blowup: %i%%)\n", size * 4, block->codeSize, 100 * (block->codeSize / (4 * size) - 1)); - ppc_box->SetValue(wxString::FromAscii((char*)xDis)); + ppc_box->SetValue(StrToWxStr((char*)xDis)); } else { - ppc_box->SetValue(wxString::FromAscii(StringFromFormat( - "(non-code address: %08x)", em_address).c_str())); - x86_box->SetValue(wxString::FromAscii("---")); + ppc_box->SetValue(StrToWxStr(StringFromFormat( + "(non-code address: %08x)", em_address))); + x86_box->SetValue("---"); } delete[] xDis; diff --git a/Source/Core/DolphinWX/Src/FrameAui.cpp b/Source/Core/DolphinWX/Src/FrameAui.cpp index fd3cbb662b..6f10d46722 100644 --- a/Source/Core/DolphinWX/Src/FrameAui.cpp +++ b/Source/Core/DolphinWX/Src/FrameAui.cpp @@ -549,7 +549,7 @@ void CFrame::OnDropDownToolbarItem(wxAuiToolBarEvent& event) for (u32 i = 0; i < Perspectives.size(); i++) { wxMenuItem* mItem = new wxMenuItem(menuPopup, IDM_PERSPECTIVES_0 + i, - StrToWxStr(Perspectives[i].Name.c_str()), + StrToWxStr(Perspectives[i].Name), wxT(""), wxITEM_CHECK); menuPopup->Append(mItem); if (i == ActivePerspective) mItem->Check(true); @@ -871,7 +871,7 @@ void CFrame::LoadIniPerspectives() ini.Get(_Section.c_str(), "Width", &_Width, "70,25"); ini.Get(_Section.c_str(), "Height", &_Height, "80,80"); - Tmp.Perspective = StrToWxStr(_Perspective.c_str()); + Tmp.Perspective = StrToWxStr(_Perspective); SplitString(_Width, ',', _SWidth); SplitString(_Height, ',', _SHeight); diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index a1dcd959fe..4b1fc820a9 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -101,7 +101,7 @@ void CFrame::CreateMenu() drives = cdio_get_devices(); // Windows Limitation of 24 character drives for (unsigned int i = 0; i < drives.size() && i < 24; i++) { - externalDrive->Append(IDM_DRIVE1 + i, StrToWxStr(drives[i].c_str())); + externalDrive->Append(IDM_DRIVE1 + i, StrToWxStr(drives[i])); } fileMenu->AppendSeparator(); diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index d385b947e5..cab4c8125b 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -614,7 +614,7 @@ void CGameListCtrl::ScanForISOs() // Update with the progress (i) and the message dialog.Update(i, wxString::Format(_("Scanning %s"), - StrToWxStr(FileName).c_str())); + StrToWxStr(FileName))); if (dialog.WasCancelled()) break; @@ -1173,10 +1173,10 @@ void CGameListCtrl::CompressSelection(bool _compress) WxStrToStr(browseDialog.GetPath()), FileName); - if (wxFileExists(StrToWxStr(OutputFileName.c_str())) && + if (wxFileExists(StrToWxStr(OutputFileName)) && wxMessageBox( wxString::Format(_("The file %s already exists.\nDo you wish to replace it?"), - StrToWxStr(OutputFileName).c_str()), + StrToWxStr(OutputFileName)), _("Confirm File Overwrite"), wxYES_NO) == wxNO) continue; @@ -1201,10 +1201,10 @@ void CGameListCtrl::CompressSelection(bool _compress) WxStrToStr(browseDialog.GetPath()), FileName); - if (wxFileExists(StrToWxStr(OutputFileName.c_str())) && + if (wxFileExists(StrToWxStr(OutputFileName)) && wxMessageBox( wxString::Format(_("The file %s already exists.\nDo you wish to replace it?"), - StrToWxStr(OutputFileName).c_str()), + StrToWxStr(OutputFileName)), _("Confirm File Overwrite"), wxYES_NO) == wxNO) continue; diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index e739ff043b..6434c8cd54 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -728,7 +728,7 @@ void CISOProperties::ExportDir(const char* _rFullPath, const char* _rExportFolde (u32)(((float)(i - index[0]) / (float)(index[1] - index[0])) * 100))); dialog.Update(i, wxString::Format(_("Extracting %s"), - StrToWxStr(fst[i]->m_FullPath).c_str())); + StrToWxStr(fst[i]->m_FullPath))); if (dialog.WasCancelled()) break; @@ -990,7 +990,7 @@ void CISOProperties::LoadGameConfig() GameIni.Get("EmuState", "EmulationIssues", &sTemp); if (!sTemp.empty()) { - EmuIssues->SetValue(StrToWxStr(sTemp.c_str())); + EmuIssues->SetValue(StrToWxStr(sTemp)); } EmuIssues->Enable(EmuState->GetSelection() != 0); @@ -1157,7 +1157,7 @@ void CISOProperties::PatchList_Load() for (std::vector::const_iterator it = onFrame.begin(); it != onFrame.end(); ++it) { PatchEngine::Patch p = *it; - Patches->Append(StrToWxStr(p.name.c_str())); + Patches->Append(StrToWxStr(p.name)); Patches->Check(index, p.active); ++index; } @@ -1366,5 +1366,5 @@ void CISOProperties::ChangeBannerDetails(int lang) SplitPath(OpenGameListItem->GetFileName(), 0, &filename, &extension); // Also sets the window's title SetTitle(StrToWxStr(StringFromFormat("%s%s: %s - ", filename.c_str(), - extension.c_str(), OpenGameListItem->GetUniqueID().c_str()).c_str()) + shortName); + extension.c_str(), OpenGameListItem->GetUniqueID().c_str())) + shortName); } diff --git a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp index d8a755aca6..1df215fb1e 100644 --- a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp @@ -34,7 +34,7 @@ void GamepadPage::ConfigExtension(wxCommandEvent& event) if (ex->switch_extension) { wxDialog dlg(this, -1, - StrToWxStr(ex->attachments[ex->switch_extension]->GetName().c_str()), + StrToWxStr(ex->attachments[ex->switch_extension]->GetName()), wxDefaultPosition, wxDefaultSize); wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL); @@ -64,7 +64,7 @@ PadSettingExtension::PadSettingExtension(wxWindow* const parent, ControllerEmu:: e = extension->attachments.end(); for (; i!=e; ++i) - ((wxChoice*)wxcontrol)->Append(StrToWxStr((*i)->GetName().c_str())); + ((wxChoice*)wxcontrol)->Append(StrToWxStr((*i)->GetName())); UpdateGUI(); } @@ -612,7 +612,7 @@ void GamepadPage::DeleteProfile(wxCommandEvent&) if (File::Exists(fnamecstr) && AskYesNoT("Are you sure you want to delete \"%s\"?", - WxStrToStr(profile_cbox->GetValue()).c_str())) + WxStrToStr(profile_cbox->GetValue()))) { File::Delete(fnamecstr); @@ -952,7 +952,7 @@ GamepadPage::GamepadPage(wxWindow* parent, InputPlugin& plugin, const unsigned i InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin, const std::string& name, const int tab_num) - : wxDialog(parent, wxID_ANY, StrToWxStr(name.c_str()), wxPoint(128,-1), wxDefaultSize) + : wxDialog(parent, wxID_ANY, StrToWxStr(name), wxPoint(128,-1), wxDefaultSize) , m_plugin(plugin) { m_pad_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT); diff --git a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp index 4e07ed990d..efb7db59af 100644 --- a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp +++ b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp @@ -228,7 +228,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) // text const char* const name = (*g)->control_group->controls[n]->name; // bit of hax so ZL, ZR show up as L, R - dc.DrawText(StrToWxStr((name[1] && name[1] < 'a') ? name[1] : name[0]), n*12 + 2, 1); + dc.DrawText(StrToWxStr(std::string(1, (name[1] && name[1] < 'a') ? name[1] : name[0])), n*12 + 2, 1); } delete[] bitmasks; @@ -300,7 +300,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) // text dc.DrawText(StrToWxStr((*g)->control_group->controls[n+trigger_count]->name), 3, n*12 + 1); - dc.DrawText(StrToWxStr((*g)->control_group->controls[n]->name[0]), 64 + 3, n*12 + 1); + dc.DrawText(StrToWxStr(std::string(1, (*g)->control_group->controls[n]->name[0])), 64 + 3, n*12 + 1); } // threshold box diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index d9fd5e6ca0..988ccae83e 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -73,7 +73,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* std::string address; netplay_section.Get("Address", &address, "localhost"); - m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(address.c_str())); + m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(address)); wxStaticText* const port_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Port :"), wxDefaultPosition, wxDefaultSize); @@ -81,7 +81,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* // string? w/e std::string port; netplay_section.Get("ConnectPort", &port, "2626"); - m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(port.c_str())); + m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(port)); wxButton* const connect_btn = new wxButton(connect_tab, wxID_ANY, _("Connect")); connect_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &NetPlaySetupDiag::OnJoin, this); @@ -114,7 +114,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* // string? w/e std::string port; netplay_section.Get("HostPort", &port, "2626"); - m_host_port_text = new wxTextCtrl(host_tab, wxID_ANY, StrToWxStr(port.c_str())); + m_host_port_text = new wxTextCtrl(host_tab, wxID_ANY, StrToWxStr(port)); wxButton* const host_btn = new wxButton(host_tab, wxID_ANY, _("Host")); host_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &NetPlaySetupDiag::OnHost, this); diff --git a/Source/Core/DolphinWX/Src/PatchAddEdit.cpp b/Source/Core/DolphinWX/Src/PatchAddEdit.cpp index 3199240d74..ead7918d34 100644 --- a/Source/Core/DolphinWX/Src/PatchAddEdit.cpp +++ b/Source/Core/DolphinWX/Src/PatchAddEdit.cpp @@ -49,7 +49,7 @@ void CPatchAddEdit::CreateGUIControls(int _selection) } else { - currentName = StrToWxStr(onFrame.at(_selection).name.c_str()); + currentName = StrToWxStr(onFrame.at(_selection).name); tempEntries = onFrame.at(_selection).entries; } diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp index 7c8a3b7e04..154a5bc602 100644 --- a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp @@ -212,9 +212,9 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = g_available_video_backends.begin(), itend = g_available_video_backends.end(); for (; it != itend; ++it) - choice_backend->AppendString(wxGetTranslation(StrToWxStr((*it)->GetName().c_str()))); + choice_backend->AppendString(wxGetTranslation(StrToWxStr((*it)->GetName()))); - choice_backend->SetStringSelection(wxGetTranslation(StrToWxStr(g_video_backend->GetName().c_str()))); + choice_backend->SetStringSelection(wxGetTranslation(StrToWxStr(g_video_backend->GetName()))); choice_backend->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_Backend, this); szr_basic->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5); @@ -236,7 +236,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = vconfig.backend_info.Adapters.begin(), itend = vconfig.backend_info.Adapters.end(); for (; it != itend; ++it) - choice_adapter->AppendString(StrToWxStr(it->c_str())); + choice_adapter->AppendString(StrToWxStr(*it)); choice_adapter->Select(vconfig.iAdapter); @@ -259,7 +259,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con RegisterControl(choice_display_resolution, wxGetTranslation(display_res_desc)); choice_display_resolution->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_DisplayResolution, this); - choice_display_resolution->SetStringSelection(StrToWxStr(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution.c_str())); + choice_display_resolution->SetStringSelection(StrToWxStr(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution)); szr_display->Add(label_display_resolution, 1, wxALIGN_CENTER_VERTICAL, 0); szr_display->Add(choice_display_resolution); @@ -355,7 +355,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = vconfig.backend_info.AAModes.begin(), itend = vconfig.backend_info.AAModes.end(); for (; it != itend; ++it) - choice_aamode->AppendString(wxGetTranslation(StrToWxStr(it->c_str()))); + choice_aamode->AppendString(wxGetTranslation(StrToWxStr(*it))); choice_aamode->Select(vconfig.iMultisampleMode); szr_enh->Add(text_aamode, 1, wxALIGN_CENTER_VERTICAL, 0); @@ -380,12 +380,12 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = vconfig.backend_info.PPShaders.begin(), itend = vconfig.backend_info.PPShaders.end(); for (; it != itend; ++it) - choice_ppshader->AppendString(StrToWxStr(it->c_str())); + choice_ppshader->AppendString(StrToWxStr(*it)); if (vconfig.sPostProcessingShader.empty()) choice_ppshader->Select(0); else - choice_ppshader->SetStringSelection(StrToWxStr(vconfig.sPostProcessingShader.c_str())); + choice_ppshader->SetStringSelection(StrToWxStr(vconfig.sPostProcessingShader)); choice_ppshader->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_PPShader, this); diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.h b/Source/Core/DolphinWX/Src/VideoConfigDiag.h index 8507fffdc1..90a42c34a1 100644 --- a/Source/Core/DolphinWX/Src/VideoConfigDiag.h +++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.h @@ -100,7 +100,7 @@ protected: else { // Select current backend again - choice_backend->SetStringSelection(StrToWxStr(g_video_backend->GetName().c_str())); + choice_backend->SetStringSelection(StrToWxStr(g_video_backend->GetName())); } } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index d0bb94a39a..f0213578c5 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -1539,7 +1539,7 @@ void TakeScreenshot(ScrStrct* threadStruct) // Save the screenshot and finally kill the wxImage object // This is really expensive when saving to PNG, but not at all when using BMP - threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename.c_str()), + threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename), wxBITMAP_TYPE_PNG); threadStruct->img->Destroy(); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp index 670c3f9c6d..e7122d2f71 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp @@ -34,7 +34,7 @@ IntegerSetting::IntegerSetting(wxWindow* parent, const wxString& label, T& se VideoConfigDialog::VideoConfigDialog(wxWindow* parent, const std::string& title, const std::string& _ininame) : wxDialog(parent, -1, - wxString(wxT("Dolphin ")).append(StrToWxStr(title.c_str())).append(wxT(" Graphics Configuration")), + wxString(wxT("Dolphin ")).append(StrToWxStr(title)).append(wxT(" Graphics Configuration")), wxDefaultPosition, wxDefaultSize), vconfig(g_SWVideoConfig), ininame(_ininame) From 95558cdc6911e6122fec94616e4d6975d2c355fb Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 28 Feb 2013 03:11:10 -0600 Subject: [PATCH 34/70] Buildfix. --- Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp | 2 +- Source/Core/DolphinWX/Src/InputConfigDiag.cpp | 2 +- Source/Core/DolphinWX/Src/WxUtils.cpp | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp index 7ec36131ff..362e617696 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp @@ -285,7 +285,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) if (!path.IsEmpty()) { - std::ifstream f(WxStrToStr(path)); + std::ifstream f(WxStrToStr(path).c_str()); std::string line; while (std::getline(f, line)) diff --git a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp index 1df215fb1e..14772d8676 100644 --- a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp @@ -612,7 +612,7 @@ void GamepadPage::DeleteProfile(wxCommandEvent&) if (File::Exists(fnamecstr) && AskYesNoT("Are you sure you want to delete \"%s\"?", - WxStrToStr(profile_cbox->GetValue()))) + WxStrToStr(profile_cbox->GetValue()).c_str())) { File::Delete(fnamecstr); diff --git a/Source/Core/DolphinWX/Src/WxUtils.cpp b/Source/Core/DolphinWX/Src/WxUtils.cpp index ee6f815648..6856c96481 100644 --- a/Source/Core/DolphinWX/Src/WxUtils.cpp +++ b/Source/Core/DolphinWX/Src/WxUtils.cpp @@ -57,10 +57,11 @@ void Explore(const char *path) std::string WxStrToStr(const wxString& str) { - return str.ToUTF8(); + return str.ToUTF8().data(); } wxString StrToWxStr(const std::string& str) { + //return wxString::FromUTF8Unchecked(str.c_str()); return wxString::FromUTF8(str.c_str()); } From 07539b9a3ff1bc55bd829d0098ac025dbfd4ad44 Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Thu, 28 Feb 2013 13:12:35 +0100 Subject: [PATCH 35/70] Fix a StringUtil regression from the arm-noglsl merge Fixes issue 6048. Thanks to Starscream for locating the regression. --- Source/Core/Common/Src/StringUtil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index 6ef3d91a73..cd08863877 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -245,7 +245,7 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st while(1) { const int pos = result.find(src); - if (pos == 16) break; + if (pos == -1) break; result.replace(pos, src.size(), dest); } return result; From bc15919e2ebefe327ce6330f7abdaccaa2fd2004 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 28 Feb 2013 16:15:32 -0600 Subject: [PATCH 36/70] Make ARMJit core default CPU core on ARM architecture --- Source/Core/Core/Src/ConfigManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index 85ecc7143f..377aa16a27 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -362,7 +362,11 @@ void SConfig::LoadSettings() // Core ini.Get("Core", "HLE_BS2", &m_LocalCoreStartupParameter.bHLE_BS2, false); +#ifdef _M_ARM + ini.Get("Core", "CPUCore", &m_LocalCoreStartupParameter.iCPUCore, 3); +#else ini.Get("Core", "CPUCore", &m_LocalCoreStartupParameter.iCPUCore, 1); +#endif ini.Get("Core", "DSPThread", &m_LocalCoreStartupParameter.bDSPThread, false); ini.Get("Core", "DSPHLE", &m_LocalCoreStartupParameter.bDSPHLE, true); ini.Get("Core", "CPUThread", &m_LocalCoreStartupParameter.bCPUThread, true); From 5c4a130688b22459662d15f11324b93fa9382eb9 Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 1 Mar 2013 10:28:42 +1100 Subject: [PATCH 37/70] Added a BluetoothEnumerateInstalledServices call so that the wiimote remembers the pairing. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 2ae34a7ca5..1119ae3f1d 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -59,6 +59,7 @@ typedef DWORD (__stdcall *PBth_BluetoothGetRadioInfo)(HANDLE, PBLUETOOTH_RADIO_I typedef DWORD (__stdcall *PBth_BluetoothRemoveDevice)(const BLUETOOTH_ADDRESS*); typedef DWORD (__stdcall *PBth_BluetoothSetServiceState)(HANDLE, const BLUETOOTH_DEVICE_INFO*, const GUID*, DWORD); typedef DWORD (__stdcall *PBth_BluetoothAuthenticateDevice)(HWND, HANDLE, BLUETOOTH_DEVICE_INFO*, PWCHAR, ULONG); +typedef DWORD (__stdcall *PBth_BluetoothEnumerateInstalledServices)(HANDLE, BLUETOOTH_DEVICE_INFO*, DWORD*, GUID*); PHidD_GetHidGuid HidD_GetHidGuid = NULL; PHidD_GetAttributes HidD_GetAttributes = NULL; @@ -74,6 +75,7 @@ PBth_BluetoothGetRadioInfo Bth_BluetoothGetRadioInfo = NULL; PBth_BluetoothRemoveDevice Bth_BluetoothRemoveDevice = NULL; PBth_BluetoothSetServiceState Bth_BluetoothSetServiceState = NULL; PBth_BluetoothAuthenticateDevice Bth_BluetoothAuthenticateDevice = NULL; +PBth_BluetoothEnumerateInstalledServices Bth_BluetoothEnumerateInstalledServices = NULL; HINSTANCE hid_lib = NULL; HINSTANCE bthprops_lib = NULL; @@ -119,12 +121,14 @@ inline void init_lib() Bth_BluetoothRemoveDevice = (PBth_BluetoothRemoveDevice)GetProcAddress(bthprops_lib, "BluetoothRemoveDevice"); Bth_BluetoothSetServiceState = (PBth_BluetoothSetServiceState)GetProcAddress(bthprops_lib, "BluetoothSetServiceState"); Bth_BluetoothAuthenticateDevice = (PBth_BluetoothAuthenticateDevice)GetProcAddress(bthprops_lib, "BluetoothAuthenticateDevice"); + Bth_BluetoothEnumerateInstalledServices = (PBth_BluetoothEnumerateInstalledServices)GetProcAddress(bthprops_lib, "BluetoothEnumerateInstalledServices"); if (!Bth_BluetoothFindDeviceClose || !Bth_BluetoothFindFirstDevice || !Bth_BluetoothFindFirstRadio || !Bth_BluetoothFindNextDevice || !Bth_BluetoothFindNextRadio || !Bth_BluetoothFindRadioClose || !Bth_BluetoothGetRadioInfo || !Bth_BluetoothRemoveDevice || - !Bth_BluetoothSetServiceState || !Bth_BluetoothAuthenticateDevice) + !Bth_BluetoothSetServiceState || !Bth_BluetoothAuthenticateDevice || + !Bth_BluetoothEnumerateInstalledServices) { PanicAlertT("Failed to load bthprops.cpl"); exit(EXIT_FAILURE); @@ -560,6 +564,14 @@ bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO& radio_info, BLUETO if (ERROR_SUCCESS != auth_result) ERROR_LOG(WIIMOTE, "AttachWiimote: BluetoothAuthenticateDevice returned %08x", auth_result); + + DWORD pcServices = 16; + GUID guids[16]; + // If this is not done, the Wii device will not remember the pairing + const DWORD srv_result = Bth_BluetoothEnumerateInstalledServices(hRadio, &btdi, &pcServices, guids); + + if (ERROR_SUCCESS != srv_result) + ERROR_LOG(WIIMOTE, "AttachWiimote: BluetoothEnumerateInstalledServices returned %08x", srv_result); #endif // Activate service const DWORD hr = Bth_BluetoothSetServiceState(hRadio, &btdi, From d0dbcc6369b1482237521308982baf84cd5989d5 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 1 Mar 2013 00:52:15 +0100 Subject: [PATCH 38/70] VideoSoftware: Cleanup PE perf metrics; returning the proper value now. --- .../Plugin_VideoSoftware/Src/BPMemLoader.cpp | 2 +- .../Plugin_VideoSoftware/Src/Rasterizer.cpp | 9 ++-- .../Src/SWPixelEngine.cpp | 11 ----- .../Plugin_VideoSoftware/Src/SWPixelEngine.h | 48 +++++++++++++++++++ .../Plugins/Plugin_VideoSoftware/Src/Tev.cpp | 14 ++---- 5 files changed, 57 insertions(+), 27 deletions(-) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp index dde31ab7d3..0d7c77c767 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp @@ -91,7 +91,7 @@ void SWBPWritten(int address, int newvalue) SWPixelEngine::pereg.boxTop = newvalue & 0x3ff; break; case BPMEM_CLEAR_PIXEL_PERF: - // TODO: Parameter? + // TODO: I didn't test if the value written to this register affects the amount of cleared registers SWPixelEngine::pereg.perfZcompInputZcomplocLo = 0; SWPixelEngine::pereg.perfZcompInputZcomplocHi = 0; SWPixelEngine::pereg.perfZcompOutputZcomplocLo = 0; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp index d30c3d7033..badb123fa0 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp @@ -150,18 +150,15 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi) if (bpmem.zcontrol.early_ztest && bpmem.zmode.testenable && g_SWVideoConfig.bZComploc) { - // TODO: Verify that perf regs are being incremented even if test is disabled - if (++SWPixelEngine::pereg.perfZcompInputZcomplocLo == 0) - SWPixelEngine::pereg.perfZcompInputZcomplocHi++; - + // TODO: Test if perf regs are incremented even if test is disabled + SWPixelEngine::pereg.IncZInputQuadCount(true); if (bpmem.zmode.testenable) { // early z if (!EfbInterface::ZCompare(x, y, z)) return; } - if (++SWPixelEngine::pereg.perfZcompOutputZcomplocLo == 0) - SWPixelEngine::pereg.perfZcompOutputZcomplocHi++; + SWPixelEngine::pereg.IncZOutputQuadCount(true); } RasterBlockPixel& pixel = rasterBlock.Pixel[xi][yi]; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp index a621542ea0..118e59629e 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp @@ -81,17 +81,6 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) if (address <= 0x2e) _uReturnValue = ((u16*)&pereg)[address >> 1]; - - if (address > 0x16) - { - ERROR_LOG(PIXELENGINE, "addr %#08x, ret %#04x; %#04x%04x, %#04x%04x, %#04x%04x, %#04x%04x, %#04x%04x, %#04x%04x\n", address, _uReturnValue, - pereg.perfZcompInputZcomplocHi, pereg.perfZcompInputZcomplocLo, - pereg.perfZcompOutputZcomplocHi, pereg.perfZcompOutputZcomplocLo, - pereg.perfZcompInputHi, pereg.perfZcompInputLo, - pereg.perfZcompOutputHi, pereg.perfZcompOutputLo, - pereg.perfBlendInputHi, pereg.perfBlendInputLo, - pereg.perfEfbCopyClocksHi, pereg.perfEfbCopyClocksLo); - } } void Write32(const u32 _iValue, const u32 _iAddress) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h index 7deb69a164..351e53456d 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h @@ -158,6 +158,54 @@ namespace SWPixelEngine u16 perfBlendInputHi; u16 perfEfbCopyClocksLo; u16 perfEfbCopyClocksHi; + + // NOTE: hardware doesn't process individual pixels but quads instead. Current software renderer architecture works on pixels though, so we have this "quad" hack here to only increment the registers on every fourth rendered pixel + void IncZInputQuadCount(bool early_ztest) + { + static int quad = 0; + if (++quad != 3) + return; + quad = 0; + + if (early_ztest) + { + if (++perfZcompInputZcomplocLo == 0) + perfZcompInputZcomplocHi++; + } + else + { + if (++perfZcompInputLo == 0) + perfZcompInputHi++; + } + } + void IncZOutputQuadCount(bool early_ztest) + { + static int quad = 0; + if (++quad != 3) + return; + quad = 0; + + if (early_ztest) + { + if (++perfZcompOutputZcomplocLo == 0) + perfZcompOutputZcomplocHi++; + } + else + { + if (++perfZcompOutputLo == 0) + perfZcompOutputHi++; + } + } + void IncBlendInputQuadCount() + { + static int quad = 0; + if (++quad != 3) + return; + quad = 0; + + if (++perfBlendInputLo == 0) + perfBlendInputHi++; + } }; extern PEReg pereg; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp index c9c408a623..3d5c0d7724 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp @@ -789,14 +789,12 @@ void Tev::Draw() if (late_ztest && bpmem.zmode.testenable) { // TODO: Check against hw if these values get incremented even if depth testing is disabled - if (++SWPixelEngine::pereg.perfZcompInputLo == 0) - SWPixelEngine::pereg.perfZcompInputHi++; + SWPixelEngine::pereg.IncZInputQuadCount(false); - if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2])) - return; + if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2])) + return; - if (++SWPixelEngine::pereg.perfZcompOutputLo == 0) - SWPixelEngine::pereg.perfZcompOutputHi++; + SWPixelEngine::pereg.IncZOutputQuadCount(false); } #if ALLOW_TEV_DUMPS @@ -820,9 +818,7 @@ void Tev::Draw() #endif INCSTAT(swstats.thisFrame.tevPixelsOut); - - if (++SWPixelEngine::pereg.perfBlendInputLo == 0) - SWPixelEngine::pereg.perfBlendInputHi++; + SWPixelEngine::pereg.IncBlendInputQuadCount(); EfbInterface::BlendTev(Position[0], Position[1], output); } From 1c9860246c1773ede5c35ba15d774cdb566fae18 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 1 Mar 2013 01:14:10 +0100 Subject: [PATCH 39/70] Build fixes for everyone! --- Source/Core/Common/Src/VideoBackendBase.h | 2 +- Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/Common/Src/VideoBackendBase.h b/Source/Core/Common/Src/VideoBackendBase.h index f502bf42b6..f1c8b0a131 100644 --- a/Source/Core/Common/Src/VideoBackendBase.h +++ b/Source/Core/Common/Src/VideoBackendBase.h @@ -22,7 +22,7 @@ #include #include "ChunkFile.h" -#include "PerfQueryBase.h" +#include "../../VideoCommon/Src/PerfQueryBase.h" typedef void (*writeFn16)(const u16,const u32); typedef void (*writeFn32)(const u32,const u32); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index 87d79fdb38..87257f15da 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -218,10 +218,10 @@ void VertexManager::vFlush() if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid); // Lego Star Wars crashes here. if (vs) VertexShaderCache::SetCurrentShader(vs->glprogid); - g_perf_query->EnableQuery(bpmem.zcontrol.zcomploc ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); + g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); Draw(); - g_perf_query->DisableQuery(bpmem.zcontrol.zcomploc ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); - //ERROR_LOG(VIDEO, "PerfQuery result: %d", g_perf_query->GetQueryResult(bpmem.zcontrol.zcomploc ? PQ_ZCOMP_OUTPUT_ZCOMPLOC : PQ_ZCOMP_OUTPUT)); + g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); + //ERROR_LOG(VIDEO, "PerfQuery result: %d", g_perf_query->GetQueryResult(bpmem.zcontrol.early_ztest ? PQ_ZCOMP_OUTPUT_ZCOMPLOC : PQ_ZCOMP_OUTPUT)); // run through vertex groups again to set alpha if (useDstAlpha && !dualSourcePossible) From cbf5efe19108a677987242f5ba6a71b38e129c05 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 1 Mar 2013 01:31:57 +0100 Subject: [PATCH 40/70] Some cleanups. PE perf metrics officially declared unsupported for the D3D9 project (out of pure laziness, anyone who cares can implement them :P). --- Source/Core/VideoCommon/Src/OnScreenDisplay.h | 2 +- Source/Core/VideoCommon/Src/VideoConfig.cpp | 1 - Source/Core/VideoCommon/Src/VideoConfig.h | 1 - Source/Plugins/Plugin_VideoDX11/Src/main.cpp | 1 - Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 9 ++++++--- Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 1 - 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Source/Core/VideoCommon/Src/OnScreenDisplay.h b/Source/Core/VideoCommon/Src/OnScreenDisplay.h index 3777e2b5d3..80187b8ac3 100644 --- a/Source/Core/VideoCommon/Src/OnScreenDisplay.h +++ b/Source/Core/VideoCommon/Src/OnScreenDisplay.h @@ -22,7 +22,7 @@ namespace OSD { // On-screen message display -void AddMessage(const char* str, u32 ms); +void AddMessage(const char* str, u32 ms = 2000); void DrawMessages(); // draw the current messages on the screen. Only call once per frame. void ClearMessages(); diff --git a/Source/Core/VideoCommon/Src/VideoConfig.cpp b/Source/Core/VideoCommon/Src/VideoConfig.cpp index 74484efb01..bd5c6a7acb 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.cpp +++ b/Source/Core/VideoCommon/Src/VideoConfig.cpp @@ -174,7 +174,6 @@ void VideoConfig::VerifyValidity() if (!backend_info.bSupports3DVision) b3DVision = false; if (!backend_info.bSupportsFormatReinterpretation) bEFBEmulateFormatChanges = false; if (!backend_info.bSupportsPixelLighting) bEnablePixelLighting = false; - if (!backend_info.bSupportsPixelPerfQuery) bDisablePixelPerf = true; } void VideoConfig::Save(const char *ini_file) diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h index 29ad6ec721..c9d2eef217 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.h +++ b/Source/Core/VideoCommon/Src/VideoConfig.h @@ -163,7 +163,6 @@ struct VideoConfig bool bSupportsDualSourceBlend; // only supported by D3D11 and OpenGL bool bSupportsFormatReinterpretation; bool bSupportsPixelLighting; - bool bSupportsPixelPerfQuery; } backend_info; // Utility diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index f858021e77..b7dd9101d3 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -95,7 +95,6 @@ void InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsFormatReinterpretation = true; g_Config.backend_info.bSupportsPixelLighting = true; - g_Config.backend_info.bSupportsPixelPerfQuery = true; IDXGIFactory* factory; IDXGIAdapter* ad; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index 8085ae4991..bf7bf16989 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -97,9 +97,6 @@ void InitBackendInfo() g_Config.backend_info.bSupports3DVision = true; g_Config.backend_info.bSupportsDualSourceBlend = false; g_Config.backend_info.bSupportsFormatReinterpretation = true; - g_Config.backend_info.bSupportsPixelPerfQuery = false; - - g_Config.backend_info.bSupportsPixelLighting = C_PLIGHTS + 40 <= maxConstants && C_PMATERIALS + 4 <= maxConstants; // adapters @@ -159,6 +156,12 @@ bool VideoBackend::Initialize(void *&window_handle) s_BackendInitialized = true; + if (!g_Config.bDisablePixelPerf) + { + OSD::AddMessage("PE perf metrics enabled although the D3D9 backend doesn't support them!"); + OSD::AddMessage("Try a different backend when issues arise."); + } + return true; } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index 266ac2a8ae..854554d968 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -136,7 +136,6 @@ void InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = false; // supported, but broken g_Config.backend_info.bSupportsFormatReinterpretation = false; g_Config.backend_info.bSupportsPixelLighting = true; - g_Config.backend_info.bSupportsPixelPerfQuery = false; // aamodes const char* caamodes[] = {"None", "2x", "4x", "8x", "8x CSAA", "8xQ CSAA", "16x CSAA", "16xQ CSAA"}; From b94f65b66608148450c22615ea896d90bbc27ed4 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 1 Mar 2013 01:37:47 +0100 Subject: [PATCH 41/70] Remove two incorrect lines. How did those even get there?! --- Source/Core/VideoCommon/Src/BPStructs.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index a8d081666f..a79af48370 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -269,8 +269,6 @@ void BPWritten(const BPCmd& bp) UPE_Copy PE_copy = bpmem.triggerEFBCopy; - g_renderer->ResumePixelPerf(true); - // Check if we are to copy from the EFB or draw to the XFB if (PE_copy.copy_to_xfb == 0) { @@ -309,8 +307,6 @@ void BPWritten(const BPCmd& bp) s_gammaLUT[PE_copy.gamma]); } - g_renderer->PausePixelPerf(true); - // Clear the rectangular region after copying it. if (PE_copy.clear) { From dea1e2827d6ce6eb5f6bfe2c64c59a36b3606b02 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 28 Feb 2013 19:33:39 -0600 Subject: [PATCH 42/70] Open std::fstream in a unicode-safe manner. --- Source/Core/Common/Src/FileUtil.h | 12 ++++++++++++ Source/Core/Common/Src/IniFile.cpp | 5 +++-- Source/Core/Common/Src/LinearDiskCache.h | 2 +- Source/Core/Common/Src/LogManager.cpp | 2 +- Source/Core/Common/Src/NandPaths.cpp | 6 ++++-- Source/Core/Core/Src/DSP/assemble.cpp | 3 ++- .../Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp | 2 +- Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp | 2 +- .../DolphinWX/Src/Debugger/CodeWindowFunctions.cpp | 3 ++- Source/Core/DolphinWX/Src/ISOProperties.cpp | 3 ++- Source/Core/VideoCommon/Src/ImageWrite.cpp | 3 ++- Source/Core/VideoCommon/Src/PixelShaderGen.cpp | 3 ++- Source/Core/VideoCommon/Src/VertexManagerBase.cpp | 6 ++++-- Source/Core/VideoCommon/Src/VertexShaderGen.cpp | 3 ++- Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp | 9 ++++++--- Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp | 6 ++++-- .../Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp | 3 ++- Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp | 6 ++++-- .../Plugin_VideoOGL/Src/VertexShaderCache.cpp | 3 ++- 19 files changed, 57 insertions(+), 25 deletions(-) diff --git a/Source/Core/Common/Src/FileUtil.h b/Source/Core/Common/Src/FileUtil.h index b8e8d9c17c..dd1abe6ae9 100644 --- a/Source/Core/Common/Src/FileUtil.h +++ b/Source/Core/Common/Src/FileUtil.h @@ -25,6 +25,7 @@ #include #include "Common.h" +#include "StringUtil.h" // User directory indices for GetUserPath enum { @@ -226,4 +227,15 @@ private: } // namespace +// To deal with Windows being dumb at unicode: +template +void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode) +{ +#ifdef _WIN32 + fstream.open(UTF8ToTStr(filename).c_str(), openmode); +#else + fstream.open(filename, openmode); +#endif +} + #endif diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp index acad498106..da44855941 100644 --- a/Source/Core/Common/Src/IniFile.cpp +++ b/Source/Core/Common/Src/IniFile.cpp @@ -25,6 +25,7 @@ #include #include +#include "FileUtil.h" #include "StringUtil.h" #include "IniFile.h" @@ -400,7 +401,7 @@ bool IniFile::Load(const char* filename) // Open file std::ifstream in; - in.open(filename, std::ios::in); + OpenFStream(in, filename, std::ios::in); if (in.fail()) return false; @@ -452,7 +453,7 @@ bool IniFile::Load(const char* filename) bool IniFile::Save(const char* filename) { std::ofstream out; - out.open(filename, std::ios::out); + OpenFStream(out, filename, std::ios::out); if (out.fail()) { diff --git a/Source/Core/Common/Src/LinearDiskCache.h b/Source/Core/Common/Src/LinearDiskCache.h index 9755c996bd..42b3d9ff15 100644 --- a/Source/Core/Common/Src/LinearDiskCache.h +++ b/Source/Core/Common/Src/LinearDiskCache.h @@ -74,7 +74,7 @@ public: m_num_entries = 0; // try opening for reading/writing - m_file.open(filename, ios_base::in | ios_base::out | ios_base::binary); + OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary); m_file.seekg(0, std::ios::end); std::fstream::pos_type end_pos = m_file.tellg(); diff --git a/Source/Core/Common/Src/LogManager.cpp b/Source/Core/Common/Src/LogManager.cpp index 3beae08c15..9b0ed43333 100644 --- a/Source/Core/Common/Src/LogManager.cpp +++ b/Source/Core/Common/Src/LogManager.cpp @@ -186,7 +186,7 @@ void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg) FileLogListener::FileLogListener(const char *filename) { - m_logfile.open(filename, std::ios::app); + OpenFStream(m_logfile, filename, std::ios::app); SetEnable(true); } diff --git a/Source/Core/Common/Src/NandPaths.cpp b/Source/Core/Common/Src/NandPaths.cpp index cec79414a7..eb0673afe0 100644 --- a/Source/Core/Common/Src/NandPaths.cpp +++ b/Source/Core/Common/Src/NandPaths.cpp @@ -86,7 +86,8 @@ bool CheckTitleTIK(u64 _titleID) static void CreateReplacementFile(std::string &filename) { - std::ofstream replace(filename.c_str()); + std::ofstream replace; + OpenFStream(replace, filename, std::ios_base::out); replace <<"\" __22__\n"; replace << "* __2a__\n"; //replace << "/ __2f__\n"; @@ -108,7 +109,8 @@ void ReadReplacements(replace_v& replacements) if (!File::Exists(filename)) CreateReplacementFile(filename); - std::ifstream f(filename.c_str()); + std::ifstream f; + OpenFStream(f, filename, std::ios_base::in); char letter; std::string replacement; diff --git a/Source/Core/Core/Src/DSP/assemble.cpp b/Source/Core/Core/Src/DSP/assemble.cpp index dd394ab82c..248b0d8ba8 100644 --- a/Source/Core/Core/Src/DSP/assemble.cpp +++ b/Source/Core/Core/Src/DSP/assemble.cpp @@ -754,7 +754,8 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass) { int disable_text = 0; // modified by Hermes - std::ifstream fsrc(fname); + std::ifstream fsrc; + OpenFStream(fsrc, fname, std::ios_base::in); if (fsrc.fail()) { diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp index 5c2a28b57a..5710fd4f25 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp @@ -297,7 +297,7 @@ void Wiimote::WriteData(const wm_write_data* const wd) { // writing the whole mii block each write :/ std::ofstream file; - file.open((File::GetUserPath(D_WIIUSER_IDX) + "mii.bin").c_str(), std::ios::binary | std::ios::out); + OpenFStream(file, File::GetUserPath(D_WIIUSER_IDX) + "mii.bin", std::ios::binary | std::ios::out); file.write((char*)m_eeprom + 0x0FCA, 0x02f0); file.close(); } diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp index ba01239bf2..c743c80294 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp @@ -106,7 +106,7 @@ void Wiimote::SpeakerData(wm_speaker_data* sd) File::Delete("rmtdump.wav"); File::Delete("rmtdump.bin"); atexit(stopdamnwav); - ofile.open("rmtdump.bin", ofile.binary | ofile.out); + OpenFStream(ofile, "rmtdump.bin", ofile.binary | ofile.out); wav.Start("rmtdump.wav", 6000/*Common::swap16(m_reg_speaker.sample_rate)*/); } wav.AddMonoSamples(samples, sd->length*2); diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp index 362e617696..fad0380eca 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp @@ -285,7 +285,8 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) if (!path.IsEmpty()) { - std::ifstream f(WxStrToStr(path).c_str()); + std::ifstream f; + OpenFStream(f, WxStrToStr(path), std::ios_base::in); std::string line; while (std::getline(f, line)) diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index 6434c8cd54..a194345585 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -137,7 +137,8 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW else { // Will fail out if GameConfig folder doesn't exist - std::ofstream f(GameIniFile.c_str()); + std::ofstream f; + OpenFStream(f, GameIniFile, std::ios_base::out); if (f) { f << "# " << OpenISO->GetUniqueID() << " - " << OpenISO->GetName() << '\n' diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp index 23b0e73427..482b4dad25 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.cpp +++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp @@ -69,7 +69,8 @@ bool SaveTGA(const char* filename, int width, int height, void* pdata) bool SaveData(const char* filename, const char* data) { - std::ofstream f(filename, std::ios::binary); + std::ofstream f; + OpenFStream(f, filename, std::ios::binary); f << data; return true; diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index 448501aad0..6793862ef9 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -252,7 +252,8 @@ void ValidatePixelShaderIDs(API_TYPE api, PIXELSHADERUIDSAFE old_id, const std:: static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%spsuid_mismatch_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << msg; file << "\n\nOld shader code:\n" << old_code; file << "\n\nNew shader code:\n" << new_code; diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp index cd5a01c6b3..6d5d122704 100644 --- a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp @@ -277,10 +277,12 @@ void VertexManager::Flush() // save the shaders char strfile[255]; sprintf(strfile, "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); - std::ofstream fps(strfile); + std::ofstream fps; + OpenFStream(fps, strfile, std::ios_base::out); fps << ps->strprog.c_str(); sprintf(strfile, "%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); - std::ofstream fvs(strfile); + std::ofstream fvs; + OpenFStream(fvs, strfile, std::ios_base::out); fvs << vs->strprog.c_str(); } diff --git a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp index cad117c2c8..2ca6f67077 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp @@ -114,7 +114,8 @@ void ValidateVertexShaderIDs(API_TYPE api, VERTEXSHADERUIDSAFE old_id, const std static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%svsuid_mismatch_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << msg; file << "\n\nOld shader code:\n" << old_code; file << "\n\nNew shader code:\n" << new_code; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp index 41e5423990..c688228945 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp @@ -64,7 +64,8 @@ bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob) static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << code; file.close(); @@ -121,7 +122,8 @@ bool CompileGeometryShader(const char* code, unsigned int len, D3DBlob** blob, static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_gs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << code; file.close(); @@ -180,7 +182,8 @@ bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob, static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << code; file.close(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp index 9c17c3df8c..c7c4cf266a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp @@ -50,7 +50,8 @@ bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecode static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << code; file.close(); @@ -105,7 +106,8 @@ bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodel static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << code; file.close(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp index 61e41008b3..572c7f19c7 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp @@ -264,7 +264,8 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << pstrprogram; file.close(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index 6ea10fc077..a6da4d6fa4 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -249,10 +249,12 @@ void VertexManager::vFlush() // save the shaders char strfile[255]; sprintf(strfile, "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); - std::ofstream fps(strfile); + std::ofstream fps; + OpenFStream(fps, strfile, std::ios_base::out); fps << ps->strprog.c_str(); sprintf(strfile, "%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); - std::ofstream fvs(strfile); + std::ofstream fvs; + OpenFStream(fvs, strfile, std::ios_base::out); fvs << vs->strprog.c_str(); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp index dbbb7ee29b..7d003b8363 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp @@ -144,7 +144,8 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << pstrprogram; file.close(); From b0630790c1c195ba7654c140d6c6baa4dcddd346 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 28 Feb 2013 19:42:29 -0600 Subject: [PATCH 43/70] It's 2013! Why can't I use C++11 yet!? --- Source/Core/Common/Src/FileUtil.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Common/Src/FileUtil.h b/Source/Core/Common/Src/FileUtil.h index dd1abe6ae9..2747c50cf4 100644 --- a/Source/Core/Common/Src/FileUtil.h +++ b/Source/Core/Common/Src/FileUtil.h @@ -234,7 +234,7 @@ void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmod #ifdef _WIN32 fstream.open(UTF8ToTStr(filename).c_str(), openmode); #else - fstream.open(filename, openmode); + fstream.open(filename.c_str(), openmode); #endif } From 99cf57eb393e61bc0a9072a6e4f4f21c57daea9d Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Fri, 1 Mar 2013 19:21:34 +1300 Subject: [PATCH 44/70] Fixes two memory leaks, one is pretty bad for OSX. Yell at pauldachz if this doesn't work. Or... say thanks. --- Source/Core/DiscIO/Src/WiiWad.cpp | 3 ++- .../InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Core/DiscIO/Src/WiiWad.cpp b/Source/Core/DiscIO/Src/WiiWad.cpp index 24e091f9f4..fa44108586 100644 --- a/Source/Core/DiscIO/Src/WiiWad.cpp +++ b/Source/Core/DiscIO/Src/WiiWad.cpp @@ -49,7 +49,8 @@ WiiWAD::WiiWAD(const std::string& _rName) if (pReader == NULL || File::IsDirectory(_rName)) { m_Valid = false; - return; + if(pReader) delete pReader; + return; } m_Valid = ParseWAD(*pReader); diff --git a/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm index 56e360019a..c22e267044 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm +++ b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm @@ -69,6 +69,7 @@ bool Keyboard::UpdateInput() CGRectMakeWithDictionaryRepresentation(boundsDictionary, &bounds); } + CFRelease(windowDescriptions); CFRelease(windowArray); CGEventRef event = CGEventCreate(nil); From a2d08d674079720037910a2b3bb82940648875f5 Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Fri, 1 Mar 2013 10:11:08 +0100 Subject: [PATCH 45/70] Fix Dolphin starting only once then crashing at startup --- Source/Core/DolphinWX/Src/LogWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/DolphinWX/Src/LogWindow.cpp b/Source/Core/DolphinWX/Src/LogWindow.cpp index 4c9c495713..7af1de1aaa 100644 --- a/Source/Core/DolphinWX/Src/LogWindow.cpp +++ b/Source/Core/DolphinWX/Src/LogWindow.cpp @@ -247,7 +247,7 @@ wxTextCtrl* CLogWindow::CreateTextCtrl(wxPanel* parent, wxWindowID id, long Styl #else TC->SetBackgroundColour(*wxBLACK); #endif - if (m_FontChoice && m_FontChoice->GetSelection() < (int)LogFont.size()) + if (m_FontChoice && m_FontChoice->GetSelection() < (int)LogFont.size() && m_FontChoice->GetSelection() >= 0) TC->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, LogFont[m_FontChoice->GetSelection()])); return TC; From ef7083d78cdeb9eb8881a0d1593164ad1dd04225 Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 1 Mar 2013 11:31:52 +0100 Subject: [PATCH 46/70] also don't cleanup efb copys on efb2ram these may be upscaled and this high res textures would be lost --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 6871c411fa..dcd3fbdd90 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -132,8 +132,7 @@ void TextureCache::Cleanup() if ( frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted - // TODO: encoding the texture back to RAM here might be a good idea - && ! (g_ActiveConfig.bCopyEFBToTexture && iter->second->IsEfbCopy()) ) + && ! iter->second->IsEfbCopy() ) { delete iter->second; textures.erase(iter++); From 5a7bb2abfae1d37d01bef16d3113a0b54813b81f Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 1 Mar 2013 19:30:37 +0100 Subject: [PATCH 47/70] D3D11: Port perf queries code to the PerfQueryBase interface. Remove deprecated PerfQuery methods from RenderBase. Windows build fix. --- Source/Core/VideoCommon/Src/RenderBase.h | 5 - .../VideoCommon/VideoCommon.vcxproj.filters | 10 +- .../Plugin_VideoDX11/Plugin_VideoDX11.vcxproj | 2 + .../Plugin_VideoDX11.vcxproj.filters | 6 + .../Plugin_VideoDX11/Src/PerfQuery.cpp | 148 ++++++++++++++++++ .../Plugins/Plugin_VideoDX11/Src/PerfQuery.h | 46 ++++++ .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 132 ---------------- Source/Plugins/Plugin_VideoDX11/Src/Render.h | 6 - .../Plugin_VideoDX11/Src/VertexManager.cpp | 4 +- Source/Plugins/Plugin_VideoDX11/Src/main.cpp | 3 + .../Plugins/Plugin_VideoOGL/Src/PerfQuery.h | 10 +- 11 files changed, 218 insertions(+), 154 deletions(-) create mode 100644 Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp create mode 100644 Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index 7f2853bcc3..55678f3f5a 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -128,11 +128,6 @@ public: static unsigned int GetPrevPixelFormat() { return prev_efb_format; } static void StorePixelFormat(unsigned int new_format) { prev_efb_format = new_format; } - virtual void ResetPixelPerf() {}; - virtual void ResumePixelPerf(bool efb_copies) {}; - virtual void PausePixelPerf(bool efb_copies) {}; - virtual u32 GetPixelPerfResult(PixelPerfQuery type) { return 0; }; - // TODO: doesn't belong here virtual void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) = 0; virtual void SetPSConstant4fv(unsigned int const_number, const float *f) = 0; diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters index 86b2e03221..330b23d370 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters @@ -101,6 +101,9 @@ Base + + Base + Base @@ -113,8 +116,6 @@ Shader Generators - - Base Util @@ -239,6 +240,9 @@ Base + + Base + Base @@ -251,8 +255,6 @@ Shader Generators - - Base Util diff --git a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj index 52d1c37aed..aab9345ef7 100644 --- a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj +++ b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj @@ -199,6 +199,7 @@ + @@ -228,6 +229,7 @@ + diff --git a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters index 6492e887ca..4b8efac92b 100644 --- a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters +++ b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters @@ -57,6 +57,9 @@ Render + + Render + @@ -117,6 +120,9 @@ Render + + Render + diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp new file mode 100644 index 0000000000..6ab91fed27 --- /dev/null +++ b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp @@ -0,0 +1,148 @@ +#include "RenderBase.h" + +#include "D3DBase.h" +#include "PerfQuery.h" + +namespace DX11 { + +PerfQuery::PerfQuery() + : m_query_read_pos() + , m_query_count() +{ + for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + { + D3D11_QUERY_DESC qdesc = CD3D11_QUERY_DESC(D3D11_QUERY_OCCLUSION, 0); + D3D::device->CreateQuery(&qdesc, &m_query_buffer[i].query); + } + ResetQuery(); +} + +PerfQuery::~PerfQuery() +{ + for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + { + // TODO: EndQuery? + m_query_buffer[i].query->Release(); + } +} + +void PerfQuery::EnableQuery(PerfQueryGroup type) +{ + // Is this sane? + if (m_query_count > ARRAYSIZE(m_query_buffer) / 2) + WeakFlush(); + + if (ARRAYSIZE(m_query_buffer) == m_query_count) + { + // TODO + FlushOne(); + ERROR_LOG(VIDEO, "flushed query buffer early!"); + } + + // start query + if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) + { + auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ARRAYSIZE(m_query_buffer)]; + + D3D::context->Begin(entry.query); + entry.query_type = type; + + ++m_query_count; + } +} + +void PerfQuery::DisableQuery(PerfQueryGroup type) +{ + // stop query + if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) + { + auto& entry = m_query_buffer[(m_query_read_pos + m_query_count + ARRAYSIZE(m_query_buffer)-1) % ARRAYSIZE(m_query_buffer)]; + D3D::context->End(entry.query); + } +} + +void PerfQuery::ResetQuery() +{ + m_query_count = 0; + std::fill_n(m_results, ARRAYSIZE(m_results), 0); +} + +u32 PerfQuery::GetQueryResult(PerfQueryType type) +{ + u32 result = 0; + + if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC) + { + result = m_results[PQG_ZCOMP_ZCOMPLOC]; + } + else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT) + { + result = m_results[PQG_ZCOMP]; + } + else if (type == PQ_BLEND_INPUT) + { + result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC]; + } + else if (type == PQ_EFB_COPY_CLOCKS) + { + result = m_results[PQG_EFB_COPY_CLOCKS]; + } + + return result / 4; +} + +void PerfQuery::FlushOne() +{ + auto& entry = m_query_buffer[m_query_read_pos]; + + UINT64 result = 0; + HRESULT hr = S_FALSE; + while (hr != S_OK) + { + // TODO: Might cause us to be stuck in an infinite loop! + hr = D3D::context->GetData(entry.query, &result, sizeof(result), 0); + } + + m_results[entry.query_type] += result * EFB_WIDTH * EFB_HEIGHT / g_renderer->GetTargetWidth() / g_renderer->GetTargetHeight(); + + m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); + --m_query_count; +} + +// TODO: could selectively flush things, but I don't think that will do much +void PerfQuery::FlushResults() +{ + while (!IsFlushed()) + FlushOne(); +} + +void PerfQuery::WeakFlush() +{ + while (!IsFlushed()) + { + auto& entry = m_query_buffer[m_query_read_pos]; + + UINT64 result = 0; + HRESULT hr = D3D::context->GetData(entry.query, &result, sizeof(result), D3D11_ASYNC_GETDATA_DONOTFLUSH); + + if (hr == S_OK) + { + m_results[entry.query_type] += result * EFB_WIDTH * EFB_HEIGHT / g_renderer->GetTargetWidth() / g_renderer->GetTargetHeight(); + + m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); + --m_query_count; + } + else + { + break; + } + } +} + +bool PerfQuery::IsFlushed() const +{ + return 0 == m_query_count; +} + + +} // namespace diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h new file mode 100644 index 0000000000..b3709d1013 --- /dev/null +++ b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h @@ -0,0 +1,46 @@ +#ifndef _PERFQUERY_H_ +#define _PERFQUERY_H_ + +#include "PerfQueryBase.h" + +namespace DX11 { + +class PerfQuery : public PerfQueryBase +{ +public: + PerfQuery(); + ~PerfQuery(); + + void EnableQuery(PerfQueryGroup type); + void DisableQuery(PerfQueryGroup type); + void ResetQuery(); + u32 GetQueryResult(PerfQueryType type); + void FlushResults(); + bool IsFlushed() const; + +private: + struct ActiveQuery + { + ID3D11Query* query; + PerfQueryGroup query_type; + }; + + void WeakFlush(); + + // Only use when non-empty + void FlushOne(); + + // when testing in SMS: 64 was too small, 128 was ok + static const int PERF_QUERY_BUFFER_SIZE = 512; + + ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE]; + int m_query_read_pos; + + // TODO: sloppy + volatile int m_query_count; + volatile u32 m_results[PQG_NUM_MEMBERS]; +}; + +} // namespace + +#endif // _PERFQUERY_H_ diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 882d20f8e6..2dcfcd041c 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -65,18 +65,6 @@ ID3D11RasterizerState* resetraststate = NULL; static ID3D11Texture2D* s_screenshot_texture = NULL; -// Using a vector of query objects to avoid flushing the gpu pipeline all the time -// TODO: Could probably optimized further by using a ring buffer or something -#define MAX_PIXEL_PERF_QUERIES 20 // 20 is an arbitrary guess -std::vector pixel_perf_queries; -static int pixel_perf_query_index = 0; - -static u64 pixel_perf = 0; -static bool pixel_perf_active = false; -static bool pixel_perf_dirty = false; - -ID3D11Query* gpu_finished_query = NULL; - // GX pipeline state struct @@ -170,9 +158,6 @@ void SetupDeviceObjects() D3D::SetDebugObjectName((ID3D11DeviceChild*)resetraststate, "rasterizer state for Renderer::ResetAPIState"); s_screenshot_texture = NULL; - - D3D11_QUERY_DESC qdesc = CD3D11_QUERY_DESC(D3D11_QUERY_EVENT, 0); - D3D::device->CreateQuery(&qdesc, &gpu_finished_query); } // Kill off all device objects @@ -180,12 +165,6 @@ void TeardownDeviceObjects() { delete g_framebuffer_manager; - while (!pixel_perf_queries.empty()) - { - SAFE_RELEASE(pixel_perf_queries.back()); - pixel_perf_queries.pop_back(); - } - SAFE_RELEASE(gpu_finished_query); SAFE_RELEASE(access_efb_cbuf); SAFE_RELEASE(clearblendstates[0]); SAFE_RELEASE(clearblendstates[1]); @@ -232,11 +211,6 @@ Renderer::Renderer() s_LastEFBScale = g_ActiveConfig.iEFBScale; CalculateTargetSize(s_backbuffer_width, s_backbuffer_height); - pixel_perf_query_index = 0; - pixel_perf = 0; - pixel_perf_active = false; - pixel_perf_dirty = false; - SetupDeviceObjects(); @@ -660,112 +634,6 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); } -void Renderer::ResetPixelPerf() -{ - if (g_ActiveConfig.bDisablePixelPerf) - return; - - if (pixel_perf_active) - PausePixelPerf(false); - - pixel_perf_query_index = 0; - pixel_perf = 0; -} - -void Renderer::ResumePixelPerf(bool efb_copies) -{ - if (g_ActiveConfig.bDisablePixelPerf) - return; - - if (efb_copies) - return; - - if(pixel_perf_active) - return; - - if (pixel_perf_queries.size() < pixel_perf_query_index+1 && pixel_perf_query_index < MAX_PIXEL_PERF_QUERIES) - { - D3D11_QUERY_DESC qdesc = CD3D11_QUERY_DESC(D3D11_QUERY_OCCLUSION, 0); - ID3D11Query* tmpquery = NULL; - D3D::device->CreateQuery(&qdesc, &tmpquery); - pixel_perf_queries.push_back(tmpquery); - pixel_perf_query_index = pixel_perf_queries.size() - 1; - } - else if (pixel_perf_queries.size() < pixel_perf_query_index+1) - { - StorePixelPerfResult(PP_ZCOMP_OUTPUT); - pixel_perf_query_index = 0; - } - // This will spam the D3D11 debug runtime output with QUERY_BEGIN_ABANDONING_PREVIOUS_RESULTS warnings which safely can be ignored. Mute them in the DX control panel if you need to read the debug runtime output. - D3D::context->Begin(pixel_perf_queries[pixel_perf_query_index]); - pixel_perf_active = true; - pixel_perf_dirty = true; -} - -void Renderer::PausePixelPerf(bool efb_copies) -{ - if (g_ActiveConfig.bDisablePixelPerf) - return; - - if(!pixel_perf_active) - return; - - D3D::context->End(pixel_perf_queries[pixel_perf_query_index]); - pixel_perf_query_index++; - pixel_perf_active = false; -} - -void Renderer::StorePixelPerfResult(PixelPerfQuery type) -{ - // First, make sure the GPU has finished rendering so that query results are valid - D3D::context->End(gpu_finished_query); - BOOL gpu_finished = FALSE; - while (!gpu_finished) - { - // If nothing goes horribly wrong here, this should complete in finite time... - D3D::context->GetData(gpu_finished_query, &gpu_finished, sizeof(gpu_finished), 0); - } - - for(int i = 0; i < pixel_perf_query_index; ++i) - { - UINT64 buf = 0; - D3D::context->GetData(pixel_perf_queries[i], &buf, sizeof(buf), 0); - - // Reported pixel metrics should be referenced to native resolution: - pixel_perf += buf * EFB_WIDTH * EFB_HEIGHT / GetTargetWidth() / GetTargetHeight(); - } - pixel_perf_dirty = false; -} - -u32 Renderer::GetPixelPerfResult(PixelPerfQuery type) -{ - if (g_ActiveConfig.bDisablePixelPerf) - return 0; - - if (type == PP_EFB_COPY_CLOCKS) - { - // not implemented - return 0; - } - - if (type == PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L || - type == PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H || - type == PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L || - type == PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H) - { - // return zero for now because ZCOMP_OUTPUT_ZCOMPLOC + ZCOMP_OUTPUT should equal BLEND_INPUT - // TODO: Instead, should keep separate counters for zcomploc and non-zcomploc registers. - return 0; - } - - // Basically we only implement PP_ZCOMP_OUTPUT, but we're returning the same value for PP_ZCOMP_INPUT and PP_BLEND_INPUT anyway - if (pixel_perf_dirty) - StorePixelPerfResult(PP_ZCOMP_OUTPUT); - - // Dividing by 4 because we're expected to return the number of 2x2 quads instead of pixels - return std::min(pixel_perf / 4, (u64)0xFFFFFFFF); -} - void SetSrcBlend(D3D11_BLEND val) { // Colors should blend against SRC_ALPHA diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.h b/Source/Plugins/Plugin_VideoDX11/Src/Render.h index 6db829c205..8f6c78fae1 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.h @@ -46,12 +46,6 @@ public: void ReinterpretPixelData(unsigned int convtype); - void ResetPixelPerf(); - void ResumePixelPerf(bool efb_copies); - void PausePixelPerf(bool efb_copies); - u32 GetPixelPerfResult(PixelPerfQuery type); - void StorePixelPerfResult(PixelPerfQuery type); // internal - void UpdateViewport(Matrix44& vpCorrection); bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index 8137e1a39f..6991b11690 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -274,9 +274,9 @@ void VertexManager::vFlush() g_nativeVertexFmt->SetupVertexPointers(); g_renderer->ApplyState(useDstAlpha); - g_renderer->ResumePixelPerf(false); + g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); Draw(stride); - g_renderer->PausePixelPerf(false); + g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index b7dd9101d3..af4d57dbf9 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -42,6 +42,7 @@ #include "D3DUtil.h" #include "D3DBase.h" +#include "PerfQuery.h" #include "PixelShaderCache.h" #include "TextureCache.h" #include "VertexManager.h" @@ -185,6 +186,7 @@ void VideoBackend::Video_Prepare() g_renderer = new Renderer; g_texture_cache = new TextureCache; g_vertex_manager = new VertexManager; + g_perf_query = new PerfQuery; VertexShaderCache::Init(); PixelShaderCache::Init(); D3D::InitUtils(); @@ -227,6 +229,7 @@ void VideoBackend::Shutdown() D3D::ShutdownUtils(); PixelShaderCache::Shutdown(); VertexShaderCache::Shutdown(); + delete g_perf_query; delete g_vertex_manager; delete g_texture_cache; delete g_renderer; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h index 76040272e3..34c64e43a1 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h @@ -17,25 +17,25 @@ public: u32 GetQueryResult(PerfQueryType type); void FlushResults(); bool IsFlushed() const; - + private: struct ActiveQuery { GLuint query_id; PerfQueryGroup query_type; }; - + // when testing in SMS: 64 was too small, 128 was ok static const int PERF_QUERY_BUFFER_SIZE = 512; - + void WeakFlush(); // Only use when non-empty void FlushOne(); - + // This contains gl query objects with unretrieved results. ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE]; int m_query_read_pos; - + // TODO: sloppy volatile int m_query_count; volatile u32 m_results[PQG_NUM_MEMBERS]; From 4058b4c38a1d591253e1b1f84a44c95161607249 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 1 Mar 2013 23:02:11 +0100 Subject: [PATCH 48/70] Add documentation to PerfQueryBase interface. Remove the config field for perf queries (wasn't used for the new interface anyway). Few other cleanups. --- Source/Core/VideoCommon/Src/BPStructs.cpp | 2 +- Source/Core/VideoCommon/Src/MainBase.cpp | 4 ++-- Source/Core/VideoCommon/Src/PerfQueryBase.h | 13 +++++++++++++ Source/Core/VideoCommon/Src/PixelEngine.cpp | 1 - Source/Core/VideoCommon/Src/VideoConfig.cpp | 4 ---- Source/Core/VideoCommon/Src/VideoConfig.h | 3 +-- Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 9 +++------ 7 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index a79af48370..fa6bc08966 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -485,7 +485,7 @@ void BPWritten(const BPCmd& bp) case BPMEM_IND_IMASK: // Index Mask ? case BPMEM_REVBITS: // Always set to 0x0F when GX_InitRevBits() is called. break; - + case BPMEM_CLEAR_PIXEL_PERF: // GXClearPixMetric writes 0xAAA here, Sunshine alternates this register between values 0x000 and 0xAAA g_perf_query->ResetQuery(); diff --git a/Source/Core/VideoCommon/Src/MainBase.cpp b/Source/Core/VideoCommon/Src/MainBase.cpp index 0d357a4f80..1472367f21 100644 --- a/Source/Core/VideoCommon/Src/MainBase.cpp +++ b/Source/Core/VideoCommon/Src/MainBase.cpp @@ -195,7 +195,7 @@ void VideoFifo_CheckPerfQueryRequest() u32 VideoBackendHardware::Video_GetQueryResult(PerfQueryType type) { - // Is this check sane? + // TODO: Is this check sane? if (!g_perf_query->IsFlushed()) { if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread) @@ -207,7 +207,7 @@ u32 VideoBackendHardware::Video_GetQueryResult(PerfQueryType type) else g_perf_query->FlushResults(); } - + return g_perf_query->GetQueryResult(type); } diff --git a/Source/Core/VideoCommon/Src/PerfQueryBase.h b/Source/Core/VideoCommon/Src/PerfQueryBase.h index 2643482379..b979449edb 100644 --- a/Source/Core/VideoCommon/Src/PerfQueryBase.h +++ b/Source/Core/VideoCommon/Src/PerfQueryBase.h @@ -28,11 +28,24 @@ public: PerfQueryBase() {}; virtual ~PerfQueryBase() {} + // Begin querying the specified value for the following host GPU commands virtual void EnableQuery(PerfQueryGroup type) {} + + // Stop querying the specified value for the following host GPU commands virtual void DisableQuery(PerfQueryGroup type) {} + + // Reset query counters to zero and drop any pending queries virtual void ResetQuery() {} + + // Return the measured value for the specified query type + // NOTE: Called from CPU thread virtual u32 GetQueryResult(PerfQueryType type) { return 0; } + + // Request the value of any pending queries - causes a pipeline flush and thus should be used carefully! virtual void FlushResults() {} + + // True if there are no further pending query results + // NOTE: Called from CPU thread virtual bool IsFlushed() const { return true; } }; diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index 2d6275096c..e5ba554678 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -299,7 +299,6 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) // Later builds returned 1 for the high register. That caused the timer to actually count down, but made the challenge unbeatable because the game always thought you didn't clear any goop at all. // Note that currently this functionality is only implemented in the D3D11 backend. _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_BLEND_INPUT) & 0xFFFF; - //ERROR_LOG(VIDEO, "PQ_BLEND_INPUT: %d", g_video_backend->Video_GetQueryResult(PQ_BLEND_INPUT)); break; case PE_PERF_BLEND_INPUT_H: diff --git a/Source/Core/VideoCommon/Src/VideoConfig.cpp b/Source/Core/VideoCommon/Src/VideoConfig.cpp index bd5c6a7acb..a76514a10c 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.cpp +++ b/Source/Core/VideoCommon/Src/VideoConfig.cpp @@ -105,7 +105,6 @@ void VideoConfig::Load(const char *ini_file) iniFile.Get("Hacks", "EFBScaledCopy", &bCopyEFBScaled, true); iniFile.Get("Hacks", "EFBCopyCacheEnable", &bEFBCopyCacheEnable, false); iniFile.Get("Hacks", "EFBEmulateFormatChanges", &bEFBEmulateFormatChanges, false); - iniFile.Get("Hacks", "DisablePixelPerf", &bDisablePixelPerf, true); iniFile.Get("Hardware", "Adapter", &iAdapter, 0); @@ -154,7 +153,6 @@ void VideoConfig::GameIniLoad(const char *ini_file) iniFile.GetIfExists("Video_Hacks", "EFBScaledCopy", &bCopyEFBScaled); iniFile.GetIfExists("Video_Hacks", "EFBCopyCacheEnable", &bEFBCopyCacheEnable); iniFile.GetIfExists("Video_Hacks", "EFBEmulateFormatChanges", &bEFBEmulateFormatChanges); - iniFile.GetIfExists("Video_Hacks", "DisablePixelPerf", &bDisablePixelPerf); iniFile.GetIfExists("Video", "ProjectionHack", &iPhackvalue[0]); iniFile.GetIfExists("Video", "PH_SZNear", &iPhackvalue[1]); @@ -233,7 +231,6 @@ void VideoConfig::Save(const char *ini_file) iniFile.Set("Hacks", "EFBScaledCopy", bCopyEFBScaled); iniFile.Set("Hacks", "EFBCopyCacheEnable", bEFBCopyCacheEnable); iniFile.Set("Hacks", "EFBEmulateFormatChanges", bEFBEmulateFormatChanges); - iniFile.Set("Hacks", "DisablePixelPerf", bDisablePixelPerf); iniFile.Set("Hardware", "Adapter", iAdapter); @@ -289,7 +286,6 @@ void VideoConfig::GameIniSave(const char* default_ini, const char* game_ini) SET_IF_DIFFERS("Video_Hacks", "EFBScaledCopy", bCopyEFBScaled); SET_IF_DIFFERS("Video_Hacks", "EFBCopyCacheEnable", bEFBCopyCacheEnable); SET_IF_DIFFERS("Video_Hacks", "EFBEmulateFormatChanges", bEFBEmulateFormatChanges); - SET_IF_DIFFERS("Video_Hacks", "DisablePixelPerf", bDisablePixelPerf); iniFile.Save(game_ini); } diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h index c9d2eef217..0531918183 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.h +++ b/Source/Core/VideoCommon/Src/VideoConfig.h @@ -115,7 +115,7 @@ struct VideoConfig int iAnaglyphStereoSeparation; int iAnaglyphFocalAngle; bool b3DVision; - + // Hacks bool bEFBAccessEnable; bool bDlistCachingEnable; @@ -133,7 +133,6 @@ struct VideoConfig bool bZTPSpeedHack; // The Legend of Zelda: Twilight Princess bool bUseBBox; bool bEnablePixelLighting; - bool bDisablePixelPerf; int iLog; // CONF_ bits int iSaveTargetId; // TODO: Should be dropped diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index bf7bf16989..970d4c7085 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -57,6 +57,7 @@ #include "ConfigManager.h" #include "VideoBackend.h" +#include "PerfQueryBase.h" namespace DX9 { @@ -156,12 +157,6 @@ bool VideoBackend::Initialize(void *&window_handle) s_BackendInitialized = true; - if (!g_Config.bDisablePixelPerf) - { - OSD::AddMessage("PE perf metrics enabled although the D3D9 backend doesn't support them!"); - OSD::AddMessage("Try a different backend when issues arise."); - } - return true; } @@ -176,6 +171,7 @@ void VideoBackend::Video_Prepare() g_vertex_manager = new VertexManager; g_renderer = new Renderer; g_texture_cache = new TextureCache; + g_perf_query = new PerfQueryBase; // VideoCommon BPInit(); Fifo_Init(); @@ -213,6 +209,7 @@ void VideoBackend::Shutdown() // internal interfaces PixelShaderCache::Shutdown(); VertexShaderCache::Shutdown(); + delete g_perf_query; delete g_texture_cache; delete g_renderer; delete g_vertex_manager; From d1acb0a937d842abaf55844d63298971e73ecee7 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 1 Mar 2013 23:12:41 +0100 Subject: [PATCH 49/70] OGL: Fix perf metrics being overcounted when using a non-native internal resolution. --- Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp | 1 + Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp index 6ab91fed27..d2a76d7d4b 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp @@ -103,6 +103,7 @@ void PerfQuery::FlushOne() hr = D3D::context->GetData(entry.query, &result, sizeof(result), 0); } + // NOTE: Reported pixel metrics should be referenced to native resolution m_results[entry.query_type] += result * EFB_WIDTH * EFB_HEIGHT / g_renderer->GetTargetWidth() / g_renderer->GetTargetHeight(); m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp index 8cee426e98..42ff918942 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp @@ -1,3 +1,4 @@ +#include "RenderBase.h" #include "GLUtil.h" #include "PerfQuery.h" @@ -61,12 +62,13 @@ bool PerfQuery::IsFlushed() const void PerfQuery::FlushOne() { auto& entry = m_query_buffer[m_query_read_pos]; - + GLuint result = 0; glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT, &result); - - m_results[entry.query_type] += result; - + + // NOTE: Reported pixel metrics should be referenced to native resolution + m_results[entry.query_type] += result * EFB_WIDTH * EFB_HEIGHT / g_renderer->GetTargetWidth() / g_renderer->GetTargetHeight(); + m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); --m_query_count; } From cb1d21c032b92412d5d795705642189657db37e3 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 1 Mar 2013 23:57:56 +0100 Subject: [PATCH 50/70] PerfQueries: Fix an integer overflow. --- Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp | 5 +++-- Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp index d2a76d7d4b..b859d50ec6 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp @@ -104,7 +104,7 @@ void PerfQuery::FlushOne() } // NOTE: Reported pixel metrics should be referenced to native resolution - m_results[entry.query_type] += result * EFB_WIDTH * EFB_HEIGHT / g_renderer->GetTargetWidth() / g_renderer->GetTargetHeight(); + m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); --m_query_count; @@ -128,7 +128,8 @@ void PerfQuery::WeakFlush() if (hr == S_OK) { - m_results[entry.query_type] += result * EFB_WIDTH * EFB_HEIGHT / g_renderer->GetTargetWidth() / g_renderer->GetTargetHeight(); + // NOTE: Reported pixel metrics should be referenced to native resolution + m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); --m_query_count; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp index 42ff918942..95311eb98d 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp @@ -67,7 +67,7 @@ void PerfQuery::FlushOne() glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT, &result); // NOTE: Reported pixel metrics should be referenced to native resolution - m_results[entry.query_type] += result * EFB_WIDTH * EFB_HEIGHT / g_renderer->GetTargetWidth() / g_renderer->GetTargetHeight(); + m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); --m_query_count; From e079d2491282f334f0d87dd16801550efcf8d4d1 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 1 Mar 2013 19:33:17 -0600 Subject: [PATCH 51/70] Kill wstring version of game description. --- Source/Core/DiscIO/Src/BannerLoader.cpp | 126 -------------------- Source/Core/DiscIO/Src/BannerLoader.h | 5 +- Source/Core/DiscIO/Src/BannerLoaderWii.cpp | 120 ++++++++++++++++--- Source/Core/DiscIO/Src/BannerLoaderWii.h | 4 +- Source/Core/DolphinWX/Src/GameListCtrl.cpp | 22 ++-- Source/Core/DolphinWX/Src/ISOFile.cpp | 9 +- Source/Core/DolphinWX/Src/ISOFile.h | 4 +- Source/Core/DolphinWX/Src/ISOProperties.cpp | 6 +- 8 files changed, 120 insertions(+), 176 deletions(-) diff --git a/Source/Core/DiscIO/Src/BannerLoader.cpp b/Source/Core/DiscIO/Src/BannerLoader.cpp index 2350896c9c..2c28401c93 100644 --- a/Source/Core/DiscIO/Src/BannerLoader.cpp +++ b/Source/Core/DiscIO/Src/BannerLoader.cpp @@ -22,25 +22,6 @@ #include "VolumeCreator.h" #include "FileUtil.h" -// HyperIris: dunno if this suitable, may be need move. -#ifdef _WIN32 -#include -#else -#include -#ifndef ANDROID -#include -#endif -#include -#endif - -#ifndef ICONV_CONST -#if defined __FreeBSD__ || __NetBSD__ -#define ICONV_CONST const -#else -#define ICONV_CONST -#endif -#endif - namespace DiscIO { void IBannerLoader::CopyToStringAndCheck(std::string& _rDestination, const char* _src) @@ -96,113 +77,6 @@ void IBannerLoader::CopyToStringAndCheck(std::string& _rDestination, const char* _rDestination = destBuffer; } -bool IBannerLoader::CopyBeUnicodeToString( std::string& _rDestination, const u16* _src, int length ) -{ - bool returnCode = false; -#ifdef WIN32 - if (_src) - { - u16* buffer = new u16[length]; - if (buffer) - { - memcpy(buffer, _src, sizeof(u16)*length); - for (int i = 0; i < length; i++) - { - buffer[i] = swap16(buffer[i]); - } - - u32 ansiNameSize = WideCharToMultiByte(932, 0, - (LPCWSTR)buffer, (int)wcslen((LPCWSTR)buffer), - NULL, NULL, NULL, NULL); - if (ansiNameSize > 0) - { - char* pAnsiStrBuffer = new char[ansiNameSize + 1]; - if (pAnsiStrBuffer) - { - memset(pAnsiStrBuffer, 0, (ansiNameSize + 1) * sizeof(char)); - if (WideCharToMultiByte(932, 0, - (LPCWSTR)buffer, (int)wcslen((LPCWSTR)buffer), - pAnsiStrBuffer, ansiNameSize, NULL, NULL)) - { - _rDestination = pAnsiStrBuffer; - returnCode = true; - } - delete[] pAnsiStrBuffer; - } - } - delete[] buffer; - } - } -#else -#ifdef ANDROID - return false; -#else - if (_src) - { - iconv_t conv_desc = iconv_open("UTF-8", "CP932"); - if (conv_desc == (iconv_t) -1) - { - // Initialization failure. - if (errno == EINVAL) - { - ERROR_LOG(DISCIO, "Conversion from CP932 to UTF-8 is not supported."); - } - else - { - ERROR_LOG(DISCIO, "Iconv initialization failure: %s\n", strerror (errno)); - } - return false; - } - - char* src_buffer = new char[length]; - for (int i = 0; i < length; i++) - src_buffer[i] = swap16(_src[i]); - - size_t inbytes = sizeof(char) * length; - size_t outbytes = 2 * inbytes; - char* utf8_buffer = new char[outbytes + 1]; - memset(utf8_buffer, 0, (outbytes + 1) * sizeof(char)); - - // Save the buffer locations because iconv increments them - char* utf8_buffer_start = utf8_buffer; - char* src_buffer_start = src_buffer; - - size_t iconv_size = iconv(conv_desc, - (ICONV_CONST char**)&src_buffer, &inbytes, - &utf8_buffer, &outbytes); - - // Handle failures - if (iconv_size == (size_t) -1) - { - ERROR_LOG(DISCIO, "iconv failed."); - switch (errno) { - case EILSEQ: - ERROR_LOG(DISCIO, "Invalid multibyte sequence."); - break; - case EINVAL: - ERROR_LOG(DISCIO, "Incomplete multibyte sequence."); - break; - case E2BIG: - ERROR_LOG(DISCIO, "Insufficient space allocated for output buffer."); - break; - default: - ERROR_LOG(DISCIO, "Error: %s.", strerror(errno)); - } - } - else - { - _rDestination = utf8_buffer_start; - returnCode = true; - } - delete[] utf8_buffer_start; - delete[] src_buffer_start; - iconv_close(conv_desc); - } -#endif -#endif - return returnCode; -} - IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume) { if (IsVolumeWiiDisc(pVolume) || IsVolumeWadFile(pVolume)) diff --git a/Source/Core/DiscIO/Src/BannerLoader.h b/Source/Core/DiscIO/Src/BannerLoader.h index 1fe48dd364..ef2e0e64b9 100644 --- a/Source/Core/DiscIO/Src/BannerLoader.h +++ b/Source/Core/DiscIO/Src/BannerLoader.h @@ -43,14 +43,11 @@ class IBannerLoader virtual bool GetCompany(std::string& _rCompany) = 0; virtual bool GetDescription(std::string* _rDescription) = 0; - virtual bool GetDescription(std::wstring& _rDescription) {return false;}; - protected: void CopyToStringAndCheck(std::string& _rDestination, const char* _src); - - bool CopyBeUnicodeToString(std::string& _rDestination, const u16* _src, int length); + private: u16 swap16(u16 data) { diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp index b23dc4d91a..d8d8076721 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include +#include #include "Common.h" #include "ColorUtil.h" @@ -24,6 +25,25 @@ #include "FileUtil.h" #include "FileHandlerARC.h" +// HyperIris: dunno if this suitable, may be need move. +#ifdef _WIN32 +#include +#else +#include +#ifndef ANDROID +#include +#endif +#include +#endif + +#ifndef ICONV_CONST +#if defined __FreeBSD__ || __NetBSD__ +#define ICONV_CONST const +#else +#define ICONV_CONST +#endif +#endif + namespace DiscIO { @@ -152,16 +172,8 @@ bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::stri { // find Banner type SWiiBanner *pBanner = (SWiiBanner*)m_pBannerFile; - - // Ensure the string is null-terminating, since the banner format - // doesn't require it - u16 *src = new u16[COMMENT_SIZE + 1]; - memcpy(src, &pBanner->m_Comment[index], COMMENT_SIZE * sizeof(u16)); - src[COMMENT_SIZE] = 0; - - ret = CopyBeUnicodeToString(s, src, COMMENT_SIZE + 1); - - delete [] src; + // TODO: trim NULLs + ret = CopyBeUnicodeToString(s, pBanner->m_Comment[index], COMMENT_SIZE); } return ret; @@ -208,11 +220,6 @@ bool CBannerLoaderWii::GetDescription(std::string* _rDescription) return GetStringFromComments(DESC_IDX, *_rDescription); } -bool CBannerLoaderWii::GetDescription(std::wstring& _rDescription) -{ - return GetStringFromComments(DESC_IDX, _rDescription); -} - void CBannerLoaderWii::decode5A3image(u32* dst, u16* src, int width, int height) { for (int y = 0; y < height; y += 4) @@ -231,4 +238,87 @@ void CBannerLoaderWii::decode5A3image(u32* dst, u16* src, int width, int height) } } +bool CBannerLoaderWii::CopyBeUnicodeToString( std::string& _rDestination, const u16* _src, int length ) +{ + bool returnCode = false; +#ifdef _WIN32 + if (_src) + { + std::wstring src; + src.resize(length); + std::transform(_src, _src + length, &src[0], (u16(&)(u16))Common::swap16); + + _rDestination = UTF16ToUTF8(src); + returnCode = true; + } +#else +#ifdef ANDROID + return false; +#else + if (_src) + { + iconv_t conv_desc = iconv_open("UTF-8", "CP932"); + if (conv_desc == (iconv_t) -1) + { + // Initialization failure. + if (errno == EINVAL) + { + ERROR_LOG(DISCIO, "Conversion from CP932 to UTF-8 is not supported."); + } + else + { + ERROR_LOG(DISCIO, "Iconv initialization failure: %s\n", strerror (errno)); + } + return false; + } + + char* src_buffer = new char[length]; + for (int i = 0; i < length; i++) + src_buffer[i] = swap16(_src[i]); + + size_t inbytes = sizeof(char) * length; + size_t outbytes = 2 * inbytes; + char* utf8_buffer = new char[outbytes + 1]; + memset(utf8_buffer, 0, (outbytes + 1) * sizeof(char)); + + // Save the buffer locations because iconv increments them + char* utf8_buffer_start = utf8_buffer; + char* src_buffer_start = src_buffer; + + size_t iconv_size = iconv(conv_desc, + (ICONV_CONST char**)&src_buffer, &inbytes, + &utf8_buffer, &outbytes); + + // Handle failures + if (iconv_size == (size_t) -1) + { + ERROR_LOG(DISCIO, "iconv failed."); + switch (errno) { + case EILSEQ: + ERROR_LOG(DISCIO, "Invalid multibyte sequence."); + break; + case EINVAL: + ERROR_LOG(DISCIO, "Incomplete multibyte sequence."); + break; + case E2BIG: + ERROR_LOG(DISCIO, "Insufficient space allocated for output buffer."); + break; + default: + ERROR_LOG(DISCIO, "Error: %s.", strerror(errno)); + } + } + else + { + _rDestination = utf8_buffer_start; + returnCode = true; + } + delete[] utf8_buffer_start; + delete[] src_buffer_start; + iconv_close(conv_desc); + } +#endif +#endif + return returnCode; +} + } // namespace diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.h b/Source/Core/DiscIO/Src/BannerLoaderWii.h index 83733cf5ed..d7150d7009 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.h +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.h @@ -43,8 +43,6 @@ class CBannerLoaderWii virtual bool GetDescription(std::string* _rDescription); - bool GetDescription(std::wstring& _rDescription); - private: enum @@ -82,6 +80,8 @@ class CBannerLoaderWii bool GetStringFromComments(const CommentIndex index, std::string& s); bool GetStringFromComments(const CommentIndex index, std::wstring& s); + + bool CopyBeUnicodeToString(std::string& _rDestination, const u16* _src, int length); }; } // namespace diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index cab4c8125b..c24f0509ba 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -456,16 +456,9 @@ void CGameListCtrl::InsertItemInReportView(long _Index) SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex); std::wstring wstring_name; - const std::wstring& wstring_description = rISOFile.GetDescription(); - std::string company; wxString name; - wxString description; - // We show the company string on Gamecube only - // On Wii we show the description instead as the company string is empty - if (rISOFile.GetPlatform() == GameListItem::GAMECUBE_DISC) - company = rISOFile.GetCompany().c_str(); int SelectedLanguage = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage; switch (rISOFile.GetCountry()) { @@ -475,11 +468,10 @@ void CGameListCtrl::InsertItemInReportView(long _Index) rISOFile.GetName(wstring_name, -1); name = wxString(rISOFile.GetName(0).c_str(), SJISConv); m_gameList.append(StringFromFormat("%s (J)\n", (const char *)name.c_str())); - description = wxString(company.size() ? company.c_str() : - rISOFile.GetDescription(0).c_str(), SJISConv); } break; case DiscIO::IVolume::COUNTRY_USA: + // Is this sane? SelectedLanguage = 0; default: { @@ -490,19 +482,21 @@ void CGameListCtrl::InsertItemInReportView(long _Index) m_gameList.append(StringFromFormat("%s (%c)\n", rISOFile.GetName(SelectedLanguage).c_str(), (rISOFile.GetCountry() == DiscIO::IVolume::COUNTRY_USA) ? 'U' : 'E')); - description = wxString(company.size() ? company.c_str() : - rISOFile.GetDescription(SelectedLanguage).c_str(), WindowsCP1252); + } break; } if (wstring_name.length()) name = wstring_name.c_str(); - if (wstring_description.length()) - description = wstring_description.c_str(); SetItem(_Index, COLUMN_TITLE, name, -1); - SetItem(_Index, COLUMN_NOTES, description, -1); + + // We show the company string on Gamecube only + // On Wii we show the description instead as the company string is empty + std::string const notes = (rISOFile.GetPlatform() == GameListItem::GAMECUBE_DISC) ? + rISOFile.GetCompany() : rISOFile.GetDescription(SelectedLanguage); + SetItem(_Index, COLUMN_NOTES, StrToWxStr(notes), -1); // Emulation state SetItemColumnImage(_Index, COLUMN_EMULATION_STATE, m_EmuStateImageIndex[rISOFile.GetEmuState()]); diff --git a/Source/Core/DolphinWX/Src/ISOFile.cpp b/Source/Core/DolphinWX/Src/ISOFile.cpp index 639190fa0e..918a72b0bf 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.cpp +++ b/Source/Core/DolphinWX/Src/ISOFile.cpp @@ -37,7 +37,7 @@ #include "ChunkFile.h" #include "ConfigManager.h" -#define CACHE_REVISION 0x10F +#define CACHE_REVISION 0x110 #define DVD_BANNER_WIDTH 96 #define DVD_BANNER_HEIGHT 32 @@ -109,7 +109,6 @@ GameListItem::GameListItem(const std::string& _rFileName) pBannerLoader->GetName(m_wNames); pBannerLoader->GetName(m_Name); pBannerLoader->GetCompany(m_Company); - pBannerLoader->GetDescription(m_wDescription); pBannerLoader->GetDescription(m_Description); if (pBannerLoader->GetBanner(g_ImageTemp)) @@ -235,7 +234,6 @@ void GameListItem::DoState(PointerWrap &p) p.Do(m_Company); p.Do(m_Description[0]); p.Do(m_Description[1]); p.Do(m_Description[2]); p.Do(m_Description[3]); p.Do(m_Description[4]); p.Do(m_Description[5]); - p.Do(m_wDescription); p.Do(m_UniqueID); p.Do(m_FileSize); p.Do(m_VolumeSize); @@ -273,11 +271,6 @@ const std::string& GameListItem::GetDescription(int index) const return m_Description[0]; } -const std::wstring& GameListItem::GetDescription() const -{ - return m_wDescription; -} - const std::string& GameListItem::GetName(int index) const { if ((index >=0) && (index < 6)) diff --git a/Source/Core/DolphinWX/Src/ISOFile.h b/Source/Core/DolphinWX/Src/ISOFile.h index e58dcf7713..1f3ecaa261 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.h +++ b/Source/Core/DolphinWX/Src/ISOFile.h @@ -37,8 +37,7 @@ public: const std::string& GetName(int index) const; bool GetName(std::wstring& wName, int index=0) const; const std::string& GetCompany() const {return m_Company;} - const std::string& GetDescription(int index) const; - const std::wstring& GetDescription() const; + const std::string& GetDescription(int index = 0) const; const std::string& GetUniqueID() const {return m_UniqueID;} const std::string GetWiiFSPath() const; DiscIO::IVolume::ECountry GetCountry() const {return m_Country;} @@ -69,7 +68,6 @@ private: std::vector m_wNames; std::string m_Company; std::string m_Description[6]; - std::wstring m_wDescription; std::string m_UniqueID; std::string m_issues; diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index a194345585..21d451a1ac 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -1339,8 +1339,7 @@ void CISOProperties::ChangeBannerDetails(int lang) else shortName = wxString(OpenGameListItem->GetName(0).c_str(), SJISConv); - if ((comment = OpenGameListItem->GetDescription().c_str()).size() == 0) - comment = wxString(OpenGameListItem->GetDescription(0).c_str(), SJISConv); + comment = StrToWxStr(OpenGameListItem->GetDescription()); maker = wxString(OpenGameListItem->GetCompany().c_str(), SJISConv); break; case DiscIO::IVolume::COUNTRY_USA: @@ -1352,8 +1351,7 @@ void CISOProperties::ChangeBannerDetails(int lang) shortName = wname.c_str(); else shortName = wxString(OpenGameListItem->GetName(lang).c_str(), WindowsCP1252); - if ((comment = OpenGameListItem->GetDescription().c_str()).size() == 0) - comment = wxString(OpenGameListItem->GetDescription(lang).c_str(), WindowsCP1252); + comment = StrToWxStr(OpenGameListItem->GetDescription(lang)); maker = wxString(OpenGameListItem->GetCompany().c_str(), WindowsCP1252); } break; From 2356e5c0e7dab9c0f541e48f8df5fd663d3b671f Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 2 Mar 2013 03:28:44 -0600 Subject: [PATCH 52/70] Eliminate some baseless restrictions in PointerWrap, mainly vector not working. --- Source/Core/Common/Src/ChunkFile.h | 230 +++++++++++++------------- Source/Core/Core/Src/HW/Wiimote.cpp | 2 +- Source/Core/Core/Src/HW/Wiimote.h | 3 +- Source/Core/Core/Src/State.cpp | 2 +- Source/Core/DolphinWX/Src/ISOFile.cpp | 2 +- 5 files changed, 123 insertions(+), 116 deletions(-) diff --git a/Source/Core/Common/Src/ChunkFile.h b/Source/Core/Common/Src/ChunkFile.h index 38e1b2176c..3c0a58f678 100644 --- a/Source/Core/Common/Src/ChunkFile.h +++ b/Source/Core/Common/Src/ChunkFile.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -45,7 +46,8 @@ struct LinkedListItem : public T class PointerWrap { public: - enum Mode { + enum Mode + { MODE_READ = 1, // load MODE_WRITE, // save MODE_MEASURE, // calculate size @@ -57,124 +59,95 @@ public: public: PointerWrap(u8 **ptr_, Mode mode_) : ptr(ptr_), mode(mode_) {} - PointerWrap(unsigned char **ptr_, int mode_) : ptr((u8**)ptr_), mode((Mode)mode_) {} - void SetMode(Mode mode_) {mode = mode_;} - Mode GetMode() const {return mode;} - u8 **GetPPtr() {return ptr;} + void SetMode(Mode mode_) { mode = mode_; } + Mode GetMode() const { return mode; } + u8** GetPPtr() { return ptr; } - void DoVoid(void *data, int size) + template + void Do(std::map& x) { - switch (mode) { - case MODE_READ: memcpy(data, *ptr, size); break; - case MODE_WRITE: memcpy(*ptr, data, size); break; - case MODE_MEASURE: break; // MODE_MEASURE - don't need to do anything - case MODE_VERIFY: for(int i = 0; i < size; i++) _dbg_assert_msg_(COMMON, ((u8*)data)[i] == (*ptr)[i], "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n", ((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i], &(*ptr)[i]); break; - default: break; // throw an error? - } - (*ptr) += size; - } - - template - void Do(std::map &x) - { - unsigned int number = (unsigned int)x.size(); - Do(number); - switch (mode) { + u32 count = (u32)x.size(); + Do(count); + + switch (mode) + { case MODE_READ: + for (x.clear(); count != 0; --count) { - x.clear(); - while (number > 0) - { - unsigned int first = 0; - Do(first); - T second; - Do(second); - x[first] = second; - --number; - } + std::pair pair; + Do(pair.first); + Do(pair.second); + x.insert(pair); } break; + case MODE_WRITE: case MODE_MEASURE: case MODE_VERIFY: + for (auto itr = x.begin(); itr != x.end(); ++itr) { - typename std::map::iterator itr = x.begin(); - while (number > 0) - { - Do(itr->first); - Do(itr->second); - --number; - ++itr; - } + Do(itr->first); + Do(itr->second); } break; } } - - // Store vectors. - template - void Do(std::vector &x) - { - u32 vec_size = (u32)x.size(); - Do(vec_size); - x.resize(vec_size); - DoArray(&x[0], vec_size); - } - // Store deques. - template - void Do(std::deque &x) + template + void DoContainer(T& x) { - u32 deq_size = (u32)x.size(); - Do(deq_size); - x.resize(deq_size); - u32 i; - for(i = 0; i < deq_size; i++) - DoVoid(&x[i],sizeof(T)); - } - - // Store strings. - void Do(std::string &x) - { - int stringLen = (int)x.length() + 1; - Do(stringLen); + u32 size = (u32)x.size(); + Do(size); + x.resize(size); - switch (mode) { - case MODE_READ: x = (char*)*ptr; break; - case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break; - case MODE_MEASURE: break; - case MODE_VERIFY: _dbg_assert_msg_(COMMON, !strcmp(x.c_str(), (char*)*ptr), "Savestate verification failure: \"%s\" != \"%s\" (at %p).\n", x.c_str(), (char*)*ptr, ptr); break; - } - (*ptr) += stringLen; + for (auto itr = x.begin(); itr != x.end(); ++itr) + Do(*itr); } - void Do(std::wstring &x) + template + void Do(std::vector& x) { - int stringLen = sizeof(wchar_t)*((int)x.length() + 1); - Do(stringLen); - - switch (mode) { - case MODE_READ: x.assign((wchar_t*)*ptr, (stringLen / sizeof(wchar_t)) - 1); break; - case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break; - case MODE_MEASURE: break; - case MODE_VERIFY: _dbg_assert_msg_(COMMON, x == (wchar_t*)*ptr, "Savestate verification failure: \"%ls\" != \"%ls\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); break; - } - (*ptr) += stringLen; + DoContainer(x); + } + + template + void Do(std::list& x) + { + DoContainer(x); + } + + template + void Do(std::deque& x) + { + DoContainer(x); + } + + template + void Do(std::basic_string& x) + { + DoContainer(x); } - template - void DoArray(T *x, int count) { - DoVoid((void *)x, sizeof(T) * count); + template + void DoArray(T* x, u32 count) + { + for (u32 i = 0; i != count; ++i) + Do(x[i]); } - template - void Do(T &x) { - DoVoid((void *)&x, sizeof(x)); + template + void Do(T& x) + { + // TODO: Bad, Do(some_non_POD) will compile and fail at runtime + // type_traits are not fully supported everywhere yet + + DoVoid((void*)&x, sizeof(x)); } - template - void DoPointer(T* &x, T*const base) { + template + void DoPointer(T*& x, T* const base) + { // pointers can be more than 2^31 apart, but you're using this function wrong if you need that much range s32 offset = x - base; Do(offset); @@ -182,7 +155,8 @@ public: x = base + offset; } - template* (*TNew)(), void (*TFree)(LinkedListItem*), void (*TDo)(PointerWrap&, T*)> + // Let's pretend std::list doesn't exist! + template * (*TNew)(), void (*TFree)(LinkedListItem*), void (*TDo)(PointerWrap&, T*)> void DoLinkedList(LinkedListItem*& list_start, LinkedListItem** list_end=0) { LinkedListItem* list_cur = list_start; @@ -242,25 +216,61 @@ public: } } - void DoMarker(const char* prevName, u32 arbitraryNumber=0x42) + void DoMarker(const char* prevName, u32 arbitraryNumber = 0x42) { u32 cookie = arbitraryNumber; Do(cookie); - if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber) + + if (mode == PointerWrap::MODE_READ && cookie != arbitraryNumber) { - PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber); + PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", + prevName, cookie, cookie, arbitraryNumber, arbitraryNumber); mode = PointerWrap::MODE_MEASURE; } } + +private: + __forceinline void DoByte(u8& x) + { + switch (mode) + { + case MODE_READ: + x = **ptr; + break; + + case MODE_WRITE: + **ptr = x; + break; + + case MODE_MEASURE: + break; + + case MODE_VERIFY: + _dbg_assert_msg_(COMMON, (x == *ptr), + "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n", + x, x, &x, *ptr, *ptr, &*ptr); + break; + + default: + break; + } + + ++(*ptr); + } + + void DoVoid(void *data, u32 size) + { + for(u32 i = 0; i != size; ++i) + DoByte(reinterpret_cast(data)[i]); + } }; - class CChunkFileReader { public: // Load file template template - static bool Load(const std::string& _rFilename, int _Revision, T& _class) + static bool Load(const std::string& _rFilename, u32 _Revision, T& _class) { INFO_LOG(COMMON, "ChunkReader: Loading %s" , _rFilename.c_str()); @@ -300,7 +310,7 @@ public: } // get size - const int sz = (int)(fileSize - headerSize); + const u32 sz = (u32)(fileSize - headerSize); if (header.ExpectedSize != sz) { ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d", @@ -309,17 +319,16 @@ public: } // read the state - u8* buffer = new u8[sz]; - if (!pFile.ReadBytes(buffer, sz)) + std::vector buffer(sz); + if (!pFile.ReadArray(&buffer[0], sz)) { ERROR_LOG(COMMON,"ChunkReader: Error reading file"); return false; } - u8 *ptr = buffer; + u8* ptr = &buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_READ); _class.DoState(p); - delete[] buffer; INFO_LOG(COMMON, "ChunkReader: Done loading %s" , _rFilename.c_str()); return true; @@ -327,7 +336,7 @@ public: // Save file template template - static bool Save(const std::string& _rFilename, int _Revision, T& _class) + static bool Save(const std::string& _rFilename, u32 _Revision, T& _class) { INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str()); File::IOFile pFile(_rFilename, "wb"); @@ -349,9 +358,8 @@ public: // Create header SChunkHeader header; - header.Compress = 0; header.Revision = _Revision; - header.ExpectedSize = (int)sz; + header.ExpectedSize = (u32)sz; // Write to file if (!pFile.WriteArray(&header, 1)) @@ -360,23 +368,21 @@ public: return false; } - if (!pFile.WriteBytes(&buffer[0], sz)) + if (!pFile.WriteArray(&buffer[0], sz)) { ERROR_LOG(COMMON,"ChunkReader: Failed writing data"); return false; } - INFO_LOG(COMMON,"ChunkReader: Done writing %s", - _rFilename.c_str()); + INFO_LOG(COMMON,"ChunkReader: Done writing %s", _rFilename.c_str()); return true; } private: struct SChunkHeader { - int Revision; - int Compress; - int ExpectedSize; + u32 Revision; + u32 ExpectedSize; }; }; diff --git a/Source/Core/Core/Src/HW/Wiimote.cpp b/Source/Core/Core/Src/HW/Wiimote.cpp index 59fe8b7fa5..e45856f5f5 100644 --- a/Source/Core/Core/Src/HW/Wiimote.cpp +++ b/Source/Core/Core/Src/HW/Wiimote.cpp @@ -133,7 +133,7 @@ unsigned int GetAttached() // input/output: ptr // input: mode // -void DoState(unsigned char **ptr, int mode) +void DoState(u8 **ptr, PointerWrap::Mode mode) { // TODO: diff --git a/Source/Core/Core/Src/HW/Wiimote.h b/Source/Core/Core/Src/HW/Wiimote.h index dd0e6df389..6b758abb5a 100644 --- a/Source/Core/Core/Src/HW/Wiimote.h +++ b/Source/Core/Core/Src/HW/Wiimote.h @@ -3,6 +3,7 @@ #define _WIIMOTE_H_ #include "../../InputCommon/Src/InputConfig.h" +#include "ChunkFile.h" #define MAX_WIIMOTES 4 @@ -25,7 +26,7 @@ void Shutdown(); void Initialize(void* const hwnd); unsigned int GetAttached(); -void DoState(unsigned char **ptr, int mode); +void DoState(u8 **ptr, PointerWrap::Mode mode); void EmuStateChange(EMUSTATE_CHANGE newState); InputPlugin *GetPlugin(); diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index 773d757337..e0a9ab7858 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 15; +static const u32 STATE_VERSION = 16; struct StateHeader { diff --git a/Source/Core/DolphinWX/Src/ISOFile.cpp b/Source/Core/DolphinWX/Src/ISOFile.cpp index 833268ad63..496a6304d4 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.cpp +++ b/Source/Core/DolphinWX/Src/ISOFile.cpp @@ -36,7 +36,7 @@ #include "ChunkFile.h" #include "ConfigManager.h" -#define CACHE_REVISION 0x10F +#define CACHE_REVISION 0x110 #define DVD_BANNER_WIDTH 96 #define DVD_BANNER_HEIGHT 32 From 6c8adf6130b32a0ffc113f4ce30f70b9d5994f10 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 2 Mar 2013 19:46:55 -0600 Subject: [PATCH 53/70] Eliminate the wstring game name. Some cleanup throughout related code. (try to make logic in ISOFile understandable by a human) Encode strings in UTF-8 rather than somehow trying to determine the encoding in the GUI code. Non-windows OSes temporarily broken. --- Source/Core/Common/Src/StringUtil.cpp | 30 +++- Source/Core/Common/Src/StringUtil.h | 4 +- Source/Core/DiscIO/Src/BannerLoader.cpp | 52 ------- Source/Core/DiscIO/Src/BannerLoader.h | 15 +- Source/Core/DiscIO/Src/BannerLoaderGC.cpp | 138 ++++++++----------- Source/Core/DiscIO/Src/BannerLoaderGC.h | 30 ++-- Source/Core/DiscIO/Src/BannerLoaderWii.cpp | 25 ++-- Source/Core/DiscIO/Src/BannerLoaderWii.h | 10 +- Source/Core/DiscIO/Src/Volume.h | 4 +- Source/Core/DiscIO/Src/VolumeCommon.cpp | 10 +- Source/Core/DiscIO/Src/VolumeDirectory.cpp | 5 +- Source/Core/DiscIO/Src/VolumeDirectory.h | 2 +- Source/Core/DiscIO/Src/VolumeGC.cpp | 13 +- Source/Core/DiscIO/Src/VolumeGC.h | 2 +- Source/Core/DiscIO/Src/VolumeWad.cpp | 48 ++----- Source/Core/DiscIO/Src/VolumeWad.h | 3 +- Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp | 18 +-- Source/Core/DiscIO/Src/VolumeWiiCrypted.h | 2 +- Source/Core/DolphinWX/Src/GameListCtrl.cpp | 26 ++-- Source/Core/DolphinWX/Src/ISOFile.cpp | 144 +++++++------------- Source/Core/DolphinWX/Src/ISOFile.h | 23 ++-- Source/Core/DolphinWX/Src/ISOProperties.cpp | 50 ++----- 22 files changed, 243 insertions(+), 411 deletions(-) diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index 38ac107ec1..aab0f3bd58 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -395,17 +395,41 @@ std::string UTF16ToUTF8(const std::wstring& input) return output; } -std::wstring UTF8ToUTF16(const std::string& input) +std::wstring CPToUTF16(u32 code_page, const std::string& input) { - auto const size = MultiByteToWideChar(CP_UTF8, 0, input.data(), input.size(), nullptr, 0); + auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0); std::wstring output; output.resize(size); - if (size != MultiByteToWideChar(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size())) + if (size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size())) output.clear(); return output; } +std::wstring UTF8ToUTF16(const std::string& input) +{ + return CPToUTF16(CP_UTF8, input); +} + +std::string SHIFTJISToUTF8(const std::string& input) +{ + return UTF16ToUTF8(CPToUTF16(932, input)); +} + +#else + +std::string UTF16ToUTF8(const std::wstring& input) +{ + // TODO: implement + return std::string(); +} + +std::string SHIFTJISToUTF8(const std::string& input) +{ + // TODO: implement + return std::string(); +} + #endif diff --git a/Source/Core/Common/Src/StringUtil.h b/Source/Core/Common/Src/StringUtil.h index 5177bc8ed8..ce5751f80b 100644 --- a/Source/Core/Common/Src/StringUtil.h +++ b/Source/Core/Common/Src/StringUtil.h @@ -97,9 +97,11 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st std::string UriDecode(const std::string & sSrc); std::string UriEncode(const std::string & sSrc); +std::string SHIFTJISToUTF8(const std::string& str); +std::string UTF16ToUTF8(const std::wstring& str); + #ifdef _WIN32 -std::string UTF16ToUTF8(const std::wstring& str); std::wstring UTF8ToUTF16(const std::string& str); #ifdef _UNICODE diff --git a/Source/Core/DiscIO/Src/BannerLoader.cpp b/Source/Core/DiscIO/Src/BannerLoader.cpp index 2c28401c93..7e641aa85b 100644 --- a/Source/Core/DiscIO/Src/BannerLoader.cpp +++ b/Source/Core/DiscIO/Src/BannerLoader.cpp @@ -24,58 +24,6 @@ namespace DiscIO { -void IBannerLoader::CopyToStringAndCheck(std::string& _rDestination, const char* _src) -{ - static bool bValidChars[256]; - static bool bInitialized = false; - - if (!bInitialized) - { - for (int i = 0; i < 0x20; i++) - { - bValidChars[i] = false; - } - - // generate valid chars - for (int i = 0x20; i < 256; i++) - { - bValidChars[i] = true; - } - - bValidChars[0x0a] = true; - //bValidChars[0xa9] = true; - //bValidChars[0xe9] = true; - - bInitialized = true; - } - - char destBuffer[2048] = {0}; - char* dest = destBuffer; - const char* src = _src; - - // copy the string and check for "unknown" characters - while (*src != 0x00) - { - u8 c = *src; - - if (c == 0x0a){c = 0x20;} - - if (bValidChars[c] == false) - { - src++; - continue; - } - - *dest = c; - dest++; - src++; - } - - // finalize the string - *dest = 0x00; - - _rDestination = destBuffer; -} IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume) { diff --git a/Source/Core/DiscIO/Src/BannerLoader.h b/Source/Core/DiscIO/Src/BannerLoader.h index ef2e0e64b9..92bb874979 100644 --- a/Source/Core/DiscIO/Src/BannerLoader.h +++ b/Source/Core/DiscIO/Src/BannerLoader.h @@ -18,6 +18,9 @@ #ifndef _BANNER_LOADER_H_ #define _BANNER_LOADER_H_ +#include +#include + #include "Filesystem.h" namespace DiscIO @@ -38,15 +41,9 @@ class IBannerLoader virtual bool GetBanner(u32* _pBannerImage) = 0; - virtual bool GetName(std::string* _rName) = 0; - virtual bool GetName(std::vector& _rNames) {return false;}; - virtual bool GetCompany(std::string& _rCompany) = 0; - - virtual bool GetDescription(std::string* _rDescription) = 0; - - protected: - - void CopyToStringAndCheck(std::string& _rDestination, const char* _src); + virtual std::vector GetNames() = 0; + virtual std::string GetCompany() = 0; + virtual std::vector GetDescriptions() = 0; private: u16 swap16(u16 data) diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp index bf9f634ff8..bf087cbfb6 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp @@ -29,7 +29,7 @@ CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem) { // load the opening.bnr size_t FileSize = (size_t) _rFileSystem.GetFileSize("opening.bnr"); - if (FileSize == sizeof(DVDBanner) || FileSize == sizeof(DVDBanner2)) + if (FileSize == BNR1_SIZE || FileSize == BNR2_SIZE) { m_pBannerFile = new u8[FileSize]; if (m_pBannerFile) @@ -62,7 +62,6 @@ bool CBannerLoaderGC::IsValid() return m_IsValid; } - bool CBannerLoaderGC::GetBanner(u32* _pBannerImage) { if (!IsValid()) @@ -70,132 +69,111 @@ bool CBannerLoaderGC::GetBanner(u32* _pBannerImage) return false; } - DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; + auto const pBanner = (DVDBanner*)m_pBannerFile; decode5A3image(_pBannerImage, pBanner->image, DVD_BANNER_WIDTH, DVD_BANNER_HEIGHT); return true; } -bool CBannerLoaderGC::GetName(std::string _rName[]) +std::vector CBannerLoaderGC::GetNames() { - bool returnCode = false; + std::vector names; if (!IsValid()) { - return false; + return names; } + u32 name_count = 0; + // find Banner type switch (m_BNRType) { case CBannerLoaderGC::BANNER_BNR1: - { - DVDBanner* pBanner = (DVDBanner*)m_pBannerFile; - char tempBuffer[65] = {0}; - if (pBanner->comment.longTitle[0]) - { - memcpy(tempBuffer, pBanner->comment.longTitle, 64); - } - else - { - memcpy(tempBuffer, pBanner->comment.shortTitle, 32); - } - for (int i = 0; i < 6; i++) - { - CopyToStringAndCheck(_rName[i], tempBuffer); - } - returnCode = true; - } + name_count = 1; break; + case CBannerLoaderGC::BANNER_BNR2: - { - DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; - - for (int i = 0; i < 6; i++) - { - char tempBuffer[65] = {0}; - if (pBanner->comment[i].longTitle[0]) - { - memcpy(tempBuffer, pBanner->comment[i].longTitle, 64); - } - else - { - memcpy(tempBuffer, pBanner->comment[i].shortTitle, 32); - } - CopyToStringAndCheck(_rName[i], tempBuffer); - } - - returnCode = true; - - } + name_count = 6; break; + default: break; } + + auto const banner = reinterpret_cast(m_pBannerFile); + + for (int i = 0; i != name_count; ++i) + { + auto& comment = banner->comment[i]; + + if (comment.longTitle[0]) + { + auto& data = comment.longTitle; + names.push_back(GetDecodedString(data)); + } + else + { + auto& data = comment.shortTitle; + names.push_back(GetDecodedString(data)); + } + } - return returnCode; + return names; } -bool CBannerLoaderGC::GetCompany(std::string& _rCompany) +std::string CBannerLoaderGC::GetCompany() { - _rCompany = "N/A"; + std::string company; - if (!IsValid()) + if (IsValid()) { - return(false); + auto const pBanner = (DVDBanner*)m_pBannerFile; + auto& data = pBanner->comment[0].shortMaker; + company = GetDecodedString(data); } - DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; - - CopyToStringAndCheck(_rCompany, pBanner->comment[0].shortMaker); - - return true; + return company; } -bool CBannerLoaderGC::GetDescription(std::string* _rDescription) +std::vector CBannerLoaderGC::GetDescriptions() { - bool returnCode = false; + std::vector descriptions; if (!IsValid()) { - return false; + return descriptions; } + u32 desc_count = 0; + // find Banner type switch (m_BNRType) { case CBannerLoaderGC::BANNER_BNR1: - { - DVDBanner* pBanner = (DVDBanner*)m_pBannerFile; - char tempBuffer[129] = {0}; - memcpy(tempBuffer, pBanner->comment.comment, 128); - for (int i = 0; i < 6; i++) - { - CopyToStringAndCheck(_rDescription[i], tempBuffer); - } - returnCode = true; - } + desc_count = 1; break; - case CBannerLoaderGC::BANNER_BNR2: - { - DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; - for (int i = 0; i< 6; i++) - { - char tempBuffer[129] = {0}; - memcpy(tempBuffer, pBanner->comment[i].comment, 128); - CopyToStringAndCheck(_rDescription[i], tempBuffer); - } - returnCode = true; - } + case CBannerLoaderGC::BANNER_BNR2: + desc_count = 6; break; + default: break; } - return returnCode; + + auto banner = reinterpret_cast(m_pBannerFile); + + for (int i = 0; i != desc_count; ++i) + { + auto& data = banner->comment[i].comment; + descriptions.push_back(GetDecodedString(data)); + } + + return descriptions; } @@ -223,13 +201,17 @@ CBannerLoaderGC::BANNER_TYPE CBannerLoaderGC::getBannerType() CBannerLoaderGC::BANNER_TYPE type = CBannerLoaderGC::BANNER_UNKNOWN; switch (bannerSignature) { + // "BNR1" case 0x31524e42: type = CBannerLoaderGC::BANNER_BNR1; break; + + // "BNR2" case 0x32524e42: type = CBannerLoaderGC::BANNER_BNR2; break; } return type; } + } // namespace diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.h b/Source/Core/DiscIO/Src/BannerLoaderGC.h index 0527c721c1..b4903561e4 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderGC.h +++ b/Source/Core/DiscIO/Src/BannerLoaderGC.h @@ -32,9 +32,10 @@ class CBannerLoaderGC virtual bool IsValid(); virtual bool GetBanner(u32* _pBannerImage); - virtual bool GetName(std::string* _rName); - virtual bool GetCompany(std::string& _rCompany); - virtual bool GetDescription(std::string* _rDescription); + + virtual std::vector GetNames(); + virtual std::string GetCompany(); + virtual std::vector GetDescriptions(); private: enum @@ -60,24 +61,25 @@ class CBannerLoaderGC char comment[128]; // Game description shown in IPL game start screen in two lines. }; - // "opening.bnr" file format for JP/US console - struct DVDBanner - { - u32 id; // 'BNR1' - u32 padding[7]; - u16 image[DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT]; // RGB5A3 96x32 texture image - DVDBannerComment comment; - }; - // "opening.bnr" file format for EU console - struct DVDBanner2 + struct DVDBanner { u32 id; // 'BNR2' u32 padding[7]; u16 image[DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT]; // RGB5A3 96x32 texture image - DVDBannerComment comment[6]; // Comments in six languages + DVDBannerComment comment[6]; // Comments in six languages (only 1 for BNR1 type) }; + static const u32 BNR1_SIZE = sizeof(DVDBanner) - sizeof(DVDBannerComment) * 5; + static const u32 BNR2_SIZE = sizeof(DVDBanner); + + template + std::string GetDecodedString(const char (&data)[N]) + { + // Can I always assume SHIFT-JIS? + return SHIFTJISToUTF8(std::string(data, strnlen(data, sizeof(data)))); + } + u8* m_pBannerFile; bool m_IsValid; BANNER_TYPE m_BNRType; diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp index d8d8076721..b94e299f04 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp @@ -196,28 +196,27 @@ bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::wstr return false; } -bool CBannerLoaderWii::GetName(std::string* _rName) +std::vector CBannerLoaderWii::GetNames() { - return GetStringFromComments(NAME_IDX, *_rName); -} + std::vector ret(1); + + if (!GetStringFromComments(NAME_IDX, ret[0])) + ret.clear(); -bool CBannerLoaderWii::GetName(std::vector& _rNames) -{ - std::wstring temp; - bool ret = GetStringFromComments(NAME_IDX, temp); - _rNames.push_back(temp); return ret; } -bool CBannerLoaderWii::GetCompany(std::string& _rCompany) +std::string CBannerLoaderWii::GetCompany() { - _rCompany = "N/A"; - return true; + return ""; } -bool CBannerLoaderWii::GetDescription(std::string* _rDescription) +std::vector CBannerLoaderWii::GetDescriptions() { - return GetStringFromComments(DESC_IDX, *_rDescription); + std::vector result(1); + if (!GetStringFromComments(DESC_IDX, result[0])) + result.clear(); + return result; } void CBannerLoaderWii::decode5A3image(u32* dst, u16* src, int width, int height) diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.h b/Source/Core/DiscIO/Src/BannerLoaderWii.h index d7150d7009..60d317155b 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.h +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.h @@ -35,13 +35,9 @@ class CBannerLoaderWii virtual bool GetBanner(u32* _pBannerImage); - virtual bool GetName(std::string* _rName); - - bool GetName(std::vector& _rNames); - - virtual bool GetCompany(std::string& _rCompany); - - virtual bool GetDescription(std::string* _rDescription); + virtual std::vector GetNames(); + virtual std::string GetCompany(); + virtual std::vector GetDescriptions(); private: diff --git a/Source/Core/DiscIO/Src/Volume.h b/Source/Core/DiscIO/Src/Volume.h index 557c71c31f..4743cfce89 100644 --- a/Source/Core/DiscIO/Src/Volume.h +++ b/Source/Core/DiscIO/Src/Volume.h @@ -37,8 +37,8 @@ public: virtual void GetTMD(u8*, u32 *_sz) const { *_sz=0; } virtual std::string GetUniqueID() const = 0; virtual std::string GetMakerID() const = 0; - virtual std::string GetName() const = 0; - virtual bool GetWName(std::vector& _rwNames) const { return false; } + virtual std::string GetName() const; + virtual std::vector GetNames() const = 0; virtual u32 GetFSTSize() const = 0; virtual std::string GetApploaderDate() const = 0; virtual bool SupportsIntegrityCheck() const { return false; } diff --git a/Source/Core/DiscIO/Src/VolumeCommon.cpp b/Source/Core/DiscIO/Src/VolumeCommon.cpp index 415af2725a..4ab433680d 100644 --- a/Source/Core/DiscIO/Src/VolumeCommon.cpp +++ b/Source/Core/DiscIO/Src/VolumeCommon.cpp @@ -111,5 +111,13 @@ u8 GetSysMenuRegion(u16 _TitleVersion) } } -}; +std::string IVolume::GetName() const +{ + auto names = GetNames(); + if (names.empty()) + return ""; + else + return names[0]; +} +} diff --git a/Source/Core/DiscIO/Src/VolumeDirectory.cpp b/Source/Core/DiscIO/Src/VolumeDirectory.cpp index dc76e2e641..be7cdeb565 100644 --- a/Source/Core/DiscIO/Src/VolumeDirectory.cpp +++ b/Source/Core/DiscIO/Src/VolumeDirectory.cpp @@ -207,11 +207,10 @@ std::string CVolumeDirectory::GetMakerID() const return "VOID"; } -std::string CVolumeDirectory::GetName() const +std::vector CVolumeDirectory::GetNames() const { _dbg_assert_(DVDINTERFACE, m_diskHeader); - std::string name = (char*)(m_diskHeader + 0x20); - return name; + return std::vector(1, (char*)(m_diskHeader + 0x20)); } void CVolumeDirectory::SetName(std::string _Name) diff --git a/Source/Core/DiscIO/Src/VolumeDirectory.h b/Source/Core/DiscIO/Src/VolumeDirectory.h index 0547be3b8a..880a6eebc1 100644 --- a/Source/Core/DiscIO/Src/VolumeDirectory.h +++ b/Source/Core/DiscIO/Src/VolumeDirectory.h @@ -50,7 +50,7 @@ public: std::string GetMakerID() const; - std::string GetName() const; + std::vector GetNames() const; void SetName(std::string); u32 GetFSTSize() const; diff --git a/Source/Core/DiscIO/Src/VolumeGC.cpp b/Source/Core/DiscIO/Src/VolumeGC.cpp index 09e2c5eaa9..6e9579571a 100644 --- a/Source/Core/DiscIO/Src/VolumeGC.cpp +++ b/Source/Core/DiscIO/Src/VolumeGC.cpp @@ -91,16 +91,15 @@ std::string CVolumeGC::GetMakerID() const return makerID; } -std::string CVolumeGC::GetName() const +std::vector CVolumeGC::GetNames() const { - if (m_pReader == NULL) - return ""; + std::vector names; - char name[128]; - if (!Read(0x20, 0x60, (u8*)&name)) - return ""; + char name[128] = {}; + if (m_pReader != NULL && Read(0x20, 0x60, (u8*)&name)) + names.push_back(name); - return name; + return names; } u32 CVolumeGC::GetFSTSize() const diff --git a/Source/Core/DiscIO/Src/VolumeGC.h b/Source/Core/DiscIO/Src/VolumeGC.h index 4221df9493..dab1ad7a9d 100644 --- a/Source/Core/DiscIO/Src/VolumeGC.h +++ b/Source/Core/DiscIO/Src/VolumeGC.h @@ -34,7 +34,7 @@ public: bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const; std::string GetUniqueID() const; std::string GetMakerID() const; - std::string GetName() const; + std::vector GetNames() const; u32 GetFSTSize() const; std::string GetApploaderDate() const; ECountry GetCountry() const; diff --git a/Source/Core/DiscIO/Src/VolumeWad.cpp b/Source/Core/DiscIO/Src/VolumeWad.cpp index 2f9f0ef961..72788f1017 100644 --- a/Source/Core/DiscIO/Src/VolumeWad.cpp +++ b/Source/Core/DiscIO/Src/VolumeWad.cpp @@ -107,13 +107,15 @@ bool CVolumeWAD::GetTitleID(u8* _pBuffer) const return true; } -bool CVolumeWAD::GetWName(std::vector& _rwNames) const +std::vector CVolumeWAD::GetNames() const { - u32 footer_size; + std::vector names; + return names; + u32 footer_size; if (!Read(0x1C, 4, (u8*)&footer_size)) { - return false; + return names; } //Japanese, English, German, French, Spanish, Italian, Dutch, unknown, unknown, Korean @@ -126,7 +128,7 @@ bool CVolumeWAD::GetWName(std::vector& _rwNames) const if (!Read(0x9C + (i*84) + OpeningBnrOffset, 84, (u8*)&temp) || Common::swap32(footer_size) < 0xF1 || !temp[0]) { - _rwNames.push_back(L""); + names.push_back(""); continue; } for (int j = 0; j < 42; ++j) @@ -141,44 +143,10 @@ bool CVolumeWAD::GetWName(std::vector& _rwNames) const out_temp.push_back(t); } - _rwNames.push_back(out_temp); + names.push_back(UTF16ToUTF8(out_temp)); } - return true; -} -std::string CVolumeWAD::GetName() const -{ - u32 footer_size; - - if (!Read(0x1C, 4, (u8*)&footer_size)) - return ""; - - - //Japanese, English, German, French, Spanish, Italian, Dutch, unknown, unknown, Korean - - // Offset to the english title - char temp[84]; - if (!Read(0xF1 + OpeningBnrOffset, 84, (u8*)&temp) || Common::swap32(footer_size) < 0xF1 || - !Common::swap16(temp[0])) - return ""; - - // Remove the null bytes due to 16bit char length - std::string out_temp; - for (unsigned int i = 0; i < sizeof(temp); i+=2) - { - // Replace null chars with a single space per null section - if (temp[i] == '\0' && i > 0) - { - if (out_temp.at(out_temp.size()-1) != ' ') - out_temp.push_back(' '); - } - else - out_temp.push_back(temp[i]); - } - // Make it a null terminated string - out_temp.replace(out_temp.end()-1, out_temp.end(), 1, '\0'); - - return out_temp; + return names; } u64 CVolumeWAD::GetSize() const diff --git a/Source/Core/DiscIO/Src/VolumeWad.h b/Source/Core/DiscIO/Src/VolumeWad.h index 956844acd1..afc16766a2 100644 --- a/Source/Core/DiscIO/Src/VolumeWad.h +++ b/Source/Core/DiscIO/Src/VolumeWad.h @@ -38,8 +38,7 @@ public: bool GetTitleID(u8* _pBuffer) const; std::string GetUniqueID() const; std::string GetMakerID() const; - std::string GetName() const; - bool GetWName(std::vector& _rwNames) const; + std::vector GetNames() const; u32 GetFSTSize() const { return 0; } std::string GetApploaderDate() const { return "0"; } ECountry GetCountry() const; diff --git a/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp index ca010b5ae4..f375b9e66d 100644 --- a/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp @@ -168,21 +168,17 @@ std::string CVolumeWiiCrypted::GetMakerID() const return makerID; } -std::string CVolumeWiiCrypted::GetName() const +std::vector CVolumeWiiCrypted::GetNames() const { - if (m_pReader == NULL) + std::vector names; + + char name[0xFF] = {}; + if (m_pReader != NULL && Read(0x20, 0x60, (u8*)&name)) { - return std::string(); + names.push_back(name); } - char name[0xFF]; - - if (!Read(0x20, 0x60, (u8*)&name)) - { - return std::string(); - } - - return name; + return names; } u32 CVolumeWiiCrypted::GetFSTSize() const diff --git a/Source/Core/DiscIO/Src/VolumeWiiCrypted.h b/Source/Core/DiscIO/Src/VolumeWiiCrypted.h index 5010e46bbd..56c2a8a363 100644 --- a/Source/Core/DiscIO/Src/VolumeWiiCrypted.h +++ b/Source/Core/DiscIO/Src/VolumeWiiCrypted.h @@ -37,7 +37,7 @@ public: void GetTMD(u8* _pBuffer, u32* _sz) const; std::string GetUniqueID() const; std::string GetMakerID() const; - std::string GetName() const; + std::vector GetNames() const; u32 GetFSTSize() const; std::string GetApploaderDate() const; ECountry GetCountry() const; diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index c24f0509ba..6a6df49ee5 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -454,10 +454,8 @@ void CGameListCtrl::InsertItemInReportView(long _Index) // Set the game's banner in the second column SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex); - - std::wstring wstring_name; - wxString name; + std::string name; int SelectedLanguage = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage; switch (rISOFile.GetCountry()) @@ -465,9 +463,8 @@ void CGameListCtrl::InsertItemInReportView(long _Index) case DiscIO::IVolume::COUNTRY_TAIWAN: case DiscIO::IVolume::COUNTRY_JAPAN: { - rISOFile.GetName(wstring_name, -1); - name = wxString(rISOFile.GetName(0).c_str(), SJISConv); - m_gameList.append(StringFromFormat("%s (J)\n", (const char *)name.c_str())); + name = rISOFile.GetName(-1); + m_gameList.append(StringFromFormat("%s (J)\n", name.c_str())); } break; case DiscIO::IVolume::COUNTRY_USA: @@ -475,22 +472,15 @@ void CGameListCtrl::InsertItemInReportView(long _Index) SelectedLanguage = 0; default: { - wxCSConv WindowsCP1252(wxFontMapper::GetEncodingName(wxFONTENCODING_CP1252)); - rISOFile.GetName(wstring_name, SelectedLanguage); - - name = wxString(rISOFile.GetName(SelectedLanguage).c_str(), WindowsCP1252); - m_gameList.append(StringFromFormat("%s (%c)\n", - rISOFile.GetName(SelectedLanguage).c_str(), - (rISOFile.GetCountry() == DiscIO::IVolume::COUNTRY_USA) ? 'U' : 'E')); + name = rISOFile.GetName(SelectedLanguage); + m_gameList.append(StringFromFormat("%s (%c)\n", name.c_str(), + (rISOFile.GetCountry() == DiscIO::IVolume::COUNTRY_USA) ? 'U' : 'E')); } break; } - - if (wstring_name.length()) - name = wstring_name.c_str(); - - SetItem(_Index, COLUMN_TITLE, name, -1); + + SetItem(_Index, COLUMN_TITLE, StrToWxStr(name), -1); // We show the company string on Gamecube only // On Wii we show the description instead as the company string is empty diff --git a/Source/Core/DolphinWX/Src/ISOFile.cpp b/Source/Core/DolphinWX/Src/ISOFile.cpp index 918a72b0bf..ec8280a726 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.cpp +++ b/Source/Core/DolphinWX/Src/ISOFile.cpp @@ -37,7 +37,7 @@ #include "ChunkFile.h" #include "ConfigManager.h" -#define CACHE_REVISION 0x110 +#define CACHE_REVISION 0x112 #define DVD_BANNER_WIDTH 96 #define DVD_BANNER_HEIGHT 32 @@ -66,26 +66,10 @@ GameListItem::GameListItem(const std::string& _rFileName) else { m_Platform = WII_WAD; - pVolume->GetWName(m_wNames); } - m_Company = "N/A"; + m_volume_names = pVolume->GetNames(); - - m_Name[0] = pVolume->GetName(); - - if(m_Name[0] == "") // Couldn't find the name in the WAD... - { - std::string FileName; - SplitPath(m_FileName, NULL, &FileName, NULL); - m_Name[0] = FileName; // Then just display the filename... Better than something like "No Name" - } - - for (int i = 0; i < 6; i++) - { - m_Name[i] = m_Name[0]; - m_Description[i] = "No Description"; - } m_Country = pVolume->GetCountry(); m_FileSize = File::GetSize(_rFileName); m_VolumeSize = pVolume->GetSize(); @@ -105,11 +89,9 @@ GameListItem::GameListItem(const std::string& _rFileName) { if (pBannerLoader->IsValid()) { - m_wNames.clear(); - pBannerLoader->GetName(m_wNames); - pBannerLoader->GetName(m_Name); - pBannerLoader->GetCompany(m_Company); - pBannerLoader->GetDescription(m_Description); + m_names = pBannerLoader->GetNames(); + m_company = pBannerLoader->GetCompany(); + m_descriptions = pBannerLoader->GetDescriptions(); if (pBannerLoader->GetBanner(g_ImageTemp)) { @@ -129,25 +111,6 @@ GameListItem::GameListItem(const std::string& _rFileName) delete pFileSystem; } - std::vector::iterator i, end = m_wNames.end(); - std::wstring wFileName; - for (i = m_wNames.begin(); i != end; ++i) - { - if (*i == L"") - { - if (!wFileName.length()) - { - std::string FileName; - SplitPath(m_FileName, NULL, &FileName, NULL); - int length = FileName.length(); - wFileName.reserve(length+1); - for (int j = 0; j < length; ++j) - wFileName.push_back(FileName[j]); - wFileName.push_back(0); - } - *i = wFileName; - } - } delete pVolume; @@ -208,32 +171,10 @@ void GameListItem::SaveToCache() void GameListItem::DoState(PointerWrap &p) { - p.Do(m_Name[0]); p.Do(m_Name[1]); p.Do(m_Name[2]); - p.Do(m_Name[3]); p.Do(m_Name[4]); p.Do(m_Name[5]); - - int wNamesSize = m_wNames.size(); - p.Do(wNamesSize); - - if (p.mode == p.MODE_READ) - { - for (int i = 0; i < wNamesSize; ++i) - { - std::wstring temp; - p.Do(temp); - m_wNames.push_back(temp); - } - } - else - { - for (int i = 0; i < wNamesSize; ++i) - { - p.Do(m_wNames[i]); - } - } - - p.Do(m_Company); - p.Do(m_Description[0]); p.Do(m_Description[1]); p.Do(m_Description[2]); - p.Do(m_Description[3]); p.Do(m_Description[4]); p.Do(m_Description[5]); + p.Do(m_volume_names); + p.Do(m_company); + p.Do(m_names); + p.Do(m_descriptions); p.Do(m_UniqueID); p.Do(m_FileSize); p.Do(m_VolumeSize); @@ -262,44 +203,51 @@ std::string GameListItem::CreateCacheFilename() return fullname; } -const std::string& GameListItem::GetDescription(int index) const +std::string GameListItem::GetCompany() const { - if ((index >=0) && (index < 6)) - { - return m_Description[index]; - } - return m_Description[0]; + if (m_company.empty()) + return "N/A"; + else + return m_company; } -const std::string& GameListItem::GetName(int index) const +// (-1 = Japanese, 0 = English, etc) +std::string GameListItem::GetDescription(int _index) const { - if ((index >=0) && (index < 6)) - { - return m_Name[index]; - } - return m_Name[0]; + const u32 index = _index + 1; + + if (index < m_descriptions.size()) + return m_descriptions[index]; + + if (!m_descriptions.empty()) + return m_descriptions[0]; + + return ""; } -bool GameListItem::GetName(std::wstring& wName, int index) const +// (-1 = Japanese, 0 = English, etc) +std::string GameListItem::GetName(int _index) const { - // This function will only succeed for wii discs with banners or WADs - // utilize the same array as for gc discs (-1= Japanese, 0 = English etc - index++; - if ((index >= 0) && (index < 10)) - { - if (m_wNames.size() > (size_t)index) - { - wName = m_wNames[index]; - return true; - } - } - if (m_wNames.size() > 0) - { - wName = m_wNames[0]; - return true; - } - return false; + u32 const index = _index + 1; + // banner name + if (index < m_names.size() && !m_names[index].empty()) + return m_names[index]; + + if (!m_names.empty() && !m_names[0].empty()) + return m_names[0]; + + // volume name + if (index < m_volume_names.size() && !m_volume_names[index].empty()) + return m_volume_names[index]; + + if (!m_volume_names.empty() && !m_volume_names[0].empty()) + return m_volume_names[0]; + + // No usable name, return filename (better than nothing) + std::string FileName; + SplitPath(m_FileName, NULL, &FileName, NULL); + return FileName; } const std::string GameListItem::GetWiiFSPath() const diff --git a/Source/Core/DolphinWX/Src/ISOFile.h b/Source/Core/DolphinWX/Src/ISOFile.h index 1f3ecaa261..ded392f56a 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.h +++ b/Source/Core/DolphinWX/Src/ISOFile.h @@ -18,6 +18,9 @@ #ifndef __ISOFILE_H_ #define __ISOFILE_H_ +#include +#include + #include "Volume.h" #include "VolumeCreator.h" @@ -34,10 +37,9 @@ public: bool IsValid() const {return m_Valid;} const std::string& GetFileName() const {return m_FileName;} - const std::string& GetName(int index) const; - bool GetName(std::wstring& wName, int index=0) const; - const std::string& GetCompany() const {return m_Company;} - const std::string& GetDescription(int index = 0) const; + std::string GetName(int index) const; + std::string GetCompany() const; + std::string GetDescription(int index = 0) const; const std::string& GetUniqueID() const {return m_UniqueID;} const std::string GetWiiFSPath() const; DiscIO::IVolume::ECountry GetCountry() const {return m_Country;} @@ -64,10 +66,15 @@ public: private: std::string m_FileName; - std::string m_Name[6]; - std::vector m_wNames; - std::string m_Company; - std::string m_Description[6]; + + // TODO: eliminate this and overwrite with names from banner when available? + std::vector m_volume_names; + + // Stuff from banner + std::string m_company; + std::vector m_names; + std::vector m_descriptions; + std::string m_UniqueID; std::string m_issues; diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index 21d451a1ac..5993111698 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -158,15 +158,8 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW // Disk header and apploader - std::wstring wname; - wxString name; - if (OpenGameListItem->GetName(wname)) - name = wname.c_str(); - else - name = wxString(OpenISO->GetName().c_str(), wxConvUTF8); - m_Name->SetValue(name); - - m_GameID->SetValue(wxString(OpenISO->GetUniqueID().c_str(), wxConvUTF8)); + m_Name->SetValue(StrToWxStr(OpenISO->GetName())); + m_GameID->SetValue(StrToWxStr(OpenISO->GetUniqueID())); switch (OpenISO->GetCountry()) { case DiscIO::IVolume::COUNTRY_EUROPE: @@ -1308,54 +1301,29 @@ void CISOProperties::OnChangeBannerLang(wxCommandEvent& event) void CISOProperties::ChangeBannerDetails(int lang) { - std::wstring wname; + std::string name; wxString shortName, comment, maker; -#ifdef _WIN32 - wxCSConv SJISConv(*(wxCSConv*)wxConvCurrent); - static bool validCP932 = ::IsValidCodePage(932) != 0; - if (validCP932) - { - SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)); - } - else - { - WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932"); - } -#else - // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) - // it returns CP-932, in order to use iconv we need to use CP932 - wxCSConv SJISConv(wxT("CP932")); -#endif switch (OpenGameListItem->GetCountry()) { case DiscIO::IVolume::COUNTRY_TAIWAN: case DiscIO::IVolume::COUNTRY_JAPAN: - - if (OpenGameListItem->GetName(wname, -1)) - shortName = wname.c_str(); - else - shortName = wxString(OpenGameListItem->GetName(0).c_str(), SJISConv); - + shortName = StrToWxStr(OpenGameListItem->GetName(-1)); comment = StrToWxStr(OpenGameListItem->GetDescription()); - maker = wxString(OpenGameListItem->GetCompany().c_str(), SJISConv); break; case DiscIO::IVolume::COUNTRY_USA: + // why? lang = 0; default: - { - wxCSConv WindowsCP1252(wxFontMapper::GetEncodingName(wxFONTENCODING_CP1252)); - if (OpenGameListItem->GetName(wname, lang)) - shortName = wname.c_str(); - else - shortName = wxString(OpenGameListItem->GetName(lang).c_str(), WindowsCP1252); + shortName = StrToWxStr(OpenGameListItem->GetName(lang)); comment = StrToWxStr(OpenGameListItem->GetDescription(lang)); - maker = wxString(OpenGameListItem->GetCompany().c_str(), WindowsCP1252); - } break; } + + maker = StrToWxStr(OpenGameListItem->GetCompany()); + // Updates the informations shown in the window m_ShortName->SetValue(shortName); m_Comment->SetValue(comment); From e183711d749fefd480ef8091acfd1230ae8c604e Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 2 Mar 2013 20:34:53 -0600 Subject: [PATCH 54/70] wxString conversion cleanup. --- .../Src/Debugger/CodeWindowFunctions.cpp | 2 +- Source/Core/DolphinWX/Src/GameListCtrl.cpp | 17 ----------------- Source/Core/DolphinWX/Src/ISOProperties.cpp | 16 ++++++++-------- Source/Core/DolphinWX/Src/MemcardManager.cpp | 10 +++++----- Source/Core/DolphinWX/Src/NetWindow.cpp | 2 +- 5 files changed, 15 insertions(+), 32 deletions(-) diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp index fad0380eca..ef4622d14f 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp @@ -209,7 +209,7 @@ void CCodeWindow::OnProfilerMenu(wxCommandEvent& event) break; } wxString OpenCommand; - OpenCommand = filetype->GetOpenCommand(wxString::From8BitData(filename.c_str())); + OpenCommand = filetype->GetOpenCommand(StrToWxStr(filename)); if(!OpenCommand.IsEmpty()) wxExecute(OpenCommand, wxEXEC_SYNC); } diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index 6a6df49ee5..562d2234cd 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -423,23 +423,6 @@ void CGameListCtrl::InsertItemInReportView(long _Index) // company: 0x007030 int ImageIndex = -1; -#ifdef _WIN32 - wxCSConv SJISConv(*(wxCSConv*)wxConvCurrent); - static bool validCP932 = ::IsValidCodePage(932) != 0; - if (validCP932) - { - SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)); - } - else - { - WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932"); - } -#else - // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) - // it returns CP-932, in order to use iconv we need to use CP932 - wxCSConv SJISConv(wxT("CP932")); -#endif - GameListItem& rISOFile = *m_ISOFiles[_Index]; m_gamePath.append(rISOFile.GetFileName() + '\n'); diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index 5993111698..43657300cb 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -152,7 +152,7 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW LoadGameConfig(); else wxMessageBox(wxString::Format(_("Could not create %s"), - wxString::From8BitData(GameIniFile.c_str()).c_str()), + StrToWxStr(GameIniFile).c_str()), _("Error"), wxOK|wxICON_ERROR, this); } @@ -199,9 +199,9 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW m_Country->SetValue(_("UNKNOWN")); break; } - wxString temp = _T("0x") + wxString::From8BitData(OpenISO->GetMakerID().c_str()); + wxString temp = _T("0x") + StrToWxStr(OpenISO->GetMakerID()); m_MakerID->SetValue(temp); - m_Date->SetValue(wxString::From8BitData(OpenISO->GetApploaderDate().c_str())); + m_Date->SetValue(StrToWxStr(OpenISO->GetApploaderDate())); m_FST->SetValue(wxString::Format(wxT("%u"), OpenISO->GetFSTSize())); // Here we set all the info to be shown (be it SJIS or Ascii) + we set the window title @@ -266,12 +266,12 @@ size_t CISOProperties::CreateDirectoryTree(wxTreeItemId& parent, // check next index if (rFileInfo->IsDirectory()) { - wxTreeItemId item = m_Treectrl->AppendItem(parent, wxString::From8BitData(itemName), 1, 1); + wxTreeItemId item = m_Treectrl->AppendItem(parent, StrToWxStr(itemName), 1, 1); CurrentIndex = CreateDirectoryTree(item, fileInfos, CurrentIndex + 1, (size_t)rFileInfo->m_FileSize); } else { - m_Treectrl->AppendItem(parent, wxString::From8BitData(itemName), 2, 2); + m_Treectrl->AppendItem(parent, StrToWxStr(itemName), 2, 2); CurrentIndex++; } } @@ -1081,7 +1081,7 @@ bool CISOProperties::SaveGameConfig() void CISOProperties::OnEditConfig(wxCommandEvent& WXUNUSED (event)) { - if (wxFileExists(wxString::From8BitData(GameIniFile.c_str()))) + if (File::Exists(GameIniFile)) { SaveGameConfig(); @@ -1102,7 +1102,7 @@ void CISOProperties::OnEditConfig(wxCommandEvent& WXUNUSED (event)) } } wxString OpenCommand; - OpenCommand = filetype->GetOpenCommand(wxString::From8BitData(GameIniFile.c_str())); + OpenCommand = filetype->GetOpenCommand(StrToWxStr(GameIniFile)); if(OpenCommand.IsEmpty()) PanicAlertT("Couldn't find open command for extension 'ini'!"); else @@ -1275,7 +1275,7 @@ void CISOProperties::ActionReplayButtonClicked(wxCommandEvent& event) CARCodeAddEdit dlg(-1, this, 1, _("Add ActionReplay Code")); if (dlg.ShowModal() == wxID_OK) { - Cheats->Append(wxString::From8BitData(arCodes.back().name.c_str())); + Cheats->Append(StrToWxStr(arCodes.back().name)); Cheats->Check((unsigned int)(arCodes.size() - 1), arCodes.back().active); } } diff --git a/Source/Core/DolphinWX/Src/MemcardManager.cpp b/Source/Core/DolphinWX/Src/MemcardManager.cpp index d9fd4d3ae6..b9b26b6da8 100644 --- a/Source/Core/DolphinWX/Src/MemcardManager.cpp +++ b/Source/Core/DolphinWX/Src/MemcardManager.cpp @@ -214,7 +214,7 @@ void CMemcardManager::CreateGUIControls() sPages->Add(m_NextPage[slot], 0, wxEXPAND|wxALL, 1); m_MemcardPath[slot] = new wxFilePickerCtrl(this, ID_MEMCARDPATH_A + slot, - wxString::From8BitData(File::GetUserPath(D_GCUSER_IDX).c_str()), _("Choose a memory card:"), + StrToWxStr(File::GetUserPath(D_GCUSER_IDX)), _("Choose a memory card:"), _("Gamecube Memory Cards (*.raw,*.gcp)") + wxString(wxT("|*.raw;*.gcp")), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL|wxFLP_OPEN); m_MemcardList[slot] = new CMemcardListCtrl(this, ID_MEMCARDLIST_A + slot, wxDefaultPosition, wxSize(350,400), @@ -265,7 +265,7 @@ void CMemcardManager::CreateGUIControls() m_Delete[i]->Disable(); if (DefaultMemcard[i].length()) { - m_MemcardPath[i]->SetPath(wxString::From8BitData(DefaultMemcard[i].c_str())); + m_MemcardPath[i]->SetPath(StrToWxStr(DefaultMemcard[i])); ChangePath(i); } } @@ -520,7 +520,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) _("Select a save file to import"), (strcmp(DefaultIOPath.c_str(), "/Users/GC") == 0) ? StrToWxStr("") - : wxString::From8BitData(DefaultIOPath.c_str()), + : StrToWxStr(DefaultIOPath), wxEmptyString, wxEmptyString, _("GameCube Savegame files(*.gci;*.gcs;*.sav)") + wxString(wxT("|*.gci;*.gcs;*.sav|")) + _("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) + @@ -557,8 +557,8 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) } wxString fileName = wxFileSelector( _("Export save as..."), - wxString::From8BitData(DefaultIOPath.c_str()), - wxString::From8BitData(gciFilename.c_str()), wxT(".gci"), + StrToWxStr(DefaultIOPath), + StrToWxStr(gciFilename), wxT(".gci"), _("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) + _("MadCatz Gameshark files(*.gcs)") + wxString(wxT("|*.gcs|")) + _("Datel MaxDrive/Pro files(*.sav)") + wxString(wxT("|*.sav")), diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index 988ccae83e..60efcedc6f 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -51,7 +51,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* std::string nickname; netplay_section.Get("Nickname", &nickname, "Player"); - m_nickname_text = new wxTextCtrl(panel, wxID_ANY, wxString::From8BitData(nickname.c_str())); + m_nickname_text = new wxTextCtrl(panel, wxID_ANY, StrToWxStr(nickname)); wxBoxSizer* const nick_szr = new wxBoxSizer(wxHORIZONTAL); nick_szr->Add(nick_lbl, 0, wxCENTER); From 88cb11ba0a24e0fb841b4fc4367f4d61ae18558e Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 2 Mar 2013 20:38:40 -0600 Subject: [PATCH 55/70] I'm confused at why SHIFT-JIS was being used here. --- Source/Core/DolphinWX/Src/LogWindow.cpp | 23 ++++------------------- Source/Core/DolphinWX/Src/LogWindow.h | 2 -- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/Source/Core/DolphinWX/Src/LogWindow.cpp b/Source/Core/DolphinWX/Src/LogWindow.cpp index 7af1de1aaa..57e2ac6b58 100644 --- a/Source/Core/DolphinWX/Src/LogWindow.cpp +++ b/Source/Core/DolphinWX/Src/LogWindow.cpp @@ -21,6 +21,8 @@ #include "IniFile.h" #include "FileUtil.h" #include "Debugger/DebuggerUIUtil.h" +#include "WxUtils.h" + #include // Milliseconds between msgQueue flushes to wxTextCtrl @@ -41,25 +43,7 @@ CLogWindow::CLogWindow(CFrame *parent, wxWindowID id, const wxPoint& pos, , x(0), y(0), winpos(0) , Parent(parent), m_ignoreLogTimer(false), m_LogAccess(true) , m_Log(NULL), m_cmdline(NULL), m_FontChoice(NULL) - , m_SJISConv(wxT("")) { -#ifdef _WIN32 - static bool validCP932 = ::IsValidCodePage(932) != 0; - if (validCP932) - { - m_SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)); - } - else - { - WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932"); - m_SJISConv = *(wxCSConv*)wxConvCurrent; - } -#else - // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) - // it returns CP-932, in order to use iconv we need to use CP932 - m_SJISConv = wxCSConv(wxT("CP932")); -#endif - m_LogManager = LogManager::GetInstance(); CreateGUIControls(); @@ -370,5 +354,6 @@ void CLogWindow::Log(LogTypes::LOG_LEVELS level, const char *text) if (msgQueue.size() >= 100) msgQueue.pop(); - msgQueue.push(std::pair((u8)level, wxString(text, m_SJISConv))); + + msgQueue.push(std::make_pair(u8(level), StrToWxStr(text))); } diff --git a/Source/Core/DolphinWX/Src/LogWindow.h b/Source/Core/DolphinWX/Src/LogWindow.h index 86fd1d3b4f..54a59c4d91 100644 --- a/Source/Core/DolphinWX/Src/LogWindow.h +++ b/Source/Core/DolphinWX/Src/LogWindow.h @@ -75,8 +75,6 @@ private: std::mutex m_LogSection; - wxCSConv m_SJISConv; - DECLARE_EVENT_TABLE() wxTextCtrl * CreateTextCtrl(wxPanel* parent, wxWindowID id = wxID_ANY, long Style = NULL); From ed90feb2b4169a98167ba90846aa27f8cd4bf50e Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 2 Mar 2013 22:59:55 -0600 Subject: [PATCH 56/70] Kill warning. --- Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp | 4 ++-- Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp index 95311eb98d..db47217655 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp @@ -9,7 +9,7 @@ PerfQuery::PerfQuery() : m_query_read_pos() , m_query_count() { - for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + for (u32 i = 0; i != ARRAYSIZE(m_query_buffer); ++i) glGenQueries(1, &m_query_buffer[i].query_id); ResetQuery(); @@ -17,7 +17,7 @@ PerfQuery::PerfQuery() PerfQuery::~PerfQuery() { - for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + for (u32 i = 0; i != ARRAYSIZE(m_query_buffer); ++i) glDeleteQueries(1, &m_query_buffer[i].query_id); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h index 34c64e43a1..b96fe7a4a0 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h @@ -26,7 +26,7 @@ private: }; // when testing in SMS: 64 was too small, 128 was ok - static const int PERF_QUERY_BUFFER_SIZE = 512; + static const u32 PERF_QUERY_BUFFER_SIZE = 512; void WeakFlush(); // Only use when non-empty @@ -34,10 +34,10 @@ private: // This contains gl query objects with unretrieved results. ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE]; - int m_query_read_pos; + u32 m_query_read_pos; // TODO: sloppy - volatile int m_query_count; + volatile u32 m_query_count; volatile u32 m_results[PQG_NUM_MEMBERS]; }; From a01f793f5986747392080ccea2bfd22821e3f4e3 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sun, 3 Mar 2013 07:37:22 +0000 Subject: [PATCH 57/70] Fix ARM build. --- .../VideoCommon/Src/GenericTextureDecoder.cpp | 34 +++++++++++++++++++ Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp b/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp index ad7cfeebf9..7546511515 100644 --- a/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp +++ b/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp @@ -1442,6 +1442,40 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth } } +void TexDecoder_DecodeTexelRGBA8FromTmem(u8 *dst, const u8 *src_ar, const u8* src_gb, int s, int t, int imageWidth) +{ + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; // TODO: Looks wrong. Shouldn't this be ((imageWidth-1)>>2)+1 ? + u32 base_ar = (tBlk * widthBlks + sBlk) << 4; + u32 base_gb = (tBlk * widthBlks + sBlk) << 4; + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blk_off = (blkT << 2) + blkS; + + u32 offset_ar = (base_ar + blk_off) << 1; + u32 offset_gb = (base_gb + blk_off) << 1; + const u8* val_addr_ar = src_ar + offset_ar; + const u8* val_addr_gb = src_gb + offset_gb; + + dst[3] = val_addr_ar[0]; // A + dst[0] = val_addr_ar[1]; // R + dst[1] = val_addr_gb[0]; // G + dst[2] = val_addr_gb[1]; // B +} + +PC_TexFormat TexDecoder_DecodeRGBA8FromTmem(u8* dst, const u8 *src_ar, const u8 *src_gb, int width, int height) +{ + // TODO for someone who cares: Make this less slow! + for (int y = 0; y < height; ++y) + for (int x = 0; x < width; ++x) + { + TexDecoder_DecodeTexelRGBA8FromTmem(dst, src_ar, src_gb, x, y, width-1); + dst += 4; + } + + return PC_TEX_FMT_RGBA32; +} const char* texfmt[] = { // pixel diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h index 09d38bb731..be46f047ca 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h @@ -69,7 +69,7 @@ bool OpenGL_ReportFBOError(const char *function, const char *file, int line); #define GL_REPORT_PROGRAM_ERROR() (void)0 #endif -#if defined __APPLE__ || defined __linux__ || defined _WIN32 +#if (defined __APPLE__ || defined __linux__ || defined _WIN32) && !(defined _M_ARM) #include #include #define HAVE_CG 1 From aeb4fc9846f19d78248994b72c0902c17df3947b Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 2 Mar 2013 22:57:49 -0600 Subject: [PATCH 58/70] Fix what I broke. --- Source/Core/Common/Src/StringUtil.cpp | 80 +++++++++++- Source/Core/Common/Src/StringUtil.h | 1 + Source/Core/DiscIO/Src/BannerLoader.cpp | 4 +- Source/Core/DiscIO/Src/BannerLoader.h | 6 - Source/Core/DiscIO/Src/BannerLoaderGC.cpp | 11 +- Source/Core/DiscIO/Src/BannerLoaderGC.h | 13 +- Source/Core/DiscIO/Src/BannerLoaderWii.cpp | 139 ++------------------- Source/Core/DiscIO/Src/BannerLoaderWii.h | 3 - Source/Core/DiscIO/Src/Volume.h | 2 + 9 files changed, 108 insertions(+), 151 deletions(-) diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index aab0f3bd58..e499fc40c3 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -17,13 +17,19 @@ #include #include +#include #include "Common.h" #include "CommonPaths.h" #include "StringUtil.h" #ifdef _WIN32 -#include + #include +#elif defined(ANDROID) + +#else + #include + #include #endif // faster than sscanf @@ -418,18 +424,80 @@ std::string SHIFTJISToUTF8(const std::string& input) return UTF16ToUTF8(CPToUTF16(932, input)); } +std::string CP1252ToUTF8(const std::string& input) +{ + return UTF16ToUTF8(CPToUTF16(1252, input)); +} + #else -std::string UTF16ToUTF8(const std::wstring& input) +template +std::string CodeToUTF8(const char* fromcode, const std::basic_string& input) { - // TODO: implement - return std::string(); + std::string result; + +#if defined(ANDROID) + result = "Not implemented on Android!"; + +#else + iconv_t const conv_desc = iconv_open("UTF-8", fromcode); + if ((iconv_t)-1 == conv_desc) + { + ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno)); + } + else + { + size_t const in_bytes = sizeof(T) * input.size(); + size_t const out_buffer_size = 4 * in_bytes; + + std::string out_buffer; + out_buffer.resize(out_buffer_size); + + auto src_buffer = &input[0]; + size_t src_bytes = in_bytes; + auto dst_buffer = &out_buffer[0]; + size_t dst_bytes = out_buffer.size(); + + size_t const iconv_size = iconv(conv_desc, (char**)(&src_buffer), &src_bytes, + &dst_buffer, &dst_bytes); + + if ((size_t)-1 == iconv_size) + { + ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno)); + } + else + { + out_buffer.resize(out_buffer_size - dst_bytes); + out_buffer.swap(result); + + // TODO: why is this needed? + result.erase(std::remove(result.begin(), result.end(), 0x00), result.end()); + } + + iconv_close(conv_desc); + } + +#endif + return result; +} + +std::string CP1252ToUTF8(const std::string& input) +{ + return CodeToUTF8("CP1252", input); } std::string SHIFTJISToUTF8(const std::string& input) { - // TODO: implement - return std::string(); + //return CodeToUTF8("CP932", input); + return CodeToUTF8("SJIS", input); +} + +std::string UTF16ToUTF8(const std::wstring& input) +{ + //return CodeToUTF8("UCS-2", input); + //return CodeToUTF8("UCS-2LE", input); + //return CodeToUTF8("UTF-16", input); + return CodeToUTF8("UTF-16LE", input); } #endif diff --git a/Source/Core/Common/Src/StringUtil.h b/Source/Core/Common/Src/StringUtil.h index ce5751f80b..9463db5bb1 100644 --- a/Source/Core/Common/Src/StringUtil.h +++ b/Source/Core/Common/Src/StringUtil.h @@ -97,6 +97,7 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st std::string UriDecode(const std::string & sSrc); std::string UriEncode(const std::string & sSrc); +std::string CP1252ToUTF8(const std::string& str); std::string SHIFTJISToUTF8(const std::string& str); std::string UTF16ToUTF8(const std::wstring& str); diff --git a/Source/Core/DiscIO/Src/BannerLoader.cpp b/Source/Core/DiscIO/Src/BannerLoader.cpp index 7e641aa85b..d38c7e9ea4 100644 --- a/Source/Core/DiscIO/Src/BannerLoader.cpp +++ b/Source/Core/DiscIO/Src/BannerLoader.cpp @@ -31,9 +31,9 @@ IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVo { return new CBannerLoaderWii(pVolume); } - if (_rFileSystem.IsValid()) + if (_rFileSystem.IsValid()) { - return new CBannerLoaderGC(_rFileSystem); + return new CBannerLoaderGC(_rFileSystem, pVolume); } return NULL; diff --git a/Source/Core/DiscIO/Src/BannerLoader.h b/Source/Core/DiscIO/Src/BannerLoader.h index 92bb874979..b30ee17a46 100644 --- a/Source/Core/DiscIO/Src/BannerLoader.h +++ b/Source/Core/DiscIO/Src/BannerLoader.h @@ -44,12 +44,6 @@ class IBannerLoader virtual std::vector GetNames() = 0; virtual std::string GetCompany() = 0; virtual std::vector GetDescriptions() = 0; - - private: - u16 swap16(u16 data) - { - return ((data & 0xff00) >> 8) | ((data & 0xff) << 8); - } }; IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume); diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp index bf087cbfb6..d8ae259b16 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp @@ -23,9 +23,10 @@ namespace DiscIO { -CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem) - : m_pBannerFile(NULL), - m_IsValid(false) +CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume) + : m_pBannerFile(NULL) + , m_IsValid(false) + , m_country(volume->GetCountry()) { // load the opening.bnr size_t FileSize = (size_t) _rFileSystem.GetFileSize("opening.bnr"); @@ -104,7 +105,7 @@ std::vector CBannerLoaderGC::GetNames() auto const banner = reinterpret_cast(m_pBannerFile); - for (int i = 0; i != name_count; ++i) + for (u32 i = 0; i != name_count; ++i) { auto& comment = banner->comment[i]; @@ -167,7 +168,7 @@ std::vector CBannerLoaderGC::GetDescriptions() auto banner = reinterpret_cast(m_pBannerFile); - for (int i = 0; i != desc_count; ++i) + for (u32 i = 0; i != desc_count; ++i) { auto& data = banner->comment[i].comment; descriptions.push_back(GetDecodedString(data)); diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.h b/Source/Core/DiscIO/Src/BannerLoaderGC.h index b4903561e4..8bc8c46483 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderGC.h +++ b/Source/Core/DiscIO/Src/BannerLoaderGC.h @@ -19,6 +19,7 @@ #define _BANNER_LOADER_GC_H_ #include "BannerLoader.h" +#include "StringUtil.h" namespace DiscIO { @@ -26,7 +27,7 @@ class CBannerLoaderGC : public IBannerLoader { public: - CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem); + CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume); virtual ~CBannerLoaderGC(); virtual bool IsValid(); @@ -76,8 +77,12 @@ class CBannerLoaderGC template std::string GetDecodedString(const char (&data)[N]) { - // Can I always assume SHIFT-JIS? - return SHIFTJISToUTF8(std::string(data, strnlen(data, sizeof(data)))); + auto const string_decoder = (DiscIO::IVolume::COUNTRY_JAPAN == m_country || + DiscIO::IVolume::COUNTRY_TAIWAN == m_country) ? + SHIFTJISToUTF8 : CP1252ToUTF8; + + // strnlen to trim NULLs + return string_decoder(std::string(data, strnlen(data, sizeof(data)))); } u8* m_pBannerFile; @@ -86,6 +91,8 @@ class CBannerLoaderGC void decode5A3image(u32* dst, u16* src, int width, int height); BANNER_TYPE getBannerType(); + + DiscIO::IVolume::ECountry const m_country; }; } // namespace diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp index b94e299f04..f606ed8876 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp @@ -25,25 +25,6 @@ #include "FileUtil.h" #include "FileHandlerARC.h" -// HyperIris: dunno if this suitable, may be need move. -#ifdef _WIN32 -#include -#else -#include -#ifndef ANDROID -#include -#endif -#include -#endif - -#ifndef ICONV_CONST -#if defined __FreeBSD__ || __NetBSD__ -#define ICONV_CONST const -#else -#define ICONV_CONST -#endif -#endif - namespace DiscIO { @@ -164,35 +145,24 @@ bool CBannerLoaderWii::GetBanner(u32* _pBannerImage) return true; } -bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& s) -{ - bool ret = false; - - if (IsValid()) - { - // find Banner type - SWiiBanner *pBanner = (SWiiBanner*)m_pBannerFile; - // TODO: trim NULLs - ret = CopyBeUnicodeToString(s, pBanner->m_Comment[index], COMMENT_SIZE); - } - - return ret; -} - -bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::wstring& s) +bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& result) { if (IsValid()) { - // find Banner type - SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile; - - std::wstring description; - for (int i = 0; i < COMMENT_SIZE; ++i) - description.push_back(Common::swap16(pBanner->m_Comment[index][i])); - - s = description; + auto const banner = reinterpret_cast(m_pBannerFile); + auto const src_ptr = banner->m_Comment[index]; + + // Trim at first NULL + auto const length = std::find(src_ptr, src_ptr + COMMENT_SIZE, 0x0) - src_ptr; + + std::wstring src; + src.resize(length); + std::transform(src_ptr, src_ptr + src.size(), src.begin(), (u16(&)(u16))Common::swap16); + result = UTF16ToUTF8(src); + return true; } + return false; } @@ -237,87 +207,4 @@ void CBannerLoaderWii::decode5A3image(u32* dst, u16* src, int width, int height) } } -bool CBannerLoaderWii::CopyBeUnicodeToString( std::string& _rDestination, const u16* _src, int length ) -{ - bool returnCode = false; -#ifdef _WIN32 - if (_src) - { - std::wstring src; - src.resize(length); - std::transform(_src, _src + length, &src[0], (u16(&)(u16))Common::swap16); - - _rDestination = UTF16ToUTF8(src); - returnCode = true; - } -#else -#ifdef ANDROID - return false; -#else - if (_src) - { - iconv_t conv_desc = iconv_open("UTF-8", "CP932"); - if (conv_desc == (iconv_t) -1) - { - // Initialization failure. - if (errno == EINVAL) - { - ERROR_LOG(DISCIO, "Conversion from CP932 to UTF-8 is not supported."); - } - else - { - ERROR_LOG(DISCIO, "Iconv initialization failure: %s\n", strerror (errno)); - } - return false; - } - - char* src_buffer = new char[length]; - for (int i = 0; i < length; i++) - src_buffer[i] = swap16(_src[i]); - - size_t inbytes = sizeof(char) * length; - size_t outbytes = 2 * inbytes; - char* utf8_buffer = new char[outbytes + 1]; - memset(utf8_buffer, 0, (outbytes + 1) * sizeof(char)); - - // Save the buffer locations because iconv increments them - char* utf8_buffer_start = utf8_buffer; - char* src_buffer_start = src_buffer; - - size_t iconv_size = iconv(conv_desc, - (ICONV_CONST char**)&src_buffer, &inbytes, - &utf8_buffer, &outbytes); - - // Handle failures - if (iconv_size == (size_t) -1) - { - ERROR_LOG(DISCIO, "iconv failed."); - switch (errno) { - case EILSEQ: - ERROR_LOG(DISCIO, "Invalid multibyte sequence."); - break; - case EINVAL: - ERROR_LOG(DISCIO, "Incomplete multibyte sequence."); - break; - case E2BIG: - ERROR_LOG(DISCIO, "Insufficient space allocated for output buffer."); - break; - default: - ERROR_LOG(DISCIO, "Error: %s.", strerror(errno)); - } - } - else - { - _rDestination = utf8_buffer_start; - returnCode = true; - } - delete[] utf8_buffer_start; - delete[] src_buffer_start; - iconv_close(conv_desc); - } -#endif -#endif - return returnCode; -} - } // namespace diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.h b/Source/Core/DiscIO/Src/BannerLoaderWii.h index 60d317155b..036eeeacbd 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.h +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.h @@ -75,9 +75,6 @@ class CBannerLoaderWii void decode5A3image(u32* dst, u16* src, int width, int height); bool GetStringFromComments(const CommentIndex index, std::string& s); - bool GetStringFromComments(const CommentIndex index, std::wstring& s); - - bool CopyBeUnicodeToString(std::string& _rDestination, const u16* _src, int length); }; } // namespace diff --git a/Source/Core/DiscIO/Src/Volume.h b/Source/Core/DiscIO/Src/Volume.h index 4743cfce89..c19aaf93a8 100644 --- a/Source/Core/DiscIO/Src/Volume.h +++ b/Source/Core/DiscIO/Src/Volume.h @@ -22,6 +22,7 @@ #include #include "Common.h" +#include "StringUtil.h" namespace DiscIO { @@ -37,6 +38,7 @@ public: virtual void GetTMD(u8*, u32 *_sz) const { *_sz=0; } virtual std::string GetUniqueID() const = 0; virtual std::string GetMakerID() const = 0; + // TODO: eliminate? virtual std::string GetName() const; virtual std::vector GetNames() const = 0; virtual u32 GetFSTSize() const = 0; From fad2b65d76dc9f0108c5ed3638c4d1ec6403c00e Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 3 Mar 2013 02:30:45 -0600 Subject: [PATCH 59/70] More wxString conversion cleanup. --- Source/Core/DolphinWX/Src/GameListCtrl.cpp | 3 +-- Source/Core/DolphinWX/Src/MemcardManager.cpp | 25 ++++---------------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index 562d2234cd..15df0fa3ee 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -966,8 +966,7 @@ void CGameListCtrl::OnOpenContainingFolder(wxCommandEvent& WXUNUSED (event)) if (!iso) return; - wxString strPath(iso->GetFileName().c_str(), wxConvUTF8); - wxFileName path = wxFileName::FileName(strPath); + wxFileName path = wxFileName::FileName(StrToWxStr(iso->GetFileName())); path.MakeAbsolute(); WxUtils::Explore(path.GetPath().char_str()); } diff --git a/Source/Core/DolphinWX/Src/MemcardManager.cpp b/Source/Core/DolphinWX/Src/MemcardManager.cpp index b9b26b6da8..0bbbbd0a7b 100644 --- a/Source/Core/DolphinWX/Src/MemcardManager.cpp +++ b/Source/Core/DolphinWX/Src/MemcardManager.cpp @@ -704,26 +704,11 @@ bool CMemcardManager::ReloadMemcard(const char *fileName, int card) std::string title = memoryCard[card]->GetSaveComment1(fileIndex); std::string comment = memoryCard[card]->GetSaveComment2(fileIndex); - bool ascii = memoryCard[card]->IsAsciiEncoding(); - -#ifdef _WIN32 - wxCSConv SJISConv(*(wxCSConv*)wxConvCurrent); - static bool validCP932 = ::IsValidCodePage(932) != 0; - if (validCP932) - { - SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)); - } - else - { - WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932"); - } -#else - // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) - // it returns CP-932, in order to use iconv we need to use CP932 - wxCSConv SJISConv(wxT("CP932")); -#endif - wxTitle = wxString(title.c_str(), ascii ? *wxConvCurrent : SJISConv); - wxComment = wxString(comment.c_str(), ascii ? *wxConvCurrent : SJISConv); + auto const string_decoder = memoryCard[card]->IsAsciiEncoding() ? + CP1252ToUTF8 : SHIFTJISToUTF8; + + wxTitle = StrToWxStr(string_decoder(title)); + wxComment = StrToWxStr(string_decoder(comment)); m_MemcardList[card]->SetItem(index, COLUMN_TITLE, wxTitle); m_MemcardList[card]->SetItem(index, COLUMN_COMMENT, wxComment); From 11e4403fb24519ed1a7c2a63f1e76ffdf7f5fa0d Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sun, 3 Mar 2013 08:38:13 +0000 Subject: [PATCH 60/70] Fix accidental change from libpulse-simple to libpulse --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ea531f030c..5560b195e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,7 +331,7 @@ if(NOT ANDROID) message("bluez NOT found, disabling bluetooth support") endif(BLUEZ_FOUND) - check_lib(PULSEAUDIO libpulse QUIET) + check_lib(PULSEAUDIO libpulse-simple QUIET) if(PULSEAUDIO_FOUND) add_definitions(-DHAVE_PULSEAUDIO=1) message("PulseAudio found, enabling PulseAudio sound backend") From cedfa452b4497590f828306b42b1e7c24915fd58 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 3 Mar 2013 14:20:45 -0600 Subject: [PATCH 61/70] Windows: Open wiimotes with the FILE_SHARE_WRITE flag like before. This should fix issues introduced by real-wiimote-scanning. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 1119ae3f1d..c3824e21be 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -36,6 +37,7 @@ #include //#define AUTHENTICATE_WIIMOTES +#define SHARE_WRITE_WIIMOTES typedef struct _HIDD_ATTRIBUTES { @@ -84,6 +86,11 @@ static int initialized = 0; std::unordered_map g_connect_times; +#ifdef SHARE_WRITE_WIIMOTES +std::unordered_set g_connected_wiimotes; +std::mutex g_connected_wiimotes_lock; +#endif + inline void init_lib() { if (!initialized) @@ -259,11 +266,22 @@ bool Wiimote::Connect() if (IsConnected()) return false; +#ifdef SHARE_WRITE_WIIMOTES + std::lock_guard lk(g_connected_wiimotes_lock); + if (g_connected_wiimotes.count(devicepath) != 0) + return false; + + auto const open_flags = FILE_SHARE_READ | FILE_SHARE_WRITE; +#else + // Having no FILE_SHARE_WRITE disallows us from connecting to the same wiimote twice. + // (And disallows using wiimotes in use by other programs) + // This is what "WiiYourself" does. + // Apparently this doesn't work for everyone. It might be their fault. + auto const open_flags = FILE_SHARE_READ; +#endif + dev_handle = CreateFile(devicepath.c_str(), - GENERIC_READ | GENERIC_WRITE, - // Having no FILE_SHARE_WRITE disallows us from connecting to the same wiimote twice. - // This is what "WiiYourself" does. - FILE_SHARE_READ, + GENERIC_READ | GENERIC_WRITE, open_flags, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (dev_handle == INVALID_HANDLE_VALUE) @@ -298,6 +316,10 @@ bool Wiimote::Connect() ERROR_LOG(WIIMOTE, "Failed to set wiimote thread priority"); } */ +#ifdef SHARE_WRITE_WIIMOTES + g_connected_wiimotes.insert(devicepath); +#endif + return true; } @@ -311,6 +333,11 @@ void Wiimote::Disconnect() CloseHandle(hid_overlap_read.hEvent); CloseHandle(hid_overlap_write.hEvent); + +#ifdef SHARE_WRITE_WIIMOTES + std::lock_guard lk(g_connected_wiimotes_lock); + g_connected_wiimotes.erase(devicepath); +#endif } bool Wiimote::IsConnected() const From c07b8a6e3754abb4be5d962d84550d4b10827240 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 3 Mar 2013 16:51:26 -0600 Subject: [PATCH 62/70] Fix more of what I broke. --- Source/Core/Common/Src/StringUtil.cpp | 52 ++++++++++++++------- Source/Core/DiscIO/Src/BannerLoaderGC.h | 5 +- Source/Core/DiscIO/Src/FileSystemGCWii.cpp | 32 +++++++------ Source/Core/DiscIO/Src/FileSystemGCWii.h | 6 +-- Source/Core/DiscIO/Src/VolumeGC.cpp | 14 ++++-- Source/Core/DiscIO/Src/VolumeGC.h | 4 ++ Source/Core/DiscIO/Src/VolumeWad.cpp | 38 +++++++-------- Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp | 7 +-- 8 files changed, 97 insertions(+), 61 deletions(-) diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index e499fc40c3..c38184776b 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -457,22 +457,33 @@ std::string CodeToUTF8(const char* fromcode, const std::basic_string& input) size_t src_bytes = in_bytes; auto dst_buffer = &out_buffer[0]; size_t dst_bytes = out_buffer.size(); - - size_t const iconv_size = iconv(conv_desc, (char**)(&src_buffer), &src_bytes, - &dst_buffer, &dst_bytes); - - if ((size_t)-1 == iconv_size) + + while (src_bytes != 0) { - ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno)); - } - else - { - out_buffer.resize(out_buffer_size - dst_bytes); - out_buffer.swap(result); + size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes, + &dst_buffer, &dst_bytes); - // TODO: why is this needed? - result.erase(std::remove(result.begin(), result.end(), 0x00), result.end()); + if ((size_t)-1 == iconv_result) + { + if (EILSEQ == errno || EINVAL == errno) + { + // Try to skip the bad character + if (src_bytes != 0) + { + --src_bytes; + ++src_buffer; + } + } + else + { + ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno)); + break; + } + } } + + out_buffer.resize(out_buffer_size - dst_bytes); + out_buffer.swap(result); iconv_close(conv_desc); } @@ -483,6 +494,8 @@ std::string CodeToUTF8(const char* fromcode, const std::basic_string& input) std::string CP1252ToUTF8(const std::string& input) { + //return CodeToUTF8("CP1252//TRANSLIT", input); + //return CodeToUTF8("CP1252//IGNORE", input); return CodeToUTF8("CP1252", input); } @@ -494,10 +507,15 @@ std::string SHIFTJISToUTF8(const std::string& input) std::string UTF16ToUTF8(const std::wstring& input) { - //return CodeToUTF8("UCS-2", input); - //return CodeToUTF8("UCS-2LE", input); - //return CodeToUTF8("UTF-16", input); - return CodeToUTF8("UTF-16LE", input); + std::string result = + // CodeToUTF8("UCS-2", input); + // CodeToUTF8("UCS-2LE", input); + // CodeToUTF8("UTF-16", input); + CodeToUTF8("UTF-16LE", input); + + // TODO: why is this needed? + result.erase(std::remove(result.begin(), result.end(), 0x00), result.end()); + return result; } #endif diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.h b/Source/Core/DiscIO/Src/BannerLoaderGC.h index 8bc8c46483..8b14a45d43 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderGC.h +++ b/Source/Core/DiscIO/Src/BannerLoaderGC.h @@ -19,6 +19,7 @@ #define _BANNER_LOADER_GC_H_ #include "BannerLoader.h" +#include "VolumeGC.h" #include "StringUtil.h" namespace DiscIO @@ -77,9 +78,7 @@ class CBannerLoaderGC template std::string GetDecodedString(const char (&data)[N]) { - auto const string_decoder = (DiscIO::IVolume::COUNTRY_JAPAN == m_country || - DiscIO::IVolume::COUNTRY_TAIWAN == m_country) ? - SHIFTJISToUTF8 : CP1252ToUTF8; + auto const string_decoder = CVolumeGC::GetStringDecoder(m_country); // strnlen to trim NULLs return string_decoder(std::string(data, strnlen(data, sizeof(data)))); diff --git a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp index 47651e2f23..93b569e043 100644 --- a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp +++ b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "FileSystemGCWii.h" #include "StringUtil.h" @@ -27,10 +28,10 @@ namespace DiscIO { CFileSystemGCWii::CFileSystemGCWii(const IVolume *_rVolume) - : IFileSystem(_rVolume), - m_Initialized(false), - m_Valid(false), - m_OffsetShift(0) + : IFileSystem(_rVolume) + , m_Initialized(false) + , m_Valid(false) + , m_OffsetShift(0) { m_Valid = DetectFileSystem(); } @@ -213,9 +214,16 @@ u32 CFileSystemGCWii::Read32(u64 _Offset) const return Common::swap32(Temp); } -void CFileSystemGCWii::GetStringFromOffset(u64 _Offset, char* Filename) const +std::string CFileSystemGCWii::GetStringFromOffset(u64 _Offset) const { - m_rVolume->Read(_Offset, 255, (u8*)Filename); + std::string data; + data.resize(255); + m_rVolume->Read(_Offset, data.size(), (u8*)&data[0]); + data.erase(std::find(data.begin(), data.end(), 0x00), data.end()); + + // TODO: Should we really always use SHIFT-JIS? + // It makes some filenames in Pikmin (NTSC-U) sane, but is it correct? + return SHIFTJISToUTF8(data); } size_t CFileSystemGCWii::GetFileList(std::vector &_rFilenames) @@ -311,18 +319,16 @@ size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _ { SFileInfo *rFileInfo = &m_FileInfoVector[CurrentIndex]; u64 uOffset = _NameTableOffset + (rFileInfo->m_NameOffset & 0xFFFFFF); - char filename[512]; - memset(filename, 0, sizeof(filename)); - GetStringFromOffset(uOffset, filename); + std::string filename = GetStringFromOffset(uOffset); // check next index if (rFileInfo->IsDirectory()) { // this is a directory, build up the new szDirectory if (_szDirectory != NULL) - CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s/", _szDirectory, filename); + CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s/", _szDirectory, filename.c_str()); else - CharArrayFromFormat(rFileInfo->m_FullPath, "%s/", filename); + CharArrayFromFormat(rFileInfo->m_FullPath, "%s/", filename.c_str()); CurrentIndex = BuildFilenames(CurrentIndex + 1, (size_t) rFileInfo->m_FileSize, rFileInfo->m_FullPath, _NameTableOffset); } @@ -330,9 +336,9 @@ size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _ { // this is a filename if (_szDirectory != NULL) - CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s", _szDirectory, filename); + CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s", _szDirectory, filename.c_str()); else - CharArrayFromFormat(rFileInfo->m_FullPath, "%s", filename); + CharArrayFromFormat(rFileInfo->m_FullPath, "%s", filename.c_str()); CurrentIndex++; } diff --git a/Source/Core/DiscIO/Src/FileSystemGCWii.h b/Source/Core/DiscIO/Src/FileSystemGCWii.h index 0e7d836d75..9054ade272 100644 --- a/Source/Core/DiscIO/Src/FileSystemGCWii.h +++ b/Source/Core/DiscIO/Src/FileSystemGCWii.h @@ -28,7 +28,7 @@ namespace DiscIO class CFileSystemGCWii : public IFileSystem { public: - CFileSystemGCWii(const IVolume *_rVolume); + CFileSystemGCWii(const IVolume* _rVolume); virtual ~CFileSystemGCWii(); virtual bool IsValid() const { return m_Valid; } virtual u64 GetFileSize(const char* _rFullPath); @@ -44,11 +44,11 @@ public: private: bool m_Initialized; bool m_Valid; - u32 m_OffsetShift; // WII offsets are all shifted + std::vector m_FileInfoVector; u32 Read32(u64 _Offset) const; - void GetStringFromOffset(u64 _Offset, char* Filename) const; + std::string GetStringFromOffset(u64 _Offset) const; const SFileInfo* FindFileInfo(const char* _rFullPath); bool DetectFileSystem(); void InitFileSystem(); diff --git a/Source/Core/DiscIO/Src/VolumeGC.cpp b/Source/Core/DiscIO/Src/VolumeGC.cpp index 6e9579571a..6210172790 100644 --- a/Source/Core/DiscIO/Src/VolumeGC.cpp +++ b/Source/Core/DiscIO/Src/VolumeGC.cpp @@ -94,10 +94,12 @@ std::string CVolumeGC::GetMakerID() const std::vector CVolumeGC::GetNames() const { std::vector names; + + auto const string_decoder = GetStringDecoder(GetCountry()); - char name[128] = {}; - if (m_pReader != NULL && Read(0x20, 0x60, (u8*)&name)) - names.push_back(name); + char name[0x60 + 1] = {}; + if (m_pReader != NULL && Read(0x20, 0x60, (u8*)name)) + names.push_back(string_decoder(name)); return names; } @@ -143,4 +145,10 @@ bool CVolumeGC::IsDiscTwo() const return discTwo; } +auto CVolumeGC::GetStringDecoder(ECountry country) -> StringDecoder +{ + return (COUNTRY_JAPAN == country || COUNTRY_TAIWAN == country) ? + SHIFTJISToUTF8 : CP1252ToUTF8; +} + } // namespace diff --git a/Source/Core/DiscIO/Src/VolumeGC.h b/Source/Core/DiscIO/Src/VolumeGC.h index dab1ad7a9d..d7729ee04c 100644 --- a/Source/Core/DiscIO/Src/VolumeGC.h +++ b/Source/Core/DiscIO/Src/VolumeGC.h @@ -40,6 +40,10 @@ public: ECountry GetCountry() const; u64 GetSize() const; bool IsDiscTwo() const; + + typedef std::string(*StringDecoder)(const std::string&); + + static StringDecoder GetStringDecoder(ECountry country); private: IBlobReader* m_pReader; diff --git a/Source/Core/DiscIO/Src/VolumeWad.cpp b/Source/Core/DiscIO/Src/VolumeWad.cpp index 72788f1017..ed95774b2e 100644 --- a/Source/Core/DiscIO/Src/VolumeWad.cpp +++ b/Source/Core/DiscIO/Src/VolumeWad.cpp @@ -15,6 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ +#include #include #include "VolumeWad.h" @@ -117,33 +118,32 @@ std::vector CVolumeWAD::GetNames() const { return names; } + + footer_size = Common::swap32(footer_size); + //Japanese, English, German, French, Spanish, Italian, Dutch, unknown, unknown, Korean - - // Offset to the english title - for (int i = 0; i < 10; i++) + for (int i = 0; i != 10; ++i) { - u16 temp[42]; - std::wstring out_temp; + static const u32 string_length = 42; + static const u32 bytes_length = string_length * sizeof(u16); + + u16 temp[string_length]; - if (!Read(0x9C + (i*84) + OpeningBnrOffset, 84, (u8*)&temp) || Common::swap32(footer_size) < 0xF1 - || !temp[0]) + if (footer_size < 0xF1 || !Read(0x9C + (i * bytes_length) + OpeningBnrOffset, bytes_length, (u8*)&temp)) { names.push_back(""); - continue; + ERROR_LOG(COMMON, "added empty WAD name"); } - for (int j = 0; j < 42; ++j) + else { - u16 t = Common::swap16(temp[j]); - if (t == 0 && j > 0) - { - if (out_temp.at(out_temp.size()-1) != ' ') - out_temp.push_back(' '); - } - else - out_temp.push_back(t); + std::wstring out_temp; + out_temp.resize(string_length); + std::transform(temp, temp + out_temp.size(), out_temp.begin(), (u16(&)(u16))Common::swap16); + out_temp.erase(std::find(out_temp.begin(), out_temp.end(), 0x00), out_temp.end()); + + names.push_back(UTF16ToUTF8(out_temp)); + ERROR_LOG(COMMON, "decoded WAD name: %s", names.back().c_str()); } - - names.push_back(UTF16ToUTF8(out_temp)); } return names; diff --git a/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp index f375b9e66d..32aa92bd08 100644 --- a/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include "VolumeWiiCrypted.h" +#include "VolumeGC.h" #include "StringUtil.h" #include "Crypto/sha1.h" @@ -171,12 +172,12 @@ std::string CVolumeWiiCrypted::GetMakerID() const std::vector CVolumeWiiCrypted::GetNames() const { std::vector names; + + auto const string_decoder = CVolumeGC::GetStringDecoder(GetCountry()); char name[0xFF] = {}; if (m_pReader != NULL && Read(0x20, 0x60, (u8*)&name)) - { - names.push_back(name); - } + names.push_back(string_decoder(name)); return names; } From ae14578bc5bddd5ebc3e97483dc844bfe5a0e7de Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 3 Mar 2013 17:56:40 -0600 Subject: [PATCH 63/70] Eliminate some netplay gamelist ugliness. --- Source/Core/Core/Src/NetPlay.h | 2 +- Source/Core/DolphinWX/Src/Frame.cpp | 4 +- Source/Core/DolphinWX/Src/GameListCtrl.cpp | 34 +++------------ Source/Core/DolphinWX/Src/GameListCtrl.h | 8 ---- Source/Core/DolphinWX/Src/NetWindow.cpp | 50 +++++++++++----------- 5 files changed, 36 insertions(+), 62 deletions(-) diff --git a/Source/Core/Core/Src/NetPlay.h b/Source/Core/Core/Src/NetPlay.h index e77f972785..96ff78995a 100644 --- a/Source/Core/Core/Src/NetPlay.h +++ b/Source/Core/Core/Src/NetPlay.h @@ -34,7 +34,7 @@ struct Rpt : public std::vector typedef std::vector NetWiimote; -#define NETPLAY_VERSION "Dolphin NetPlay r6423" +#define NETPLAY_VERSION "Dolphin NetPlay 2013-03-03" // messages enum diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index b0b53cc5ea..a0a030081e 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -659,7 +659,7 @@ void CFrame::OnGameListCtrl_ItemActivated(wxListEvent& WXUNUSED (event)) // 1. Boot the selected iso // 2. Boot the default or last loaded iso. // 3. Call BrowseForDirectory if the gamelist is empty - if (!m_GameListCtrl->GetGameNames().size() && + if (!m_GameListCtrl->GetISO(0) && !((SConfig::GetInstance().m_ListGC && SConfig::GetInstance().m_ListWii && SConfig::GetInstance().m_ListWad) && @@ -693,7 +693,7 @@ void CFrame::OnGameListCtrl_ItemActivated(wxListEvent& WXUNUSED (event)) m_GameListCtrl->Update(); } - else if (!m_GameListCtrl->GetGameNames().size()) + else if (!m_GameListCtrl->GetISO(0)) m_GameListCtrl->BrowseForDirectory(); else // Game started by double click diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index 15df0fa3ee..1a828bbf14 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -285,10 +285,6 @@ void CGameListCtrl::Update() m_imageListSmall = NULL; } - // NetPlay : Set/Reset the GameList string - m_gameList.clear(); - m_gamePath.clear(); - Hide(); ScanForISOs(); @@ -406,15 +402,6 @@ wxString NiceSizeFormat(s64 _size) return(NiceString); } -std::string CGameListCtrl::GetGamePaths() const -{ - return m_gamePath; -} -std::string CGameListCtrl::GetGameNames() const -{ - return m_gameList; -} - void CGameListCtrl::InsertItemInReportView(long _Index) { // When using wxListCtrl, there is no hope of per-column text colors. @@ -424,7 +411,6 @@ void CGameListCtrl::InsertItemInReportView(long _Index) int ImageIndex = -1; GameListItem& rISOFile = *m_ISOFiles[_Index]; - m_gamePath.append(rISOFile.GetFileName() + '\n'); // Insert a first row with nothing in it, that will be used as the Index long ItemIndex = InsertItem(_Index, wxEmptyString); @@ -438,31 +424,25 @@ void CGameListCtrl::InsertItemInReportView(long _Index) // Set the game's banner in the second column SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex); - std::string name; - int SelectedLanguage = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage; + + // Is this sane? switch (rISOFile.GetCountry()) { case DiscIO::IVolume::COUNTRY_TAIWAN: case DiscIO::IVolume::COUNTRY_JAPAN: - { - name = rISOFile.GetName(-1); - m_gameList.append(StringFromFormat("%s (J)\n", name.c_str())); - } + SelectedLanguage = -1; break; + case DiscIO::IVolume::COUNTRY_USA: - // Is this sane? SelectedLanguage = 0; + break; + default: - { - name = rISOFile.GetName(SelectedLanguage); - m_gameList.append(StringFromFormat("%s (%c)\n", name.c_str(), - (rISOFile.GetCountry() == DiscIO::IVolume::COUNTRY_USA) ? 'U' : 'E')); - - } break; } + std::string const name = rISOFile.GetName(SelectedLanguage); SetItem(_Index, COLUMN_TITLE, StrToWxStr(name), -1); // We show the company string on Gamecube only diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.h b/Source/Core/DolphinWX/Src/GameListCtrl.h index 5d97c12724..f1923e97c5 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.h +++ b/Source/Core/DolphinWX/Src/GameListCtrl.h @@ -47,10 +47,6 @@ public: void Update(); - // Net Play method - std::string GetGamePaths() const; - std::string GetGameNames() const; - void BrowseForDirectory(); const GameListItem *GetSelectedISO(); const GameListItem *GetISO(size_t index) const; @@ -84,10 +80,6 @@ private: } } - // NetPlay string for the gamelist - std::string m_gameList; - std::string m_gamePath; - int last_column; int last_sort; wxSize lastpos; diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index 60efcedc6f..8cfe41dc93 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -24,6 +24,7 @@ #include "Frame.h" #include +#include #define NETPLAY_TITLEBAR "Dolphin NetPlay" @@ -35,6 +36,21 @@ static NetPlay* netplay_ptr = NULL; extern CFrame* main_frame; NetPlayDiag *NetPlayDiag::npd = NULL; +std::string BuildGameName(const GameListItem& game) +{ + auto const selected_lang = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage; + + // TODO: this should use the name from the volume not the banner + // (I seems banner name can sometimes depend on save contents) + return game.GetName(selected_lang) + " (" + game.GetUniqueID() + ")"; +} + +void FillWithGameNames(wxListBox* game_lbox, const CGameListCtrl& game_list) +{ + for (u32 i = 0 ; auto game = game_list.GetISO(i); ++i) + game_lbox->Append(StrToWxStr(BuildGameName(*game))); +} + NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* const game_list) : wxFrame(parent, wxID_ANY, wxT(NETPLAY_TITLEBAR), wxDefaultPosition, wxDefaultSize) , m_game_list(game_list) @@ -121,11 +137,8 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* m_game_lbox = new wxListBox(host_tab, wxID_ANY); m_game_lbox->Bind(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, &NetPlaySetupDiag::OnHost, this); - - std::istringstream ss(game_list->GetGameNames()); - std::string game; - while (std::getline(ss,game)) - m_game_lbox->Append(StrToWxStr(game)); + + FillWithGameNames(m_game_lbox, *game_list); wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL); top_szr->Add(port_lbl, 0, wxCENTER | wxRIGHT, 5); @@ -360,24 +373,17 @@ void NetPlayDiag::OnChat(wxCommandEvent&) void NetPlayDiag::OnStart(wxCommandEvent&) { - // find path for selected game - std::string ntmp, ptmp, path; - std::istringstream nss(m_game_list->GetGameNames()), pss(m_game_list->GetGamePaths()); - - while(std::getline(nss,ntmp)) + // find path for selected game, sloppy.. + for (u32 i = 0 ; auto game = m_game_list->GetISO(i); ++i) { - std::getline(pss,ptmp); - if (m_selected_game == ntmp) + if (m_selected_game == BuildGameName(*game)) { - path = ptmp; - break; + netplay_ptr->StartGame(game->GetFileName()); + return; } } - - if (path.length()) - netplay_ptr->StartGame(path); - else - PanicAlertT("Game not found!!"); + + PanicAlertT("Game not found!"); } void NetPlayDiag::OnStop(wxCommandEvent&) @@ -550,11 +556,7 @@ ChangeGameDiag::ChangeGameDiag(wxWindow* const parent, const CGameListCtrl* cons m_game_lbox = new wxListBox(this, wxID_ANY); m_game_lbox->Bind(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, &ChangeGameDiag::OnPick, this); - // fill list with games - std::istringstream ss(game_list->GetGameNames()); - std::string game; - while (std::getline(ss,game)) - m_game_lbox->Append(StrToWxStr(game)); + FillWithGameNames(m_game_lbox, *game_list); wxButton* const ok_btn = new wxButton(this, wxID_OK, _("Change")); ok_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &ChangeGameDiag::OnPick, this); From a30636cb88679d5f7a886aba6e5de83f4123f968 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 3 Mar 2013 18:00:48 -0600 Subject: [PATCH 64/70] Buildfix. --- Source/Core/DolphinWX/Src/NetWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index 8cfe41dc93..28c7f930d7 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -22,6 +22,7 @@ #include "NetPlay.h" #include "NetWindow.h" #include "Frame.h" +#include "ConfigManager.h" #include #include From 6026b298449f480ea96285242c4ed9253c854a22 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 3 Mar 2013 18:29:56 -0600 Subject: [PATCH 65/70] Separate banner and volume name getting functions. Game properties now shows the correct "banner" name in more cases. --- Source/Core/DolphinWX/Src/ISOFile.cpp | 50 +++++++++++++++------ Source/Core/DolphinWX/Src/ISOFile.h | 2 + Source/Core/DolphinWX/Src/ISOProperties.cpp | 21 ++++----- Source/Core/DolphinWX/Src/NetWindow.cpp | 12 ++--- 4 files changed, 54 insertions(+), 31 deletions(-) diff --git a/Source/Core/DolphinWX/Src/ISOFile.cpp b/Source/Core/DolphinWX/Src/ISOFile.cpp index ec8280a726..797780c32e 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.cpp +++ b/Source/Core/DolphinWX/Src/ISOFile.cpp @@ -226,28 +226,50 @@ std::string GameListItem::GetDescription(int _index) const } // (-1 = Japanese, 0 = English, etc) -std::string GameListItem::GetName(int _index) const +std::string GameListItem::GetVolumeName(int _index) const { u32 const index = _index + 1; - // banner name - if (index < m_names.size() && !m_names[index].empty()) - return m_names[index]; - - if (!m_names.empty() && !m_names[0].empty()) - return m_names[0]; - - // volume name if (index < m_volume_names.size() && !m_volume_names[index].empty()) return m_volume_names[index]; - if (!m_volume_names.empty() && !m_volume_names[0].empty()) + if (!m_volume_names.empty()) return m_volume_names[0]; + + return ""; +} - // No usable name, return filename (better than nothing) - std::string FileName; - SplitPath(m_FileName, NULL, &FileName, NULL); - return FileName; +// (-1 = Japanese, 0 = English, etc) +std::string GameListItem::GetBannerName(int _index) const +{ + u32 const index = _index + 1; + + if (index < m_names.size() && !m_names[index].empty()) + return m_names[index]; + + if (!m_names.empty()) + return m_names[0]; + + return ""; +} + +// (-1 = Japanese, 0 = English, etc) +std::string GameListItem::GetName(int _index) const +{ + // Prefer name from banner, fallback to name from volume, fallback to filename + + std::string name = GetBannerName(_index); + + if (name.empty()) + name = GetVolumeName(_index); + + if (name.empty()) + { + // No usable name, return filename (better than nothing) + SplitPath(GetFileName(), NULL, &name, NULL); + } + + return name; } const std::string GameListItem::GetWiiFSPath() const diff --git a/Source/Core/DolphinWX/Src/ISOFile.h b/Source/Core/DolphinWX/Src/ISOFile.h index ded392f56a..354a2f7fad 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.h +++ b/Source/Core/DolphinWX/Src/ISOFile.h @@ -37,6 +37,8 @@ public: bool IsValid() const {return m_Valid;} const std::string& GetFileName() const {return m_FileName;} + std::string GetBannerName(int index) const; + std::string GetVolumeName(int index) const; std::string GetName(int index) const; std::string GetCompany() const; std::string GetDescription(int index = 0) const; diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index 43657300cb..f6ca1cb851 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -1301,28 +1301,25 @@ void CISOProperties::OnChangeBannerLang(wxCommandEvent& event) void CISOProperties::ChangeBannerDetails(int lang) { - std::string name; - wxString shortName, - comment, - maker; - + // why? switch (OpenGameListItem->GetCountry()) { case DiscIO::IVolume::COUNTRY_TAIWAN: case DiscIO::IVolume::COUNTRY_JAPAN: - shortName = StrToWxStr(OpenGameListItem->GetName(-1)); - comment = StrToWxStr(OpenGameListItem->GetDescription()); + lang = -1; break; + case DiscIO::IVolume::COUNTRY_USA: - // why? lang = 0; + break; + default: - shortName = StrToWxStr(OpenGameListItem->GetName(lang)); - comment = StrToWxStr(OpenGameListItem->GetDescription(lang)); break; } - - maker = StrToWxStr(OpenGameListItem->GetCompany()); + + wxString const shortName = StrToWxStr(OpenGameListItem->GetBannerName(lang)); + wxString const comment = StrToWxStr(OpenGameListItem->GetDescription(lang)); + wxString const maker = StrToWxStr(OpenGameListItem->GetCompany()); // Updates the informations shown in the window m_ShortName->SetValue(shortName); diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index 28c7f930d7..76bb76881b 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -22,7 +22,6 @@ #include "NetPlay.h" #include "NetWindow.h" #include "Frame.h" -#include "ConfigManager.h" #include #include @@ -39,11 +38,14 @@ NetPlayDiag *NetPlayDiag::npd = NULL; std::string BuildGameName(const GameListItem& game) { - auto const selected_lang = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage; + // Lang needs to be consistent + auto const lang = 0; - // TODO: this should use the name from the volume not the banner - // (I seems banner name can sometimes depend on save contents) - return game.GetName(selected_lang) + " (" + game.GetUniqueID() + ")"; + std::string name(game.GetBannerName(lang)); + if (name.empty()) + name = game.GetVolumeName(lang); + + return name + " (" + game.GetUniqueID() + ")"; } void FillWithGameNames(wxListBox* game_lbox, const CGameListCtrl& game_list) From bdc96342baa369fc63c013ce385aa780e096ff8f Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 3 Mar 2013 18:40:50 -0600 Subject: [PATCH 66/70] More string conversion cleanup. --- Source/Core/DolphinWX/Src/LogWindow.cpp | 2 +- Source/Core/DolphinWX/Src/Main.cpp | 2 +- Source/Core/DolphinWX/Src/VideoConfigDiag.cpp | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/Core/DolphinWX/Src/LogWindow.cpp b/Source/Core/DolphinWX/Src/LogWindow.cpp index 57e2ac6b58..27e5856410 100644 --- a/Source/Core/DolphinWX/Src/LogWindow.cpp +++ b/Source/Core/DolphinWX/Src/LogWindow.cpp @@ -192,7 +192,7 @@ void CLogWindow::SaveSettings() void CLogWindow::OnSubmit(wxCommandEvent& WXUNUSED (event)) { if (!m_cmdline) return; - Console_Submit(m_cmdline->GetValue().To8BitData()); + Console_Submit(WxStrToStr(m_cmdline->GetValue()).c_str()); m_cmdline->SetValue(wxEmptyString); } diff --git a/Source/Core/DolphinWX/Src/Main.cpp b/Source/Core/DolphinWX/Src/Main.cpp index 60a8157c28..09387f2764 100644 --- a/Source/Core/DolphinWX/Src/Main.cpp +++ b/Source/Core/DolphinWX/Src/Main.cpp @@ -445,7 +445,7 @@ bool wxMsgAlert(const char* caption, const char* text, bool yes_no, int /*Style* std::string wxStringTranslator(const char *text) { - return WxStrToStr(wxGetTranslation(wxString::From8BitData(text))); + return WxStrToStr(wxGetTranslation(wxString::FromUTF8(text))); } // Accessor for the main window class diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp index 154a5bc602..cf44c231fe 100644 --- a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp @@ -180,8 +180,7 @@ wxArrayString GetListOfResolutions() VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, const std::string& _ininame) : wxDialog(parent, -1, - wxString::Format(_("Dolphin %s Graphics Configuration"), - wxGetTranslation(wxString::From8BitData(title.c_str()))), + wxString::Format(_("Dolphin %s Graphics Configuration"), wxGetTranslation(StrToWxStr(title))), wxDefaultPosition, wxDefaultSize) , vconfig(g_Config) , ininame(_ininame) From 6b2818199c0674abcbd40b258ca9de2d65d0d132 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 3 Mar 2013 19:00:29 -0600 Subject: [PATCH 67/70] Fix WAD volume name extracting. --- Source/Core/DiscIO/Src/VolumeWad.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/Core/DiscIO/Src/VolumeWad.cpp b/Source/Core/DiscIO/Src/VolumeWad.cpp index ed95774b2e..a10e5bdb42 100644 --- a/Source/Core/DiscIO/Src/VolumeWad.cpp +++ b/Source/Core/DiscIO/Src/VolumeWad.cpp @@ -111,7 +111,6 @@ bool CVolumeWAD::GetTitleID(u8* _pBuffer) const std::vector CVolumeWAD::GetNames() const { std::vector names; - return names; u32 footer_size; if (!Read(0x1C, 4, (u8*)&footer_size)) @@ -132,7 +131,6 @@ std::vector CVolumeWAD::GetNames() const if (footer_size < 0xF1 || !Read(0x9C + (i * bytes_length) + OpeningBnrOffset, bytes_length, (u8*)&temp)) { names.push_back(""); - ERROR_LOG(COMMON, "added empty WAD name"); } else { @@ -142,7 +140,6 @@ std::vector CVolumeWAD::GetNames() const out_temp.erase(std::find(out_temp.begin(), out_temp.end(), 0x00), out_temp.end()); names.push_back(UTF16ToUTF8(out_temp)); - ERROR_LOG(COMMON, "decoded WAD name: %s", names.back().c_str()); } } From 989f0663eb212164e11e80626fa89900d2f1ae3e Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 3 Mar 2013 19:14:13 -0600 Subject: [PATCH 68/70] Make "Crypto" file opening unicode-safe on Windows. --- Source/Core/Common/Src/Crypto/md5.cpp | 9 ++++++--- Source/Core/Common/Src/Crypto/sha1.cpp | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Source/Core/Common/Src/Crypto/md5.cpp b/Source/Core/Common/Src/Crypto/md5.cpp index 7fff7713da..ef31636aea 100644 --- a/Source/Core/Common/Src/Crypto/md5.cpp +++ b/Source/Core/Common/Src/Crypto/md5.cpp @@ -37,6 +37,8 @@ #include #include +#include "FileUtil.h" + /* * 32-bit integer manipulation macros (little endian) */ @@ -301,7 +303,10 @@ int md5_file( char *path, unsigned char output[16] ) md5_context ctx; unsigned char buf[1024]; - if( ( f = fopen( path, "rb" ) ) == NULL ) + File::IOFile file(path, "rb"); + f = file.GetHandle(); + + if (f == NULL) return( 1 ); md5_starts( &ctx ); @@ -315,11 +320,9 @@ int md5_file( char *path, unsigned char output[16] ) if( ferror( f ) != 0 ) { - fclose( f ); return( 2 ); } - fclose( f ); return( 0 ); } diff --git a/Source/Core/Common/Src/Crypto/sha1.cpp b/Source/Core/Common/Src/Crypto/sha1.cpp index 17ad930986..3d26dc8a50 100644 --- a/Source/Core/Common/Src/Crypto/sha1.cpp +++ b/Source/Core/Common/Src/Crypto/sha1.cpp @@ -36,6 +36,8 @@ #include #include +#include "FileUtil.h" + /* * 32-bit integer manipulation macros (big endian) */ @@ -335,7 +337,10 @@ int sha1_file( char *path, unsigned char output[20] ) sha1_context ctx; unsigned char buf[1024]; - if( ( f = fopen( path, "rb" ) ) == NULL ) + File::IOFile file(path, "rb"); + f = file.GetHandle(); + + if (f == NULL) return( 1 ); sha1_starts( &ctx ); @@ -349,11 +354,9 @@ int sha1_file( char *path, unsigned char output[20] ) if( ferror( f ) != 0 ) { - fclose( f ); return( 2 ); } - fclose( f ); return( 0 ); } From 814c2ffdfd213dfa78078471d298e2657b7e14e9 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 3 Mar 2013 19:18:04 -0600 Subject: [PATCH 69/70] Fix some leaking file handles and buildfix probably. --- Source/Core/Common/Src/ArmCPUDetect.cpp | 17 +++++++++-------- Source/Core/Common/Src/Crypto/md5.cpp | 2 +- Source/Core/Common/Src/Crypto/sha1.cpp | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Source/Core/Common/Src/ArmCPUDetect.cpp b/Source/Core/Common/Src/ArmCPUDetect.cpp index c03ab08c48..8b5cbf9b79 100644 --- a/Source/Core/Common/Src/ArmCPUDetect.cpp +++ b/Source/Core/Common/Src/ArmCPUDetect.cpp @@ -18,6 +18,7 @@ #include "Common.h" #include "CPUDetect.h" #include "StringUtil.h" +#include "FileUtil.h" const char procfile[] = "/proc/cpuinfo"; @@ -27,9 +28,9 @@ char *GetCPUString() char *cpu_string = 0; // Count the number of processor lines in /proc/cpuinfo char buf[1024]; - FILE *fp; - fp = fopen(procfile, "r"); + File::IOFile file(procfile, "r"); + auto const fp = file.GetHandle(); if (!fp) return 0; @@ -47,9 +48,9 @@ bool CheckCPUFeature(const char *feature) { const char marker[] = "Features\t: "; char buf[1024]; - FILE *fp; - - fp = fopen(procfile, "r"); + + File::IOFile file(procfile, "r"); + auto const fp = file.GetHandle(); if (!fp) return 0; @@ -73,9 +74,9 @@ int GetCoreCount() const char marker[] = "processor\t: "; int cores = 0; char buf[1024]; - FILE *fp; - - fp = fopen(procfile, "r"); + + File::IOFile file(procfile, "r"); + auto const fp = file.GetHandle(); if (!fp) return 0; diff --git a/Source/Core/Common/Src/Crypto/md5.cpp b/Source/Core/Common/Src/Crypto/md5.cpp index ef31636aea..7b8dc149f4 100644 --- a/Source/Core/Common/Src/Crypto/md5.cpp +++ b/Source/Core/Common/Src/Crypto/md5.cpp @@ -37,7 +37,7 @@ #include #include -#include "FileUtil.h" +#include "../FileUtil.h" /* * 32-bit integer manipulation macros (little endian) diff --git a/Source/Core/Common/Src/Crypto/sha1.cpp b/Source/Core/Common/Src/Crypto/sha1.cpp index 3d26dc8a50..45b88b2b6e 100644 --- a/Source/Core/Common/Src/Crypto/sha1.cpp +++ b/Source/Core/Common/Src/Crypto/sha1.cpp @@ -36,7 +36,7 @@ #include #include -#include "FileUtil.h" +#include "../FileUtil.h" /* * 32-bit integer manipulation macros (big endian) From 0041ec618c46ea2bf99fb1fc068e7c4a263cb4c2 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 3 Mar 2013 20:16:01 -0600 Subject: [PATCH 70/70] Don't null-terminate some random std::string. --- Source/Core/Core/Src/HW/GCMemcard.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Source/Core/Core/Src/HW/GCMemcard.cpp b/Source/Core/Core/Src/HW/GCMemcard.cpp index dd15a32914..a2c9690b4e 100644 --- a/Source/Core/Core/Src/HW/GCMemcard.cpp +++ b/Source/Core/Core/Src/HW/GCMemcard.cpp @@ -432,7 +432,6 @@ std::string GCMemcard::DEntry_BIFlags(u8 index) const flags.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } - flags.push_back(0); return flags; } @@ -469,7 +468,6 @@ std::string GCMemcard::DEntry_IconFmt(u8 index) const format.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } - format.push_back(0); return format; } @@ -485,7 +483,6 @@ std::string GCMemcard::DEntry_AnimSpeed(u8 index) const speed.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } - speed.push_back(0); return speed; } @@ -498,7 +495,6 @@ std::string GCMemcard::DEntry_Permissions(u8 index) const permissionsString.push_back((Permissions & 16) ? 'x' : 'M'); permissionsString.push_back((Permissions & 8) ? 'x' : 'C'); permissionsString.push_back((Permissions & 4) ? 'P' : 'x'); - permissionsString.push_back(0); return permissionsString; }