refactor: remove dead code and fix thread safety in console_helpers

This commit is contained in:
MatthewBeshay 2026-04-03 17:29:45 +11:00
parent 5bbb045e86
commit 116cf4887d
26 changed files with 93 additions and 597 deletions

View file

@ -84,7 +84,7 @@ void LeaderboardManager::printStats(ReadView& view) {
ReadScore score = view.m_queries[i];
app.DebugPrintf("\tname='%s'\n",
wstringtofilename(std::wstring(score.m_name)));
wstringtofilename(std::wstring(score.m_name)).c_str());
app.DebugPrintf("\trank='%i'\n", score.m_rank);
app.DebugPrintf("\tstatsData=[");

View file

@ -29,7 +29,6 @@
#include "XboxStubs.h"
#include "console_helpers/StringHelpers.h"
#include "platform/PlatformServices.h"
#include "console_helpers/ThreadName.h"
#include "console_helpers/compression.h"
#include "java/File.h"
#include "minecraft/client/Minecraft.h"
@ -196,7 +195,6 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft* minecraft,
new C4JThread(&CGameNetworkManager::ServerThreadProc, lpParameter,
"Server", 256 * 1024);
thread->setProcessor(CPU_CORE_SERVER);
thread->run();
app.DebugPrintf("[NET] Waiting for server ready...\n");
@ -828,7 +826,7 @@ int CGameNetworkManager::ServerThreadProc(void* lpParameter) {
}
}
SetThreadName(-1, "Minecraft Server thread");
C4JThread::setThreadName(static_cast<std::uint32_t>(-1), "Minecraft Server thread");
Compression::UseDefaultThreadStorage();
OldChunkStorage::UseDefaultThreadStorage();
Entity::useSmallIds();

View file

@ -12,8 +12,7 @@
#include "app/common/src/Network/GameNetworkManager.h"
#include "app/common/src/Network/NetworkPlayerInterface.h"
#include "console_helpers/C4JThread.h" // 4jcraft TODO
#include "console_helpers/ThreadName.h" // 4jcraft TODO
#include "console_helpers/C4JThread.h"
#include "java/InputOutputStream/InputStream.h"
#include "java/InputOutputStream/OutputStream.h"

View file

