mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-04-15 12:51:29 -06:00
Merge branch 'cemu-project:main' into main
This commit is contained in:
commit
b2058d679c
20
.github/workflows/build.yml
vendored
20
.github/workflows/build.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: "Checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: "recursive"
|
||||
fetch-depth: 0
|
||||
@ -83,7 +83,7 @@ jobs:
|
||||
run: mv bin/Cemu_release bin/Cemu
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: cemu-bin-linux-${{ matrix.arch }}
|
||||
path: ./bin/Cemu
|
||||
@ -103,9 +103,9 @@ jobs:
|
||||
needs: build-ubuntu
|
||||
steps:
|
||||
- name: Checkout Upstream Repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: cemu-bin-linux-${{ matrix.arch }}
|
||||
path: bin
|
||||
@ -122,7 +122,7 @@ jobs:
|
||||
dist/linux/appimage.sh ${{ runner.arch }}
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: cemu-appimage-${{ matrix.arch }}
|
||||
path: artifacts
|
||||
@ -131,7 +131,7 @@ jobs:
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- name: "Checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: "recursive"
|
||||
|
||||
@ -193,13 +193,13 @@ jobs:
|
||||
makensis /DPRODUCT_VERSION=${{ inputs.next_version_major }}.${{ inputs.next_version_minor }} installer.nsi
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: cemu-bin-windows-x64
|
||||
path: ./bin/Cemu.exe
|
||||
|
||||
- name: Upload NSIS Installer
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: cemu-installer-windows-x64
|
||||
path: ./src/resource/cemu-${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}-windows-x64-installer.exe
|
||||
@ -211,7 +211,7 @@ jobs:
|
||||
arch: [x86_64, arm64]
|
||||
steps:
|
||||
- name: "Checkout repo"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: "recursive"
|
||||
|
||||
@ -289,7 +289,7 @@ jobs:
|
||||
rm bin/tmp.dmg
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: cemu-bin-macos-${{ matrix.arch }}
|
||||
path: ./bin/Cemu.dmg
|
||||
|
||||
12
.github/workflows/deploy_release.yml
vendored
12
.github/workflows/deploy_release.yml
vendored
@ -58,7 +58,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [call-release-build, calculate-version]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@ -78,27 +78,27 @@ jobs:
|
||||
if [ -n "${{ github.event.inputs.changelog9 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog9 }}\n"; fi
|
||||
echo -e "$CHANGELOG"
|
||||
echo "RELEASE_BODY=$CHANGELOG" >> $GITHUB_ENV
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: cemu-bin-linux-x64
|
||||
path: cemu-bin-linux-x64
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: cemu-appimage-x64
|
||||
path: cemu-appimage-x64
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: cemu-bin-windows-x64
|
||||
path: cemu-bin-windows-x64
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: cemu-installer-windows-x64
|
||||
path: cemu-installer-windows-x64
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
pattern: cemu-bin-macos*
|
||||
path: cemu-macos
|
||||
|
||||
@ -23,7 +23,7 @@ jobs:
|
||||
next_version_minor: ${{ steps.calculate_next_version.outputs.next_version_minor }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Get all releases
|
||||
id: get_all_releases
|
||||
|
||||
4
.github/workflows/generate_pot.yml
vendored
4
.github/workflows/generate_pot.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout repo"
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: "Install gettext"
|
||||
run: |
|
||||
@ -36,7 +36,7 @@ jobs:
|
||||
-o cemu.pot
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: POT file
|
||||
path: ./cemu.pot
|
||||
|
||||
40
dependencies/vcpkg_overlay_ports/wxwidgets/fix-listctrl-layout.patch
vendored
Normal file
40
dependencies/vcpkg_overlay_ports/wxwidgets/fix-listctrl-layout.patch
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp
|
||||
index 5e1cd98a8b..169ab7847d 100644
|
||||
--- a/src/msw/listctrl.cpp
|
||||
+++ b/src/msw/listctrl.cpp
|
||||
@@ -1385,20 +1385,29 @@ bool wxListCtrl::GetSubItemRect(long item, long subItem, wxRect& rect, int code)
|
||||
|
||||
wxCopyRECTToRect(rectWin, rect);
|
||||
|
||||
- // We can't use wxGetListCtrlSubItemRect() for the 0th subitem as 0 means
|
||||
- // the entire row for this function, so we need to calculate it ourselves.
|
||||
- if ( subItem == 0 && code == wxLIST_RECT_BOUNDS )
|
||||
+ // We can't trust the native LVM_GETSUBITEMRECT for LVIR_BOUNDS because:
|
||||
+ // - subitem 0 returns the entire row bounds, not just column 0
|
||||
+ // - when column 0 is narrower than the icon, the native control clamps
|
||||
+ // all subitems' left edge to at least the icon width, misaligning them
|
||||
+ //
|
||||
+ // So for all subitems we calculate x and width from GetColumnWidth() in
|
||||
+ // visual (column order) order, which always reflects the real column sizes.
|
||||
+ if ( subItem != wxLIST_GETSUBITEMRECT_WHOLEITEM && code == wxLIST_RECT_BOUNDS )
|
||||
{
|
||||
- // Because the columns can be reordered, we need to sum the widths of
|
||||
- // all preceding columns to get the correct x position.
|
||||
+ // Start from the row's left edge (which accounts for scrolling).
|
||||
+ RECT rowRect;
|
||||
+ wxGetListCtrlItemRect(GetHwnd(), item, LVIR_BOUNDS, rowRect);
|
||||
+ int x = rowRect.left;
|
||||
+
|
||||
for ( auto col : GetColumnsOrder() )
|
||||
{
|
||||
if ( col == subItem )
|
||||
break;
|
||||
|
||||
- rect.x += GetColumnWidth(col);
|
||||
+ x += GetColumnWidth(col);
|
||||
}
|
||||
|
||||
+ rect.x = x;
|
||||
rect.width = GetColumnWidth(subItem);
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO wxWidgets/wxWidgets
|
||||
REF "bfd436b"
|
||||
SHA512 bd3fd6d0d0db3b6fa34eceae1119e21ffd2f62221dcd249f8b8b82a6e65d83a05101e4e1e4ca9b9c4d7937add73b113bb029b03b05d2c3d87d17c1922d800a24
|
||||
REF "v${VERSION}"
|
||||
SHA512 c47460c8bc150445e7774a287a79bd70b6d96b91ea46b51f238a317f068e466d570c5a94e2204d112e42da781a5cef98236718efff4b7f539d61a12ceaf65eb7
|
||||
HEAD_REF master
|
||||
PATCHES
|
||||
install-layout.patch
|
||||
@ -12,14 +12,15 @@ vcpkg_from_github(
|
||||
fix-pcre2.patch
|
||||
gtk3-link-libraries.patch
|
||||
sdl2.patch
|
||||
fix-listctrl-layout.patch
|
||||
)
|
||||
|
||||
# Submodule dependencies
|
||||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH lexilla_SOURCE_PATH
|
||||
REPO wxWidgets/lexilla
|
||||
REF "27c20a6ae5eebf418debeac0166052ed6fb653bc"
|
||||
SHA512 7e5de7f664509473b691af8261fca34c2687772faca7260eeba5f2984516e6f8edf88c27192e056c9dda996e2ad2c20f6d1dff1c4bd2f3c0d74852cb50ca424a
|
||||
REF "0dbce0b418b8b3d2ef30304d0bf53ff58c07ed84"
|
||||
SHA512 61f7b0217f4518121ecad32f015b53600e565bdd499d4020468cf6c8a533d516c6881115aa5e640afca5ea428535f47680cde426fa3dbabe9e4423b4526853fd
|
||||
HEAD_REF wx
|
||||
)
|
||||
file(COPY "${lexilla_SOURCE_PATH}/" DESTINATION "${SOURCE_PATH}/src/stc/lexilla")
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wxwidgets",
|
||||
"version": "3.3.1",
|
||||
"version": "3.3.2",
|
||||
"description": [
|
||||
"Widget toolkit and tools library for creating graphical user interfaces (GUIs) for cross-platform applications. ",
|
||||
"Set WXWIDGETS_USE_STL in a custom triplet to build with the wxUSE_STL build option.",
|
||||
|
||||
@ -140,6 +140,8 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u
|
||||
depth = 1;
|
||||
}
|
||||
uint32 height = word1.get_HEIGHT() + 1;
|
||||
if (dim == Latte::E_DIM::DIM_1D || dim == Latte::E_DIM::DIM_1D_ARRAY)
|
||||
height = 1;
|
||||
if (Latte::IsCompressedFormat(word1.get_DATA_FORMAT()))
|
||||
pitch /= 4;
|
||||
// view slice
|
||||
|
||||
@ -45,7 +45,7 @@ public:
|
||||
VKRMoveableRefCounter(VKRMoveableRefCounter&& rhs) noexcept
|
||||
{
|
||||
this->refs = std::move(rhs.refs);
|
||||
this->m_refCount = rhs.m_refCount;
|
||||
this->m_refCount.store(rhs.m_refCount);
|
||||
rhs.m_refCount = 0;
|
||||
this->selfRef = rhs.selfRef;
|
||||
rhs.selfRef = nullptr;
|
||||
@ -88,21 +88,13 @@ protected:
|
||||
// does nothing by default
|
||||
}
|
||||
|
||||
int m_refCount{};
|
||||
std::atomic_int_least32_t m_refCount{};
|
||||
private:
|
||||
VKRMoveableRefCounterRef* selfRef;
|
||||
std::vector<VKRMoveableRefCounterRef*> refs;
|
||||
#ifdef CEMU_DEBUG_ASSERT
|
||||
std::vector<VKRMoveableRefCounterRef*> reverseRefs;
|
||||
#endif
|
||||
|
||||
void moveObj(VKRMoveableRefCounter&& rhs)
|
||||
{
|
||||
this->refs = std::move(rhs.refs);
|
||||
this->m_refCount = rhs.m_refCount;
|
||||
this->selfRef = rhs.selfRef;
|
||||
this->selfRef->ref = this;
|
||||
}
|
||||
};
|
||||
|
||||
class VKRDestructibleObject : public VKRMoveableRefCounter
|
||||
|
||||
@ -1177,8 +1177,6 @@ void PipelineCompiler::CompileThreadPool_Stop()
|
||||
while (!s_pipelineCompileRequests.empty())
|
||||
{
|
||||
PipelineCompiler* pipelineCompiler = s_pipelineCompileRequests.pop();
|
||||
if (!pipelineCompiler)
|
||||
break;
|
||||
if (pipelineCompiler)
|
||||
delete pipelineCompiler;
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ void gx2Export_GX2CopyColorBufferToScanBuffer(PPCInterpreter_t* hCPU)
|
||||
gx2WriteGather_submitU32AsBE((uint32)colorBuffer->surface.pitch);
|
||||
gx2WriteGather_submitU32AsBE((uint32)colorBuffer->surface.tileMode.value());
|
||||
gx2WriteGather_submitU32AsBE((uint32)colorBuffer->surface.swizzle);
|
||||
gx2WriteGather_submitU32AsBE(_swapEndianU32(colorBuffer->viewFirstSlice));
|
||||
gx2WriteGather_submitU32AsBE((uint32)colorBuffer->viewFirstSlice);
|
||||
gx2WriteGather_submitU32AsBE((uint32)colorBuffer->surface.format.value());
|
||||
gx2WriteGather_submitU32AsBE(hCPU->gpr[4]);
|
||||
|
||||
@ -161,9 +161,9 @@ void _GX2InitScanBuffer(GX2ColorBuffer* colorBuffer, sint32 width, sint32 height
|
||||
colorBuffer->surface.resFlag = GX2_RESFLAG_USAGE_TEXTURE | GX2_RESFLAG_USAGE_COLOR_BUFFER;
|
||||
colorBuffer->surface.width = width;
|
||||
colorBuffer->surface.height = height;
|
||||
colorBuffer->viewFirstSlice = _swapEndianU32(0);
|
||||
colorBuffer->viewNumSlices = _swapEndianU32(1);
|
||||
colorBuffer->viewMip = _swapEndianU32(0);
|
||||
colorBuffer->viewFirstSlice = 0;
|
||||
colorBuffer->viewNumSlices = 1;
|
||||
colorBuffer->viewMip = 0;
|
||||
colorBuffer->surface.numLevels = 1;
|
||||
colorBuffer->surface.dim = Latte::E_DIM::DIM_2D;
|
||||
colorBuffer->surface.swizzle = 0;
|
||||
|
||||
@ -13,8 +13,8 @@ namespace GX2
|
||||
void GX2SetClearDepthStencil(GX2DepthBuffer* depthBuffer, float depthClearValue, uint8 stencilClearValue)
|
||||
{
|
||||
GX2ReserveCmdSpace(4);
|
||||
*(uint32*)&depthBuffer->clearDepth = _swapEndianU32(*(uint32*)&depthClearValue);
|
||||
depthBuffer->clearStencil = _swapEndianU32(stencilClearValue);
|
||||
depthBuffer->clearDepth = depthClearValue;
|
||||
depthBuffer->clearStencil = stencilClearValue;
|
||||
Latte::LATTE_DB_STENCIL_CLEAR stencilClearReg;
|
||||
stencilClearReg.set_clearValue(stencilClearValue);
|
||||
Latte::LATTE_DB_DEPTH_CLEAR depthClearReg;
|
||||
@ -28,7 +28,7 @@ namespace GX2
|
||||
void GX2SetClearDepth(GX2DepthBuffer* depthBuffer, float depthClearValue)
|
||||
{
|
||||
GX2ReserveCmdSpace(3);
|
||||
*(uint32*)&depthBuffer->clearDepth = _swapEndianU32(*(uint32*)&depthClearValue);
|
||||
depthBuffer->clearDepth = depthClearValue;
|
||||
Latte::LATTE_DB_DEPTH_CLEAR depthClearReg;
|
||||
depthClearReg.set_clearValue(depthClearValue);
|
||||
gx2WriteGather_submit(pm4HeaderType3(IT_SET_CONTEXT_REG, 1 + 1),
|
||||
@ -40,7 +40,7 @@ namespace GX2
|
||||
void GX2SetClearStencil(GX2DepthBuffer* depthBuffer, uint8 stencilClearValue)
|
||||
{
|
||||
GX2ReserveCmdSpace(3);
|
||||
depthBuffer->clearStencil = _swapEndianU32(stencilClearValue);
|
||||
depthBuffer->clearStencil = stencilClearValue;
|
||||
Latte::LATTE_DB_STENCIL_CLEAR stencilClearReg;
|
||||
stencilClearReg.set_clearValue(stencilClearValue);
|
||||
gx2WriteGather_submit(pm4HeaderType3(IT_SET_CONTEXT_REG, 1 + 1),
|
||||
@ -109,8 +109,8 @@ namespace GX2
|
||||
colorWidth = colorBuffer->surface.width;
|
||||
colorHeight = colorBuffer->surface.height;
|
||||
colorPitch = colorBuffer->surface.pitch;
|
||||
colorFirstSlice = _swapEndianU32(colorBuffer->viewFirstSlice);
|
||||
colorNumSlices = _swapEndianU32(colorBuffer->viewNumSlices);
|
||||
colorFirstSlice = colorBuffer->viewFirstSlice;
|
||||
colorNumSlices = colorBuffer->viewNumSlices;
|
||||
}
|
||||
// depth buffer
|
||||
MPTR depthPhysAddr = MPTR_NULL;
|
||||
@ -129,8 +129,8 @@ namespace GX2
|
||||
depthWidth = depthBuffer->surface.width;
|
||||
depthHeight = depthBuffer->surface.height;
|
||||
depthPitch = depthBuffer->surface.pitch;
|
||||
depthFirstSlice = _swapEndianU32(depthBuffer->viewFirstSlice);
|
||||
depthNumSlices = _swapEndianU32(depthBuffer->viewNumSlices);
|
||||
depthFirstSlice = depthBuffer->viewFirstSlice;
|
||||
depthNumSlices = depthBuffer->viewNumSlices;
|
||||
}
|
||||
gx2WriteGather_submit(pm4HeaderType3(IT_HLE_CLEAR_COLOR_DEPTH_STENCIL, 23),
|
||||
hleClearFlags,
|
||||
|
||||
@ -17,12 +17,12 @@ void gx2Export_GX2InitColorBufferRegs(PPCInterpreter_t* hCPU)
|
||||
ppcDefineParamStructPtr(colorBuffer, GX2ColorBuffer, 0);
|
||||
|
||||
LatteAddrLib::AddrSurfaceInfo_OUT surfaceInfo;
|
||||
LatteAddrLib::GX2CalculateSurfaceInfo(colorBuffer->surface.format, colorBuffer->surface.width, colorBuffer->surface.height, colorBuffer->surface.depth, colorBuffer->surface.dim, colorBuffer->surface.tileMode, colorBuffer->surface.aa, _swapEndianU32(colorBuffer->viewMip), &surfaceInfo);
|
||||
LatteAddrLib::GX2CalculateSurfaceInfo(colorBuffer->surface.format, colorBuffer->surface.width, colorBuffer->surface.height, colorBuffer->surface.depth, colorBuffer->surface.dim, colorBuffer->surface.tileMode, colorBuffer->surface.aa, colorBuffer->viewMip, &surfaceInfo);
|
||||
|
||||
uint32 pitchHeight = (surfaceInfo.height * surfaceInfo.pitch) >> 6;
|
||||
#ifdef CEMU_DEBUG_ASSERT
|
||||
if (colorBuffer->viewNumSlices != _swapEndianU32(1))
|
||||
cemuLog_logDebug(LogType::Force, "GX2InitColorBufferRegs(): With unsupported slice count {}", _swapEndianU32(colorBuffer->viewNumSlices));
|
||||
if (colorBuffer->viewNumSlices != 1)
|
||||
cemuLog_logDebug(LogType::Force, "GX2InitColorBufferRegs(): With unsupported slice count {}", (uint32)colorBuffer->viewNumSlices);
|
||||
if (surfaceInfo.pitch < 7)
|
||||
cemuLog_logDebug(LogType::Force, "GX2InitColorBufferRegs(): Pitch too small (pitch = {})", surfaceInfo.pitch);
|
||||
if ((surfaceInfo.pitch & 7) != 0)
|
||||
@ -101,8 +101,8 @@ void gx2Export_GX2InitColorBufferRegs(PPCInterpreter_t* hCPU)
|
||||
uint32 regView = 0;
|
||||
if (colorBuffer->surface.tileMode != Latte::E_GX2TILEMODE::TM_LINEAR_SPECIAL)
|
||||
{
|
||||
regView |= (_swapEndianU32(colorBuffer->viewFirstSlice) & 0x7FF);
|
||||
regView |= (((_swapEndianU32(colorBuffer->viewNumSlices) + _swapEndianU32(colorBuffer->viewFirstSlice) - 1) & 0x7FF) << 13);
|
||||
regView |= ((uint32)colorBuffer->viewFirstSlice & 0x7FF);
|
||||
regView |= ((((uint32)colorBuffer->viewNumSlices + (uint32)colorBuffer->viewFirstSlice - 1) & 0x7FF) << 13);
|
||||
}
|
||||
colorBuffer->reg_view = regView;
|
||||
colorBuffer->reg_mask = 0;
|
||||
@ -118,7 +118,7 @@ void gx2Export_GX2InitDepthBufferRegs(PPCInterpreter_t* hCPU)
|
||||
ppcDefineParamStructPtr(depthBuffer, GX2DepthBuffer, 0);
|
||||
|
||||
LatteAddrLib::AddrSurfaceInfo_OUT surfaceInfo;
|
||||
LatteAddrLib::GX2CalculateSurfaceInfo(depthBuffer->surface.format, depthBuffer->surface.width, depthBuffer->surface.height, depthBuffer->surface.depth, depthBuffer->surface.dim, depthBuffer->surface.tileMode, depthBuffer->surface.aa, _swapEndianU32(depthBuffer->viewMip), &surfaceInfo);
|
||||
LatteAddrLib::GX2CalculateSurfaceInfo(depthBuffer->surface.format, depthBuffer->surface.width, depthBuffer->surface.height, depthBuffer->surface.depth, depthBuffer->surface.dim, depthBuffer->surface.tileMode, depthBuffer->surface.aa, depthBuffer->viewMip, &surfaceInfo);
|
||||
|
||||
cemu_assert_debug(depthBuffer->viewNumSlices != 0);
|
||||
|
||||
@ -140,18 +140,12 @@ void gx2Export_GX2SetColorBuffer(PPCInterpreter_t* hCPU)
|
||||
GX2ColorBuffer* colorBufferBE = (GX2ColorBuffer*)memory_getPointerFromVirtualOffset(hCPU->gpr[3]);
|
||||
|
||||
#ifdef CEMU_DEBUG_ASSERT
|
||||
cemuLog_log(LogType::GX2, "ColorBuffer tileMode {:01x} PhysAddr {:08x} fmt {:04x} res {}x{} Mip {} Slice {}", (uint32)colorBufferBE->surface.tileMode.value(), (uint32)colorBufferBE->surface.imagePtr, (uint32)colorBufferBE->surface.format.value(), (uint32)colorBufferBE->surface.width, (uint32)colorBufferBE->surface.height, _swapEndianU32(colorBufferBE->viewMip), _swapEndianU32(colorBufferBE->viewFirstSlice));
|
||||
cemuLog_log(LogType::GX2, "ColorBuffer tileMode {:01x} PhysAddr {:08x} fmt {:04x} res {}x{} Mip {} Slice {}", (uint32)colorBufferBE->surface.tileMode.value(), (uint32)colorBufferBE->surface.imagePtr, (uint32)colorBufferBE->surface.format.value(), (uint32)colorBufferBE->surface.width, (uint32)colorBufferBE->surface.height, (uint32)colorBufferBE->viewMip, (uint32)colorBufferBE->viewFirstSlice);
|
||||
#endif
|
||||
|
||||
// regs[0] = mmCB_COLOR0_SIZE
|
||||
// regs[1] = mmCB_COLOR0_INFO
|
||||
// regs[2] = mmCB_COLOR0_VIEW
|
||||
// regs[3] = mmCB_COLOR0_MASK
|
||||
// regs[4] = mmCB_COLOR0_TILE
|
||||
|
||||
uint32 targetIndex = hCPU->gpr[4];
|
||||
|
||||
uint32 viewMip = _swapEndianU32(colorBufferBE->viewMip);
|
||||
uint32 viewMip = colorBufferBE->viewMip;
|
||||
uint32 colorBufferBase = memory_virtualToPhysical(colorBufferBE->surface.imagePtr);
|
||||
|
||||
if( viewMip != 0 )
|
||||
@ -165,7 +159,7 @@ void gx2Export_GX2SetColorBuffer(PPCInterpreter_t* hCPU)
|
||||
}
|
||||
|
||||
Latte::E_GX2TILEMODE tileMode = colorBufferBE->surface.tileMode;
|
||||
uint32 viewMipIndex = _swapEndianU32(colorBufferBE->viewMip);
|
||||
uint32 viewMipIndex = colorBufferBE->viewMip;
|
||||
uint32 swizzle = colorBufferBE->surface.swizzle;
|
||||
|
||||
if (Latte::TM_IsMacroTiled(tileMode) && viewMipIndex < ((swizzle >> 16) & 0xFF))
|
||||
@ -210,7 +204,7 @@ void gx2Export_GX2SetDepthBuffer(PPCInterpreter_t* hCPU)
|
||||
|
||||
cemuLog_log(LogType::GX2, "DepthBuffer tileMode {:01x} PhysAddr {:08x} fmt {:04x} res {}x{}", (uint32)depthBufferBE->surface.tileMode.value(), (uint32)depthBufferBE->surface.imagePtr, (uint32)depthBufferBE->surface.format.value(), (uint32)depthBufferBE->surface.width, (uint32)depthBufferBE->surface.height);
|
||||
|
||||
uint32 viewMip = _swapEndianU32(depthBufferBE->viewMip);
|
||||
uint32 viewMip = depthBufferBE->viewMip;
|
||||
|
||||
// todo: current code for the PM4 packets is a hack, replace with proper implementation
|
||||
|
||||
@ -256,8 +250,8 @@ void gx2Export_GX2SetDepthBuffer(PPCInterpreter_t* hCPU)
|
||||
|
||||
// set DB_DEPTH_VIEW
|
||||
uint32 db_view = 0;
|
||||
db_view |= (_swapEndianU32(depthBufferBE->viewFirstSlice)&0x7FF);
|
||||
db_view |= (((_swapEndianU32(depthBufferBE->viewNumSlices)+_swapEndianU32(depthBufferBE->viewFirstSlice)-1)&0x7FF)<<13);
|
||||
db_view |= ((uint32)depthBufferBE->viewFirstSlice&0x7FF);
|
||||
db_view |= ((((uint32)depthBufferBE->viewNumSlices+(uint32)depthBufferBE->viewFirstSlice-1)&0x7FF)<<13);
|
||||
gx2WriteGather_submitU32AsBE(pm4HeaderType3(IT_SET_CONTEXT_REG, 2));
|
||||
gx2WriteGather_submitU32AsBE(mmDB_DEPTH_VIEW - 0xA000);
|
||||
gx2WriteGather_submitU32AsBE(db_view);
|
||||
|
||||
@ -33,17 +33,17 @@ static_assert(sizeof(GX2Surface) == 0x74);
|
||||
|
||||
struct GX2ColorBuffer
|
||||
{
|
||||
/* +0x00 */ GX2Surface surface;
|
||||
/* +0x74 */ uint32 viewMip;
|
||||
/* +0x78 */ uint32 viewFirstSlice;
|
||||
/* +0x7C */ uint32 viewNumSlices;
|
||||
/* +0x80 */ MPTR auxData;
|
||||
/* +0x84 */ uint32 auxSize;
|
||||
/* +0x88 */ uint32be reg_size; // CB_COLOR*_SIZE
|
||||
/* +0x8C */ uint32be reg_info; // CB_COLOR*_INFO
|
||||
/* +0x90 */ uint32be reg_view; // CB_COLOR*_VIEW
|
||||
/* +0x94 */ uint32be reg_mask; // CB_COLOR*_MASK
|
||||
/* +0x98 */ uint32be reg4; // ?
|
||||
/* +0x00 */ GX2Surface surface;
|
||||
/* +0x74 */ uint32be viewMip;
|
||||
/* +0x78 */ uint32be viewFirstSlice;
|
||||
/* +0x7C */ uint32be viewNumSlices;
|
||||
/* +0x80 */ MEMPTR<void> auxData;
|
||||
/* +0x84 */ uint32be auxSize2;
|
||||
/* +0x88 */ uint32be reg_size; // CB_COLOR*_SIZE
|
||||
/* +0x8C */ uint32be reg_info; // CB_COLOR*_INFO
|
||||
/* +0x90 */ uint32be reg_view; // CB_COLOR*_VIEW
|
||||
/* +0x94 */ uint32be reg_mask; // CB_COLOR*_MASK
|
||||
/* +0x98 */ uint32be reg4; // ?
|
||||
};
|
||||
|
||||
static_assert(sizeof(GX2ColorBuffer) == 0x9C);
|
||||
@ -51,13 +51,13 @@ static_assert(sizeof(GX2ColorBuffer) == 0x9C);
|
||||
struct GX2DepthBuffer
|
||||
{
|
||||
/* +0x00 */ GX2Surface surface;
|
||||
/* +0x74 */ uint32 viewMip;
|
||||
/* +0x78 */ uint32 viewFirstSlice;
|
||||
/* +0x7C */ uint32 viewNumSlices;
|
||||
/* +0x80 */ MPTR hiZPtr;
|
||||
/* +0x84 */ uint32 hiZSize;
|
||||
/* +0x88 */ float clearDepth;
|
||||
/* +0x8C */ uint32 clearStencil;
|
||||
/* +0x74 */ uint32be viewMip;
|
||||
/* +0x78 */ uint32be viewFirstSlice;
|
||||
/* +0x7C */ uint32be viewNumSlices;
|
||||
/* +0x80 */ MEMPTR<void> hiZPtr;
|
||||
/* +0x84 */ uint32be hiZSize;
|
||||
/* +0x88 */ float32be clearDepth;
|
||||
/* +0x8C */ uint32be clearStencil;
|
||||
/* +0x90 */ uint32be reg_size;
|
||||
/* +0x94 */ uint32be reg_view;
|
||||
/* +0x98 */ uint32be reg_base;
|
||||
|
||||
@ -435,13 +435,13 @@ void gx2Export_GX2ResolveAAColorBuffer(PPCInterpreter_t* hCPU)
|
||||
GX2ColorBuffer* srcColorBuffer = (GX2ColorBuffer*)memory_getPointerFromVirtualOffset(hCPU->gpr[3]);
|
||||
GX2Surface* srcSurface = &srcColorBuffer->surface;
|
||||
GX2Surface* dstSurface = (GX2Surface*)memory_getPointerFromVirtualOffset(hCPU->gpr[4]);
|
||||
uint32 srcMip = _swapEndianU32(srcColorBuffer->viewMip);
|
||||
uint32 srcMip = srcColorBuffer->viewMip;
|
||||
uint32 dstMip = hCPU->gpr[5];
|
||||
uint32 srcSlice = _swapEndianU32(srcColorBuffer->viewFirstSlice);
|
||||
uint32 srcSlice = srcColorBuffer->viewFirstSlice;
|
||||
uint32 dstSlice = hCPU->gpr[6];
|
||||
|
||||
#ifdef CEMU_DEBUG_ASSERT
|
||||
if( _swapEndianU32(srcColorBuffer->viewMip) != 0 || _swapEndianU32(srcColorBuffer->viewFirstSlice) != 0 )
|
||||
if( srcColorBuffer->viewMip != 0 || srcColorBuffer->viewFirstSlice != 0 )
|
||||
assert_dbg();
|
||||
#endif
|
||||
|
||||
@ -618,7 +618,7 @@ void gx2Export_GX2ConvertDepthBufferToTextureSurface(PPCInterpreter_t* hCPU)
|
||||
|
||||
sint32 srcMip = 0;
|
||||
|
||||
uint32 numSlices = std::max<uint32>(_swapEndianU32(depthBuffer->viewNumSlices), 1);
|
||||
uint32 numSlices = std::max<uint32>(depthBuffer->viewNumSlices, 1);
|
||||
GX2::GX2ReserveCmdSpace((1 + 13 * 2) * numSlices);
|
||||
for (uint32 subSliceIndex = 0; subSliceIndex < numSlices; subSliceIndex++)
|
||||
{
|
||||
|
||||
@ -134,7 +134,7 @@ void padscoreExport_WPADGetInfoAsync(PPCInterpreter_t* hCPU)
|
||||
ppcDefineParamU32(channel, 0);
|
||||
ppcDefineParamStructPtr(wpadInfo, WPADInfo_t, 1);
|
||||
ppcDefineParamMPTR(callbackFunc, 2);
|
||||
cemuLog_log(LogType::InputAPI, "WPADGetInfoAsync({}, 0x{:08x}, 0x{:08x})", channel, fmt::ptr(wpadInfo), callbackFunc);
|
||||
cemuLog_log(LogType::InputAPI, "WPADGetInfoAsync({}, 0x{:08x}, 0x{:08x})", channel, memory_getVirtualOffsetFromPointer(wpadInfo), callbackFunc);
|
||||
|
||||
if (channel < InputManager::kMaxWPADControllers)
|
||||
{
|
||||
|
||||
@ -127,7 +127,11 @@ XMLConfigParser CemuConfig::Load(XMLConfigParser& parser)
|
||||
// graphics
|
||||
auto graphic = parser.get("Graphic");
|
||||
graphic_api = graphic.get("api", kOpenGL);
|
||||
graphic.get("vkDevice", vk_graphic_device_uuid);
|
||||
graphic.get("device", legacy_graphic_device_uuid);
|
||||
if (graphic.get("vkDevice").valid())
|
||||
graphic.get("vkDevice", vk_graphic_device_uuid);
|
||||
else
|
||||
vk_graphic_device_uuid = legacy_graphic_device_uuid;
|
||||
mtl_graphic_device_uuid = graphic.get("mtlDevice", 0);
|
||||
vsync = graphic.get("VSync", 0);
|
||||
overrideAppGammaPreference = graphic.get("OverrideAppGammaPreference", false);
|
||||
@ -359,6 +363,7 @@ XMLConfigParser CemuConfig::Save(XMLConfigParser& parser)
|
||||
// graphics
|
||||
auto graphic = config.set("Graphic");
|
||||
graphic.set("api", graphic_api);
|
||||
graphic.set("device", legacy_graphic_device_uuid);
|
||||
graphic.set("vkDevice", vk_graphic_device_uuid);
|
||||
graphic.set("mtlDevice", mtl_graphic_device_uuid);
|
||||
graphic.set("VSync", vsync);
|
||||
|
||||
@ -432,6 +432,7 @@ struct CemuConfig
|
||||
|
||||
// graphics
|
||||
ConfigValue<GraphicAPI> graphic_api{ kVulkan };
|
||||
std::array<uint8, 16> legacy_graphic_device_uuid{}; // placeholder option for backwards compatibility with settings from 2.6 and before (renamed to "vkDevice")
|
||||
std::array<uint8, 16> vk_graphic_device_uuid;
|
||||
uint64 mtl_graphic_device_uuid{ 0 };
|
||||
ConfigValue<int> vsync{ 0 }; // 0 = off, 1+ = depending on render backend
|
||||
|
||||
@ -190,6 +190,7 @@ wxGameList::wxGameList(wxWindow* parent, wxWindowID id)
|
||||
Bind(wxEVT_LIST_COL_END_DRAG, &wxGameList::OnColumnResize, this);
|
||||
Bind(wxEVT_LIST_COL_RIGHT_CLICK, &wxGameList::OnColumnRightClick, this);
|
||||
Bind(wxEVT_SIZE, &wxGameList::OnGameListSize, this);
|
||||
m_bulkUpdateTimer.Bind(wxEVT_TIMER, &wxGameList::OnTimerBulkAddEntriesToGameList, this);
|
||||
|
||||
m_callbackIdTitleList = CafeTitleList::RegisterCallback([](CafeTitleListCallbackEvent* evt, void* ctx) { ((wxGameList*)ctx)->HandleTitleListCallback(evt); }, this);
|
||||
|
||||
@ -303,7 +304,7 @@ int wxGameList::GetColumnDefaultWidth(int column)
|
||||
switch (column)
|
||||
{
|
||||
case ColumnIcon:
|
||||
return kListIconWidth;
|
||||
return kListIconWidth+2;
|
||||
case ColumnName:
|
||||
return DefaultColumnSize::name;
|
||||
case ColumnVersion:
|
||||
@ -712,7 +713,7 @@ void wxGameList::OnContextMenuSelected(wxCommandEvent& event)
|
||||
GetConfig().SetGameListFavorite(title_id, !GetConfig().IsGameListFavorite(title_id));
|
||||
SortEntries();
|
||||
UpdateItemColors();
|
||||
//SaveConfig();
|
||||
SaveConfig(true);
|
||||
break;
|
||||
case kContextMenuEditName:
|
||||
{
|
||||
@ -993,7 +994,7 @@ void wxGameList::ApplyGameListColumnWidths()
|
||||
const auto& config = GetWxGUIConfig();
|
||||
wxWindowUpdateLocker lock(this);
|
||||
if(config.show_icon_column)
|
||||
SetColumnWidth(ColumnIcon, kListIconWidth);
|
||||
SetColumnWidth(ColumnIcon, kListIconWidth+2);
|
||||
else
|
||||
SetColumnWidth(ColumnIcon, 0);
|
||||
SetColumnWidth(ColumnName, config.column_width.name);
|
||||
@ -1079,112 +1080,142 @@ void wxGameList::OnClose(wxCloseEvent& event)
|
||||
m_exit = true;
|
||||
}
|
||||
|
||||
int wxGameList::FindInsertPosition(TitleId titleId)
|
||||
int wxGameList::FindInsertPosition(TitleId titleId, bool& entryAlreadyExists)
|
||||
{
|
||||
entryAlreadyExists = false;
|
||||
SortData data{this, ItemColumns(GetSortIndicator()), IsAscendingSortIndicator()};
|
||||
const auto itemCount = GetItemCount();
|
||||
|
||||
if (itemCount == 0)
|
||||
return 0;
|
||||
// todo - optimize this with binary search
|
||||
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
sint32 low = 0;
|
||||
sint32 high = itemCount;
|
||||
while (low < high)
|
||||
{
|
||||
if (SortComparator(titleId, (uint64)GetItemData(i), &data) <= 0)
|
||||
return i;
|
||||
sint32 mid = low + (high - low) / 2;
|
||||
auto cmp = SortComparator(titleId, (uint64)GetItemData(mid), &data);
|
||||
if (cmp <= 0)
|
||||
{
|
||||
if (cmp == 0)
|
||||
{
|
||||
entryAlreadyExists = true;
|
||||
return mid;
|
||||
}
|
||||
high = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
return itemCount;
|
||||
return low;
|
||||
}
|
||||
|
||||
void wxGameList::OnTimerBulkAddEntriesToGameList(wxTimerEvent& event)
|
||||
{
|
||||
std::vector<TitleId> titleIdsToUpdate;
|
||||
std::swap(titleIdsToUpdate, m_bulkTitlesToAdd);
|
||||
|
||||
wxWindowUpdateLocker lock(this);
|
||||
bool hasAnyNewEntry = false;
|
||||
for (auto& titleId : titleIdsToUpdate)
|
||||
{
|
||||
GameInfo2 gameInfo = CafeTitleList::GetGameInfo(titleId);
|
||||
if (!gameInfo.IsValid() || gameInfo.IsSystemDataTitle())
|
||||
{
|
||||
// entry no longer exists or is not a valid game
|
||||
// we dont need to remove list entries here because all delete operations should trigger a full list refresh
|
||||
continue;
|
||||
}
|
||||
TitleId baseTitleId = gameInfo.GetBaseTitleId();
|
||||
bool isNewEntry = false;
|
||||
|
||||
int icon = -1; /* 0 is the default empty icon */
|
||||
int icon_small = -1; /* 0 is the default empty icon */
|
||||
QueryIconForTitle(baseTitleId, icon, icon_small);
|
||||
|
||||
bool entryAlreadyExists = false;
|
||||
auto index = FindInsertPosition(baseTitleId, entryAlreadyExists);
|
||||
if(!entryAlreadyExists)
|
||||
{
|
||||
// entry doesn't exist
|
||||
index = InsertItem(index, wxString::FromUTF8(GetNameByTitleId(baseTitleId)));
|
||||
SetItemPtrData(index, baseTitleId);
|
||||
isNewEntry = true;
|
||||
hasAnyNewEntry = true;
|
||||
}
|
||||
|
||||
if (m_style == Style::kList)
|
||||
{
|
||||
SetItemColumnImage(index, ColumnIcon, icon_small);
|
||||
|
||||
SetItem(index, ColumnName, wxString::FromUTF8(GetNameByTitleId(baseTitleId)));
|
||||
|
||||
SetItem(index, ColumnVersion, fmt::format("{}", gameInfo.GetVersion()));
|
||||
|
||||
if(gameInfo.HasAOC())
|
||||
SetItem(index, ColumnDLC, fmt::format("{}", gameInfo.GetAOCVersion()));
|
||||
else
|
||||
SetItem(index, ColumnDLC, wxString());
|
||||
|
||||
if (isNewEntry)
|
||||
{
|
||||
iosu::pdm::GameListStat playTimeStat;
|
||||
if (iosu::pdm::GetStatForGamelist(baseTitleId, playTimeStat))
|
||||
{
|
||||
// time played
|
||||
uint32 minutesPlayed = playTimeStat.numMinutesPlayed;
|
||||
if (minutesPlayed == 0)
|
||||
SetItem(index, ColumnGameTime, wxEmptyString);
|
||||
else if (minutesPlayed < 60)
|
||||
SetItem(index, ColumnGameTime, formatWxString(wxPLURAL("{} minute", "{} minutes", minutesPlayed), minutesPlayed));
|
||||
else
|
||||
{
|
||||
uint32 hours = minutesPlayed / 60;
|
||||
uint32 minutes = minutesPlayed % 60;
|
||||
wxString hoursText = formatWxString(wxPLURAL("{} hour", "{} hours", hours), hours);
|
||||
wxString minutesText = formatWxString(wxPLURAL("{} minute", "{} minutes", minutes), minutes);
|
||||
SetItem(index, ColumnGameTime, hoursText + " " + minutesText);
|
||||
}
|
||||
|
||||
// last played
|
||||
if (playTimeStat.last_played.year != 0)
|
||||
{
|
||||
const wxDateTime tmp((wxDateTime::wxDateTime_t)playTimeStat.last_played.day, (wxDateTime::Month)playTimeStat.last_played.month, (wxDateTime::wxDateTime_t)playTimeStat.last_played.year, 0, 0, 0, 0);
|
||||
SetItem(index, ColumnGameStarted, tmp.FormatDate());
|
||||
}
|
||||
else
|
||||
SetItem(index, ColumnGameStarted, _("never"));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetItem(index, ColumnGameTime, wxEmptyString);
|
||||
SetItem(index, ColumnGameStarted, _("never"));
|
||||
}
|
||||
}
|
||||
const auto region_text = fmt::format("{}", gameInfo.GetRegion());
|
||||
SetItem(index, ColumnRegion, wxGetTranslation(region_text));
|
||||
SetItem(index, ColumnTitleID, fmt::format("{:016x}", baseTitleId));
|
||||
}
|
||||
else if (m_style == Style::kIcons)
|
||||
{
|
||||
SetItemImage(index, icon);
|
||||
}
|
||||
else if (m_style == Style::kSmallIcons)
|
||||
{
|
||||
SetItemImage(index, icon_small);
|
||||
}
|
||||
}
|
||||
if (hasAnyNewEntry)
|
||||
UpdateItemColors();
|
||||
}
|
||||
|
||||
void wxGameList::OnGameEntryUpdatedByTitleId(wxTitleIdEvent& event)
|
||||
{
|
||||
if (m_bulkTitlesToAdd.size() < 100)
|
||||
m_bulkUpdateTimer.StartOnce(100); // if timer is started already this will delay it
|
||||
const auto titleId = event.GetTitleId();
|
||||
GameInfo2 gameInfo = CafeTitleList::GetGameInfo(titleId);
|
||||
if (!gameInfo.IsValid() || gameInfo.IsSystemDataTitle())
|
||||
{
|
||||
// entry no longer exists or is not a valid game
|
||||
// we dont need to remove list entries here because all delete operations should trigger a full list refresh
|
||||
return;
|
||||
}
|
||||
TitleId baseTitleId = gameInfo.GetBaseTitleId();
|
||||
bool isNewEntry = false;
|
||||
|
||||
int icon = -1; /* 0 is the default empty icon */
|
||||
int icon_small = -1; /* 0 is the default empty icon */
|
||||
QueryIconForTitle(baseTitleId, icon, icon_small);
|
||||
|
||||
auto index = FindListItemByTitleId(baseTitleId);
|
||||
if(index == wxNOT_FOUND)
|
||||
{
|
||||
// entry doesn't exist
|
||||
index = InsertItem(FindInsertPosition(baseTitleId), wxString::FromUTF8(GetNameByTitleId(baseTitleId)));
|
||||
SetItemPtrData(index, baseTitleId);
|
||||
isNewEntry = true;
|
||||
}
|
||||
|
||||
if (m_style == Style::kList)
|
||||
{
|
||||
SetItemColumnImage(index, ColumnIcon, icon_small);
|
||||
|
||||
SetItem(index, ColumnName, wxString::FromUTF8(GetNameByTitleId(baseTitleId)));
|
||||
|
||||
SetItem(index, ColumnVersion, fmt::format("{}", gameInfo.GetVersion()));
|
||||
|
||||
if(gameInfo.HasAOC())
|
||||
SetItem(index, ColumnDLC, fmt::format("{}", gameInfo.GetAOCVersion()));
|
||||
else
|
||||
SetItem(index, ColumnDLC, wxString());
|
||||
|
||||
if (isNewEntry)
|
||||
{
|
||||
iosu::pdm::GameListStat playTimeStat;
|
||||
if (iosu::pdm::GetStatForGamelist(baseTitleId, playTimeStat))
|
||||
{
|
||||
// time played
|
||||
uint32 minutesPlayed = playTimeStat.numMinutesPlayed;
|
||||
if (minutesPlayed == 0)
|
||||
SetItem(index, ColumnGameTime, wxEmptyString);
|
||||
else if (minutesPlayed < 60)
|
||||
SetItem(index, ColumnGameTime, formatWxString(wxPLURAL("{} minute", "{} minutes", minutesPlayed), minutesPlayed));
|
||||
else
|
||||
{
|
||||
uint32 hours = minutesPlayed / 60;
|
||||
uint32 minutes = minutesPlayed % 60;
|
||||
wxString hoursText = formatWxString(wxPLURAL("{} hour", "{} hours", hours), hours);
|
||||
wxString minutesText = formatWxString(wxPLURAL("{} minute", "{} minutes", minutes), minutes);
|
||||
SetItem(index, ColumnGameTime, hoursText + " " + minutesText);
|
||||
}
|
||||
|
||||
// last played
|
||||
if (playTimeStat.last_played.year != 0)
|
||||
{
|
||||
const wxDateTime tmp((wxDateTime::wxDateTime_t)playTimeStat.last_played.day, (wxDateTime::Month)playTimeStat.last_played.month, (wxDateTime::wxDateTime_t)playTimeStat.last_played.year, 0, 0, 0, 0);
|
||||
SetItem(index, ColumnGameStarted, tmp.FormatDate());
|
||||
}
|
||||
else
|
||||
SetItem(index, ColumnGameStarted, _("never"));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetItem(index, ColumnGameTime, wxEmptyString);
|
||||
SetItem(index, ColumnGameStarted, _("never"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const auto region_text = fmt::format("{}", gameInfo.GetRegion());
|
||||
SetItem(index, ColumnRegion, wxGetTranslation(region_text));
|
||||
SetItem(index, ColumnTitleID, fmt::format("{:016x}", baseTitleId));
|
||||
}
|
||||
else if (m_style == Style::kIcons)
|
||||
{
|
||||
SetItemImage(index, icon);
|
||||
}
|
||||
else if (m_style == Style::kSmallIcons)
|
||||
{
|
||||
SetItemImage(index, icon_small);
|
||||
}
|
||||
if (isNewEntry)
|
||||
UpdateItemColors(index);
|
||||
m_bulkTitlesToAdd.emplace_back(titleId);
|
||||
}
|
||||
|
||||
void wxGameList::OnItemActivated(wxListEvent& event)
|
||||
|
||||
@ -3,8 +3,6 @@
|
||||
#include "config/CemuConfig.h"
|
||||
#include "Cafe/TitleList/TitleId.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <wx/listctrl.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/panel.h>
|
||||
@ -57,6 +55,7 @@ public:
|
||||
void CreateShortcut(GameInfo2& gameInfo);
|
||||
|
||||
long FindListItemByTitleId(uint64 title_id) const;
|
||||
|
||||
void OnClose(wxCloseEvent& event);
|
||||
|
||||
private:
|
||||
@ -93,7 +92,7 @@ private:
|
||||
int dir;
|
||||
};
|
||||
|
||||
int FindInsertPosition(TitleId titleId);
|
||||
int FindInsertPosition(TitleId titleId, bool& entryAlreadyExists);
|
||||
std::weak_ordering SortComparator(uint64 titleId1, uint64 titleId2, SortData* sortData);
|
||||
static int SortFunction(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData);
|
||||
|
||||
@ -132,6 +131,10 @@ private:
|
||||
|
||||
std::map<TitleId, std::string> m_name_cache;
|
||||
|
||||
// bulk update handling
|
||||
std::vector<TitleId> m_bulkTitlesToAdd;
|
||||
wxTimer m_bulkUpdateTimer;
|
||||
|
||||
// list mode
|
||||
void CreateListColumns();
|
||||
|
||||
@ -156,6 +159,8 @@ private:
|
||||
void AdjustLastColumnWidth();
|
||||
int GetColumnDefaultWidth(int column);
|
||||
|
||||
void OnTimerBulkAddEntriesToGameList(wxTimerEvent& event);
|
||||
|
||||
static inline std::once_flag s_launch_file_once;
|
||||
};
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ BreakpointWindow::BreakpointWindow(DebuggerWindow2& parent, const wxPoint& main_
|
||||
|
||||
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_breakpoints = new wxListView(this, wxID_ANY);
|
||||
m_breakpoints = new wxListView(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL);
|
||||
m_breakpoints->EnableCheckBoxes(true);
|
||||
|
||||
wxListItem col0;
|
||||
@ -162,10 +162,12 @@ void BreakpointWindow::OnBreakpointToggled(wxListEvent& event)
|
||||
void BreakpointWindow::OnLeftDClick(wxMouseEvent& event)
|
||||
{
|
||||
const auto position = event.GetPosition();
|
||||
const sint32 index = (position.y / m_breakpoints->GetCharHeight()) - 2;
|
||||
if (index < 0 || index >= m_breakpoints->GetItemCount())
|
||||
int flags = 0;
|
||||
const long index = m_breakpoints->HitTest(position, flags);
|
||||
|
||||
if (index == wxNOT_FOUND)
|
||||
return;
|
||||
|
||||
|
||||
sint32 x = position.x;
|
||||
const auto enabled_width = m_breakpoints->GetColumnWidth(ColumnEnabled);
|
||||
if (x <= enabled_width)
|
||||
@ -173,7 +175,7 @@ void BreakpointWindow::OnLeftDClick(wxMouseEvent& event)
|
||||
|
||||
x -= enabled_width;
|
||||
const auto address_width = m_breakpoints->GetColumnWidth(ColumnAddress);
|
||||
if(x <= address_width)
|
||||
if (x <= address_width)
|
||||
{
|
||||
const auto item = m_breakpoints->GetItemText(index, ColumnAddress);
|
||||
const auto address = std::stoul(item.ToStdString(), nullptr, 16);
|
||||
@ -183,13 +185,13 @@ void BreakpointWindow::OnLeftDClick(wxMouseEvent& event)
|
||||
}
|
||||
|
||||
x -= address_width;
|
||||
const auto type_width = m_breakpoints->GetColumnWidth(ColumnType);
|
||||
const auto type_width = m_breakpoints->GetColumnWidth(ColumnType);
|
||||
if (x <= type_width)
|
||||
return;
|
||||
|
||||
x -= type_width;
|
||||
const auto comment_width = m_breakpoints->GetColumnWidth(ColumnComment);
|
||||
if(x <= comment_width)
|
||||
if (x <= comment_width)
|
||||
{
|
||||
if (index >= debuggerState.breakpoints.size())
|
||||
return;
|
||||
@ -213,9 +215,9 @@ void BreakpointWindow::OnLeftDClick(wxMouseEvent& event)
|
||||
|
||||
void BreakpointWindow::OnRightDown(wxMouseEvent& event)
|
||||
{
|
||||
const auto position = event.GetPosition();
|
||||
const sint32 index = (position.y / m_breakpoints->GetCharHeight()) - 2;
|
||||
if (index < 0 || index >= m_breakpoints->GetItemCount())
|
||||
int flags = 0;
|
||||
const long index = m_breakpoints->HitTest(event.GetPosition(), flags);
|
||||
if (index == wxNOT_FOUND || index < 0 || index >= m_breakpoints->GetItemCount())
|
||||
{
|
||||
wxMenu menu;
|
||||
menu.Append(MENU_ID_CREATE_CODE_BP_EXECUTION, _("Create execution breakpoint"));
|
||||
@ -244,19 +246,16 @@ void BreakpointWindow::OnContextMenuClickSelected(wxCommandEvent& evt)
|
||||
if (evt.GetId() == MENU_ID_DELETE_BP)
|
||||
{
|
||||
long sel = m_breakpoints->GetFirstSelected();
|
||||
if (sel != wxNOT_FOUND)
|
||||
{
|
||||
if (sel >= debuggerState.breakpoints.size())
|
||||
return;
|
||||
if (sel == wxNOT_FOUND || sel < 0 || sel >= m_breakpoints->GetItemCount())
|
||||
return;
|
||||
|
||||
auto it = debuggerState.breakpoints.begin();
|
||||
std::advance(it, sel);
|
||||
auto it = debuggerState.breakpoints.begin();
|
||||
std::advance(it, sel);
|
||||
|
||||
debugger_deleteBreakpoint(*it);
|
||||
debugger_deleteBreakpoint(*it);
|
||||
|
||||
wxCommandEvent evt(wxEVT_BREAKPOINT_CHANGE);
|
||||
wxPostEvent(this->m_parent, evt);
|
||||
}
|
||||
wxCommandEvent evt(wxEVT_BREAKPOINT_CHANGE);
|
||||
wxPostEvent(this->m_parent, evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user