diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f498bc890..99b390d14b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -400,7 +400,7 @@ set(CommonARM Common/ArmCPUDetect.cpp Common/ArmEmitter.h Common/ArmEmitter.cpp - Common/ColorConvNEON.cpp + Common/Data/Convert/ColorConvNEON.cpp ) source_group(ARM FILES ${CommonARM}) @@ -460,6 +460,8 @@ add_library(Common STATIC Common/Data/Collections/ThreadSafeList.h Common/Data/Color/RGBAUtil.cpp Common/Data/Color/RGBAUtil.h + Common/Data/Convert/ColorConv.cpp + Common/Data/Convert/ColorConv.h Common/Data/Convert/SmallDataConvert.cpp Common/Data/Convert/SmallDataConvert.h Common/Data/Encoding/Base64.cpp @@ -573,6 +575,8 @@ add_library(Common STATIC Common/Net/HTTPHeaders.h Common/Net/HTTPServer.cpp Common/Net/HTTPServer.h + Common/Net/NetBuffer.cpp + Common/Net/NetBuffer.h Common/Net/Resolve.cpp Common/Net/Resolve.h Common/Net/Sinks.cpp @@ -624,8 +628,6 @@ add_library(Common STATIC Common/Buffer.h Common/Buffer.cpp Common/CodeBlock.h - Common/ColorConv.cpp - Common/ColorConv.h Common/Common.h Common/CommonFuncs.h Common/CommonTypes.h diff --git a/Common/Buffer.cpp b/Common/Buffer.cpp index 68c7e7682e..fd25b0ad97 100644 --- a/Common/Buffer.cpp +++ b/Common/Buffer.cpp @@ -1,24 +1,7 @@ +#include +#include +#include -#include -#include -#include - -#ifdef _WIN32 -#include -#undef min -#undef max -#else -#include -#include -#endif - -#ifndef MSG_NOSIGNAL -// Default value to 0x00 (do nothing) in systems where it's not supported. -#define MSG_NOSIGNAL 0x00 -#endif - -#include "Common/File/FileDescriptor.h" -#include "Common/TimeUtil.h" #include "Common/Buffer.h" #include "Common/Log.h" @@ -36,14 +19,14 @@ char *Buffer::Append(size_t length) { } void Buffer::Append(const std::string &str) { - char *ptr = Append(str.size()); - memcpy(ptr, str.data(), str.size()); + char *ptr = Append(str.size()); + memcpy(ptr, str.data(), str.size()); } void Buffer::Append(const char *str) { - size_t len = strlen(str); - char *dest = Append(len); - memcpy(dest, str, len); + size_t len = strlen(str); + char *dest = Append(len); + memcpy(dest, str, len); } void Buffer::Append(const Buffer &other) { @@ -55,10 +38,10 @@ void Buffer::Append(const Buffer &other) { } void Buffer::AppendValue(int value) { - char buf[16]; - // This is slow. - sprintf(buf, "%i", value); - Append(buf); + char buf[16]; + // This is slow. + sprintf(buf, "%i", value); + Append(buf); } void Buffer::Take(size_t length, std::string *dest) { @@ -78,14 +61,14 @@ void Buffer::Take(size_t length, char *dest) { } int Buffer::TakeLineCRLF(std::string *dest) { - int after_next_line = OffsetToAfterNextCRLF(); - if (after_next_line < 0) - return after_next_line; - else { - Take(after_next_line - 2, dest); - Skip(2); // Skip the CRLF - return after_next_line - 2; - } + int after_next_line = OffsetToAfterNextCRLF(); + if (after_next_line < 0) { + return after_next_line; + } else { + Take(after_next_line - 2, dest); + Skip(2); // Skip the CRLF + return after_next_line - 2; + } } void Buffer::Skip(size_t length) { @@ -97,48 +80,39 @@ void Buffer::Skip(size_t length) { } int Buffer::SkipLineCRLF() { - int after_next_line = OffsetToAfterNextCRLF(); - if (after_next_line < 0) - return after_next_line; - else { - Skip(after_next_line); - return after_next_line - 2; - } + int after_next_line = OffsetToAfterNextCRLF(); + if (after_next_line < 0) { + return after_next_line; + } else { + Skip(after_next_line); + return after_next_line - 2; + } } int Buffer::OffsetToAfterNextCRLF() { - for (int i = 0; i < (int)data_.size() - 1; i++) { - if (data_[i] == '\r' && data_[i + 1] == '\n') { - return i + 2; - } - } - return -1; + for (int i = 0; i < (int)data_.size() - 1; i++) { + if (data_[i] == '\r' && data_[i + 1] == '\n') { + return i + 2; + } + } + return -1; } void Buffer::Printf(const char *fmt, ...) { - char buffer[2048]; - va_list vl; - va_start(vl, fmt); - size_t retval = vsnprintf(buffer, sizeof(buffer), fmt, vl); - if ((int)retval >= (int)sizeof(buffer)) { - // Output was truncated. TODO: Do something. - ERROR_LOG(IO, "Buffer::Printf truncated output"); - } - if (retval < 0) { - ERROR_LOG(IO, "Buffer::Printf failed"); - } - va_end(vl); - char *ptr = Append(retval); - memcpy(ptr, buffer, retval); -} - -bool Buffer::Flush(int fd) { - // Look into using send() directly. - bool success = data_.size() == fd_util::WriteLine(fd, &data_[0], data_.size()); - if (success) { - data_.resize(0); - } - return success; + char buffer[2048]; + va_list vl; + va_start(vl, fmt); + size_t retval = vsnprintf(buffer, sizeof(buffer), fmt, vl); + if ((int)retval >= (int)sizeof(buffer)) { + // Output was truncated. TODO: Do something. + ERROR_LOG(IO, "Buffer::Printf truncated output"); + } + if (retval < 0) { + ERROR_LOG(IO, "Buffer::Printf failed"); + } + va_end(vl); + char *ptr = Append(retval); + memcpy(ptr, buffer, retval); } bool Buffer::FlushToFile(const char *filename) { @@ -152,116 +126,6 @@ bool Buffer::FlushToFile(const char *filename) { return true; } -bool Buffer::FlushSocket(uintptr_t sock, double timeout, bool *cancelled) { - static constexpr float CANCEL_INTERVAL = 0.25f; - for (size_t pos = 0, end = data_.size(); pos < end; ) { - bool ready = false; - double leftTimeout = timeout; - while (!ready && (leftTimeout >= 0 || cancelled)) { - if (cancelled && *cancelled) - return false; - ready = fd_util::WaitUntilReady(sock, CANCEL_INTERVAL, true); - if (!ready && leftTimeout >= 0.0) { - leftTimeout -= CANCEL_INTERVAL; - if (leftTimeout < 0) { - ERROR_LOG(IO, "FlushSocket timed out"); - return false; - } - } - } - int sent = send(sock, &data_[pos], (int)(end - pos), MSG_NOSIGNAL); - if (sent < 0) { - ERROR_LOG(IO, "FlushSocket failed"); - return false; - } - pos += sent; - - // Buffer full, don't spin. - if (sent == 0 && timeout < 0.0) { - sleep_ms(1); - } - } - data_.resize(0); - return true; -} - -bool Buffer::ReadAll(int fd, int hintSize) { - std::vector buf; - if (hintSize >= 65536 * 16) { - buf.resize(65536); - } else if (hintSize >= 1024 * 16) { - buf.resize(hintSize / 16); - } else { - buf.resize(4096); - } - - while (true) { - int retval = recv(fd, &buf[0], (int)buf.size(), MSG_NOSIGNAL); - if (retval == 0) { - break; - } else if (retval < 0) { - ERROR_LOG(IO, "Error reading from buffer: %i", retval); - return false; - } - char *p = Append((size_t)retval); - memcpy(p, &buf[0], retval); - } - return true; -} - -bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress, bool *cancelled) { - static constexpr float CANCEL_INTERVAL = 0.25f; - std::vector buf; - if (knownSize >= 65536 * 16) { - buf.resize(65536); - } else if (knownSize >= 1024 * 16) { - buf.resize(knownSize / 16); - } else { - buf.resize(1024); - } - - int total = 0; - while (true) { - bool ready = false; - while (!ready && cancelled) { - if (*cancelled) - return false; - ready = fd_util::WaitUntilReady(fd, CANCEL_INTERVAL, false); - } - int retval = recv(fd, &buf[0], (int)buf.size(), MSG_NOSIGNAL); - if (retval == 0) { - return true; - } else if (retval < 0) { - ERROR_LOG(IO, "Error reading from buffer: %i", retval); - return false; - } - char *p = Append((size_t)retval); - memcpy(p, &buf[0], retval); - total += retval; - if (progress) - *progress = (float)total / (float)knownSize; - } - return true; -} - -int Buffer::Read(int fd, size_t sz) { - char buf[1024]; - int retval; - size_t received = 0; - while ((retval = recv(fd, buf, (int)std::min(sz, sizeof(buf)), MSG_NOSIGNAL)) > 0) { - if (retval < 0) { - return retval; - } - char *p = Append((size_t)retval); - memcpy(p, buf, retval); - sz -= retval; - received += retval; - if (sz == 0) - return 0; - } - return (int)received; -} - void Buffer::PeekAll(std::string *dest) { dest->resize(data_.size()); memcpy(&(*dest)[0], &data_[0], data_.size()); diff --git a/Common/Buffer.h b/Common/Buffer.h index ef93a2945c..2e92669b29 100644 --- a/Common/Buffer.h +++ b/Common/Buffer.h @@ -10,8 +10,15 @@ class Buffer { public: Buffer(); + Buffer(Buffer &&) = default; ~Buffer(); + static Buffer Void() { + Buffer buf; + buf.void_ = true; + return buf; + } + // Write max [length] bytes to the returned pointer. // Any other operation on this Buffer invalidates the pointer. char *Append(size_t length); @@ -59,25 +66,19 @@ public: // Writes the entire buffer to the file descriptor. Also resets the // size to zero. On failure, data remains in buffer and nothing is // written. - bool Flush(int fd); bool FlushToFile(const char *filename); - bool FlushSocket(uintptr_t sock, double timeout = -1.0, bool *cancelled = nullptr); // Windows portability - - bool ReadAll(int fd, int hintSize = 0); - bool ReadAllWithProgress(int fd, int knownSize, float *progress, bool *cancelled); - - // < 0: error - // >= 0: number of bytes read - int Read(int fd, size_t sz); // Utilities. Try to avoid checking for size. size_t size() const { return data_.size(); } bool empty() const { return size() == 0; } void clear() { data_.resize(0); } + bool IsVoid() { return void_; } -private: +protected: // TODO: Find a better internal representation, like a cord. std::vector data_; + bool void_ = false; +private: DISALLOW_COPY_AND_ASSIGN(Buffer); }; diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 7595b60f80..384ac4b8b6 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -452,6 +452,7 @@ + @@ -469,12 +470,12 @@ - + - + @@ -705,7 +706,7 @@ - + true true true @@ -775,6 +776,7 @@ + @@ -791,7 +793,7 @@ - + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index dd834136fc..f341effcae 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -32,8 +32,6 @@ - - GL\GLInterface @@ -70,7 +68,6 @@ - ext\libpng17 @@ -384,6 +381,16 @@ GPU + + Data\Convert + + + Data\Convert + + + + Net + @@ -410,8 +417,6 @@ - - GL\GLInterface @@ -432,7 +437,6 @@ - ext\libpng17 @@ -740,6 +744,16 @@ GPU + + Data\Convert + + + Data\Convert + + + + Net + diff --git a/Common/ColorConv.cpp b/Common/Data/Convert/ColorConv.cpp similarity index 95% rename from Common/ColorConv.cpp rename to Common/Data/Convert/ColorConv.cpp index 0e48cca0bc..5404e89bca 100644 --- a/Common/ColorConv.cpp +++ b/Common/Data/Convert/ColorConv.cpp @@ -16,12 +16,12 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "ppsspp_config.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/Data/Convert/SmallDataConvert.h" -#include "ColorConv.h" // NEON is in a separate file so that it can be compiled with a runtime check. -#include "ColorConvNEON.h" -#include "Common.h" -#include "CPUDetect.h" +#include "Common/Data/Convert/ColorConvNEON.h" +#include "Common/Common.h" +#include "Common/CPUDetect.h" #ifdef _M_SSE #include @@ -172,6 +172,15 @@ void ConvertBGRA8888ToRGBA8888(u32 *dst, const u32 *src, u32 numPixels) { } } +void ConvertBGRA8888ToRGB888(u8 *dst, const u32 *src, u32 numPixels) { + for (uint32_t x = 0; x < numPixels; ++x) { + uint32_t c = src[x]; + dst[x * 3 + 0] = (c >> 16) & 0xFF; + dst[x * 3 + 1] = (c >> 8) & 0xFF; + dst[x * 3 + 2] = (c >> 0) & 0xFF; + } +} + void ConvertRGBA8888ToRGBA5551(u16 *dst, const u32 *src, u32 numPixels) { #if _M_SSE >= 0x401 const __m128i maskAG = _mm_set1_epi32(0x8000F800); @@ -280,6 +289,12 @@ void ConvertRGBA8888ToRGBA4444(u16 *dst, const u32 *src, u32 numPixels) { } } +void ConvertRGBA8888ToRGB888(u8 *dst, const u32 *src, u32 numPixels) { + for (uint32_t x = 0; x < numPixels; ++x) { + memcpy(dst + x * 3, src + x, 3); + } +} + void ConvertRGB565ToRGBA8888(u32 *dst32, const u16 *src, u32 numPixels) { #ifdef _M_SSE const __m128i mask5 = _mm_set1_epi16(0x001f); @@ -637,6 +652,21 @@ void ConvertRGB565ToBGR565Basic(u16 *dst, const u16 *src, u32 numPixels) { } } +void ConvertBGRA5551ToABGR1555(u16 *dst, const u16 *src, u32 numPixels) { + const u32 *src32 = (const u32 *)src; + u32 *dst32 = (u32 *)dst; + for (u32 i = 0; i < numPixels / 2; i++) { + const u32 c = src32[i]; + dst32[i] = ((c >> 15) & 0x00010001) | ((c << 1) & 0xFFFEFFFE); + } + + if (numPixels & 1) { + const u32 i = numPixels - 1; + const u16 c = src[i]; + dst[i] = (c >> 15) | (c << 1); + } +} + // Reuse the logic from the header - if these aren't defined, we need externs. #ifndef ConvertRGBA4444ToABGR4444 Convert16bppTo16bppFunc ConvertRGBA4444ToABGR4444 = &ConvertRGBA4444ToABGR4444Basic; diff --git a/Common/ColorConv.h b/Common/Data/Convert/ColorConv.h similarity index 95% rename from Common/ColorConv.h rename to Common/Data/Convert/ColorConv.h index 9e66b73ea8..e695f3ce8f 100644 --- a/Common/ColorConv.h +++ b/Common/Data/Convert/ColorConv.h @@ -18,8 +18,8 @@ #pragma once #include "ppsspp_config.h" -#include "CommonTypes.h" -#include "ColorConvNEON.h" +#include "Common/CommonTypes.h" +#include "Common/Data/Convert/ColorConvNEON.h" void SetupColorConv(); @@ -110,10 +110,12 @@ typedef void (*Convert32bppTo32bppFunc)(u32 *dst, const u32 *src, u32 numPixels) void ConvertBGRA8888ToRGBA8888(u32 *dst, const u32 *src, u32 numPixels); #define ConvertRGBA8888ToBGRA8888 ConvertBGRA8888ToRGBA8888 +void ConvertBGRA8888ToRGB888(u8 *dst, const u32 *src, u32 numPixels); void ConvertRGBA8888ToRGBA5551(u16 *dst, const u32 *src, u32 numPixels); void ConvertRGBA8888ToRGB565(u16 *dst, const u32 *src, u32 numPixels); void ConvertRGBA8888ToRGBA4444(u16 *dst, const u32 *src, u32 numPixels); +void ConvertRGBA8888ToRGB888(u8 *dst, const u32 *src, u32 numPixels); void ConvertBGRA8888ToRGBA5551(u16 *dst, const u32 *src, u32 numPixels); void ConvertBGRA8888ToRGB565(u16 *dst, const u32 *src, u32 numPixels); @@ -134,6 +136,7 @@ void ConvertRGB565ToBGRA8888(u32 *dst, const u16 *src, u32 numPixels); void ConvertRGBA4444ToABGR4444Basic(u16 *dst, const u16 *src, u32 numPixels); void ConvertRGBA5551ToABGR1555Basic(u16 *dst, const u16 *src, u32 numPixels); void ConvertRGB565ToBGR565Basic(u16 *dst, const u16 *src, u32 numPixels); +void ConvertBGRA5551ToABGR1555(u16 *dst, const u16 *src, u32 numPixels); #if PPSSPP_ARCH(ARM64) #define ConvertRGBA4444ToABGR4444 ConvertRGBA4444ToABGR4444NEON diff --git a/Common/ColorConvNEON.cpp b/Common/Data/Convert/ColorConvNEON.cpp similarity index 97% rename from Common/ColorConvNEON.cpp rename to Common/Data/Convert/ColorConvNEON.cpp index 375bcd0e75..27c230448a 100644 --- a/Common/ColorConvNEON.cpp +++ b/Common/Data/Convert/ColorConvNEON.cpp @@ -23,9 +23,9 @@ #else #include #endif -#include "ColorConvNEON.h" -#include "Common.h" -#include "CPUDetect.h" +#include "Common/Data/Convert/ColorConvNEON.h" +#include "Common/Common.h" +#include "Common/CPUDetect.h" // TODO: More NEON color conversion funcs. diff --git a/Common/ColorConvNEON.h b/Common/Data/Convert/ColorConvNEON.h similarity index 95% rename from Common/ColorConvNEON.h rename to Common/Data/Convert/ColorConvNEON.h index 43002411cd..e80fbbd324 100644 --- a/Common/ColorConvNEON.h +++ b/Common/Data/Convert/ColorConvNEON.h @@ -17,7 +17,7 @@ #pragma once -#include "ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" void ConvertRGBA4444ToABGR4444NEON(u16 *dst, const u16 *src, u32 numPixels); void ConvertRGBA5551ToABGR1555NEON(u16 *dst, const u16 *src, u32 numPixels); diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index e38712767e..ebb093bd44 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -245,7 +245,8 @@ bool IsDirectory(const std::string &filename) std::wstring copy = ConvertUTF8ToWString(fn); WIN32_FILE_ATTRIBUTE_DATA data{}; if (!GetFileAttributesEx(copy.c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) { - WARN_LOG(COMMON, "GetFileAttributes failed on %s: %08x", fn.c_str(), (uint32_t)GetLastError()); + auto err = GetLastError(); + WARN_LOG(COMMON, "GetFileAttributes failed on %s: %08x %s", fn.c_str(), (uint32_t)err, GetStringErrorMsg(err).c_str()); return false; } DWORD result = data.dwFileAttributes; @@ -311,7 +312,7 @@ bool CreateDir(const std::string &path) WARN_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: already exists", path.c_str()); return true; } - ERROR_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: %08x", path.c_str(), (uint32_t)error); + ERROR_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: %08x %s", path.c_str(), (uint32_t)error, GetStringErrorMsg(error).c_str()); return false; #else if (mkdir(fn.c_str(), 0755) == 0) diff --git a/Common/File/PathBrowser.cpp b/Common/File/PathBrowser.cpp index 5bd0c43e88..116c7cf1b3 100644 --- a/Common/File/PathBrowser.cpp +++ b/Common/File/PathBrowser.cpp @@ -32,7 +32,8 @@ bool LoadRemoteFileList(const std::string &url, bool *cancel, std::vector diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 0acb176dea..454cde20f5 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -6,6 +6,7 @@ #include "ppsspp_config.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/Data/Convert/SmallDataConvert.h" #include "Common/Math/math_util.h" #include "Common/Math/lin/matrix4x4.h" @@ -812,15 +813,6 @@ public: GLRFramebuffer *framebuffer_ = nullptr; }; -// TODO: SSE/NEON optimize, and move to ColorConv.cpp. -void MoveABit(u16 *dest, const u16 *src, size_t count) { - for (int i = 0; i < count; i++) { - u16 data = src[i]; - data = (data >> 15) | (data << 1); - dest[i] = data; - } -} - void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback callback) { if ((width != width_ || height != height_ || depth != depth_) && level == 0) { // When switching to texStorage we need to handle this correctly. @@ -843,14 +835,14 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int if (texDataPopulated) { if (format_ == DataFormat::A1R5G5B5_UNORM_PACK16) { format_ = DataFormat::R5G5B5A1_UNORM_PACK16; - MoveABit((u16 *)texData, (const u16 *)texData, width * height * depth); + ConvertBGRA5551ToABGR1555((u16 *)texData, (const u16 *)texData, width * height * depth); } } else { // Emulate support for DataFormat::A1R5G5B5_UNORM_PACK16. if (format_ == DataFormat::A1R5G5B5_UNORM_PACK16) { format_ = DataFormat::R5G5B5A1_UNORM_PACK16; for (int y = 0; y < height; y++) { - MoveABit((u16 *)(texData + y * width * alignment), (const u16 *)(data + y * stride * alignment), width); + ConvertBGRA5551ToABGR1555((u16 *)(texData + y * width * alignment), (const u16 *)(data + y * stride * alignment), width); } } else { for (int y = 0; y < height; y++) { diff --git a/Common/GPU/thin3d.cpp b/Common/GPU/thin3d.cpp index ce09c0356c..312bd91312 100644 --- a/Common/GPU/thin3d.cpp +++ b/Common/GPU/thin3d.cpp @@ -2,10 +2,10 @@ #include #include -#include "Common/System/Display.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/GPU/thin3d.h" #include "Common/Log.h" -#include "Common/ColorConv.h" +#include "Common/System/Display.h" namespace Draw { @@ -396,8 +396,6 @@ DrawContext::~DrawContext() { DestroyPresets(); } -// TODO: Use the functions we have in Common/ColorConv.cpp. -// Could also make C fake-simd for 64-bit, two 8888 pixels fit in a register :) void ConvertFromRGBA8888(uint8_t *dst, const uint8_t *src, uint32_t dstStride, uint32_t srcStride, uint32_t width, uint32_t height, DataFormat format) { // Must skip stride in the cases below. Some games pack data into the cracks, like MotoGP. const uint32_t *src32 = (const uint32_t *)src; @@ -415,9 +413,7 @@ void ConvertFromRGBA8888(uint8_t *dst, const uint8_t *src, uint32_t dstStride, u } } else if (format == Draw::DataFormat::R8G8B8_UNORM) { for (uint32_t y = 0; y < height; ++y) { - for (uint32_t x = 0; x < width; ++x) { - memcpy(dst + x * 3, src32 + x, 3); - } + ConvertRGBA8888ToRGB888(dst, src32, width); src32 += srcStride; dst += dstStride * 3; } @@ -455,8 +451,6 @@ void ConvertFromRGBA8888(uint8_t *dst, const uint8_t *src, uint32_t dstStride, u } } -// TODO: Use the functions we have in Common/ColorConv.cpp. -// Could also make C fake-simd for 64-bit, two 8888 pixels fit in a register :) void ConvertFromBGRA8888(uint8_t *dst, const uint8_t *src, uint32_t dstStride, uint32_t srcStride, uint32_t width, uint32_t height, DataFormat format) { // Must skip stride in the cases below. Some games pack data into the cracks, like MotoGP. const uint32_t *src32 = (const uint32_t *)src; @@ -481,12 +475,7 @@ void ConvertFromBGRA8888(uint8_t *dst, const uint8_t *src, uint32_t dstStride, u } } else if (format == Draw::DataFormat::R8G8B8_UNORM) { for (uint32_t y = 0; y < height; ++y) { - for (uint32_t x = 0; x < width; ++x) { - uint32_t c = src32[x]; - dst[x * 3 + 0] = (c >> 16) & 0xFF; - dst[x * 3 + 1] = (c >> 8) & 0xFF; - dst[x * 3 + 2] = (c >> 0) & 0xFF; - } + ConvertBGRA8888ToRGB888(dst, src32, width); src32 += srcStride; dst += dstStride * 3; } diff --git a/Common/Net/HTTPClient.cpp b/Common/Net/HTTPClient.cpp index d4f4eb8df7..f06072cc7d 100644 --- a/Common/Net/HTTPClient.cpp +++ b/Common/Net/HTTPClient.cpp @@ -31,7 +31,7 @@ #include "Common/File/FileDescriptor.h" #include "Common/Thread/ThreadUtil.h" #include "Common/Data/Encoding/Compression.h" -#include "Common/Buffer.h" +#include "Common/Net/NetBuffer.h" #include "Common/Log.h" namespace net { @@ -147,7 +147,6 @@ bool Connection::Connect(int maxTries, double timeout, bool *cancelConnect) { // Something connected. Pick the first one that did (if multiple.) for (int sock : sockets) { if ((intptr_t)sock_ == -1 && FD_ISSET(sock, &fds)) { - fd_util::SetNonBlocking(sock, false); sock_ = sock; } else { closesocket(sock); @@ -244,35 +243,35 @@ void DeChunk(Buffer *inbuffer, Buffer *outbuffer, int contentLength, float *prog } } -int Client::GET(const char *resource, Buffer *output, std::vector &responseHeaders, float *progress, bool *cancelled) { +int Client::GET(const char *resource, Buffer *output, std::vector &responseHeaders, RequestProgress *progress) { const char *otherHeaders = "Accept: */*\r\n" "Accept-Encoding: gzip\r\n"; - int err = SendRequest("GET", resource, otherHeaders, progress, cancelled); + int err = SendRequest("GET", resource, otherHeaders, progress); if (err < 0) { return err; } - Buffer readbuf; - int code = ReadResponseHeaders(&readbuf, responseHeaders, progress, cancelled); + net::Buffer readbuf; + int code = ReadResponseHeaders(&readbuf, responseHeaders, progress); if (code < 0) { return code; } - err = ReadResponseEntity(&readbuf, responseHeaders, output, progress, cancelled); + err = ReadResponseEntity(&readbuf, responseHeaders, output, progress); if (err < 0) { return err; } return code; } -int Client::GET(const char *resource, Buffer *output, float *progress, bool *cancelled) { +int Client::GET(const char *resource, Buffer *output, RequestProgress *progress) { std::vector responseHeaders; - int code = GET(resource, output, responseHeaders, progress, cancelled); + int code = GET(resource, output, responseHeaders, progress); return code; } -int Client::POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output, float *progress) { +int Client::POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output, RequestProgress *progress) { char otherHeaders[2048]; if (mime.empty()) { snprintf(otherHeaders, sizeof(otherHeaders), "Content-Length: %lld\r\n", (long long)data.size()); @@ -284,7 +283,7 @@ int Client::POST(const char *resource, const std::string &data, const std::strin return err; } - Buffer readbuf; + net::Buffer readbuf; std::vector responseHeaders; int code = ReadResponseHeaders(&readbuf, responseHeaders, progress); if (code < 0) { @@ -298,20 +297,18 @@ int Client::POST(const char *resource, const std::string &data, const std::strin return code; } -int Client::POST(const char *resource, const std::string &data, Buffer *output, float *progress) { +int Client::POST(const char *resource, const std::string &data, Buffer *output, RequestProgress *progress) { return POST(resource, data, "", output, progress); } -int Client::SendRequest(const char *method, const char *resource, const char *otherHeaders, float *progress, bool *cancelled) { - return SendRequestWithData(method, resource, "", otherHeaders, progress, cancelled); +int Client::SendRequest(const char *method, const char *resource, const char *otherHeaders, RequestProgress *progress) { + return SendRequestWithData(method, resource, "", otherHeaders, progress); } -int Client::SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders, float *progress, bool *cancelled) { - if (progress) { - *progress = 0.01f; - } +int Client::SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders, RequestProgress *progress) { + progress->progress = 0.01f; - Buffer buffer; + net::Buffer buffer; const char *tpl = "%s %s HTTP/%s\r\n" "Host: %s\r\n" @@ -326,28 +323,25 @@ int Client::SendRequestWithData(const char *method, const char *resource, const userAgent_.c_str(), otherHeaders ? otherHeaders : ""); buffer.Append(data); - bool flushed = buffer.FlushSocket(sock(), dataTimeout_); + bool flushed = buffer.FlushSocket(sock(), dataTimeout_, progress->cancelled); if (!flushed) { return -1; // TODO error code. } return 0; } -int Client::ReadResponseHeaders(Buffer *readbuf, std::vector &responseHeaders, float *progress, bool *cancelled) { +int Client::ReadResponseHeaders(net::Buffer *readbuf, std::vector &responseHeaders, RequestProgress *progress) { // Snarf all the data we can into RAM. A little unsafe but hey. static constexpr float CANCEL_INTERVAL = 0.25f; bool ready = false; - double leftTimeout = dataTimeout_; + double endTimeout = time_now_d() + dataTimeout_; while (!ready) { - if (cancelled && *cancelled) + if (progress->cancelled && *progress->cancelled) return -1; ready = fd_util::WaitUntilReady(sock(), CANCEL_INTERVAL, false); - if (!ready && leftTimeout >= 0.0) { - leftTimeout -= CANCEL_INTERVAL; - if (leftTimeout < 0) { - ERROR_LOG(IO, "HTTP headers timed out"); - return -1; - } + if (!ready && time_now_d() > endTimeout) { + ERROR_LOG(IO, "HTTP headers timed out"); + return -1; } }; // Let's hope all the headers are available in a single packet... @@ -389,7 +383,7 @@ int Client::ReadResponseHeaders(Buffer *readbuf, std::vector &respo return code; } -int Client::ReadResponseEntity(Buffer *readbuf, const std::vector &responseHeaders, Buffer *output, float *progress, bool *cancelled) { +int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vector &responseHeaders, Buffer *output, RequestProgress *progress) { bool gzip = false; bool chunked = false; int contentLength = 0; @@ -421,51 +415,50 @@ int Client::ReadResponseEntity(Buffer *readbuf, const std::vector & contentLength = 0; } - if (!contentLength && progress) { + if (!contentLength) { // Content length is unknown. // Set progress to 1% so it looks like something is happening... - *progress = 0.1f; + progress->progress = 0.1f; } - if (!contentLength || !progress) { + if (!contentLength) { // No way to know how far along we are. Let's just not update the progress counter. - if (!readbuf->ReadAllWithProgress(sock(), contentLength, nullptr, cancelled)) + if (!readbuf->ReadAllWithProgress(sock(), contentLength, nullptr, &progress->kBps, progress->cancelled)) return -1; } else { // Let's read in chunks, updating progress between each. - if (!readbuf->ReadAllWithProgress(sock(), contentLength, progress, cancelled)) + if (!readbuf->ReadAllWithProgress(sock(), contentLength, &progress->progress, &progress->kBps, progress->cancelled)) return -1; } // output now contains the rest of the reply. Dechunk it. - if (chunked) { - DeChunk(readbuf, output, contentLength, progress); - } else { - output->Append(*readbuf); - } - - // If it's gzipped, we decompress it and put it back in the buffer. - if (gzip) { - std::string compressed, decompressed; - output->TakeAll(&compressed); - bool result = decompress_string(compressed, &decompressed); - if (!result) { - ERROR_LOG(IO, "Error decompressing using zlib"); - if (progress) - *progress = 0.0f; - return -1; + if (!output->IsVoid()) { + if (chunked) { + DeChunk(readbuf, output, contentLength, &progress->progress); + } else { + output->Append(*readbuf); + } + + // If it's gzipped, we decompress it and put it back in the buffer. + if (gzip) { + std::string compressed, decompressed; + output->TakeAll(&compressed); + bool result = decompress_string(compressed, &decompressed); + if (!result) { + ERROR_LOG(IO, "Error decompressing using zlib"); + progress->progress = 0.0f; + return -1; + } + output->Append(decompressed); } - output->Append(decompressed); } - if (progress) { - *progress = 1.0f; - } + progress->progress = 1.0f; return 0; } Download::Download(const std::string &url, const std::string &outfile) - : url_(url), outfile_(outfile) { + : progress_(&cancelled_), url_(url), outfile_(outfile) { } Download::~Download() { @@ -486,7 +479,7 @@ void Download::Join() { void Download::SetFailed(int code) { failed_ = true; - progress_ = 1.0f; + progress_.progress = 1.0f; completed_ = true; } @@ -515,7 +508,7 @@ int Download::PerformGET(const std::string &url) { return -1; } - return client.GET(fileUrl.Resource().c_str(), &buffer_, responseHeaders_, &progress_, &cancelled_); + return client.GET(fileUrl.Resource().c_str(), &buffer_, responseHeaders_, &progress_); } std::string Download::RedirectLocation(const std::string &baseUrl) { @@ -569,7 +562,7 @@ void Download::Do() { resultCode_ = resultCode; } - progress_ = 1.0f; + progress_.progress = 1.0f; // Set this last to ensure no race conditions when checking Done. Users must always check // Done before looking at the result code. diff --git a/Common/Net/HTTPClient.h b/Common/Net/HTTPClient.h index 9281863f1b..2087f1ea71 100644 --- a/Common/Net/HTTPClient.h +++ b/Common/Net/HTTPClient.h @@ -5,10 +5,9 @@ #include #include +#include "Common/Net/NetBuffer.h" #include "Common/Net/Resolve.h" -#include "Common/Buffer.h" - namespace net { class Connection { @@ -44,26 +43,35 @@ namespace http { bool GetHeaderValue(const std::vector &responseHeaders, const std::string &header, std::string *value); +struct RequestProgress { + RequestProgress() {} + explicit RequestProgress(bool *c) : cancelled(c) {} + + float progress = 0.0f; + float kBps = 0.0f; + bool *cancelled = nullptr; +}; + class Client : public net::Connection { public: Client(); ~Client(); // Return value is the HTTP return code. 200 means OK. < 0 means some local error. - int GET(const char *resource, Buffer *output, float *progress = nullptr, bool *cancelled = nullptr); - int GET(const char *resource, Buffer *output, std::vector &responseHeaders, float *progress = nullptr, bool *cancelled = nullptr); + int GET(const char *resource, Buffer *output, RequestProgress *progress); + int GET(const char *resource, Buffer *output, std::vector &responseHeaders, RequestProgress *progress); // Return value is the HTTP return code. - int POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output, float *progress = nullptr); - int POST(const char *resource, const std::string &data, Buffer *output, float *progress = nullptr); + int POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output, RequestProgress *progress); + int POST(const char *resource, const std::string &data, Buffer *output, RequestProgress *progress); // HEAD, PUT, DELETE aren't implemented yet, but can be done with SendRequest. - int SendRequest(const char *method, const char *resource, const char *otherHeaders = nullptr, float *progress = nullptr, bool *cancelled = nullptr); - int SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders = nullptr, float *progress = nullptr, bool *cancelled = nullptr); - int ReadResponseHeaders(Buffer *readbuf, std::vector &responseHeaders, float *progress = nullptr, bool *cancelled = nullptr); + int SendRequest(const char *method, const char *resource, const char *otherHeaders, RequestProgress *progress); + int SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders, RequestProgress *progress); + int ReadResponseHeaders(net::Buffer *readbuf, std::vector &responseHeaders, RequestProgress *progress); // If your response contains a response, you must read it. - int ReadResponseEntity(Buffer *readbuf, const std::vector &responseHeaders, Buffer *output, float *progress = nullptr, bool *cancelled = nullptr); + int ReadResponseEntity(net::Buffer *readbuf, const std::vector &responseHeaders, Buffer *output, RequestProgress *progress); void SetDataTimeout(double t) { dataTimeout_ = t; @@ -76,7 +84,7 @@ public: protected: std::string userAgent_; const char *httpVersion_; - double dataTimeout_ = -1.0; + double dataTimeout_ = 900.0; }; // Not particularly efficient, but hey - it's a background download, that's pretty cool :P @@ -90,7 +98,8 @@ public: void Join(); // Returns 1.0 when done. That one value can be compared exactly - or just use Done(). - float Progress() const { return progress_; } + float Progress() const { return progress_.progress; } + float SpeedKBps() const { return progress_.kBps; } bool Done() const { return completed_; } bool Failed() const { return failed_; } @@ -134,7 +143,7 @@ private: int PerformGET(const std::string &url); std::string RedirectLocation(const std::string &baseUrl); void SetFailed(int code); - float progress_ = 0.0f; + RequestProgress progress_; Buffer buffer_; std::vector responseHeaders_; std::string url_; diff --git a/Common/Net/HTTPHeaders.h b/Common/Net/HTTPHeaders.h index dec2501d69..5900b01874 100644 --- a/Common/Net/HTTPHeaders.h +++ b/Common/Net/HTTPHeaders.h @@ -3,7 +3,7 @@ #include #include -#include "Common/Buffer.h" +#include "Common/Net/NetBuffer.h" namespace net { class InputSink; diff --git a/Common/Net/HTTPServer.cpp b/Common/Net/HTTPServer.cpp index 4a4227d423..882d49a965 100644 --- a/Common/Net/HTTPServer.cpp +++ b/Common/Net/HTTPServer.cpp @@ -35,10 +35,9 @@ #include #include "Common/Net/HTTPServer.h" +#include "Common/Net/NetBuffer.h" #include "Common/Net/Sinks.h" #include "Common/File/FileDescriptor.h" - -#include "Common/Buffer.h" #include "Common/Log.h" void NewThreadExecutor::Run(std::function &&func) { diff --git a/Common/Net/NetBuffer.cpp b/Common/Net/NetBuffer.cpp new file mode 100644 index 0000000000..331f24b55e --- /dev/null +++ b/Common/Net/NetBuffer.cpp @@ -0,0 +1,112 @@ +#include "ppsspp_config.h" +#ifdef _WIN32 +#include +#undef min +#undef max +#else +#include +#include +#endif +#include +#include + +#ifndef MSG_NOSIGNAL +// Default value to 0x00 (do nothing) in systems where it's not supported. +#define MSG_NOSIGNAL 0x00 +#endif + +#include "Common/File/FileDescriptor.h" +#include "Common/Log.h" +#include "Common/Net/NetBuffer.h" +#include "Common/TimeUtil.h" + +namespace net { + +bool Buffer::FlushSocket(uintptr_t sock, double timeout, bool *cancelled) { + static constexpr float CANCEL_INTERVAL = 0.25f; + for (size_t pos = 0, end = data_.size(); pos < end; ) { + bool ready = false; + double endTimeout = time_now_d() + timeout; + while (!ready) { + if (cancelled && *cancelled) + return false; + ready = fd_util::WaitUntilReady(sock, CANCEL_INTERVAL, true); + if (!ready && time_now_d() > endTimeout) { + ERROR_LOG(IO, "FlushSocket timed out"); + return false; + } + } + int sent = send(sock, &data_[pos], (int)(end - pos), MSG_NOSIGNAL); + if (sent < 0) { + ERROR_LOG(IO, "FlushSocket failed"); + return false; + } + pos += sent; + } + data_.resize(0); + return true; +} + +bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress, float *kBps, bool *cancelled) { + static constexpr float CANCEL_INTERVAL = 0.25f; + std::vector buf; + // We're non-blocking and reading from an OS buffer, so try to read as much as we can at a time. + if (knownSize >= 65536 * 16) { + buf.resize(65536); + } else if (knownSize >= 1024 * 16) { + buf.resize(knownSize / 16); + } else { + buf.resize(1024); + } + + double st = time_now_d(); + int total = 0; + while (true) { + bool ready = false; + while (!ready && cancelled) { + if (*cancelled) + return false; + ready = fd_util::WaitUntilReady(fd, CANCEL_INTERVAL, false); + } + int retval = recv(fd, &buf[0], (int)buf.size(), MSG_NOSIGNAL); + if (retval == 0) { + return true; + } else if (retval < 0) { +#if PPSSPP_PLATFORM(WINDOWS) + if (WSAGetLastError() != WSAEWOULDBLOCK) +#else + if (errno != EWOULDBLOCK) +#endif + ERROR_LOG(IO, "Error reading from buffer: %i", retval); + return false; + } + char *p = Append((size_t)retval); + memcpy(p, &buf[0], retval); + total += retval; + if (progress) + *progress = (float)total / (float)knownSize; + if (kBps) + *kBps = (float)(total / (time_now_d() - st)) / 1024.0f; + } + return true; +} + +int Buffer::Read(int fd, size_t sz) { + char buf[1024]; + int retval; + size_t received = 0; + while ((retval = recv(fd, buf, (int)std::min(sz, sizeof(buf)), MSG_NOSIGNAL)) > 0) { + if (retval < 0) { + return retval; + } + char *p = Append((size_t)retval); + memcpy(p, buf, retval); + sz -= retval; + received += retval; + if (sz == 0) + return 0; + } + return (int)received; +} + +} diff --git a/Common/Net/NetBuffer.h b/Common/Net/NetBuffer.h new file mode 100644 index 0000000000..6247aca985 --- /dev/null +++ b/Common/Net/NetBuffer.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Common/Buffer.h" + +namespace net { + +class Buffer : public ::Buffer { +public: + bool FlushSocket(uintptr_t sock, double timeout, bool *cancelled = nullptr); + + bool ReadAllWithProgress(int fd, int knownSize, float *progress, float *kBps, bool *cancelled); + + // < 0: error + // >= 0: number of bytes read + int Read(int fd, size_t sz); +}; + +} diff --git a/Core/AVIDump.cpp b/Core/AVIDump.cpp index 1e3f1803d5..b55fa12a10 100644 --- a/Core/AVIDump.cpp +++ b/Core/AVIDump.cpp @@ -23,8 +23,8 @@ extern "C" { #endif +#include "Common/Data/Convert/ColorConv.h" #include "Common/File/FileUtil.h" -#include "Common/ColorConv.h" #include "Core/Config.h" #include "Core/AVIDump.h" diff --git a/Core/FileLoaders/HTTPFileLoader.cpp b/Core/FileLoaders/HTTPFileLoader.cpp index 5aa692b0d6..5f385910a4 100644 --- a/Core/FileLoaders/HTTPFileLoader.cpp +++ b/Core/FileLoaders/HTTPFileLoader.cpp @@ -24,7 +24,7 @@ #include "Core/FileLoaders/HTTPFileLoader.h" HTTPFileLoader::HTTPFileLoader(const std::string &filename) - : url_(filename), filename_(filename) { + : url_(filename), progress_(&cancel_), filename_(filename) { } void HTTPFileLoader::Prepare() { @@ -137,7 +137,7 @@ int HTTPFileLoader::SendHEAD(const Url &url, std::vector &responseH return -400; } - int err = client_.SendRequest("HEAD", url.Resource().c_str()); + int err = client_.SendRequest("HEAD", url.Resource().c_str(), nullptr, &progress_); if (err < 0) { ERROR_LOG(LOADER, "HTTP request failed, failed to send request: %s port %d", url.Host().c_str(), url.Port()); latestError_ = "Could not connect (could not request data)"; @@ -145,8 +145,8 @@ int HTTPFileLoader::SendHEAD(const Url &url, std::vector &responseH return -400; } - Buffer readbuf; - return client_.ReadResponseHeaders(&readbuf, responseHeaders); + net::Buffer readbuf; + return client_.ReadResponseHeaders(&readbuf, responseHeaders, &progress_); } HTTPFileLoader::~HTTPFileLoader() { @@ -203,9 +203,9 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f return 0; } - Buffer readbuf; + net::Buffer readbuf; std::vector responseHeaders; - int code = client_.ReadResponseHeaders(&readbuf, responseHeaders); + int code = client_.ReadResponseHeaders(&readbuf, responseHeaders, &progress_); if (code != 206) { ERROR_LOG(LOADER, "HTTP server did not respond with range, received code=%03d", code); latestError_ = "Invalid response reading data"; @@ -235,8 +235,8 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f } // TODO: Would be nice to read directly. - Buffer output; - int res = client_.ReadResponseEntity(&readbuf, responseHeaders, &output); + net::Buffer output; + int res = client_.ReadResponseEntity(&readbuf, responseHeaders, &output, &progress_); if (res != 0) { ERROR_LOG(LOADER, "Unable to read HTTP response entity: %d", res); // Let's take anything we got anyway. Not worse than returning nothing? @@ -259,8 +259,8 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f void HTTPFileLoader::Connect() { if (!connected_) { - cancelConnect_ = false; + cancel_ = false; // Latency is important here, so reduce the timeout. - connected_ = client_.Connect(3, 10.0, &cancelConnect_); + connected_ = client_.Connect(3, 10.0, &cancel_); } } diff --git a/Core/FileLoaders/HTTPFileLoader.h b/Core/FileLoaders/HTTPFileLoader.h index d8cb6f3c47..6bbba43eff 100644 --- a/Core/FileLoaders/HTTPFileLoader.h +++ b/Core/FileLoaders/HTTPFileLoader.h @@ -46,7 +46,7 @@ public: virtual size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override; void Cancel() override { - cancelConnect_ = true; + cancel_ = true; } std::string LatestError() const override { @@ -70,9 +70,10 @@ private: s64 filepos_ = 0; Url url_; http::Client client_; + http::RequestProgress progress_; std::string filename_; bool connected_ = false; - bool cancelConnect_ = false; + bool cancel_ = false; const char *latestError_ = ""; std::once_flag preparedFlag_; diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 89869e7ca1..40184ee07d 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -36,6 +36,7 @@ #include "Common/File/FileUtil.h" #include "Common/File/DiskFree.h" #include "Common/File/VFS/VFS.h" +#include "Common/SysError.h" #include "Core/FileSystems/DirectoryFileSystem.h" #include "Core/FileSystems/ISOFileSystem.h" #include "Core/HLE/sceKernel.h" @@ -631,7 +632,8 @@ int DirectoryFileSystem::OpenFile(std::string filename, FileAccess access, const err = ReplayApplyDisk(ReplayAction::FILE_OPEN, err, CoreTiming::GetGlobalTimeUs()); if (err != 0) { #ifdef _WIN32 - ERROR_LOG(FILESYS, "DirectoryFileSystem::OpenFile: FAILED, %i - access = %i", (int)GetLastError(), (int)access); + auto win32err = GetLastError(); + ERROR_LOG(FILESYS, "DirectoryFileSystem::OpenFile: FAILED, %i - access = %i, %s", (int)win32err, (int)access, GetStringErrorMsg(win32err).c_str()); #else ERROR_LOG(FILESYS, "DirectoryFileSystem::OpenFile: FAILED, %i - access = %i", errno, (int)access); #endif diff --git a/Core/Instance.cpp b/Core/Instance.cpp index a36aca0049..e8a5590dbd 100644 --- a/Core/Instance.cpp +++ b/Core/Instance.cpp @@ -25,14 +25,13 @@ #include #endif -#include "Common/Log.h" - #if PPSSPP_PLATFORM(WINDOWS) - #include "Common/CommonWindows.h" - #endif +#include "Common/Log.h" +#include "Common/SysError.h" + #include uint8_t PPSSPP_ID = 0; @@ -65,7 +64,8 @@ static bool UpdateInstanceCounter(void (*callback)(volatile InstanceInfo *)) { sizeof(InstanceInfo)); if (!buf) { - ERROR_LOG(SCENET, "Could not map view of file %s (%08x)", ID_SHM_NAME, (uint32_t)GetLastError()); + auto err = GetLastError(); + ERROR_LOG(SCENET, "Could not map view of file %s, %08x %s", ID_SHM_NAME, (uint32_t)err, GetStringErrorMsg(err).c_str()); return false; } @@ -137,7 +137,7 @@ void InitInstanceCounter() { DWORD lasterr = GetLastError(); if (!hIDMapFile) { - ERROR_LOG(SCENET, "Could not create %s file mapping object (%08x)", ID_SHM_NAME, (uint32_t)lasterr); + ERROR_LOG(SCENET, "Could not create %s file mapping object, %08x %s", ID_SHM_NAME, (uint32_t)lasterr, GetStringErrorMsg(lasterr).c_str()); PPSSPP_ID = 1; return; } diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index 3b7cb2d31d..487dd9c295 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -261,11 +261,12 @@ namespace Reporting bool SendReportRequest(const char *uri, const std::string &data, const std::string &mimeType, Buffer *output = NULL) { http::Client http; - Buffer theVoid; + http::RequestProgress progress; + Buffer theVoid = Buffer::Void(); http.SetUserAgent(StringFromFormat("PPSSPP/%s", PPSSPP_GIT_VERSION)); - if (output == NULL) + if (output == nullptr) output = &theVoid; const char *serverHost = ServerHostname(); @@ -274,7 +275,7 @@ namespace Reporting if (http.Resolve(serverHost, ServerPort())) { http.Connect(); - int result = http.POST(uri, data, mimeType, output); + int result = http.POST(uri, data, mimeType, output, &progress); http.Disconnect(); return result >= 200 && result < 300; diff --git a/Core/Screenshot.cpp b/Core/Screenshot.cpp index 8a06d54ab7..2324e7f96c 100644 --- a/Core/Screenshot.cpp +++ b/Core/Screenshot.cpp @@ -21,7 +21,7 @@ #include #include "ext/jpge/jpge.h" -#include "Common/ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/File/FileUtil.h" #include "Common/Log.h" #include "Common/System/Display.h" diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 32a54c37a2..05a2ad6da9 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -21,10 +21,10 @@ #include "ext/xxhash.h" -#include "Common/Data/Text/I18n.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/Data/Format/IniFile.h" +#include "Common/Data/Text/I18n.h" #include "Common/Data/Text/Parsers.h" -#include "Common/ColorConv.h" #include "Common/File/FileUtil.h" #include "Common/StringUtils.h" #include "Core/Config.h" diff --git a/Core/Util/GameManager.cpp b/Core/Util/GameManager.cpp index 3e0c618b0e..7063cf0a8d 100644 --- a/Core/Util/GameManager.cpp +++ b/Core/Util/GameManager.cpp @@ -82,6 +82,12 @@ bool GameManager::DownloadAndInstall(std::string storeFileUrl) { return true; } +bool GameManager::IsDownloading(std::string storeZipUrl) { + if (curDownload_) + return curDownload_->url() == storeZipUrl; + return false; +} + bool GameManager::CancelDownload() { if (!curDownload_) return false; @@ -91,6 +97,12 @@ bool GameManager::CancelDownload() { return true; } +float GameManager::DownloadSpeedKBps() { + if (curDownload_) + return curDownload_->SpeedKBps(); + return 0.0f; +} + bool GameManager::Uninstall(std::string name) { if (name.empty()) { ERROR_LOG(HLE, "Cannot remove an empty-named game"); diff --git a/Core/Util/GameManager.h b/Core/Util/GameManager.h index 63460f66d7..a13939c56e 100644 --- a/Core/Util/GameManager.h +++ b/Core/Util/GameManager.h @@ -43,11 +43,14 @@ public: // This starts off a background process. bool DownloadAndInstall(std::string storeZipUrl); + bool IsDownloading(std::string storeZipUrl); bool Uninstall(std::string name); // Cancels the download in progress, if any. bool CancelDownload(); + float DownloadSpeedKBps(); + // Call from time to time to check on completed downloads from the // main UI thread. void Update(); diff --git a/Core/WebServer.cpp b/Core/WebServer.cpp index 3efeedc020..9b7f388543 100644 --- a/Core/WebServer.cpp +++ b/Core/WebServer.cpp @@ -63,7 +63,8 @@ static ServerStatus RetrieveStatus() { static bool RegisterServer(int port) { bool success = false; http::Client http; - Buffer theVoid; + http::RequestProgress progress; + Buffer theVoid = Buffer::Void(); http.SetUserAgent(StringFromFormat("PPSSPP/%s", PPSSPP_GIT_VERSION)); @@ -73,7 +74,7 @@ static bool RegisterServer(int port) { std::string ip = fd_util::GetLocalIP(http.sock()); snprintf(resource4, sizeof(resource4) - 1, "/match/update?local=%s&port=%d", ip.c_str(), port); - if (http.GET(resource4, &theVoid) > 0) + if (http.GET(resource4, &theVoid, &progress) > 0) success = true; theVoid.Skip(theVoid.size()); http.Disconnect(); @@ -86,7 +87,7 @@ static bool RegisterServer(int port) { // We register both IPv4 and IPv6 in case the other client is using a different one. if (resource4[0] != 0 && http.Connect(timeout)) { - if (http.GET(resource4, &theVoid) > 0) + if (http.GET(resource4, &theVoid, &progress) > 0) success = true; theVoid.Skip(theVoid.size()); http.Disconnect(); @@ -98,7 +99,7 @@ static bool RegisterServer(int port) { std::string ip = fd_util::GetLocalIP(http.sock()); snprintf(resource6, sizeof(resource6) - 1, "/match/update?local=%s&port=%d", ip.c_str(), port); - if (http.GET(resource6, &theVoid) > 0) + if (http.GET(resource6, &theVoid, &progress) > 0) success = true; theVoid.Skip(theVoid.size()); http.Disconnect(); diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 2393431c76..b5569bcd7a 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -17,8 +17,8 @@ #include +#include "Common/Data/Convert/ColorConv.h" #include "Common/Profiler/Profiler.h" -#include "Common/ColorConv.h" #include "Core/Config.h" #include "GPU/Common/DrawEngineCommon.h" #include "GPU/Common/SplineCommon.h" diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 349e244747..2690d94274 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -21,8 +21,8 @@ #include "Common/GPU/thin3d.h" #include "Common/GPU/OpenGL/GLFeatures.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/Data/Text/I18n.h" -#include "Common/ColorConv.h" #include "Common/Common.h" #include "Core/Config.h" #include "Core/ConfigValues.h" diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index b54820473b..4cfd94162f 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -18,8 +18,8 @@ #include #include "ppsspp_config.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/Profiler/Profiler.h" -#include "Common/ColorConv.h" #include "Common/MemoryUtil.h" #include "Common/StringUtils.h" #include "Core/Config.h" diff --git a/GPU/Common/TextureDecoder.cpp b/GPU/Common/TextureDecoder.cpp index 2e10ac1f36..750fc3f9b7 100644 --- a/GPU/Common/TextureDecoder.cpp +++ b/GPU/Common/TextureDecoder.cpp @@ -17,8 +17,8 @@ #include "ppsspp_config.h" #include "ext/xxhash.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/CPUDetect.h" -#include "Common/ColorConv.h" #include "GPU/GPU.h" #include "GPU/GPUState.h" @@ -26,8 +26,6 @@ // NEON is in a separate file so that it can be compiled with a runtime check. #include "GPU/Common/TextureDecoderNEON.h" -// TODO: Move some common things into here. - #ifdef _M_SSE #include #if _M_SSE >= 0x401 diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index 920083577f..ecf247e530 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -20,10 +20,10 @@ #include "ppsspp_config.h" -#include "Common/Log.h" -#include "Common/CPUDetect.h" -#include "Common/ColorConv.h" #include "Common/Common.h" +#include "Common/CPUDetect.h" +#include "Common/Data/Convert/ColorConv.h" +#include "Common/Log.h" #include "Core/Config.h" #include "Core/ConfigValues.h" #include "Core/MemMap.h" diff --git a/GPU/D3D11/DepalettizeShaderD3D11.cpp b/GPU/D3D11/DepalettizeShaderD3D11.cpp index faf6c22de2..e2a1c58e91 100644 --- a/GPU/D3D11/DepalettizeShaderD3D11.cpp +++ b/GPU/D3D11/DepalettizeShaderD3D11.cpp @@ -19,8 +19,8 @@ #include #include "Common/Common.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/Log.h" -#include "Common/ColorConv.h" #include "Common/StringUtils.h" #include "Core/Reporting.h" #include "GPU/D3D11/TextureCacheD3D11.h" diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 0828b68a1d..40391fbfc5 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -20,11 +20,11 @@ #include #include "Common/Common.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/System/Display.h" #include "Common/Math/lin/matrix4x4.h" #include "Common/Math/math_util.h" #include "Common/GPU/thin3d.h" -#include "Common/ColorConv.h" #include "Core/MemMap.h" #include "Core/Config.h" diff --git a/GPU/D3D11/TextureScalerD3D11.cpp b/GPU/D3D11/TextureScalerD3D11.cpp index 17dcfa3c25..45aa67e18d 100644 --- a/GPU/D3D11/TextureScalerD3D11.cpp +++ b/GPU/D3D11/TextureScalerD3D11.cpp @@ -18,7 +18,7 @@ #include #include -#include "Common/ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" #include "Core/ThreadPools.h" #include "GPU/Common/TextureScalerCommon.h" #include "GPU/D3D11/TextureScalerD3D11.h" @@ -54,4 +54,4 @@ void TextureScalerD3D11::ConvertTo8888(u32 format, u32* source, u32* &dest, int dest = source; ERROR_LOG(G3D, "iXBRZTexScaling: unsupported texture format"); } -} \ No newline at end of file +} diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp index 08c40135b3..b06c0c4e06 100644 --- a/GPU/Directx9/FramebufferManagerDX9.cpp +++ b/GPU/Directx9/FramebufferManagerDX9.cpp @@ -18,7 +18,7 @@ #include "Common/Math/lin/matrix4x4.h" #include "Common/GPU/thin3d.h" -#include "Common/ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" #include "Core/MemMap.h" #include "Core/Config.h" #include "Core/ConfigValues.h" diff --git a/GPU/Directx9/TextureScalerDX9.cpp b/GPU/Directx9/TextureScalerDX9.cpp index 4508358d7e..574fa3eebc 100644 --- a/GPU/Directx9/TextureScalerDX9.cpp +++ b/GPU/Directx9/TextureScalerDX9.cpp @@ -18,7 +18,7 @@ #include #include "Common/Common.h" -#include "Common/ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" #include "Core/ThreadPools.h" #include "GPU/Common/TextureScalerCommon.h" #include "GPU/Directx9/TextureScalerDX9.h" diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index be01c06702..5870c899ef 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -17,12 +17,12 @@ #include +#include "Common/Data/Convert/ColorConv.h" #include "Common/Profiler/Profiler.h" #include "Common/GPU/OpenGL/GLCommon.h" #include "Common/GPU/OpenGL/GLDebugLog.h" #include "Common/GPU/OpenGL/GLSLProgram.h" #include "Common/GPU/thin3d.h" -#include "Common/ColorConv.h" #include "Core/MemMap.h" #include "Core/Config.h" #include "Core/ConfigValues.h" diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index e15b900aca..783ea75c40 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -19,12 +19,12 @@ #include #include "ext/xxhash.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/Data/Text/I18n.h" #include "Common/Math/math_util.h" #include "Common/Profiler/Profiler.h" #include "Common/GPU/OpenGL/GLRenderManager.h" -#include "Common/ColorConv.h" #include "Core/Config.h" #include "Core/Host.h" #include "Core/MemMap.h" diff --git a/GPU/GLES/TextureScalerGLES.cpp b/GPU/GLES/TextureScalerGLES.cpp index 2a22d8b178..abe06bb5bd 100644 --- a/GPU/GLES/TextureScalerGLES.cpp +++ b/GPU/GLES/TextureScalerGLES.cpp @@ -20,7 +20,7 @@ #include "GPU/Common/TextureScalerCommon.h" #include "GPU/GLES/TextureScalerGLES.h" -#include "Common/ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/Log.h" #include "Core/ThreadPools.h" #include "Common/GPU/DataFormat.h" diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 48310c36f3..dfc9365245 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -5,7 +5,7 @@ #include "Common/Profiler/Profiler.h" -#include "Common/ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/GraphicsContext.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index 943b3f5656..f961175c2c 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -19,10 +19,10 @@ #include #include +#include "Common/Data/Convert/ColorConv.h" #include "Common/Profiler/Profiler.h" #include "Core/ThreadPools.h" -#include "Common/ColorConv.h" #include "Core/Config.h" #include "Core/MemMap.h" #include "Core/Reporting.h" diff --git a/GPU/Software/RasterizerRectangle.cpp b/GPU/Software/RasterizerRectangle.cpp index 828a7d622b..bbc7e27463 100644 --- a/GPU/Software/RasterizerRectangle.cpp +++ b/GPU/Software/RasterizerRectangle.cpp @@ -3,17 +3,15 @@ #include #include +#include "Common/Data/Convert/ColorConv.h" #include "Common/Profiler/Profiler.h" -#include "Core/System.h" - -#include "Common/ColorConv.h" #include "Core/Config.h" #include "Core/MemMap.h" #include "Core/Reporting.h" +#include "Core/System.h" #include "GPU/GPUState.h" -#include "Rasterizer.h" #include "GPU/Common/TextureCacheCommon.h" #include "GPU/Software/SoftGpu.h" #include "GPU/Software/Rasterizer.h" diff --git a/GPU/Software/Sampler.cpp b/GPU/Software/Sampler.cpp index 2fccf208b2..607aafd3dd 100644 --- a/GPU/Software/Sampler.cpp +++ b/GPU/Software/Sampler.cpp @@ -18,7 +18,7 @@ #include "ppsspp_config.h" #include #include -#include "Common/ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" #include "Core/Reporting.h" #include "GPU/Common/TextureDecoder.h" #include "GPU/GPUState.h" diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 26ef1cbbb9..134276b1ff 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -21,7 +21,7 @@ #include "GPU/GPUState.h" #include "GPU/ge_constants.h" #include "GPU/Common/TextureDecoder.h" -#include "Common/ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/GraphicsContext.h" #include "Core/Config.h" #include "Core/ConfigValues.h" diff --git a/GPU/Vulkan/DepalettizeShaderVulkan.cpp b/GPU/Vulkan/DepalettizeShaderVulkan.cpp index 4d11207eb2..7768218998 100644 --- a/GPU/Vulkan/DepalettizeShaderVulkan.cpp +++ b/GPU/Vulkan/DepalettizeShaderVulkan.cpp @@ -15,7 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "Common/ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/GPU/Vulkan/VulkanImage.h" #include "Common/GPU/Vulkan/VulkanMemory.h" #include "Common/GPU/Vulkan/VulkanContext.h" diff --git a/GPU/Vulkan/FramebufferManagerVulkan.cpp b/GPU/Vulkan/FramebufferManagerVulkan.cpp index a9e2fb230b..ac60198cb9 100644 --- a/GPU/Vulkan/FramebufferManagerVulkan.cpp +++ b/GPU/Vulkan/FramebufferManagerVulkan.cpp @@ -21,6 +21,7 @@ #include "Common/System/Display.h" #include "Common/Math/lin/matrix4x4.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/Data/Convert/SmallDataConvert.h" #include "Common/GPU/thin3d.h" @@ -28,7 +29,6 @@ #include "Common/GPU/Vulkan/VulkanMemory.h" #include "Common/GPU/Vulkan/VulkanImage.h" #include "Common/GPU/Vulkan/VulkanRenderManager.h" -#include "Common/ColorConv.h" #include "Core/MemMap.h" #include "Core/Config.h" #include "Core/ConfigValues.h" diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index a108395022..eff8a70e3d 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -26,7 +26,7 @@ #include "Common/GPU/thin3d.h" #include "Common/GPU/Vulkan/VulkanRenderManager.h" -#include "Common/ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/StringUtils.h" #include "Core/Config.h" #include "Core/Host.h" diff --git a/GPU/Vulkan/TextureScalerVulkan.cpp b/GPU/Vulkan/TextureScalerVulkan.cpp index 66720c0f36..e714e3eb0c 100644 --- a/GPU/Vulkan/TextureScalerVulkan.cpp +++ b/GPU/Vulkan/TextureScalerVulkan.cpp @@ -18,8 +18,8 @@ #include #include "Common/Common.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/GPU/Vulkan/VulkanContext.h" -#include "Common/ColorConv.h" #include "Common/Log.h" #include "Core/ThreadPools.h" #include "GPU/Common/TextureScalerCommon.h" diff --git a/UI/RemoteISOScreen.cpp b/UI/RemoteISOScreen.cpp index 8a61fad262..1efb63ee3e 100644 --- a/UI/RemoteISOScreen.cpp +++ b/UI/RemoteISOScreen.cpp @@ -136,7 +136,8 @@ bool RemoteISOConnectScreen::FindServer(std::string &resultHost, int &resultPort } SetStatus("Loading game list from [URL]...", host, port); - code = http.GET(subdir.c_str(), &result); + http::RequestProgress progress(&scanCancelled); + code = http.GET(subdir.c_str(), &result, &progress); http.Disconnect(); if (code != 200) { @@ -189,7 +190,8 @@ bool RemoteISOConnectScreen::FindServer(std::string &resultHost, int &resultPort SetStatus("Looking for peers...", "", 0); if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT)) { if (http.Connect(2, 20.0, &scanCancelled)) { - code = http.GET("/match/list", &result); + http::RequestProgress progress(&scanCancelled); + code = http.GET("/match/list", &result, &progress); http.Disconnect(); } } diff --git a/UI/Store.cpp b/UI/Store.cpp index 2ccf72c6a7..cd50c7269a 100644 --- a/UI/Store.cpp +++ b/UI/Store.cpp @@ -222,11 +222,13 @@ private: bool IsGameInstalled() { return g_GameManager.IsGameInstalled(entry_.file); } + std::string DownloadURL(); StoreEntry entry_; UI::Button *installButton_ = nullptr; UI::Button *launchButton_ = nullptr; UI::Button *cancelButton_ = nullptr; + UI::TextView *speedView_ = nullptr; bool wasInstalled_ = false; }; @@ -243,10 +245,16 @@ void ProductView::CreateViews() { auto st = GetI18NCategory("Store"); auto di = GetI18NCategory("Dialog"); wasInstalled_ = IsGameInstalled(); + bool isDownloading = g_GameManager.IsDownloading(DownloadURL()); if (!wasInstalled_) { launchButton_ = nullptr; - installButton_ = Add(new Button(st->T("Install"))); + LinearLayout *progressDisplay = new LinearLayout(ORIENT_HORIZONTAL); + installButton_ = progressDisplay->Add(new Button(st->T("Install"))); installButton_->OnClick.Handle(this, &ProductView::OnInstall); + + speedView_ = progressDisplay->Add(new TextView("")); + speedView_->SetVisibility(isDownloading ? V_VISIBLE : V_GONE); + Add(progressDisplay); } else { installButton_ = nullptr; Add(new TextView(st->T("Already Installed"))); @@ -258,7 +266,7 @@ void ProductView::CreateViews() { cancelButton_ = Add(new Button(di->T("Cancel"))); cancelButton_->OnClick.Handle(this, &ProductView::OnCancel); - cancelButton_->SetVisibility(V_GONE); + cancelButton_->SetVisibility(isDownloading ? V_VISIBLE : V_GONE); // Add star rating, comments etc? Add(new TextView(entry_.description, ALIGN_LEFT | FLAG_WRAP_TEXT, false)); @@ -277,31 +285,47 @@ void ProductView::Update() { if (installButton_) { installButton_->SetEnabled(g_GameManager.GetState() == GameManagerState::IDLE); } - if (cancelButton_ && g_GameManager.GetState() != GameManagerState::DOWNLOADING) - cancelButton_->SetVisibility(UI::V_GONE); + if (g_GameManager.GetState() == GameManagerState::DOWNLOADING) { + if (speedView_) { + float speed = g_GameManager.DownloadSpeedKBps(); + speedView_->SetText(StringFromFormat("%0.1f KB/s", speed)); + } + } else { + if (cancelButton_) + cancelButton_->SetVisibility(UI::V_GONE); + if (speedView_) + speedView_->SetVisibility(UI::V_GONE); + } if (launchButton_) launchButton_->SetEnabled(g_GameManager.GetState() == GameManagerState::IDLE); View::Update(); } -UI::EventReturn ProductView::OnInstall(UI::EventParams &e) { - std::string fileUrl; +std::string ProductView::DownloadURL() { if (entry_.downloadURL.empty()) { // Construct the URL, easy to predict from our server std::string shortName = entry_.file; if (shortName.find('.') == std::string::npos) shortName += ".zip"; - fileUrl = storeBaseUrl + "files/" + shortName; + return storeBaseUrl + "files/" + shortName; } else { // Use the provided URL, for external hosting. - fileUrl = entry_.downloadURL; + return entry_.downloadURL; } +} + +UI::EventReturn ProductView::OnInstall(UI::EventParams &e) { + std::string fileUrl = DownloadURL(); if (installButton_) { installButton_->SetEnabled(false); } if (cancelButton_) { cancelButton_->SetVisibility(UI::V_VISIBLE); } + if (speedView_) { + speedView_->SetVisibility(UI::V_VISIBLE); + speedView_->SetText(""); + } INFO_LOG(SYSTEM, "Triggering install of '%s'", fileUrl.c_str()); g_GameManager.DownloadAndInstall(fileUrl); return UI::EVENT_DONE; diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index b408128a15..4f5deb5d70 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -386,6 +386,7 @@ + @@ -457,8 +458,8 @@ - - + + @@ -513,6 +514,7 @@ + @@ -568,8 +570,8 @@ - - + + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index c15bfcac05..851b917b4c 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -92,8 +92,8 @@ - - + + @@ -124,6 +124,7 @@ Crypto + ext\libpng17 @@ -381,8 +382,8 @@ - - + + @@ -415,6 +416,7 @@ Crypto + diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 939edb6e3e..1bb1df6c7c 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -21,9 +21,9 @@ #include #include -#include "Common/Data/Text/Parsers.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/Data/Encoding/Utf8.h" -#include "Common/ColorConv.h" +#include "Common/Data/Text/Parsers.h" #include "Common/StringUtils.h" #include "Core/Config.h" #include "Core/Screenshot.h" diff --git a/android/jni/Android.mk b/android/jni/Android.mk index f3281da7b5..a9e52cc2a9 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -60,7 +60,7 @@ ARCH_FILES := \ $(SRC)/GPU/Common/TextureDecoderNEON.cpp.neon \ $(SRC)/Core/Util/AudioFormatNEON.cpp.neon \ $(SRC)/Common/ArmEmitter.cpp \ - $(SRC)/Common/ColorConvNEON.cpp.neon \ + $(SRC)/Common/Data/Convert/ColorConvNEON.cpp.neon \ $(SRC)/Common/Math/fast/fast_matrix_neon.S.neon \ $(SRC)/Core/MIPS/ARM/ArmCompALU.cpp \ $(SRC)/Core/MIPS/ARM/ArmCompBranch.cpp \ @@ -87,7 +87,7 @@ ARCH_FILES := \ $(SRC)/GPU/Common/TextureDecoderNEON.cpp \ $(SRC)/Core/Util/AudioFormatNEON.cpp \ $(SRC)/Common/Arm64Emitter.cpp \ - $(SRC)/Common/ColorConvNEON.cpp \ + $(SRC)/Common/Data/Convert/ColorConvNEON.cpp \ $(SRC)/Core/MIPS/ARM64/Arm64CompALU.cpp \ $(SRC)/Core/MIPS/ARM64/Arm64CompBranch.cpp \ $(SRC)/Core/MIPS/ARM64/Arm64CompFPU.cpp \ @@ -228,6 +228,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/Crypto/sha1.cpp \ $(SRC)/Common/Crypto/sha256.cpp \ $(SRC)/Common/Data/Color/RGBAUtil.cpp \ + $(SRC)/Common/Data/Convert/ColorConv.cpp \ $(SRC)/Common/Data/Convert/SmallDataConvert.cpp \ $(SRC)/Common/Data/Encoding/Base64.cpp \ $(SRC)/Common/Data/Encoding/Compression.cpp \ @@ -273,6 +274,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/Net/HTTPClient.cpp \ $(SRC)/Common/Net/HTTPHeaders.cpp \ $(SRC)/Common/Net/HTTPServer.cpp \ + $(SRC)/Common/Net/NetBuffer.cpp \ $(SRC)/Common/Net/Resolve.cpp \ $(SRC)/Common/Net/Sinks.cpp \ $(SRC)/Common/Net/URL.cpp \ @@ -292,7 +294,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/UI/ViewGroup.cpp \ $(SRC)/Common/Serialize/Serializer.cpp \ $(SRC)/Common/ArmCPUDetect.cpp \ - $(SRC)/Common/ColorConv.cpp \ $(SRC)/Common/CPUDetect.cpp \ $(SRC)/Common/ExceptionHandlerSetup.cpp \ $(SRC)/Common/FakeCPUDetect.cpp \ diff --git a/headless/Compare.cpp b/headless/Compare.cpp index d8d856e5b2..223b65759f 100644 --- a/headless/Compare.cpp +++ b/headless/Compare.cpp @@ -23,7 +23,7 @@ #include #include "headless/Compare.h" -#include "Common/ColorConv.h" +#include "Common/Data/Convert/ColorConv.h" #include "Common/Data/Format/PNGLoad.h" #include "Common/File/FileUtil.h" #include "Common/StringUtils.h" diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 881021e6fd..3bba3a5ab0 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -197,6 +197,7 @@ SOURCES_CXX += \ $(COMMONDIR)/Net/HTTPClient.cpp \ $(COMMONDIR)/Net/HTTPHeaders.cpp \ $(COMMONDIR)/Net/HTTPServer.cpp \ + $(COMMONDIR)/Net/NetBuffer.cpp \ $(COMMONDIR)/Net/Resolve.cpp \ $(COMMONDIR)/Net/Sinks.cpp \ $(COMMONDIR)/Net/URL.cpp \ @@ -251,7 +252,7 @@ SOURCES_CXX += \ $(GPUCOMMONDIR)/IndexGenerator.cpp \ $(GPUCOMMONDIR)/TextureDecoder.cpp \ $(GPUCOMMONDIR)/PostShader.cpp \ - $(COMMONDIR)/ColorConv.cpp \ + $(COMMONDIR)/Data/Convert/ColorConv.cpp \ $(GPUDIR)/Debugger/Breakpoints.cpp \ $(GPUDIR)/Debugger/Debugger.cpp \ $(GPUDIR)/Debugger/Playback.cpp \ @@ -543,7 +544,7 @@ ifeq ($(WITH_DYNAREC),1) $(COREDIR)/MIPS/ARM/ArmCompVFPUNEON.cpp \ $(COREDIR)/MIPS/ARM/ArmCompVFPUNEONUtil.cpp \ $(COREDIR)/Util/AudioFormatNEON.cpp \ - $(COMMONDIR)/ColorConvNEON.cpp \ + $(COMMONDIR)/Data/Convert/ColorConvNEON.cpp \ $(GPUDIR)/Common/TextureDecoderNEON.cpp SOURCES_C += $(EXTDIR)/libpng17/arm/arm_init.c \ @@ -572,7 +573,7 @@ ifeq ($(WITH_DYNAREC),1) $(COREDIR)/MIPS/ARM/ArmCompVFPUNEON.cpp \ $(COREDIR)/MIPS/ARM/ArmCompVFPUNEONUtil.cpp \ $(COREDIR)/Util/AudioFormatNEON.cpp \ - $(COMMONDIR)/ColorConvNEON.cpp \ + $(COMMONDIR)/Data/Convert/ColorConvNEON.cpp \ $(GPUDIR)/Common/TextureDecoderNEON.cpp SOURCES_C += $(EXTDIR)/libpng17/arm/arm_init.c \