@ -83,8 +83,6 @@ UIScene_FullscreenProgress::UIScene_FullscreenProgress(int iPad, void* initData,
m_labelTip.setVisible(m_CompletionData->bShowTips);
thread = new C4JThread(params->func, params->lpParam, "FullscreenProgress");
thread->setProcessor(CPU_CORE_UI_SCENE); // TODO 4J Stu - Make sure this is
// a good thread/core to use
m_threadCompleted = false;
thread->run();

View file

@ -7,7 +7,6 @@
#include "app/common/src/Network/Socket.h"
#include "console_helpers/StringHelpers.h"
#include "console_helpers/ThreadName.h"
#include "minecraft/client/User.h"
#include "minecraft/client/multiplayer/ClientConnection.h"
#include "minecraft/client/multiplayer/ConnectScreen.h"

View file

@ -13,27 +13,6 @@ using C4JThreadStartFunc = int(void* lpThreadParameter);
class Level;
inline constexpr int CPU_CORE_MAIN_THREAD = 0;
inline constexpr int CPU_CORE_CHUNK_REBUILD_A = 1;
inline constexpr int CPU_CORE_SAVE_THREAD_A = 1;
inline constexpr int CPU_CORE_TILE_UPDATE = 1;
inline constexpr int CPU_CORE_CONNECTIONS = 1;
inline constexpr int CPU_CORE_CHUNK_UPDATE = 2;
inline constexpr int CPU_CORE_REMOVE_PLAYER = 2;
inline constexpr int CPU_CORE_CHUNK_REBUILD_B = 3;
inline constexpr int CPU_CORE_SAVE_THREAD_B = 3;
inline constexpr int CPU_CORE_UI_SCENE = 3;
inline constexpr int CPU_CORE_POST_PROCESSING = 3;
inline constexpr int CPU_CORE_SERVER = 4;
inline constexpr int CPU_CORE_CHUNK_REBUILD_C = 5;
inline constexpr int CPU_CORE_SAVE_THREAD_C = 5;
inline constexpr int CPU_CORE_LEADERBOARDS = 5;
class C4JThread {
public:
struct WaitResult {
@ -106,7 +85,6 @@ public:
EventQueue(const EventQueue&) = delete;
EventQueue& operator=(const EventQueue&) = delete;
void setProcessor(int proc);
void setPriority(ThreadPriority priority);
void sendEvent(Level* pLevel);
void waitForFinish();
@ -124,7 +102,6 @@ public:
UpdateFunc* m_updateFunc;
ThreadInitFunc* m_threadInitFunc;
std::string m_threadName;
int m_processor;
ThreadPriority m_priority;
bool m_busy;
std::once_flag m_initOnce;
@ -148,7 +125,6 @@ public:
return m_hasStarted.load(std::memory_order_acquire);
}
void setProcessor(int proc);
void setPriority(ThreadPriority priority);
std::uint32_t waitForCompletion(int timeoutMs);
@ -169,9 +145,6 @@ public:
static void setThreadName(std::uint32_t threadId, const char* threadName);
static void setCurrentThreadName(const char* threadName);
static void pushAffinityAllCores();
static void popAffinity();
// TODO(C++26): When we switch to C++26, replace EventQueue with
// std::execution (senders/receivers) for structured concurrency.
// TODO(C++26): When we switch to C++26, use std::hazard_pointer / std::rcu
@ -193,7 +166,6 @@ private:
std::thread m_threadHandle;
std::unique_ptr<Event> m_completionFlag;
std::atomic<int> m_requestedProcessor;
std::atomic<ThreadPriority> m_requestedPriority;
std::atomic<std::int64_t> m_nativeTid;

View file

@ -6,7 +6,7 @@ enum ByteOrder {
BIGENDIAN,
LITTLEENDIAN,
LOCALSYTEM_ENDIAN = LITTLEENDIAN,
LOCALSYSTEM_ENDIAN = LITTLEENDIAN,
};
enum EDefaultSkins {
eDefaultSkins_ServerSelected,

View file

@ -36,7 +36,7 @@ std::wstring convStringToWstring(const std::string& converting);
std::wstring u16string_to_wstring(const std::u16string& converting);
std::u16string wstring_to_u16string(const std::wstring& converting);
std::u8string wstring_to_u8string(const std::wstring& converting);
const char* wstringtofilename(const std::wstring& name);
std::string wstringtofilename(const std::wstring& name);
std::wstring filenametowstring(const char* name);
std::vector<std::wstring>& stringSplit(const std::wstring& s, wchar_t delim,

View file

@ -1,4 +0,0 @@
#pragma once
#include <cstdint>
void SetThreadName(std::uint32_t threadId, const char* threadName);

View file

@ -1,22 +1,19 @@
#pragma once
#include <mutex>
#include <vector>
#include "minecraft/world/level/storage/ConsoleSaveFileIO/FileHeader.h"
class Compression {
public:
// Enum maps directly some external tools
enum ECompressionTypes {
eCompressionType_None = 0,
eCompressionType_RLE = 1,
eCompressionType_LZXRLE = 2,
eCompressionType_ZLIBRLE = 3,
eCompressionType_PS3ZLIB = 4
};
private:
// 4J added so we can have separate contexts and rleBuf for different
// threads
class ThreadStorage {
public:
Compression* compression;
@ -27,16 +24,11 @@ private:
static ThreadStorage* m_tlsCompressionDefault;
public:
// Each new thread that needs to use Compression will need to call one of
// the following 2 functions, to either create its own local storage, or
// share the default storage already allocated by the main thread
static void CreateNewThreadStorage();
static void UseDefaultThreadStorage();
static void ReleaseThreadStorage();
static Compression* getCompression();
public:
int32_t Compress(void* pDestination, unsigned int* pDestSize, void* pSource,
unsigned int SrcSize);
int32_t Decompress(void* pDestination, unsigned int* pDestSize,
@ -49,14 +41,10 @@ public:
void* pSource, unsigned int SrcSize);
int32_t DecompressRLE(void* pDestination, unsigned int* pDestSize,
void* pSource, unsigned int SrcSize);
static void VitaVirtualDecompress(void* pDestination,
unsigned int* pDestSize, void* pSource,
unsigned int SrcSize);
void SetDecompressionType(ECompressionTypes type) {
m_decompressType = type;
} // for loading a save from a different platform (Sony cloud storage cross
// play)
}
ECompressionTypes GetDecompressionType() { return m_decompressType; }
void SetDecompressionType(ESavePlatform platform);
@ -64,25 +52,13 @@ public:
~Compression();
private:
int32_t DecompressWithType(void* pDestination, unsigned int* pDestSize,
void* pSource, unsigned int SrcSize);
void* compressionContext;
void* decompressionContext;
std::mutex rleCompressLock;
std::mutex rleDecompressLock;
unsigned char rleCompressBuf[1024 * 100];
static const unsigned int staticRleSize = 1024 * 200;
unsigned char rleDecompressBuf[staticRleSize];
std::vector<unsigned char> rleCompressBuf;
std::vector<unsigned char> rleDecompressBuf;
ECompressionTypes m_decompressType;
ECompressionTypes m_localDecompressType;
};
// extern Compression gCompression;
#if defined(_WIN64) || defined(__linux__)
#define APPROPRIATE_COMPRESSION_TYPE Compression::eCompressionType_ZLIBRLE
#else
#define APPROPRIATE_COMPRESSION_TYPE Compression::eCompressionType_LZXRLE
#endif

View file

@ -1,5 +1,3 @@
#include <sched.h>
#include <algorithm>
#include <atomic>
#include <bit>
@ -15,7 +13,6 @@
#include <queue>
#include <string>
#include <thread>
#include <vector>
#if defined(_WIN32)
#include <Windows.h>
@ -75,12 +72,6 @@ void formatThreadName(std::string& out, const char* name) {
out = buf;
}
bool isProcessorIndexPlausible(int proc) {
if (proc < 0) return true;
const unsigned hw = std::thread::hardware_concurrency();
return hw == 0U || static_cast<unsigned>(proc) < hw;
}
std::int64_t getNativeThreadId() {
#if defined(__linux__)
return static_cast<std::int64_t>(::syscall(SYS_gettid));
@ -138,63 +129,6 @@ void setThreadNamePlatform([[maybe_unused]] std::uint32_t threadId,
#endif
}
#if defined(_WIN32)
thread_local std::vector<DWORD_PTR> g_affinityMaskStack;
#elif defined(__linux__)
thread_local std::vector<cpu_set_t> g_affinityMaskStack;
#endif
void setAffinityPlatform(std::thread& threadHandle, bool isSelf, int proc) {
#if defined(_WIN32)
void* handle = nullptr;
if (threadHandle.joinable())
handle = threadHandle.native_handle();
else if (isSelf)
handle = ::GetCurrentThread();
else
return;
DWORD_PTR mask = 0;
if (proc < 0) {
DWORD_PTR processMask = 0, systemMask = 0;
if (!::GetProcessAffinityMask(::GetCurrentProcess(), &processMask,
&systemMask) ||
processMask == 0)
return;
mask = processMask;
} else {
constexpr auto bitCount =
static_cast<unsigned>(sizeof(DWORD_PTR) * CHAR_BIT);
if (static_cast<unsigned>(proc) >= bitCount) return;
mask = static_cast<DWORD_PTR>(1) << static_cast<unsigned>(proc);
}
(void)::SetThreadAffinityMask(handle, mask);
#elif defined(__linux__)
pthread_t handle;
if (threadHandle.joinable())
handle = threadHandle.native_handle();
else if (isSelf)
handle = ::pthread_self();
else
return;
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
if (proc < 0) {
if (::sched_getaffinity(0, sizeof(cpuset), &cpuset) != 0) return;
} else {
if (proc >= CPU_SETSIZE) return;
CPU_SET(proc, &cpuset);
}
(void)::pthread_setaffinity_np(handle, sizeof(cpuset), &cpuset);
#else
(void)threadHandle;
(void)isSelf;
(void)proc;
#endif
}
void setPriorityPlatform(std::thread& threadHandle, bool isSelf,
C4JThread::ThreadPriority priority,
std::atomic<std::int64_t>& nativeTid) {
@ -276,7 +210,6 @@ C4JThread::C4JThread(C4JThreadStartFunc* startFunc, void* param,
m_threadID(),
m_threadHandle(),
m_completionFlag(std::make_unique<Event>(Event::Mode::ManualClear)),
m_requestedProcessor(-1),
m_requestedPriority(kUnsetPriority),
m_nativeTid(0) {
formatThreadName(m_threadName, threadName);
@ -293,7 +226,6 @@ C4JThread::C4JThread(const char* mainThreadName)
m_threadID(std::this_thread::get_id()),
m_threadHandle(),
m_completionFlag(std::make_unique<Event>(Event::Mode::ManualClear)),
m_requestedProcessor(-1),
m_requestedPriority(kUnsetPriority),
m_nativeTid(getNativeThreadId()) {
formatThreadName(m_threadName, mainThreadName);
@ -327,12 +259,6 @@ void C4JThread::entryPoint(C4JThread* pThread) {
setCurrentThreadName(pThread->m_threadName.c_str());
const int requestedProcessor =
pThread->m_requestedProcessor.load(std::memory_order_acquire);
if (requestedProcessor >= 0) {
pThread->setProcessor(requestedProcessor);
}
const auto requestedPriority =
pThread->m_requestedPriority.load(std::memory_order_acquire);
if (requestedPriority != kUnsetPriority) {
@ -368,12 +294,6 @@ void C4JThread::run() {
m_threadHandle = std::thread(&C4JThread::entryPoint, this);
m_threadID = m_threadHandle.get_id();
const int requestedProcessor =
m_requestedProcessor.load(std::memory_order_acquire);
if (requestedProcessor >= 0) {
setProcessor(requestedProcessor);
}
const auto requestedPriority =
m_requestedPriority.load(std::memory_order_acquire);
if (requestedPriority != kUnsetPriority) {
@ -381,12 +301,6 @@ void C4JThread::run() {
}
}
void C4JThread::setProcessor(int proc) {
m_requestedProcessor.store(proc, std::memory_order_release);
if (!isProcessorIndexPlausible(proc)) return;
setAffinityPlatform(m_threadHandle, ms_currentThread == this, proc);
}
void C4JThread::setPriority(ThreadPriority priority) {
m_requestedPriority.store(priority, std::memory_order_release);
setPriorityPlatform(m_threadHandle, ms_currentThread == this, priority,
@ -547,7 +461,6 @@ C4JThread::EventQueue::EventQueue(UpdateFunc* updateFunc,
m_updateFunc(updateFunc),
m_threadInitFunc(threadInitFunc),
m_threadName(threadName ? threadName : "Unnamed"),
m_processor(-1),
m_priority(kUnsetPriority),
m_busy(false),
m_initOnce(),
@ -561,11 +474,6 @@ C4JThread::EventQueue::~EventQueue() {
if (m_thread) (void)m_thread->waitForCompletion(kInfiniteTimeout);
}
void C4JThread::EventQueue::setProcessor(int proc) {
m_processor = proc;
if (m_thread) m_thread->setProcessor(proc);
}
void C4JThread::EventQueue::setPriority(ThreadPriority priority) {
m_priority = priority;
if (m_thread) m_thread->setPriority(priority);
@ -575,7 +483,6 @@ void C4JThread::EventQueue::init() {
std::call_once(m_initOnce, [this]() {
m_thread =
std::make_unique<C4JThread>(threadFunc, this, m_threadName.c_str());
if (m_processor >= 0) m_thread->setProcessor(m_processor);
if (m_priority != kUnsetPriority) m_thread->setPriority(m_priority);
m_thread->run();
});
@ -657,43 +564,3 @@ void C4JThread::EventQueue::threadPoll() {
ShutdownManager::HasFinished(ShutdownManager::eEventQueueThreads);
}
void C4JThread::pushAffinityAllCores() {
#if defined(_WIN32)
DWORD_PTR processMask = 0, systemMask = 0;
if (!::GetProcessAffinityMask(::GetCurrentProcess(), &processMask,
&systemMask) ||
processMask == 0)
return;
const DWORD_PTR prev =
::SetThreadAffinityMask(::GetCurrentThread(), processMask);
if (prev != 0) g_affinityMaskStack.push_back(prev);
#elif defined(__linux__)
cpu_set_t prev;
if (::pthread_getaffinity_np(::pthread_self(), sizeof(prev), &prev) != 0)
return;
g_affinityMaskStack.push_back(prev);
cpu_set_t all;
if (::sched_getaffinity(0, sizeof(all), &all) != 0) {
g_affinityMaskStack.pop_back();
return;
}
(void)::pthread_setaffinity_np(::pthread_self(), sizeof(all), &all);
#endif
}
void C4JThread::popAffinity() {
#if defined(_WIN32)
if (g_affinityMaskStack.empty()) return;
const DWORD_PTR prev = g_affinityMaskStack.back();
g_affinityMaskStack.pop_back();
(void)::SetThreadAffinityMask(::GetCurrentThread(), prev);
#elif defined(__linux__)
if (g_affinityMaskStack.empty()) return;
const cpu_set_t prev = g_affinityMaskStack.back();
g_affinityMaskStack.pop_back();
(void)::pthread_setaffinity_np(::pthread_self(), sizeof(prev), &prev);
#endif
}

View file

@ -1,7 +1,6 @@
#include <ctype.h>
#include <algorithm>
#include <cassert>
#include <cwctype>
#include <cstddef>
#include <sstream>
#include <string>
@ -11,10 +10,14 @@
std::wstring toLower(const std::wstring& a) {
std::wstring out = std::wstring(a);
std::transform(out.begin(), out.end(), out.begin(), ::tolower);
std::transform(out.begin(), out.end(), out.begin(), std::towlower);
return out;
}
// 4jcraft TODO: this intentionally returns the original string (not empty)
// for whitespace-only input. Callers in animation file parsing
// (AbstractTexturePack::getAnimationString) depend on this behavior -
// returning empty here breaks clock/compass texture frame loading.
std::wstring trimString(const std::wstring& a) {
std::wstring b;
int start = (int)a.find_first_not_of(L" \t\n\r");
@ -132,26 +135,18 @@ std::u8string wstring_to_u8string(const std::wstring& converting) {
}
}
// Convert for filename std::wstrings to a straight character pointer for Xbox
// APIs. The returned string is only valid until this function is called again,
// and it isn't thread-safe etc. as I'm just storing the returned name in a
// local static to save having to clear it up everywhere this is used.
const char* wstringtofilename(const std::wstring& name) {
static char buf[256];
assert(name.length() < 256);
for (unsigned int i = 0; i < name.length(); i++) {
wchar_t c = name[i];
std::string wstringtofilename(const std::wstring& name) {
std::string result;
result.reserve(name.size());
for (wchar_t c : name) {
#if defined(__linux__)
if (c == '\\') c = '/';
if (c == L'\\') c = L'/';
#else
if (c == '/') c = '\\';
if (c == L'/') c = L'\\';
#endif
assert(c < 128); // Will we have to do any conversion of non-ASCII
// characters in filenames?
buf[i] = (char)c;
result += static_cast<char>(c);
}
buf[name.length()] = 0;
return buf;
return result;
}
std::wstring filenametowstring(const char* name) {

View file

@ -1,28 +0,0 @@
#include <cstdint>
// From Xbox documentation
typedef struct tagTHREADNAME_INFO {
std::uint32_t dwType; // Must be 0x1000
const char* szName; // Pointer to name (in user address space)
std::uint32_t dwThreadID; // Thread ID (-1 for caller thread)
std::uint32_t dwFlags; // Reserved for future use; must be zero
} THREADNAME_INFO;
void SetThreadName(std::uint32_t threadId, const char* threadName) {
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = threadId;
info.dwFlags = 0;
#if (defined _WINDOWS64 | 0)
__try {
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(std::uint32_t),
reinterpret_cast<uintptr_t*>(&info));
} __except (GetExceptionCode() == 0x406D1388 ? EXCEPTION_CONTINUE_EXECUTION
: EXCEPTION_EXECUTE_HANDLER) {
}
#endif
}

View file

@ -2,30 +2,19 @@
#include <assert.h>
#include <string.h>
#include <zconf.h>
#include <cstdint>
#include <mutex>
#include "app/include/XboxStubs.h"
#include "minecraft/world/level/storage/ConsoleSaveFileIO/FileHeader.h"
#if defined(_WIN64) || defined(__linux__)
// zconf.h defines "typedef unsigned char Byte" which conflicts with the
// project's "class Byte" from BasicTypeContainers.h (via stdafx.h).
// Rename zlib's Byte to zlib_Byte before the include so the typedef lands
// under that alias; Bytef (= Byte FAR) will resolve to zlib_Byte as well.
#define Byte zlib_Byte
#include <zlib.h>
#undef Byte
#endif
thread_local Compression::ThreadStorage* Compression::m_tlsCompression =
nullptr;
Compression::ThreadStorage* Compression::m_tlsCompressionDefault = nullptr;
Compression::ThreadStorage::ThreadStorage() { compression = new Compression(); }
Compression::ThreadStorage::~ThreadStorage() { delete compression; }
void Compression::CreateNewThreadStorage() {
@ -53,33 +42,28 @@ Compression* Compression::getCompression() {
int32_t Compression::CompressLZXRLE(void* pDestination, unsigned int* pDestSize,
void* pSource, unsigned int SrcSize) {
std::lock_guard<std::mutex> lock(rleCompressLock);
// static unsigned char rleBuf[1024*100];
if (rleCompressBuf.size() < SrcSize * 2)
rleCompressBuf.resize(SrcSize * 2);
unsigned char* pucIn = (unsigned char*)pSource;
unsigned char* pucEnd = pucIn + SrcSize;
unsigned char* pucOut = (unsigned char*)rleCompressBuf;
unsigned char* pucOut = rleCompressBuf.data();
// Compress with RLE first:
// 0 - 254 - encodes a single byte
// 255 followed by 0, 1, 2 - encodes a 1, 2, or 3 255s
// 255 followed by 3-255, followed by a byte - encodes a run of n + 1 bytes
do {
unsigned char thisOne = *pucIn++;
unsigned int count = 1;
while ((pucIn != pucEnd) && (*pucIn == thisOne) && (count < 256)) {
pucIn++;
count++;
}
if (count <= 3) {
if (thisOne == 255) {
*pucOut++ = 255;
*pucOut++ = count - 1;
} else {
for (unsigned int i = 0; i < count; i++) {
for (unsigned int i = 0; i < count; i++)
*pucOut++ = thisOne;
}
}
} else {
*pucOut++ = 255;
@ -87,68 +71,9 @@ int32_t Compression::CompressLZXRLE(void* pDestination, unsigned int* pDestSize,
*pucOut++ = thisOne;
}
} while (pucIn != pucEnd);
unsigned int rleSize = (unsigned int)(pucOut - rleCompressBuf);
Compress(pDestination, pDestSize, rleCompressBuf, rleSize);
// printf("Compressed from %d to %d to %d\n",SrcSize,rleSize,*pDestSize);
return 0;
}
int32_t Compression::CompressRLE(void* pDestination, unsigned int* pDestSize,
void* pSource, unsigned int SrcSize) {
unsigned int rleSize;
{
std::lock_guard<std::mutex> lock(rleCompressLock);
// static unsigned char rleBuf[1024*100];
unsigned char* pucIn = (unsigned char*)pSource;
unsigned char* pucEnd = pucIn + SrcSize;
unsigned char* pucOut = (unsigned char*)rleCompressBuf;
// Compress with RLE first:
// 0 - 254 - encodes a single byte
// 255 followed by 0, 1, 2 - encodes a 1, 2, or 3 255s
// 255 followed by 3-255, followed by a byte - encodes a run of n + 1
// bytes
do {
unsigned char thisOne = *pucIn++;
unsigned int count = 1;
while ((pucIn != pucEnd) && (*pucIn == thisOne) && (count < 256)) {
pucIn++;
count++;
}
if (count <= 3) {
if (thisOne == 255) {
*pucOut++ = 255;
*pucOut++ = count - 1;
} else {
for (unsigned int i = 0; i < count; i++) {
*pucOut++ = thisOne;
}
}
} else {
*pucOut++ = 255;
*pucOut++ = count - 1;
*pucOut++ = thisOne;
}
} while (pucIn != pucEnd);
rleSize = (unsigned int)(pucOut - rleCompressBuf);
}
// Return
if (rleSize <= *pDestSize) {
*pDestSize = rleSize;
memcpy(pDestination, rleCompressBuf, *pDestSize);
} else {
#if !defined(_CONTENT_PACKAGE)
assert(false);
#endif
}
unsigned int rleSize = (unsigned int)(pucOut - rleCompressBuf.data());
Compress(pDestination, pDestSize, rleCompressBuf.data(), rleSize);
return 0;
}
@ -156,32 +81,14 @@ int32_t Compression::DecompressLZXRLE(void* pDestination,
unsigned int* pDestSize, void* pSource,
unsigned int SrcSize) {
std::lock_guard<std::mutex> lock(rleDecompressLock);
// 4J Stu - Fix for #13676 - Crash: Crash while attempting to load a world
// after updating TU Some saves can have chunks that decompress into very
// large sizes, so I have doubled the size of this buffer Ideally we should
// be able to dynamically allocate the buffer if it's going to be too big,
// as most chunks only use 5% of this buffer
// 4J Stu - Changed this again to dynamically allocate a buffer if it's
// going to be too big
unsigned char* pucIn = nullptr;
unsigned int rleSize = *pDestSize;
if (rleDecompressBuf.size() < rleSize)
rleDecompressBuf.resize(rleSize);
// const unsigned int staticRleSize = 1024*200;
// static unsigned char rleBuf[staticRleSize];
unsigned int rleSize = staticRleSize;
unsigned char* dynamicRleBuf = nullptr;
Decompress(rleDecompressBuf.data(), &rleSize, pSource, SrcSize);
if (*pDestSize > rleSize) {
rleSize = *pDestSize;
dynamicRleBuf = new unsigned char[rleSize];
Decompress(dynamicRleBuf, &rleSize, pSource, SrcSize);
pucIn = (unsigned char*)dynamicRleBuf;
} else {
Decompress(rleDecompressBuf, &rleSize, pSource, SrcSize);
pucIn = (unsigned char*)rleDecompressBuf;
}
// unsigned char *pucIn = (unsigned char *)rleDecompressBuf;
unsigned char* pucIn = rleDecompressBuf.data();
unsigned char* pucEnd = pucIn + rleSize;
unsigned char* pucOut = (unsigned char*)pDestination;
@ -191,26 +98,65 @@ int32_t Compression::DecompressLZXRLE(void* pDestination,
unsigned int count = *pucIn++;
if (count < 3) {
count++;
for (unsigned int i = 0; i < count; i++) {
for (unsigned int i = 0; i < count; i++)
*pucOut++ = 255;
}
} else {
count++;
unsigned char data = *pucIn++;
for (unsigned int i = 0; i < count; i++) {
for (unsigned int i = 0; i < count; i++)
*pucOut++ = data;
}
}
} else {
*pucOut++ = thisOne;
}
}
*pDestSize = (unsigned int)(pucOut - (unsigned char*)pDestination);
return 0;
}
// printf("Decompressed from %d to %d to %d\n",SrcSize,rleSize,*pDestSize);
int32_t Compression::CompressRLE(void* pDestination, unsigned int* pDestSize,
void* pSource, unsigned int SrcSize) {
unsigned int rleSize;
{
std::lock_guard<std::mutex> lock(rleCompressLock);
if (dynamicRleBuf != nullptr) delete[] dynamicRleBuf;
if (rleCompressBuf.size() < SrcSize * 2)
rleCompressBuf.resize(SrcSize * 2);
unsigned char* pucIn = (unsigned char*)pSource;
unsigned char* pucEnd = pucIn + SrcSize;
unsigned char* pucOut = rleCompressBuf.data();
do {
unsigned char thisOne = *pucIn++;
unsigned int count = 1;
while ((pucIn != pucEnd) && (*pucIn == thisOne) && (count < 256)) {
pucIn++;
count++;
}
if (count <= 3) {
if (thisOne == 255) {
*pucOut++ = 255;
*pucOut++ = count - 1;
} else {
for (unsigned int i = 0; i < count; i++)
*pucOut++ = thisOne;
}
} else {
*pucOut++ = 255;
*pucOut++ = count - 1;
*pucOut++ = thisOne;
}
} while (pucIn != pucEnd);
rleSize = (unsigned int)(pucOut - rleCompressBuf.data());
}
if (rleSize <= *pDestSize) {
*pDestSize = rleSize;
memcpy(pDestination, rleCompressBuf.data(), *pDestSize);
} else {
assert(false);
}
return 0;
}
@ -218,7 +164,6 @@ int32_t Compression::DecompressRLE(void* pDestination, unsigned int* pDestSize,
void* pSource, unsigned int SrcSize) {
std::lock_guard<std::mutex> lock(rleDecompressLock);
// unsigned char *pucIn = (unsigned char *)rleDecompressBuf;
unsigned char* pucIn = (unsigned char*)pSource;
unsigned char* pucEnd = pucIn + SrcSize;
unsigned char* pucOut = (unsigned char*)pDestination;
@ -229,250 +174,57 @@ int32_t Compression::DecompressRLE(void* pDestination, unsigned int* pDestSize,
unsigned int count = *pucIn++;
if (count < 3) {
count++;
for (unsigned int i = 0; i < count; i++) {
for (unsigned int i = 0; i < count; i++)
*pucOut++ = 255;
}
} else {
count++;
unsigned char data = *pucIn++;
for (unsigned int i = 0; i < count; i++) {
for (unsigned int i = 0; i < count; i++)
*pucOut++ = data;
}
}
} else {
*pucOut++ = thisOne;
}
}
*pDestSize = (unsigned int)(pucOut - (unsigned char*)pDestination);
return 0;
}
int32_t Compression::Compress(void* pDestination, unsigned int* pDestSize,
void* pSource, unsigned int SrcSize) {
// Using zlib for x64 compression - 360 is using native 360 compression and
// PS3 a stubbed non-compressing version of this
#if defined(_WIN64) || defined(__linux__)
size_t destSize = (size_t)(*pDestSize);
int res = ::compress((Bytef*)pDestination, (uLongf*)&destSize,
(Bytef*)pSource, SrcSize);
*pDestSize = (unsigned int)destSize;
return ((res == Z_OK) ? 0 : -1);
#else
size_t destSize = (size_t)(*pDestSize);
int32_t res = XMemCompress(compressionContext, pDestination, &destSize,
pSource, SrcSize);
*pDestSize = (unsigned int)destSize;
return res;
#endif
}
int32_t Compression::Decompress(void* pDestination, unsigned int* pDestSize,
void* pSource, unsigned int SrcSize) {
if (m_decompressType !=
m_localDecompressType) // check if we're decompressing data from a
// different platform
{
// only used for loading a save from a different platform (Sony cloud
// storage cross play)
return DecompressWithType(pDestination, pDestSize, pSource, SrcSize);
}
// Using zlib for x64 compression - 360 is using native 360 compression and
// PS3 a stubbed non-compressing version of this
#if defined(_WIN64) || defined(__linux__)
size_t destSize = (size_t)(*pDestSize);
int res = ::uncompress((Bytef*)pDestination, (uLongf*)&destSize,
(Bytef*)pSource, SrcSize);
*pDestSize = (unsigned int)destSize;
return ((res == Z_OK) ? 0 : -1);
#else
size_t destSize = (size_t)(*pDestSize);
int32_t res = XMemDecompress(decompressionContext, pDestination,
(size_t*)&destSize, pSource, SrcSize);
*pDestSize = (unsigned int)destSize;
return res;
#endif
}
// MGH - same as VirtualDecompress in PSVitaStubs, but for use on other
// platforms (so no virtual mem stuff)
void Compression::VitaVirtualDecompress(
void* pDestination, unsigned int* pDestSize, void* pSource,
unsigned int SrcSize) // (void* buf, size_t dwSize, void* dst)
{
std::uint8_t* pSrc = (std::uint8_t*)pSource;
int Offset = 0;
int Page = 0;
int Index = 0;
std::uint8_t* Data = (std::uint8_t*)pDestination;
while (Index != SrcSize) {
// is this a normal value
if (pSrc[Index]) {
// just copy it across
Data[Offset] = pSrc[Index];
Offset += 1;
} else {
// how many zeros do we have
Index += 1;
int Count = pSrc[Index];
// to do : this should really be a sequence of memsets
for (int i = 0; i < Count; i += 1) {
Data[Offset] = 0;
Offset += 1;
}
}
Index += 1;
}
*pDestSize = Offset;
}
int32_t Compression::DecompressWithType(void* pDestination,
unsigned int* pDestSize, void* pSource,
unsigned int SrcSize) {
switch (m_decompressType) {
case eCompressionType_RLE: // 4J-JEV, RLE is just that; don't want to
// break here though.
case eCompressionType_None:
memcpy(pDestination, pSource, SrcSize);
*pDestSize = SrcSize;
return 0;
case eCompressionType_LZXRLE: {
#if defined(_WIN64)
size_t destSize = (size_t)(*pDestSize);
int32_t res = XMemDecompress(decompressionContext, pDestination,
(size_t*)&destSize, pSource, SrcSize);
*pDestSize = (unsigned int)destSize;
return res;
#else
assert(0);
#endif
} break;
case eCompressionType_ZLIBRLE:
#if defined(_WIN64) || defined(__linux__)
if (pDestination != nullptr)
return ::uncompress(
(Bytef*)pDestination, (unsigned long*)pDestSize,
(const Bytef*)pSource, SrcSize); // Decompress
else
break; // Cannot decompress when destination is nullptr
#else
assert(0);
break;
#endif
case eCompressionType_PS3ZLIB:
#if defined(_WIN64)
// Note that we're missing the normal zlib header and footer so
// we'll use inflate to decompress the payload and skip all the CRC
// checking, etc
if (pDestination != nullptr) {
// Read big-endian srcize from array
std::uint8_t* pbDestSize =
reinterpret_cast<std::uint8_t*>(pDestSize);
std::uint8_t* pbSource =
reinterpret_cast<std::uint8_t*>(pSource);
for (int i = 3; i >= 0; i--) {
pbDestSize[3 - i] = pbSource[i];
}
std::vector<uint8_t> uncompr = std::vector<uint8_t>(*pDestSize);
// Build decompression stream
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.next_out = uncompr.data;
strm.avail_out = uncompr.length;
// Skip those first 4 bytes
strm.next_in = reinterpret_cast<std::uint8_t*>(pSource) + 4;
strm.avail_in = SrcSize - 4;
int hr = inflateInit2(&strm, -15);
// Run inflate() on input until end of stream
do {
hr = inflate(&strm, Z_NO_FLUSH);
// Check
switch (hr) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
case Z_STREAM_ERROR:
(void)inflateEnd(&strm);
assert(false);
}
} while (hr != Z_STREAM_END);
inflateEnd(
&strm); // MGH - added, to clean up zlib, was causing a
// leak on Vita when dowloading a PS3 save
// Copy the uncompressed data to the destination
memcpy(pDestination, uncompr.data, uncompr.length);
*pDestSize = uncompr.length;
// Delete uncompressed data
delete uncompr.data;
return 0;
} else
break; // Cannot decompress when destination is nullptr
#else
assert(0);
#endif
}
assert(false);
return -1;
}
Compression::Compression() {
// Using zlib for x64 compression - 360 is using native 360 compression and
// PS3 a stubbed non-compressing version of this
// The default parameters for compression context allocated about 6.5MB,
// reducing the partition size here from the default 512KB to 128KB brings
// this down to about 3MB
XMEMCODEC_PARAMETERS_LZX params;
params.Flags = 0;
params.WindowSize = 128 * 1024;
params.CompressionPartitionSize = 128 * 1024;
XMemCreateCompressionContext(XMEMCODEC_LZX, &params, 0,
&compressionContext);
XMemCreateDecompressionContext(XMEMCODEC_LZX, &params, 0,
&decompressionContext);
m_localDecompressType = eCompressionType_ZLIBRLE;
m_decompressType = m_localDecompressType;
}
Compression::~Compression() {
XMemDestroyCompressionContext(compressionContext);
XMemDestroyDecompressionContext(decompressionContext);
}
Compression::~Compression() {}
void Compression::SetDecompressionType(ESavePlatform platform) {
switch (platform) {
case SAVE_FILE_PLATFORM_X360:
Compression::getCompression()->SetDecompressionType(
Compression::eCompressionType_LZXRLE);
break;
case SAVE_FILE_PLATFORM_PS3:
Compression::getCompression()->SetDecompressionType(
Compression::eCompressionType_PS3ZLIB);
break;
case SAVE_FILE_PLATFORM_XBONE:
case SAVE_FILE_PLATFORM_PS4:
case SAVE_FILE_PLATFORM_PSVITA:
case SAVE_FILE_PLATFORM_WIN64:
Compression::getCompression()->SetDecompressionType(
Compression::eCompressionType_ZLIBRLE);
getCompression()->SetDecompressionType(eCompressionType_ZLIBRLE);
break;
default:
assert(0);
break;
}
}
/*Compression gCompression;*/

View file

@ -7,7 +7,6 @@
#include <unordered_set>
#include <vector>
#include "console_helpers/HashExtension.h"
#include "java/JavaIntHash.h"
#include "minecraft/world/entity/Entity.h"

View file

@ -202,7 +202,6 @@ GameRenderer::GameRenderer(Minecraft* mc) {
m_updateEvents->set(eUpdateEventIsFinished);
m_updateThread = new C4JThread(runUpdate, nullptr, "Chunk update");
m_updateThread->setProcessor(CPU_CORE_CHUNK_UPDATE);
m_updateThread->run();
#endif
}

View file

@ -4029,14 +4029,6 @@ void LevelRenderer::staticCtor() {
s_activationEventA[i] = new C4JThread::Event();
// Threads 1,3 and 5 are generally idle so use them
if ((i % 3) == 0)
rebuildThreads[i]->setProcessor(CPU_CORE_CHUNK_REBUILD_A);
else if ((i % 3) == 1) {
rebuildThreads[i]->setProcessor(CPU_CORE_CHUNK_REBUILD_B);
} else if ((i % 3) == 2)
rebuildThreads[i]->setProcessor(CPU_CORE_CHUNK_REBUILD_C);
// ResumeThread( saveThreads[j] );
rebuildThreads[i]->run();
}

View file

@ -1228,13 +1228,10 @@ BufferedImage* Textures::readImage(
name, false, isTu,
drive); // new BufferedImage(name,false,isTu,drive);
} else {
const char* pchName = wstringtofilename(name);
{
drive = skins->getDefault()->getPath(isTu);
}
const char* pchDrive = wstringtofilename(drive);
if (IsOriginalImage(texId, name) || isTu) {
img = skins->getDefault()->getImageResource(
name, false, isTu,

View file

@ -160,9 +160,10 @@ std::wstring AbstractTexturePack::getAnimationString(
BufferedImage* AbstractTexturePack::getImageResource(
const std::wstring& File, bool filenameHasExtension /*= false*/,
bool bTitleUpdateTexture /*=false*/, const std::wstring& drive /*=L""*/) {
const char* pchTexture = wstringtofilename(File);
std::string pchTexture = wstringtofilename(File);
std::string pchDrive = wstringtofilename(drive);
app.DebugPrintf("AbstractTexturePack::getImageResource - %s, drive is %s\n",
pchTexture, wstringtofilename(drive));
pchTexture.c_str(), pchDrive.c_str());
return new BufferedImage(TexturePack::getResource(L"/" + File),
filenameHasExtension, bTitleUpdateTexture, drive);

View file

@ -116,19 +116,16 @@ Connection::Connection(Socket* socket, const std::wstring& id,
m_hWakeReadThread = new C4JThread::Event;
m_hWakeWriteThread = new C4JThread::Event;
const char* szId = wstringtofilename(id);
std::string szId = wstringtofilename(id);
char readThreadName[256];
char writeThreadName[256];
sprintf(readThreadName, "%s read\n", szId);
sprintf(writeThreadName, "%s write\n", szId);
sprintf(readThreadName, "%s read\n", szId.c_str());
sprintf(writeThreadName, "%s write\n", szId.c_str());
readThread =
new C4JThread(runRead, (void*)this, readThreadName, READ_STACK_SIZE);
writeThread =
new C4JThread(runWrite, this, writeThreadName, WRITE_STACK_SIZE);
readThread->setProcessor(CPU_CORE_CONNECTIONS);
writeThread->setProcessor(CPU_CORE_CONNECTIONS);
readThread->run();
writeThread->run();

View file

@ -4,7 +4,6 @@
#include <unordered_map>
#include <unordered_set>
#include "console_helpers/HashExtension.h"
#include "java/JavaIntHash.h"
class Entity;

View file

@ -91,7 +91,6 @@ void ServerLevel::staticCtor() {
m_updateTrigger = new C4JThread::EventArray(3);
m_updateThread = new C4JThread(runUpdate, nullptr, "Tile update");
m_updateThread->setProcessor(CPU_CORE_TILE_UPDATE);
m_updateThread->run();
RANDOM_BONUS_ITEMS = std::vector<WeighedTreasure*>(20);

View file

@ -1200,7 +1200,7 @@ int CompressedTileStorage::getHighestNonEmptyY() {
void CompressedTileStorage::write(DataOutputStream* dos) {
dos->writeInt(allocatedSize);
if (indicesAndData) {
if (LOCALSYTEM_ENDIAN == BIGENDIAN) {
if (LOCALSYSTEM_ENDIAN == BIGENDIAN) {
// The first 1024 bytes are an array of shorts, so we need to
// reverse the endianness
std::vector<uint8_t> indicesCopy(1024);
@ -1236,7 +1236,7 @@ void CompressedTileStorage::read(DataInputStream* dis) {
std::vector<uint8_t> wrapper(allocatedSize);
dis->readFully(wrapper);
memcpy(indicesAndData, wrapper.data(), allocatedSize);
if (LOCALSYTEM_ENDIAN == BIGENDIAN) {
if (LOCALSYSTEM_ENDIAN == BIGENDIAN) {
reverseIndices(indicesAndData);
}

View file

@ -12,7 +12,6 @@
#include "app/common/src/Console_Debug_enum.h"
#include "app/linux/Linux_App.h"
#include "console_helpers/C4JThread.h"
#include "console_helpers/ThreadName.h"
#include "console_helpers/compression.h"
#include "java/InputOutputStream/BufferedOutputStream.h"
#include "java/InputOutputStream/ByteArrayInputStream.h"
@ -324,7 +323,7 @@ void McRegionChunkStorage::staticCtor() {
for (unsigned int i = 0; i < 3; ++i) {
char threadName[256];
sprintf(threadName, "McRegion Save thread %d\n", i);
SetThreadName(0, threadName);
C4JThread::setThreadName(0, threadName);
// saveThreads[j] =
// CreateThread(nullptr,0,runSaveThreadProc,&threadData[j],CREATE_SUSPENDED,&threadId[j]);
@ -333,14 +332,6 @@ void McRegionChunkStorage::staticCtor() {
// app.DebugPrintf("Created new thread: %s\n",threadName);
// Threads 1,3 and 5 are generally idle so use them
if (i == 0)
s_saveThreads[i]->setProcessor(CPU_CORE_SAVE_THREAD_A);
else if (i == 1) {
s_saveThreads[i]->setProcessor(CPU_CORE_SAVE_THREAD_B);
} else if (i == 2)
s_saveThreads[i]->setProcessor(CPU_CORE_SAVE_THREAD_C);
// ResumeThread( saveThreads[j] );
s_saveThreads[i]->run();
}

View file

@ -4,7 +4,6 @@
#include <string>
#include <unordered_map>
#include "console_helpers/HashExtension.h"
#include "java/Class.h"
#include "java/JavaIntHash.h"