mirror of
https://github.com/project-slippi/Ishiiruka.git
synced 2025-10-06 00:12:42 +02:00
Merge latest master changes
This commit is contained in:
@@ -541,6 +541,11 @@ if(ENABLE_EVDEV)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
message("Using named pipes as controller inputs")
|
||||
add_definitions(-DUSE_PIPES=1)
|
||||
endif()
|
||||
|
||||
########################################
|
||||
# Setup include directories (and make sure they are preferred over the Externals)
|
||||
#
|
||||
|
@@ -6,7 +6,9 @@ find_library(MINIUPNPC_LIBRARY miniupnpc)
|
||||
|
||||
if(MINIUPNPC_INCLUDE_DIR)
|
||||
file(STRINGS "${MINIUPNPC_INCLUDE_DIR}/miniupnpc.h" MINIUPNPC_API_VERSION_STR REGEX "^#define[\t ]+MINIUPNPC_API_VERSION[\t ]+[0-9]+")
|
||||
string(REGEX REPLACE "^#define[\t ]+MINIUPNPC_API_VERSION[\t ]+([0-9]+)" "\\1" MINIUPNPC_API_VERSION ${MINIUPNPC_API_VERSION_STR})
|
||||
if(MINIUPNPC_API_VERSION_STR)
|
||||
string(REGEX REPLACE "^#define[\t ]+MINIUPNPC_API_VERSION[\t ]+([0-9]+)" "\\1" MINIUPNPC_API_VERSION ${MINIUPNPC_API_VERSION_STR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
[Core]
|
||||
# Values set here will override the main Dolphin settings.
|
||||
FastDiscSpeed = True
|
||||
|
||||
[EmuState]
|
||||
# The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
|
2712
Languages/po/ar.po
2712
Languages/po/ar.po
File diff suppressed because it is too large
Load Diff
2738
Languages/po/ca.po
2738
Languages/po/ca.po
File diff suppressed because it is too large
Load Diff
2733
Languages/po/cs.po
2733
Languages/po/cs.po
File diff suppressed because it is too large
Load Diff
2748
Languages/po/de.po
2748
Languages/po/de.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2741
Languages/po/el.po
2741
Languages/po/el.po
File diff suppressed because it is too large
Load Diff
2650
Languages/po/en.po
2650
Languages/po/en.po
File diff suppressed because it is too large
Load Diff
2736
Languages/po/es.po
2736
Languages/po/es.po
File diff suppressed because it is too large
Load Diff
2707
Languages/po/fa.po
2707
Languages/po/fa.po
File diff suppressed because it is too large
Load Diff
2823
Languages/po/fr.po
2823
Languages/po/fr.po
File diff suppressed because it is too large
Load Diff
2650
Languages/po/he.po
2650
Languages/po/he.po
File diff suppressed because it is too large
Load Diff
2708
Languages/po/hu.po
2708
Languages/po/hu.po
File diff suppressed because it is too large
Load Diff
2820
Languages/po/it.po
2820
Languages/po/it.po
File diff suppressed because it is too large
Load Diff
2776
Languages/po/ja.po
2776
Languages/po/ja.po
File diff suppressed because it is too large
Load Diff
2733
Languages/po/ko.po
2733
Languages/po/ko.po
File diff suppressed because it is too large
Load Diff
2733
Languages/po/nb.po
2733
Languages/po/nb.po
File diff suppressed because it is too large
Load Diff
2734
Languages/po/nl.po
2734
Languages/po/nl.po
File diff suppressed because it is too large
Load Diff
2733
Languages/po/pl.po
2733
Languages/po/pl.po
File diff suppressed because it is too large
Load Diff
2690
Languages/po/pt.po
2690
Languages/po/pt.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2699
Languages/po/ru.po
2699
Languages/po/ru.po
File diff suppressed because it is too large
Load Diff
2636
Languages/po/sr.po
2636
Languages/po/sr.po
File diff suppressed because it is too large
Load Diff
2807
Languages/po/sv.po
2807
Languages/po/sv.po
File diff suppressed because it is too large
Load Diff
2733
Languages/po/tr.po
2733
Languages/po/tr.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/Arm64Emitter.h"
|
||||
@@ -312,6 +313,12 @@ const u8* ARM64XEmitter::AlignCodePage()
|
||||
return m_code;
|
||||
}
|
||||
|
||||
void ARM64XEmitter::Write32(u32 value)
|
||||
{
|
||||
std::memcpy(m_code, &value, sizeof(u32));
|
||||
m_code += sizeof(u32);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::FlushIcache()
|
||||
{
|
||||
FlushIcacheSection(m_lastCacheFlushEnd, m_code);
|
||||
@@ -815,32 +822,32 @@ void ARM64XEmitter::EncodeLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64
|
||||
Write32((size << 30) | (0b111 << 27) | (op << 22) | ((imm & 0x1FF) << 12) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
static inline bool IsInRangeImm19(s64 distance)
|
||||
static constexpr bool IsInRangeImm19(s64 distance)
|
||||
{
|
||||
return (distance >= -0x40000 && distance <= 0x3FFFF);
|
||||
}
|
||||
|
||||
static inline bool IsInRangeImm14(s64 distance)
|
||||
static constexpr bool IsInRangeImm14(s64 distance)
|
||||
{
|
||||
return (distance >= -0x2000 && distance <= 0x1FFF);
|
||||
}
|
||||
|
||||
static inline bool IsInRangeImm26(s64 distance)
|
||||
static constexpr bool IsInRangeImm26(s64 distance)
|
||||
{
|
||||
return (distance >= -0x2000000 && distance <= 0x1FFFFFF);
|
||||
}
|
||||
|
||||
static inline u32 MaskImm19(s64 distance)
|
||||
static constexpr u32 MaskImm19(s64 distance)
|
||||
{
|
||||
return distance & 0x7FFFF;
|
||||
}
|
||||
|
||||
static inline u32 MaskImm14(s64 distance)
|
||||
static constexpr u32 MaskImm14(s64 distance)
|
||||
{
|
||||
return distance & 0x3FFF;
|
||||
}
|
||||
|
||||
static inline u32 MaskImm26(s64 distance)
|
||||
static constexpr u32 MaskImm26(s64 distance)
|
||||
{
|
||||
return distance & 0x3FFFFFF;
|
||||
}
|
||||
|
@@ -81,19 +81,19 @@ enum ARM64Reg
|
||||
INVALID_REG = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
inline bool Is64Bit(ARM64Reg reg) { return (reg & 0x20) != 0; }
|
||||
inline bool IsSingle(ARM64Reg reg) { return (reg & 0xC0) == 0x40; }
|
||||
inline bool IsDouble(ARM64Reg reg) { return (reg & 0xC0) == 0x80; }
|
||||
inline bool IsScalar(ARM64Reg reg) { return IsSingle(reg) || IsDouble(reg); }
|
||||
inline bool IsQuad(ARM64Reg reg) { return (reg & 0xC0) == 0xC0; }
|
||||
inline bool IsVector(ARM64Reg reg) { return (reg & 0xC0) != 0; }
|
||||
inline bool IsGPR(ARM64Reg reg) { return (int)reg < 0x40; }
|
||||
constexpr bool Is64Bit(ARM64Reg reg) { return (reg & 0x20) != 0; }
|
||||
constexpr bool IsSingle(ARM64Reg reg) { return (reg & 0xC0) == 0x40; }
|
||||
constexpr bool IsDouble(ARM64Reg reg) { return (reg & 0xC0) == 0x80; }
|
||||
constexpr bool IsScalar(ARM64Reg reg) { return IsSingle(reg) || IsDouble(reg); }
|
||||
constexpr bool IsQuad(ARM64Reg reg) { return (reg & 0xC0) == 0xC0; }
|
||||
constexpr bool IsVector(ARM64Reg reg) { return (reg & 0xC0) != 0; }
|
||||
constexpr bool IsGPR(ARM64Reg reg) { return static_cast<int>(reg) < 0x40; }
|
||||
|
||||
inline ARM64Reg DecodeReg(ARM64Reg reg) { return (ARM64Reg)(reg & 0x1F); }
|
||||
inline ARM64Reg EncodeRegTo64(ARM64Reg reg) { return (ARM64Reg)(reg | 0x20); }
|
||||
inline ARM64Reg EncodeRegToSingle(ARM64Reg reg) { return (ARM64Reg)(DecodeReg(reg) + S0); }
|
||||
inline ARM64Reg EncodeRegToDouble(ARM64Reg reg) { return (ARM64Reg)((reg & ~0xC0) | 0x80); }
|
||||
inline ARM64Reg EncodeRegToQuad(ARM64Reg reg) { return (ARM64Reg)(reg | 0xC0); }
|
||||
constexpr ARM64Reg DecodeReg(ARM64Reg reg) { return static_cast<ARM64Reg>(reg & 0x1F); }
|
||||
constexpr ARM64Reg EncodeRegTo64(ARM64Reg reg) { return static_cast<ARM64Reg>(reg | 0x20); }
|
||||
constexpr ARM64Reg EncodeRegToSingle(ARM64Reg reg) { return static_cast<ARM64Reg>(DecodeReg(reg) + S0); }
|
||||
constexpr ARM64Reg EncodeRegToDouble(ARM64Reg reg) { return static_cast<ARM64Reg>((reg & ~0xC0) | 0x80); }
|
||||
constexpr ARM64Reg EncodeRegToQuad(ARM64Reg reg) { return static_cast<ARM64Reg>(reg | 0xC0); }
|
||||
|
||||
// For AND/TST/ORR/EOR etc
|
||||
bool IsImmLogical(uint64_t value, unsigned int width, unsigned int *n, unsigned int *imm_s, unsigned int *imm_r);
|
||||
@@ -359,11 +359,7 @@ private:
|
||||
void EncodeLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm);
|
||||
|
||||
protected:
|
||||
inline void Write32(u32 value)
|
||||
{
|
||||
*(u32*)m_code = value;
|
||||
m_code += 4;
|
||||
}
|
||||
void Write32(u32 value);
|
||||
|
||||
public:
|
||||
ARM64XEmitter()
|
||||
|
93
Source/Core/Common/BitField.natvis
Normal file
93
Source/Core/Common/BitField.natvis
Normal file
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015 Scott Mansell
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the owner nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-->
|
||||
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
<!--
|
||||
This is a re-implementation of the abstract bitfield class' algrothm (in BitField.h)
|
||||
for Visual Studio to use for pretty-printing during debugging.
|
||||
-->
|
||||
<Type Name="BitField<*,*,*>">
|
||||
<DisplayString Condition="$T2 == 1"><![CDATA[{(storage & (1 << $T1)) != 0}]]></DisplayString>
|
||||
<DisplayString><![CDATA[{(storage >> $T1) & ((1 << $T2) - 1)}]]></DisplayString>
|
||||
<Expand>
|
||||
<Item Name="Offset">$T1</Item>
|
||||
<Item Name="Size">$T2</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
|
||||
<!--Specialised versions for signed types-->
|
||||
<Type Name="BitField<*,*,__int64>">
|
||||
<!-- This is what I have do to get a sign extension in this crappy natvis "language"
|
||||
Basically, we check the top bit, if it's one, we add the remaining
|
||||
bits to the smallest (most negative) number. -->
|
||||
<DisplayString Condition="(storage & (1 << ($T1 + $T2))) != 0">
|
||||
<![CDATA[{(-1 * (1 << ($T2-1))) + ((storage >> $T1) & ((1 << ($T2-1)) - 1))}]]>
|
||||
</DisplayString>
|
||||
<DisplayString><![CDATA[{(storage >> $T1) & ((1 << ($T2-1)) - 1)}]]></DisplayString>
|
||||
<Expand>
|
||||
<Item Name="Offset">$T1</Item>
|
||||
<Item Name="Size">$T2</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<!-- Oh, and I can't do a generic match for all signed types, so these are identical to the __int64 case above
|
||||
Would be nice if std::numeric_limits<$T3>::is_signed or std::is_signed<$T3>::value worked -->
|
||||
<Type Name="BitField<*,*,__int32>">
|
||||
<DisplayString Condition="(storage & (1 << ($T1 + $T2))) != 0">
|
||||
<![CDATA[{(-1 * (1 << ($T2-1))) + ((storage >> $T1) & ((1 << ($T2-1)) - 1))}]]>
|
||||
</DisplayString>
|
||||
<DisplayString><![CDATA[{(storage >> $T1) & ((1 << ($T2-1)) - 1)}]]></DisplayString>
|
||||
<Expand>
|
||||
<Item Name="Offset">$T1</Item>
|
||||
<Item Name="Size">$T2</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="BitField<*,*,__int16>">
|
||||
<DisplayString Condition="(storage & (1 << ($T1 + $T2))) != 0">
|
||||
<![CDATA[{(-1 * (1 << ($T2-1))) + ((storage >> $T1) & ((1 << ($T2-1)) - 1))}]]>
|
||||
</DisplayString>
|
||||
<DisplayString><![CDATA[{(storage >> $T1) & ((1 << ($T2-1)) - 1)}]]></DisplayString>
|
||||
<Expand>
|
||||
<Item Name="Offset">$T1</Item>
|
||||
<Item Name="Size">$T2</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="BitField<*,*,__int8>">
|
||||
<DisplayString Condition="(storage & (1 << ($T1 + $T2))) != 0">
|
||||
<![CDATA[{(-1 * (1 << ($T2-1))) + ((storage >> $T1) & ((1 << ($T2-1)) - 1))}]]>
|
||||
</DisplayString>
|
||||
<DisplayString><![CDATA[{(storage >> $T1) & ((1 << ($T2-1)) - 1)}]]></DisplayString>
|
||||
<Expand>
|
||||
<Item Name="Offset">$T1</Item>
|
||||
<Item Name="Size">$T2</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
</AutoVisualizer>
|
@@ -192,7 +192,10 @@
|
||||
<Project>{41279555-f94f-4ebc-99de-af863c10c5c4}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="BitField.natvis" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
@@ -190,6 +190,8 @@
|
||||
<ClInclude Include="GL\GLInterfaceBase.h">
|
||||
<Filter>GL\GLInterface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Assert.h" />
|
||||
<ClInclude Include="NonCopyable.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BreakPoints.cpp" />
|
||||
@@ -255,4 +257,7 @@
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<Natvis Include="BitField.natvis" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@@ -77,6 +77,7 @@
|
||||
#define WII_WC24CONF_DIR "shared2" DIR_SEP "wc24"
|
||||
#define THEMES_DIR "Themes"
|
||||
#define ANAGLYPH_DIR "Anaglyph"
|
||||
#define PIPES_DIR "Pipes"
|
||||
|
||||
// Filenames
|
||||
// Files in the directory returned by GetUserPath(D_CONFIG_IDX)
|
||||
|
@@ -791,6 +791,7 @@ static void RebuildUserDirectories(unsigned int dir_index)
|
||||
s_user_paths[D_LOGS_IDX] = s_user_paths[D_USER_IDX] + LOGS_DIR DIR_SEP;
|
||||
s_user_paths[D_MAILLOGS_IDX] = s_user_paths[D_LOGS_IDX] + MAIL_LOGS_DIR DIR_SEP;
|
||||
s_user_paths[D_THEMES_IDX] = s_user_paths[D_USER_IDX] + THEMES_DIR DIR_SEP;
|
||||
s_user_paths[D_PIPES_IDX] = s_user_paths[D_USER_IDX] + PIPES_DIR DIR_SEP;
|
||||
s_user_paths[F_DOLPHINCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + DOLPHIN_CONFIG;
|
||||
s_user_paths[F_DEBUGGERCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + DEBUGGER_CONFIG;
|
||||
s_user_paths[F_LOGGERCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + LOGGER_CONFIG;
|
||||
|
@@ -43,6 +43,7 @@ enum {
|
||||
D_LOGS_IDX,
|
||||
D_MAILLOGS_IDX,
|
||||
D_THEMES_IDX,
|
||||
D_PIPES_IDX,
|
||||
F_DOLPHINCONFIG_IDX,
|
||||
F_DEBUGGERCONFIG_IDX,
|
||||
F_LOGGERCONFIG_IDX,
|
||||
|
@@ -4,7 +4,4 @@
|
||||
|
||||
#include "Common/GL/GLExtensions/gl_common.h"
|
||||
|
||||
typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
|
||||
|
||||
extern PFNGLCOPYIMAGESUBDATAPROC glCopyImageSubData;
|
||||
|
||||
|
@@ -4,8 +4,5 @@
|
||||
|
||||
#include "Common/GL/GLExtensions/gl_common.h"
|
||||
|
||||
typedef void (*PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
|
||||
typedef void (*PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
|
||||
|
||||
extern PFNGLTEXSTORAGE2DMULTISAMPLEPROC glTexStorage2DMultisample;
|
||||
extern PFNGLTEXSTORAGE3DMULTISAMPLEPROC glTexStorage3DMultisample;
|
||||
|
@@ -2,6 +2,9 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "Common/GL/GLInterface/EGL.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
||||
|
@@ -225,7 +225,6 @@ std::string Timer::GetTimeFormatted()
|
||||
}
|
||||
|
||||
// Returns a timestamp with decimals for precise time comparisons
|
||||
// ----------------
|
||||
double Timer::GetDoubleTime()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -245,7 +244,7 @@ double Timer::GetDoubleTime()
|
||||
// sure that we are detecting actual actions, perhaps 60 seconds is
|
||||
// enough really, but I leave a year of seconds anyway, in case the
|
||||
// user's clock is incorrect or something like that.
|
||||
TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60);
|
||||
TmpSeconds = TmpSeconds - DOUBLE_TIME_OFFSET;
|
||||
|
||||
// Make a smaller integer that fits in the double
|
||||
u32 Seconds = (u32)TmpSeconds;
|
||||
@@ -261,4 +260,16 @@ double Timer::GetDoubleTime()
|
||||
return TmpTime;
|
||||
}
|
||||
|
||||
// Formats a timestamp from GetDoubleTime() into a date and time string
|
||||
std::string Timer::GetDateTimeFormatted(double time)
|
||||
{
|
||||
// revert adjustments from GetDoubleTime() to get a normal Unix timestamp again
|
||||
time_t seconds = (time_t)time + DOUBLE_TIME_OFFSET;
|
||||
tm* localTime = localtime(&seconds);
|
||||
|
||||
char tmp[32] = {};
|
||||
strftime(tmp, sizeof(tmp), "%x %X", localTime);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
} // Namespace Common
|
||||
|
@@ -26,15 +26,22 @@ public:
|
||||
static void RestoreResolution();
|
||||
static u64 GetTimeSinceJan1970();
|
||||
static u64 GetLocalTimeSinceJan1970();
|
||||
// Returns a timestamp with decimals for precise time comparisons
|
||||
static double GetDoubleTime();
|
||||
|
||||
static std::string GetTimeFormatted();
|
||||
// Formats a timestamp from GetDoubleTime() into a date and time string
|
||||
static std::string GetDateTimeFormatted(double time);
|
||||
std::string GetTimeElapsedFormatted() const;
|
||||
u64 GetTimeElapsed();
|
||||
|
||||
static u32 GetTimeMs();
|
||||
static u64 GetTimeUs();
|
||||
|
||||
// Arbitrarily chosen value (38 years) that is subtracted in GetDoubleTime()
|
||||
// to increase sub-second precision of the resulting double timestamp
|
||||
static const int DOUBLE_TIME_OFFSET = (38 * 365 * 24 * 60 * 60);
|
||||
|
||||
private:
|
||||
u64 m_LastTime;
|
||||
u64 m_StartTime;
|
||||
|
@@ -15,6 +15,8 @@ struct PatchInfo {
|
||||
} static const s_patches[] = {
|
||||
// 10.0.10240.16384 (th1.150709-1700)
|
||||
{ L"ucrtbase.dll", 0xF61ED, 0x6AE7B, 5 },
|
||||
// 10.0.10240.16390 (th1_st1.150714-1601)
|
||||
{ L"ucrtbase.dll", 0xF5ED9, 0x6AE7B, 5 },
|
||||
// 10.0.10137.0 (th1.150602-2238)
|
||||
{ L"ucrtbase.dll", 0xF8B5E, 0x63ED6, 2 },
|
||||
// 10.0.10150.0 (th1.150616-1659)
|
||||
|
@@ -56,7 +56,10 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
||||
// Write necessary values
|
||||
// Here we write values to memory that the apploader does not take care of. Game info goes
|
||||
// to 0x80000000 according to YAGCD 4.2.
|
||||
DVDInterface::DVDRead(/*offset*/0x00000000, /*address*/0x00000000, 0x20, false); // write disc info
|
||||
|
||||
// It's possible to boot DOL and ELF files without a disc inserted
|
||||
if (DVDInterface::VolumeIsValid())
|
||||
DVDInterface::DVDRead(/*offset*/0x00000000, /*address*/0x00000000, 0x20, false); // write disc info
|
||||
|
||||
PowerPC::HostWrite_U32(0x0D15EA5E, 0x80000020); // Booted from bootrom. 0xE5207C22 = booted from jtag
|
||||
PowerPC::HostWrite_U32(Memory::REALRAM_SIZE, 0x80000028); // Physical Memory Size (24MB on retail)
|
||||
@@ -81,6 +84,9 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
||||
|
||||
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
|
||||
|
||||
if (!DVDInterface::VolumeIsValid())
|
||||
return false;
|
||||
|
||||
// Load Apploader to Memory - The apploader is hardcoded to begin at 0x2440 on the disc,
|
||||
// but the size can differ between discs. Compare with YAGCD chap 13.
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
|
@@ -10,6 +10,12 @@
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
// Ordered in order of prefered use.
|
||||
// Not all of these are actually available
|
||||
const std::array<X64Reg, 15> DSPJitRegCache::m_allocation_order = {{
|
||||
R8, R9, R10, R11, R12, R13, R14, R15, RSI, RDI, RBX, RCX, RDX, RAX, RBP
|
||||
}};
|
||||
|
||||
static void* GetRegisterPointer(size_t reg)
|
||||
{
|
||||
switch (reg)
|
||||
@@ -943,17 +949,11 @@ void DSPJitRegCache::WriteReg(int dreg, OpArg arg)
|
||||
PutReg(dreg, true);
|
||||
}
|
||||
|
||||
//ordered in order of prefered use
|
||||
//not all of these are actually available
|
||||
static X64Reg alloc_order[] = {
|
||||
R8,R9,R10,R11,R12,R13,R14,R15,RSI,RDI,RBX,RCX,RDX,RAX,RBP
|
||||
};
|
||||
|
||||
X64Reg DSPJitRegCache::SpillXReg()
|
||||
{
|
||||
int max_use_ctr_diff = 0;
|
||||
X64Reg least_recent_use_reg = INVALID_REG;
|
||||
for (X64Reg reg : alloc_order)
|
||||
for (X64Reg reg : m_allocation_order)
|
||||
{
|
||||
if (xregs[reg].guest_reg <= DSP_REG_MAX_MEM_BACKED &&
|
||||
!regs[xregs[reg].guest_reg].used)
|
||||
@@ -974,7 +974,7 @@ X64Reg DSPJitRegCache::SpillXReg()
|
||||
}
|
||||
|
||||
//just choose one.
|
||||
for (X64Reg reg : alloc_order)
|
||||
for (X64Reg reg : m_allocation_order)
|
||||
{
|
||||
if (xregs[reg].guest_reg <= DSP_REG_MAX_MEM_BACKED &&
|
||||
!regs[xregs[reg].guest_reg].used)
|
||||
@@ -1007,13 +1007,14 @@ void DSPJitRegCache::SpillXReg(X64Reg reg)
|
||||
|
||||
X64Reg DSPJitRegCache::FindFreeXReg()
|
||||
{
|
||||
for (X64Reg x : alloc_order)
|
||||
for (X64Reg x : m_allocation_order)
|
||||
{
|
||||
if (xregs[x].guest_reg == DSP_REG_NONE)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_REG;
|
||||
}
|
||||
|
||||
|
@@ -32,56 +32,6 @@ enum DSPJitSignExtend
|
||||
|
||||
class DSPJitRegCache
|
||||
{
|
||||
private:
|
||||
struct X64CachedReg
|
||||
{
|
||||
size_t guest_reg; //including DSPJitRegSpecial
|
||||
bool pushed;
|
||||
};
|
||||
|
||||
struct DynamicReg
|
||||
{
|
||||
Gen::OpArg loc;
|
||||
void *mem;
|
||||
size_t size;
|
||||
bool dirty;
|
||||
bool used;
|
||||
int last_use_ctr;
|
||||
int parentReg;
|
||||
int shift;//current shift if parentReg == DSP_REG_NONE
|
||||
//otherwise the shift this part can be found at
|
||||
Gen::X64Reg host_reg;
|
||||
/* TODO:
|
||||
+ drop sameReg
|
||||
+ add parentReg
|
||||
+ add shift:
|
||||
- if parentReg != DSP_REG_NONE, this is the shift where this
|
||||
register is found in the parentReg
|
||||
- if parentReg == DSP_REG_NONE, this is the current shift _state_
|
||||
*/
|
||||
};
|
||||
|
||||
std::array<DynamicReg, 37> regs;
|
||||
std::array<X64CachedReg, 16> xregs;
|
||||
|
||||
DSPEmitter &emitter;
|
||||
bool temporary;
|
||||
bool merged;
|
||||
|
||||
int use_ctr;
|
||||
private:
|
||||
// Find a free host reg
|
||||
Gen::X64Reg FindFreeXReg();
|
||||
Gen::X64Reg SpillXReg();
|
||||
Gen::X64Reg FindSpillFreeXReg();
|
||||
void SpillXReg(Gen::X64Reg reg);
|
||||
|
||||
void MovToHostReg(size_t reg, Gen::X64Reg host_reg, bool load);
|
||||
void MovToHostReg(size_t reg, bool load);
|
||||
void RotateHostReg(size_t reg, int shift, bool emit);
|
||||
void MovToMemory(size_t reg);
|
||||
void FlushMemBackedRegs();
|
||||
|
||||
public:
|
||||
DSPJitRegCache(DSPEmitter &_emitter);
|
||||
|
||||
@@ -176,4 +126,56 @@ public:
|
||||
void GetXReg(Gen::X64Reg reg);
|
||||
// Unreserve the given host reg
|
||||
void PutXReg(Gen::X64Reg reg);
|
||||
|
||||
private:
|
||||
struct X64CachedReg
|
||||
{
|
||||
size_t guest_reg; // Including DSPJitRegSpecial
|
||||
bool pushed;
|
||||
};
|
||||
|
||||
struct DynamicReg
|
||||
{
|
||||
Gen::OpArg loc;
|
||||
void *mem;
|
||||
size_t size;
|
||||
bool dirty;
|
||||
bool used;
|
||||
int last_use_ctr;
|
||||
int parentReg;
|
||||
int shift; // Current shift if parentReg == DSP_REG_NONE
|
||||
// otherwise the shift this part can be found at
|
||||
Gen::X64Reg host_reg;
|
||||
|
||||
// TODO:
|
||||
// + drop sameReg
|
||||
// + add parentReg
|
||||
// + add shift:
|
||||
// - if parentReg != DSP_REG_NONE, this is the shift where this
|
||||
// register is found in the parentReg
|
||||
// - if parentReg == DSP_REG_NONE, this is the current shift _state_
|
||||
};
|
||||
|
||||
// Find a free host reg
|
||||
Gen::X64Reg FindFreeXReg();
|
||||
Gen::X64Reg SpillXReg();
|
||||
Gen::X64Reg FindSpillFreeXReg();
|
||||
void SpillXReg(Gen::X64Reg reg);
|
||||
|
||||
void MovToHostReg(size_t reg, Gen::X64Reg host_reg, bool load);
|
||||
void MovToHostReg(size_t reg, bool load);
|
||||
void RotateHostReg(size_t reg, int shift, bool emit);
|
||||
void MovToMemory(size_t reg);
|
||||
void FlushMemBackedRegs();
|
||||
|
||||
static const std::array<Gen::X64Reg, 15> m_allocation_order;
|
||||
|
||||
std::array<DynamicReg, 37> regs;
|
||||
std::array<X64CachedReg, 16> xregs;
|
||||
|
||||
DSPEmitter& emitter;
|
||||
bool temporary;
|
||||
bool merged;
|
||||
|
||||
int use_ctr;
|
||||
};
|
||||
|
@@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
@@ -109,15 +111,10 @@ void LoadCPReg(u32 subCmd, u32 value, CPMemory& cpMem)
|
||||
|
||||
u32 CalculateVertexSize(int vatIndex, const CPMemory& cpMem)
|
||||
{
|
||||
u32 vertexSize = 0;
|
||||
|
||||
int sizes[21];
|
||||
CalculateVertexElementSizes(sizes, vatIndex, cpMem);
|
||||
|
||||
for (auto& size : sizes)
|
||||
vertexSize += size;
|
||||
|
||||
return vertexSize;
|
||||
return std::accumulate(std::begin(sizes), std::end(sizes), 0U);
|
||||
}
|
||||
|
||||
void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory& cpMem)
|
||||
|
@@ -30,7 +30,7 @@ FifoDataFile::~FifoDataFile()
|
||||
|
||||
bool FifoDataFile::HasBrokenEFBCopies() const
|
||||
{
|
||||
return version < 2;
|
||||
return m_Version < 2;
|
||||
}
|
||||
|
||||
void FifoDataFile::SetIsWii(bool isWii)
|
||||
@@ -150,6 +150,7 @@ FifoDataFile* FifoDataFile::Load(const std::string &filename, bool flagsOnly)
|
||||
FifoDataFile* dataFile = new FifoDataFile;
|
||||
|
||||
dataFile->m_Flags = header.flags;
|
||||
dataFile->m_Version = header.file_version;
|
||||
|
||||
if (flagsOnly)
|
||||
{
|
||||
|
@@ -94,7 +94,7 @@ private:
|
||||
u32 m_XFRegs[XF_REGS_SIZE];
|
||||
|
||||
u32 m_Flags;
|
||||
u32 version;
|
||||
u32 m_Version;
|
||||
|
||||
std::vector<FifoFrameInfo> m_Frames;
|
||||
};
|
||||
|
@@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MathUtil.h"
|
||||
|
@@ -19,6 +19,9 @@ const std::string hotkey_labels[] =
|
||||
_trans("Stop"),
|
||||
_trans("Reset"),
|
||||
_trans("Frame Advance"),
|
||||
_trans("Frame Advance Decrease Speed"),
|
||||
_trans("Frame Advance Increase Speed"),
|
||||
_trans("Frame Advance Reset Speed"),
|
||||
|
||||
_trans("Start Recording"),
|
||||
_trans("Play Recording"),
|
||||
|
@@ -17,6 +17,9 @@ enum Hotkey
|
||||
HK_STOP,
|
||||
HK_RESET,
|
||||
HK_FRAME_ADVANCE,
|
||||
HK_FRAME_ADVANCE_DECREASE_SPEED,
|
||||
HK_FRAME_ADVANCE_INCREASE_SPEED,
|
||||
HK_FRAME_ADVANCE_RESET_SPEED,
|
||||
|
||||
HK_START_RECORDING,
|
||||
HK_PLAY_RECORDING,
|
||||
|
@@ -65,8 +65,6 @@ typedef std::map<u32, std::shared_ptr<IWII_IPC_HLE_Device>> TDeviceMap;
|
||||
static TDeviceMap g_DeviceMap;
|
||||
|
||||
// STATE_TO_SAVE
|
||||
typedef std::map<u32, std::string> TFileNameMap;
|
||||
|
||||
#define IPC_MAX_FDS 0x18
|
||||
#define ES_MAX_COUNT 2
|
||||
static std::shared_ptr<IWII_IPC_HLE_Device> g_FdMap[IPC_MAX_FDS];
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/State.h"
|
||||
#include "Core/HW/CPU.h"
|
||||
@@ -67,7 +68,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
|
||||
static std::thread g_save_thread;
|
||||
|
||||
// Don't forget to increase this after doing changes on the savestate system
|
||||
static const u32 STATE_VERSION = 49; // Last changed in PR 3108
|
||||
static const u32 STATE_VERSION = 50; // Last changed in PR 3108
|
||||
|
||||
// Maps savestate versions to Dolphin versions.
|
||||
// Versions after 42 don't need to be added to this list,
|
||||
@@ -118,7 +119,8 @@ void EnableCompression(bool compression)
|
||||
g_use_compression = compression;
|
||||
}
|
||||
|
||||
static std::string DoState(PointerWrap& p)
|
||||
// Returns true if state version matches current Dolphin state version, false otherwise.
|
||||
static bool DoStateVersion(PointerWrap& p, std::string* version_created_by)
|
||||
{
|
||||
u32 version = STATE_VERSION;
|
||||
{
|
||||
@@ -128,15 +130,15 @@ static std::string DoState(PointerWrap& p)
|
||||
version = cookie - COOKIE_BASE;
|
||||
}
|
||||
|
||||
std::string version_created_by = scm_rev_str;
|
||||
*version_created_by = scm_rev_str;
|
||||
if (version > 42)
|
||||
p.Do(version_created_by);
|
||||
p.Do(*version_created_by);
|
||||
else
|
||||
version_created_by.clear();
|
||||
version_created_by->clear();
|
||||
|
||||
if (version != STATE_VERSION)
|
||||
{
|
||||
if (version_created_by.empty() && s_old_versions.count(version))
|
||||
if (version_created_by->empty() && s_old_versions.count(version))
|
||||
{
|
||||
// The savestate is from an old version that doesn't
|
||||
// save the Dolphin version number to savestates, but
|
||||
@@ -147,9 +149,21 @@ static std::string DoState(PointerWrap& p)
|
||||
std::string oldest_version = version_range.first;
|
||||
std::string newest_version = version_range.second;
|
||||
|
||||
version_created_by = "Dolphin " + oldest_version + " - " + newest_version;
|
||||
*version_created_by = "Dolphin " + oldest_version + " - " + newest_version;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
p.DoMarker("Version");
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string DoState(PointerWrap& p)
|
||||
{
|
||||
std::string version_created_by;
|
||||
if (!DoStateVersion(p, &version_created_by))
|
||||
{
|
||||
// because the version doesn't match, fail.
|
||||
// this will trigger an OSD message like "Can't load state from other revisions"
|
||||
// we could use the version numbers to maintain some level of backward compatibility, but currently don't.
|
||||
@@ -157,8 +171,6 @@ static std::string DoState(PointerWrap& p)
|
||||
return version_created_by;
|
||||
}
|
||||
|
||||
p.DoMarker("Version");
|
||||
|
||||
// Begin with video backend, so that it gets a chance to clear its caches and writeback modified things to RAM
|
||||
g_video_backend->DoState(p);
|
||||
p.DoMarker("video_backend");
|
||||
@@ -373,6 +385,7 @@ static void CompressAndDumpState(CompressAndDumpState_args save_args)
|
||||
}
|
||||
|
||||
Core::DisplayMessage(StringFromFormat("Saved State to %s", filename.c_str()), 2000);
|
||||
Host_UpdateMainFrame();
|
||||
}
|
||||
|
||||
void SaveAs(const std::string& filename, bool wait)
|
||||
@@ -435,6 +448,19 @@ bool ReadHeader(const std::string& filename, StateHeader& header)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string GetInfoStringOfSlot(int slot)
|
||||
{
|
||||
std::string filename = MakeStateFilename(slot);
|
||||
if (!File::Exists(filename))
|
||||
return "Empty";
|
||||
|
||||
State::StateHeader header;
|
||||
if (!ReadHeader(filename, header))
|
||||
return "Unknown";
|
||||
|
||||
return Common::Timer::GetDateTimeFormatted(header.time);
|
||||
}
|
||||
|
||||
static void LoadFileStateData(const std::string& filename, std::vector<u8>& ret_data)
|
||||
{
|
||||
Flush();
|
||||
|
@@ -33,6 +33,10 @@ void EnableCompression(bool compression);
|
||||
|
||||
bool ReadHeader(const std::string& filename, StateHeader& header);
|
||||
|
||||
// Returns a string containing information of the savestate in the given slot
|
||||
// which can be presented to the user for identification purposes
|
||||
std::string GetInfoStringOfSlot(int slot);
|
||||
|
||||
// These don't happen instantly - they get scheduled as events.
|
||||
// ...But only if we're not in the main CPU thread.
|
||||
// If we're in the main CPU thread then they run immediately instead
|
||||
|
@@ -74,11 +74,10 @@ static SPartitionGroup PartitionGroup[4];
|
||||
|
||||
void MarkAsUsed(u64 _Offset, u64 _Size);
|
||||
void MarkAsUsedE(u64 _PartitionDataOffset, u64 _Offset, u64 _Size);
|
||||
void ReadFromVolume(u64 _Offset, u64 _Length, u32& _Buffer, bool _Decrypt);
|
||||
void ReadFromVolume(u64 _Offset, u64 _Length, u64& _Buffer, bool _Decrypt);
|
||||
void ReadFromVolume(u64 _Offset, u32& _Buffer, bool _Decrypt);
|
||||
void ReadFromVolume(u64 _Offset, u64& _Buffer, bool _Decrypt);
|
||||
bool ParseDisc();
|
||||
bool ParsePartitionData(SPartition& _rPartition);
|
||||
u32 GetDOLSize(u64 _DOLOffset);
|
||||
|
||||
|
||||
bool SetupScrub(const std::string& filename, int block_size)
|
||||
@@ -96,6 +95,9 @@ bool SetupScrub(const std::string& filename, int block_size)
|
||||
m_BlocksPerCluster = CLUSTER_SIZE / m_BlockSize;
|
||||
|
||||
m_Disc = CreateVolumeFromFilename(filename);
|
||||
if (!m_Disc)
|
||||
return false;
|
||||
|
||||
m_FileSize = m_Disc->GetSize();
|
||||
|
||||
u32 numClusters = (u32)(m_FileSize / CLUSTER_SIZE);
|
||||
@@ -190,14 +192,14 @@ void MarkAsUsedE(u64 _PartitionDataOffset, u64 _Offset, u64 _Size)
|
||||
}
|
||||
|
||||
// Helper functions for reading the BE volume
|
||||
void ReadFromVolume(u64 _Offset, u64 _Length, u32& _Buffer, bool _Decrypt)
|
||||
void ReadFromVolume(u64 _Offset, u32& _Buffer, bool _Decrypt)
|
||||
{
|
||||
m_Disc->Read(_Offset, _Length, (u8*)&_Buffer, _Decrypt);
|
||||
m_Disc->Read(_Offset, sizeof(u32), (u8*)&_Buffer, _Decrypt);
|
||||
_Buffer = Common::swap32(_Buffer);
|
||||
}
|
||||
void ReadFromVolume(u64 _Offset, u64 _Length, u64& _Buffer, bool _Decrypt)
|
||||
void ReadFromVolume(u64 _Offset, u64& _Buffer, bool _Decrypt)
|
||||
{
|
||||
m_Disc->Read(_Offset, _Length, (u8*)&_Buffer, _Decrypt);
|
||||
m_Disc->Read(_Offset, sizeof(u32), (u8*)&_Buffer, _Decrypt);
|
||||
_Buffer = Common::swap32((u32)_Buffer);
|
||||
_Buffer <<= 2;
|
||||
}
|
||||
@@ -209,8 +211,8 @@ bool ParseDisc()
|
||||
|
||||
for (int x = 0; x < 4; x++)
|
||||
{
|
||||
ReadFromVolume(0x40000 + (x * 8) + 0, 4, PartitionGroup[x].numPartitions, false);
|
||||
ReadFromVolume(0x40000 + (x * 8) + 4, 4, PartitionGroup[x].PartitionsOffset, false);
|
||||
ReadFromVolume(0x40000 + (x * 8) + 0, PartitionGroup[x].numPartitions, false);
|
||||
ReadFromVolume(0x40000 + (x * 8) + 4, PartitionGroup[x].PartitionsOffset, false);
|
||||
|
||||
// Read all partitions
|
||||
for (u32 i = 0; i < PartitionGroup[x].numPartitions; i++)
|
||||
@@ -220,16 +222,16 @@ bool ParseDisc()
|
||||
Partition.GroupNumber = x;
|
||||
Partition.Number = i;
|
||||
|
||||
ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 0, 4, Partition.Offset, false);
|
||||
ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 4, 4, Partition.Type, false);
|
||||
ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 0, Partition.Offset, false);
|
||||
ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 4, Partition.Type, false);
|
||||
|
||||
ReadFromVolume(Partition.Offset + 0x2a4, 4, Partition.Header.TMDSize, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2a8, 4, Partition.Header.TMDOffset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2ac, 4, Partition.Header.CertChainSize, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2b0, 4, Partition.Header.CertChainOffset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2b4, 4, Partition.Header.H3Offset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2b8, 4, Partition.Header.DataOffset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2bc, 4, Partition.Header.DataSize, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2a4, Partition.Header.TMDSize, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2a8, Partition.Header.TMDOffset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2ac, Partition.Header.CertChainSize, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2b0, Partition.Header.CertChainOffset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2b4, Partition.Header.H3Offset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2b8, Partition.Header.DataOffset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2bc, Partition.Header.DataSize, false);
|
||||
|
||||
PartitionGroup[x].PartitionsVec.push_back(Partition);
|
||||
}
|
||||
@@ -283,8 +285,8 @@ bool ParsePartitionData(SPartition& _rPartition)
|
||||
{
|
||||
// Mark things as used which are not in the filesystem
|
||||
// Header, Header Information, Apploader
|
||||
ReadFromVolume(0x2440 + 0x14, 4, _rPartition.Header.ApploaderSize, true);
|
||||
ReadFromVolume(0x2440 + 0x18, 4, _rPartition.Header.ApploaderTrailerSize, true);
|
||||
ReadFromVolume(0x2440 + 0x14, _rPartition.Header.ApploaderSize, true);
|
||||
ReadFromVolume(0x2440 + 0x18, _rPartition.Header.ApploaderTrailerSize, true);
|
||||
MarkAsUsedE(_rPartition.Offset
|
||||
+ _rPartition.Header.DataOffset
|
||||
, 0
|
||||
@@ -293,16 +295,16 @@ bool ParsePartitionData(SPartition& _rPartition)
|
||||
+ _rPartition.Header.ApploaderTrailerSize);
|
||||
|
||||
// DOL
|
||||
ReadFromVolume(0x420, 4, _rPartition.Header.DOLOffset, true);
|
||||
_rPartition.Header.DOLSize = GetDOLSize(_rPartition.Header.DOLOffset);
|
||||
ReadFromVolume(0x420, _rPartition.Header.DOLOffset, true);
|
||||
_rPartition.Header.DOLSize = filesystem->GetBootDOLSize(_rPartition.Header.DOLOffset);
|
||||
MarkAsUsedE(_rPartition.Offset
|
||||
+ _rPartition.Header.DataOffset
|
||||
, _rPartition.Header.DOLOffset
|
||||
, _rPartition.Header.DOLSize);
|
||||
|
||||
// FST
|
||||
ReadFromVolume(0x424, 4, _rPartition.Header.FSTOffset, true);
|
||||
ReadFromVolume(0x428, 4, _rPartition.Header.FSTSize, true);
|
||||
ReadFromVolume(0x424, _rPartition.Header.FSTOffset, true);
|
||||
ReadFromVolume(0x428, _rPartition.Header.FSTSize, true);
|
||||
MarkAsUsedE(_rPartition.Offset
|
||||
+ _rPartition.Header.DataOffset
|
||||
, _rPartition.Header.FSTOffset
|
||||
@@ -327,31 +329,6 @@ bool ParsePartitionData(SPartition& _rPartition)
|
||||
return ParsedOK;
|
||||
}
|
||||
|
||||
u32 GetDOLSize(u64 _DOLOffset)
|
||||
{
|
||||
u32 offset = 0, size = 0, max = 0;
|
||||
|
||||
// Iterate through the 7 code segments
|
||||
for (u8 i = 0; i < 7; i++)
|
||||
{
|
||||
ReadFromVolume(_DOLOffset + 0x00 + i * 4, 4, offset, true);
|
||||
ReadFromVolume(_DOLOffset + 0x90 + i * 4, 4, size, true);
|
||||
if (offset + size > max)
|
||||
max = offset + size;
|
||||
}
|
||||
|
||||
// Iterate through the 11 data segments
|
||||
for (u8 i = 0; i < 11; i++)
|
||||
{
|
||||
ReadFromVolume(_DOLOffset + 0x1c + i * 4, 4, offset, true);
|
||||
ReadFromVolume(_DOLOffset + 0xac + i * 4, 4, size, true);
|
||||
if (offset + size > max)
|
||||
max = offset + size;
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
} // namespace DiscScrubber
|
||||
|
||||
} // namespace DiscIO
|
||||
|
@@ -150,27 +150,32 @@ bool CFileSystemGCWii::ExportApploader(const std::string& _rExportFolder) const
|
||||
|
||||
u32 CFileSystemGCWii::GetBootDOLSize() const
|
||||
{
|
||||
u32 DolOffset = m_rVolume->Read32(0x420, m_Wii) << GetOffsetShift();
|
||||
u32 DolSize = 0, offset = 0, size = 0;
|
||||
return GetBootDOLSize((u64)m_rVolume->Read32(0x420, m_Wii) << GetOffsetShift());
|
||||
}
|
||||
|
||||
u32 CFileSystemGCWii::GetBootDOLSize(u64 dol_offset) const
|
||||
{
|
||||
u32 dol_size = 0;
|
||||
u32 offset = 0;
|
||||
u32 size = 0;
|
||||
|
||||
// Iterate through the 7 code segments
|
||||
for (u8 i = 0; i < 7; i++)
|
||||
{
|
||||
offset = m_rVolume->Read32(DolOffset + 0x00 + i * 4, m_Wii);
|
||||
size = m_rVolume->Read32(DolOffset + 0x90 + i * 4, m_Wii);
|
||||
if (offset + size > DolSize)
|
||||
DolSize = offset + size;
|
||||
offset = m_rVolume->Read32(dol_offset + 0x00 + i * 4, m_Wii);
|
||||
size = m_rVolume->Read32(dol_offset + 0x90 + i * 4, m_Wii);
|
||||
dol_size = std::max(offset + size, dol_size);
|
||||
}
|
||||
|
||||
// Iterate through the 11 data segments
|
||||
for (u8 i = 0; i < 11; i++)
|
||||
{
|
||||
offset = m_rVolume->Read32(DolOffset + 0x1c + i * 4, m_Wii);
|
||||
size = m_rVolume->Read32(DolOffset + 0xac + i * 4, m_Wii);
|
||||
if (offset + size > DolSize)
|
||||
DolSize = offset + size;
|
||||
offset = m_rVolume->Read32(dol_offset + 0x1c + i * 4, m_Wii);
|
||||
size = m_rVolume->Read32(dol_offset + 0xac + i * 4, m_Wii);
|
||||
dol_size = std::max(offset + size, dol_size);
|
||||
}
|
||||
return DolSize;
|
||||
|
||||
return dol_size;
|
||||
}
|
||||
|
||||
bool CFileSystemGCWii::GetBootDOL(u8* &buffer, u32 DolSize) const
|
||||
|
@@ -32,6 +32,7 @@ public:
|
||||
bool ExportDOL(const std::string& _rExportFolder) const override;
|
||||
bool GetBootDOL(u8* &buffer, u32 DolSize) const override;
|
||||
u32 GetBootDOLSize() const override;
|
||||
u32 GetBootDOLSize(u64 dol_offset) const override;
|
||||
|
||||
private:
|
||||
bool m_Initialized;
|
||||
|
@@ -52,6 +52,7 @@ public:
|
||||
virtual const std::string GetFileName(u64 _Address) = 0;
|
||||
virtual bool GetBootDOL(u8* &buffer, u32 DolSize) const = 0;
|
||||
virtual u32 GetBootDOLSize() const = 0;
|
||||
virtual u32 GetBootDOLSize(u64 dol_offset) const = 0;
|
||||
|
||||
virtual const IVolume *GetVolume() const { return m_rVolume; }
|
||||
protected:
|
||||
|
@@ -37,7 +37,7 @@ void Resources::Init()
|
||||
m_regions[DiscIO::IVolume::COUNTRY_RUSSIA].load(GIFN("Flag_Russia"));
|
||||
m_regions[DiscIO::IVolume::COUNTRY_SPAIN].load(GIFN("Flag_Spain"));
|
||||
m_regions[DiscIO::IVolume::COUNTRY_TAIWAN].load(GIFN("Flag_Taiwan"));
|
||||
m_regions[DiscIO::IVolume::COUNTRY_WORLD].load(GIFN("Flag_Europe")); // Uses European flag as a placeholder
|
||||
m_regions[DiscIO::IVolume::COUNTRY_WORLD].load(GIFN("Flag_International"));
|
||||
m_regions[DiscIO::IVolume::COUNTRY_UNKNOWN].load(GIFN("Flag_Unknown"));
|
||||
|
||||
m_platforms.resize(4);
|
||||
|
@@ -337,7 +337,7 @@ void GFXDebuggerPanel::OnClearScreenButton(wxCommandEvent& event)
|
||||
|
||||
void GFXDebuggerPanel::OnClearTextureCacheButton(wxCommandEvent& event)
|
||||
{
|
||||
TextureCache::Invalidate();
|
||||
TextureCacheBase::Invalidate();
|
||||
}
|
||||
|
||||
void GFXDebuggerPanel::OnClearVertexShaderCacheButton(wxCommandEvent& event)
|
||||
|
@@ -595,7 +595,7 @@ void FifoPlayerDlg::OnFrameListSelectionChanged(wxCommandEvent& event)
|
||||
{
|
||||
size_t num_objects = player.GetAnalyzedFrameInfo(event.GetInt()).objectStarts.size();
|
||||
for (size_t i = 0; i < num_objects; ++i)
|
||||
m_objectsList->Append(wxString::Format("Object %u", (u32)i));
|
||||
m_objectsList->Append(wxString::Format(_("Object %zu"), i));
|
||||
}
|
||||
|
||||
// Update object list
|
||||
@@ -858,7 +858,7 @@ void FifoPlayerDlg::UpdateAnalyzerGui()
|
||||
|
||||
for (size_t i = 0; i < num_frames; ++i)
|
||||
{
|
||||
m_framesList->Append(wxString::Format("Frame %u", (u32)i));
|
||||
m_framesList->Append(wxString::Format(_("Frame %zu"), i));
|
||||
}
|
||||
|
||||
wxCommandEvent ev = wxCommandEvent(wxEVT_LISTBOX);
|
||||
@@ -872,7 +872,7 @@ wxString FifoPlayerDlg::CreateFileFrameCountLabel() const
|
||||
FifoDataFile *file = FifoPlayer::GetInstance().GetFile();
|
||||
|
||||
if (file)
|
||||
return CreateIntegerLabel(file->GetFrameCount(), _("Frame"));
|
||||
return wxString::Format(_("%u frames"), file->GetFrameCount());
|
||||
|
||||
return _("No file loaded");
|
||||
}
|
||||
@@ -882,7 +882,7 @@ wxString FifoPlayerDlg::CreateCurrentFrameLabel() const
|
||||
FifoDataFile *file = FifoPlayer::GetInstance().GetFile();
|
||||
|
||||
if (file)
|
||||
return _("Frame ") + wxString::Format("%u", FifoPlayer::GetInstance().GetCurrentFrameNum());
|
||||
return wxString::Format(_("Frame %u"), FifoPlayer::GetInstance().GetCurrentFrameNum());
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
@@ -892,7 +892,7 @@ wxString FifoPlayerDlg::CreateFileObjectCountLabel() const
|
||||
FifoDataFile *file = FifoPlayer::GetInstance().GetFile();
|
||||
|
||||
if (file)
|
||||
return CreateIntegerLabel(FifoPlayer::GetInstance().GetFrameObjectCount(), _("Object"));
|
||||
return wxString::Format(_("%u objects"), FifoPlayer::GetInstance().GetFrameObjectCount());
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
@@ -907,7 +907,7 @@ wxString FifoPlayerDlg::CreateRecordingFifoSizeLabel() const
|
||||
for (size_t i = 0; i < file->GetFrameCount(); ++i)
|
||||
fifoBytes += file->GetFrame(i).fifoDataSize;
|
||||
|
||||
return CreateIntegerLabel(fifoBytes, _("FIFO Byte"));
|
||||
return wxString::Format(_("%zu FIFO bytes"), fifoBytes);
|
||||
}
|
||||
|
||||
return _("No recorded file");
|
||||
@@ -927,7 +927,7 @@ wxString FifoPlayerDlg::CreateRecordingMemSizeLabel() const
|
||||
memBytes += memUpdate.size;
|
||||
}
|
||||
|
||||
return CreateIntegerLabel(memBytes, _("Memory Byte"));
|
||||
return wxString::Format(_("%zu memory bytes"), memBytes);
|
||||
}
|
||||
|
||||
return wxEmptyString;
|
||||
@@ -938,23 +938,11 @@ wxString FifoPlayerDlg::CreateRecordingFrameCountLabel() const
|
||||
FifoDataFile *file = FifoRecorder::GetInstance().GetRecordedFile();
|
||||
|
||||
if (file)
|
||||
{
|
||||
size_t numFrames = file->GetFrameCount();
|
||||
return CreateIntegerLabel(numFrames, _("Frame"));
|
||||
}
|
||||
return wxString::Format(_("%u frames"), file->GetFrameCount());
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
wxString FifoPlayerDlg::CreateIntegerLabel(size_t size, const wxString& label) const
|
||||
{
|
||||
wxString postfix;
|
||||
if (size != 1)
|
||||
postfix = _("s");
|
||||
|
||||
return wxString::Format("%u ", (u32)size) + label + postfix;
|
||||
}
|
||||
|
||||
bool FifoPlayerDlg::GetSaveButtonEnabled() const
|
||||
{
|
||||
return (FifoRecorder::GetInstance().GetRecordedFile() != nullptr);
|
||||
|
@@ -66,7 +66,6 @@ private:
|
||||
wxString CreateRecordingFifoSizeLabel() const;
|
||||
wxString CreateRecordingMemSizeLabel() const;
|
||||
wxString CreateRecordingFrameCountLabel() const;
|
||||
wxString CreateIntegerLabel(size_t size, const wxString& label) const;
|
||||
|
||||
bool GetSaveButtonEnabled() const;
|
||||
|
||||
|
@@ -1291,7 +1291,6 @@ void CFrame::ParseHotkeys()
|
||||
case HK_CHANGE_DISC:
|
||||
case HK_REFRESH_LIST:
|
||||
case HK_RESET:
|
||||
case HK_FRAME_ADVANCE:
|
||||
case HK_START_RECORDING:
|
||||
case HK_PLAY_RECORDING:
|
||||
case HK_EXPORT_RECORDING:
|
||||
@@ -1333,6 +1332,8 @@ void CFrame::ParseHotkeys()
|
||||
// Pause and Unpause
|
||||
if (IsHotkey(HK_PLAY_PAUSE))
|
||||
DoPause();
|
||||
// Frame advance
|
||||
HandleFrameSkipHotkeys();
|
||||
// Stop
|
||||
if (IsHotkey(HK_STOP))
|
||||
DoStop();
|
||||
@@ -1531,3 +1532,61 @@ void CFrame::ParseHotkeys()
|
||||
if (IsHotkey(HK_UNDO_SAVE_STATE))
|
||||
State::UndoSaveState();
|
||||
}
|
||||
|
||||
void CFrame::HandleFrameSkipHotkeys()
|
||||
{
|
||||
static const int MAX_FRAME_SKIP_DELAY = 60;
|
||||
static int frameStepCount = 0;
|
||||
static const int FRAME_STEP_DELAY = 30;
|
||||
static int holdFrameStepDelay = 1;
|
||||
static int holdFrameStepDelayCount = 0;
|
||||
static bool holdFrameStep = false;
|
||||
|
||||
if (IsHotkey(HK_FRAME_ADVANCE_DECREASE_SPEED))
|
||||
{
|
||||
++holdFrameStepDelay;
|
||||
if (holdFrameStepDelay > MAX_FRAME_SKIP_DELAY)
|
||||
holdFrameStepDelay = MAX_FRAME_SKIP_DELAY;
|
||||
}
|
||||
else if (IsHotkey(HK_FRAME_ADVANCE_INCREASE_SPEED))
|
||||
{
|
||||
--holdFrameStepDelay;
|
||||
if (holdFrameStepDelay < 0)
|
||||
holdFrameStepDelay = 0;
|
||||
}
|
||||
else if (IsHotkey(HK_FRAME_ADVANCE_RESET_SPEED))
|
||||
{
|
||||
holdFrameStepDelay = 1;
|
||||
}
|
||||
else if (IsHotkey(HK_FRAME_ADVANCE, true))
|
||||
{
|
||||
if (holdFrameStepDelayCount < holdFrameStepDelay && holdFrameStep)
|
||||
++holdFrameStepDelayCount;
|
||||
|
||||
if ((frameStepCount == 0 || frameStepCount == FRAME_STEP_DELAY) && !holdFrameStep)
|
||||
{
|
||||
wxCommandEvent evt;
|
||||
evt.SetId(IDM_FRAMESTEP);
|
||||
CFrame::OnFrameStep(evt);
|
||||
if (holdFrameStepDelay > 0 && frameStepCount == 0)
|
||||
holdFrameStep = true;
|
||||
}
|
||||
|
||||
if (frameStepCount < FRAME_STEP_DELAY)
|
||||
++frameStepCount;
|
||||
|
||||
if (frameStepCount == FRAME_STEP_DELAY && holdFrameStep && holdFrameStepDelayCount >= holdFrameStepDelay)
|
||||
{
|
||||
holdFrameStep = false;
|
||||
holdFrameStepDelayCount = 0;
|
||||
}
|
||||
}
|
||||
else if (frameStepCount > 0)
|
||||
{
|
||||
// Reset values of frame advance to default
|
||||
frameStepCount = 0;
|
||||
holdFrameStep = false;
|
||||
holdFrameStepDelayCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -211,6 +211,7 @@ private:
|
||||
wxAuiNotebook * GetNotebookFromId(u32 NBId);
|
||||
int GetNotebookCount();
|
||||
wxAuiNotebook *CreateEmptyNotebook();
|
||||
void HandleFrameSkipHotkeys();
|
||||
|
||||
// Perspectives
|
||||
void AddRemoveBlankPage();
|
||||
|
@@ -462,8 +462,8 @@ wxString CFrame::GetMenuLabel(int Id)
|
||||
case HK_LOAD_STATE_SLOT_8:
|
||||
case HK_LOAD_STATE_SLOT_9:
|
||||
case HK_LOAD_STATE_SLOT_10:
|
||||
Label = wxString::Format(_("Slot %i"),
|
||||
Id - HK_LOAD_STATE_SLOT_1 + 1);
|
||||
Label = wxString::Format(_("Slot %i - %s"),
|
||||
Id - HK_LOAD_STATE_SLOT_1 + 1, State::GetInfoStringOfSlot(Id - HK_LOAD_STATE_SLOT_1 + 1).c_str());
|
||||
break;
|
||||
|
||||
case HK_SAVE_STATE_SLOT_1:
|
||||
@@ -476,8 +476,8 @@ wxString CFrame::GetMenuLabel(int Id)
|
||||
case HK_SAVE_STATE_SLOT_8:
|
||||
case HK_SAVE_STATE_SLOT_9:
|
||||
case HK_SAVE_STATE_SLOT_10:
|
||||
Label = wxString::Format(_("Slot %i"),
|
||||
Id - HK_SAVE_STATE_SLOT_1 + 1);
|
||||
Label = wxString::Format(_("Slot %i - %s"),
|
||||
Id - HK_SAVE_STATE_SLOT_1 + 1, State::GetInfoStringOfSlot(Id - HK_SAVE_STATE_SLOT_1 + 1).c_str());
|
||||
break;
|
||||
case HK_SAVE_STATE_FILE:
|
||||
Label = _("Save State...");
|
||||
@@ -522,7 +522,8 @@ wxString CFrame::GetMenuLabel(int Id)
|
||||
case HK_SELECT_STATE_SLOT_8:
|
||||
case HK_SELECT_STATE_SLOT_9:
|
||||
case HK_SELECT_STATE_SLOT_10:
|
||||
Label = wxString::Format(_("Select Slot %i"), Id - HK_SELECT_STATE_SLOT_1 + 1);
|
||||
Label = wxString::Format(_("Select Slot %i - %s"),
|
||||
Id - HK_SELECT_STATE_SLOT_1 + 1, State::GetInfoStringOfSlot(Id - HK_SELECT_STATE_SLOT_1 + 1).c_str());
|
||||
break;
|
||||
|
||||
|
||||
@@ -1680,7 +1681,7 @@ void CFrame::OnFrameSkip(wxCommandEvent& event)
|
||||
void CFrame::OnSelectSlot(wxCommandEvent& event)
|
||||
{
|
||||
g_saveSlot = event.GetId() - IDM_SELECT_SLOT_1 + 1;
|
||||
Core::DisplayMessage(StringFromFormat("Selected slot %d", g_saveSlot), 1000);
|
||||
Core::DisplayMessage(StringFromFormat("Selected slot %d - %s", g_saveSlot, State::GetInfoStringOfSlot(g_saveSlot).c_str()), 2500);
|
||||
}
|
||||
|
||||
void CFrame::OnLoadCurrentSlot(wxCommandEvent& event)
|
||||
|
@@ -1080,6 +1080,9 @@ void CGameListCtrl::CompressSelection(bool _compress)
|
||||
|
||||
if (!iso->IsCompressed() && _compress)
|
||||
{
|
||||
if (iso->GetPlatform() == DiscIO::IVolume::WII_DISC && !WiiCompressWarning())
|
||||
return;
|
||||
|
||||
std::string FileName, FileExt;
|
||||
SplitPath(iso->GetFileName(), nullptr, &FileName, &FileExt);
|
||||
m_currentFilename = FileName;
|
||||
@@ -1093,7 +1096,7 @@ void CGameListCtrl::CompressSelection(bool _compress)
|
||||
if (File::Exists(OutputFileName) &&
|
||||
wxMessageBox(
|
||||
wxString::Format(_("The file %s already exists.\nDo you wish to replace it?"),
|
||||
StrToWxStr(OutputFileName)),
|
||||
StrToWxStr(OutputFileName)),
|
||||
_("Confirm File Overwrite"),
|
||||
wxYES_NO) == wxNO)
|
||||
continue;
|
||||
@@ -1121,7 +1124,7 @@ void CGameListCtrl::CompressSelection(bool _compress)
|
||||
if (File::Exists(OutputFileName) &&
|
||||
wxMessageBox(
|
||||
wxString::Format(_("The file %s already exists.\nDo you wish to replace it?"),
|
||||
StrToWxStr(OutputFileName)),
|
||||
StrToWxStr(OutputFileName)),
|
||||
_("Confirm File Overwrite"),
|
||||
wxYES_NO) == wxNO)
|
||||
continue;
|
||||
@@ -1178,6 +1181,9 @@ void CGameListCtrl::OnCompressISO(wxCommandEvent& WXUNUSED (event))
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iso->GetPlatform() == DiscIO::IVolume::WII_DISC && !WiiCompressWarning())
|
||||
return;
|
||||
|
||||
path = wxFileSelector(
|
||||
_("Save compressed GCM/ISO"),
|
||||
StrToWxStr(FilePath),
|
||||
@@ -1292,3 +1298,10 @@ void CGameListCtrl::UnselectAll()
|
||||
SetItemState(i, 0, wxLIST_STATE_SELECTED);
|
||||
}
|
||||
}
|
||||
bool CGameListCtrl::WiiCompressWarning()
|
||||
{
|
||||
return wxMessageBox(
|
||||
_("Compressing a Wii disc image will irreversibly change the compressed copy by removing padding data. Your disc image will still work. Continue?"),
|
||||
_("Warning"),
|
||||
wxYES_NO) == wxYES;
|
||||
}
|
||||
|
@@ -107,4 +107,5 @@ private:
|
||||
static size_t m_numberItem;
|
||||
static bool CompressCB(const std::string& text, float percent, void* arg);
|
||||
static bool MultiCompressCB(const std::string& text, float percent, void* arg);
|
||||
static bool WiiCompressWarning();
|
||||
};
|
||||
|
@@ -108,7 +108,7 @@ bool DolphinApp::Initialize(int& c, wxChar **v)
|
||||
|
||||
bool DolphinApp::OnInit()
|
||||
{
|
||||
if (!wxApp::OnInit() || DolphinEmulatorDotComTextFileExists())
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
Bind(wxEVT_QUERY_END_SESSION, &DolphinApp::OnEndSession, this);
|
||||
@@ -269,23 +269,6 @@ void DolphinApp::MacOpenFile(const wxString& fileName)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool DolphinApp::DolphinEmulatorDotComTextFileExists()
|
||||
{
|
||||
if (!File::Exists("www.dolphin-emulator.com.txt"))
|
||||
return false;
|
||||
|
||||
File::Delete("www.dolphin-emulator.com.txt");
|
||||
wxMessageDialog dlg(nullptr, _(
|
||||
"This version of Dolphin was downloaded from a website stealing money from developers of the emulator. Please "
|
||||
"download Dolphin from the official website instead: https://dolphin-emu.org/"),
|
||||
_("Unofficial version detected"), wxOK | wxICON_WARNING);
|
||||
dlg.ShowModal();
|
||||
|
||||
wxLaunchDefaultBrowser("https://dolphin-emu.org/?ref=badver");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DolphinApp::AfterInit()
|
||||
{
|
||||
if (!m_batch_mode)
|
||||
|
@@ -33,7 +33,6 @@ private:
|
||||
void OnEndSession(wxCloseEvent& event);
|
||||
void InitLanguageSupport();
|
||||
void AfterInit();
|
||||
static bool DolphinEmulatorDotComTextFileExists();
|
||||
|
||||
bool m_batch_mode = false;
|
||||
bool m_confirm_stop = false;
|
||||
|
@@ -129,7 +129,6 @@ static wxString log_fps_to_file_desc = _("Log the number of frames rendered per
|
||||
static wxString show_input_display_desc = _("Display the inputs read by the emulator.\n\nIf unsure, leave this unchecked.");
|
||||
static wxString show_stats_desc = _("Show various statistics.\n\nIf unsure, leave this unchecked.");
|
||||
static wxString texfmt_desc = _("Modify textures to show the format they're encoded in. Needs an emulation reset in most cases.\n\nIf unsure, leave this unchecked.");
|
||||
static wxString efb_copy_regions_desc = _("[BROKEN]\nHighlight regions the EFB was copied from.\n\nIf unsure, leave this unchecked.");
|
||||
static wxString xfb_desc = _("Disable any XFB emulation.\nSpeeds up emulation a lot but causes heavy glitches in many games which rely on them (especially homebrew applications).\n\nIf unsure, leave this checked.");
|
||||
static wxString xfb_virtual_desc = _("Emulate XFBs using GPU texture objects.\nFixes many games which don't work without XFB emulation while not being as slow as real XFB emulation. However, it may still fail for a lot of other games (especially homebrew applications).\n\nIf unsure, leave this checked.");
|
||||
static wxString xfb_real_desc = _("Emulate XFBs accurately.\nSlows down emulation a lot and prohibits high-resolution rendering but is necessary to emulate a number of games properly.\n\nIf unsure, check virtual XFB emulation instead.");
|
||||
@@ -680,7 +679,6 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
|
||||
wxGridSizer* const szr_debug = new wxGridSizer(2, 5, 5);
|
||||
|
||||
szr_debug->Add(CreateCheckBox(page_advanced, _("Enable Wireframe"), (wireframe_desc), vconfig.bWireFrame));
|
||||
szr_debug->Add(CreateCheckBox(page_advanced, _("Show EFB Copy Regions"), (efb_copy_regions_desc), vconfig.bShowEFBCopyRegions));
|
||||
szr_debug->Add(CreateCheckBox(page_advanced, _("Show Statistics"), (show_stats_desc), vconfig.bOverlayStats));
|
||||
szr_debug->Add(CreateCheckBox(page_advanced, _("Texture Format Overlay"), (texfmt_desc), vconfig.bTexFmtOverlayEnable));
|
||||
|
||||
|
@@ -42,6 +42,10 @@ if(LIBEVDEV_FOUND AND LIBUDEV_FOUND)
|
||||
set(LIBS ${LIBS} ${LIBEVDEV_LIBRARY} ${LIBUDEV_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
set(SRCS ${SRCS} ControllerInterface/Pipes/Pipes.cpp)
|
||||
endif()
|
||||
|
||||
if(SDL_FOUND OR SDL2_FOUND)
|
||||
set(SRCS ${SRCS} ControllerInterface/SDL/SDL.cpp)
|
||||
if (SDL2_FOUND)
|
||||
|
@@ -29,6 +29,9 @@
|
||||
#ifdef CIFACE_USE_EVDEV
|
||||
#include "InputCommon/ControllerInterface/evdev/evdev.h"
|
||||
#endif
|
||||
#ifdef CIFACE_USE_PIPES
|
||||
#include "InputCommon/ControllerInterface/Pipes/Pipes.h"
|
||||
#endif
|
||||
|
||||
using namespace ciface::ExpressionParser;
|
||||
|
||||
@@ -75,6 +78,9 @@ void ControllerInterface::Initialize(void* const hwnd)
|
||||
#ifdef CIFACE_USE_EVDEV
|
||||
ciface::evdev::Init(m_devices);
|
||||
#endif
|
||||
#ifdef CIFACE_USE_PIPES
|
||||
ciface::Pipes::Init(m_devices);
|
||||
#endif
|
||||
|
||||
m_is_init = true;
|
||||
}
|
||||
|
@@ -38,6 +38,9 @@
|
||||
#if defined(HAVE_LIBEVDEV) && defined(HAVE_LIBUDEV)
|
||||
#define CIFACE_USE_EVDEV
|
||||
#endif
|
||||
#if defined(USE_PIPES)
|
||||
#define CIFACE_USE_PIPES
|
||||
#endif
|
||||
|
||||
//
|
||||
// ControllerInterface
|
||||
|
178
Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp
Normal file
178
Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
// Copyright 2015 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "InputCommon/ControllerInterface/Pipes/Pipes.h"
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace Pipes
|
||||
{
|
||||
|
||||
static const std::array<std::string, 12> s_button_tokens
|
||||
{{
|
||||
"A",
|
||||
"B",
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"START",
|
||||
"L",
|
||||
"R",
|
||||
"D_UP",
|
||||
"D_DOWN",
|
||||
"D_LEFT",
|
||||
"D_RIGHT"
|
||||
}};
|
||||
|
||||
static const std::array<std::string, 2> s_shoulder_tokens
|
||||
{{
|
||||
"L",
|
||||
"R"
|
||||
}};
|
||||
|
||||
static const std::array<std::string, 2> s_axis_tokens
|
||||
{{
|
||||
"MAIN",
|
||||
"C"
|
||||
}};
|
||||
|
||||
void Init(std::vector<Core::Device*>& devices)
|
||||
{
|
||||
// Search the Pipes directory for files that we can open in read-only,
|
||||
// non-blocking mode. The device name is the virtual name of the file.
|
||||
File::FSTEntry fst;
|
||||
int found = 0;
|
||||
std::string dir_path = File::GetUserPath(D_PIPES_IDX);
|
||||
if (!File::Exists(dir_path))
|
||||
return;
|
||||
fst = File::ScanDirectoryTree(dir_path, false);
|
||||
if (!fst.isDirectory)
|
||||
return;
|
||||
for (unsigned int i = 0; i < fst.size; ++i)
|
||||
{
|
||||
const File::FSTEntry& child = fst.children[i];
|
||||
if (child.isDirectory)
|
||||
continue;
|
||||
int fd = open(child.physicalName.c_str(), O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
continue;
|
||||
devices.push_back(new PipeDevice(fd, child.virtualName, found++));
|
||||
}
|
||||
}
|
||||
|
||||
PipeDevice::PipeDevice(int fd, const std::string& name, int id)
|
||||
: m_fd(fd), m_name(name), m_id(id)
|
||||
{
|
||||
for (const auto& tok : s_button_tokens)
|
||||
{
|
||||
PipeInput* btn = new PipeInput("Button " + tok);
|
||||
AddInput(btn);
|
||||
m_buttons[tok] = btn;
|
||||
}
|
||||
for (const auto& tok : s_shoulder_tokens)
|
||||
{
|
||||
AddAxis(tok, 0.0);
|
||||
}
|
||||
for (const auto& tok : s_axis_tokens)
|
||||
{
|
||||
AddAxis(tok + " X", 0.5);
|
||||
AddAxis(tok + " Y", 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
PipeDevice::~PipeDevice()
|
||||
{
|
||||
close(m_fd);
|
||||
}
|
||||
|
||||
void PipeDevice::UpdateInput()
|
||||
{
|
||||
// Read any pending characters off the pipe. If we hit a newline,
|
||||
// then dequeue a command off the front of m_buf and parse it.
|
||||
char buf[32];
|
||||
ssize_t bytes_read = read(m_fd, buf, sizeof buf);
|
||||
while (bytes_read > 0)
|
||||
{
|
||||
m_buf.append(buf, bytes_read);
|
||||
bytes_read = read(m_fd, buf, sizeof buf);
|
||||
}
|
||||
std::size_t newline = m_buf.find("\n");
|
||||
while (newline != std::string::npos)
|
||||
{
|
||||
std::string command = m_buf.substr(0, newline);
|
||||
ParseCommand(command);
|
||||
m_buf.erase(0, newline + 1);
|
||||
newline = m_buf.find("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void PipeDevice::AddAxis(const std::string& name, double value)
|
||||
{
|
||||
// Dolphin uses separate axes for left/right, which complicates things.
|
||||
PipeInput* ax_hi = new PipeInput("Axis " + name + " +");
|
||||
ax_hi->SetState(value);
|
||||
PipeInput* ax_lo = new PipeInput("Axis " + name + " -");
|
||||
ax_lo->SetState(value);
|
||||
m_axes[name + " +"] = ax_hi;
|
||||
m_axes[name + " -"] = ax_lo;
|
||||
AddAnalogInputs(ax_lo, ax_hi);
|
||||
}
|
||||
|
||||
void PipeDevice::SetAxis(const std::string& entry, double value)
|
||||
{
|
||||
value = MathUtil::Clamp(value, 0.0, 1.0);
|
||||
double hi = std::max(0.0, value - 0.5) * 2.0;
|
||||
double lo = (0.5 - std::min(0.5, value)) * 2.0;
|
||||
auto search_hi = m_axes.find(entry + " +");
|
||||
if (search_hi != m_axes.end())
|
||||
search_hi->second->SetState(hi);
|
||||
auto search_lo = m_axes.find(entry + " -");
|
||||
if (search_lo != m_axes.end())
|
||||
search_lo->second->SetState(lo);
|
||||
}
|
||||
|
||||
void PipeDevice::ParseCommand(const std::string& command)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
SplitString(command, ' ', tokens);
|
||||
if (tokens.size() < 2 || tokens.size() > 4)
|
||||
return;
|
||||
if (tokens[0] == "PRESS" || tokens[0] == "RELEASE")
|
||||
{
|
||||
auto search = m_buttons.find(tokens[1]);
|
||||
if (search != m_buttons.end())
|
||||
search->second->SetState(tokens[0] == "PRESS" ? 1.0 : 0.0);
|
||||
}
|
||||
else if (tokens[0] == "SET")
|
||||
{
|
||||
if (tokens.size() == 3)
|
||||
{
|
||||
double value = strtod(tokens[2].c_str(), nullptr);
|
||||
SetAxis(tokens[1], (value / 2.0) + 0.5);
|
||||
}
|
||||
else if (tokens.size() == 4)
|
||||
{
|
||||
double x = strtod(tokens[2].c_str(), nullptr);
|
||||
double y = strtod(tokens[3].c_str(), nullptr);
|
||||
SetAxis(tokens[1] + " X", x);
|
||||
SetAxis(tokens[1] + " Y", y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
65
Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h
Normal file
65
Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright 2015 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "InputCommon/ControllerInterface/Device.h"
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace Pipes
|
||||
{
|
||||
// To create a piped controller input, create a named pipe in the
|
||||
// Pipes directory and write commands out to it. Commands are separated
|
||||
// by a newline character, with spaces separating command tokens.
|
||||
// Command syntax is as follows, where curly brackets are one-of and square
|
||||
// brackets are inclusive numeric ranges. Cases are sensitive. Numeric inputs
|
||||
// are clamped to [0, 1] and otherwise invalid commands are discarded.
|
||||
// {PRESS, RELEASE} {A, B, X, Y, Z, START, L, R, D_UP, D_DOWN, D_LEFT, D_RIGHT}
|
||||
// SET {L, R} [0, 1]
|
||||
// SET {MAIN, C} [0, 1] [0, 1]
|
||||
|
||||
void Init(std::vector<Core::Device*>& devices);
|
||||
|
||||
class PipeDevice : public Core::Device
|
||||
{
|
||||
public:
|
||||
PipeDevice(int fd, const std::string& name, int id);
|
||||
~PipeDevice();
|
||||
|
||||
void UpdateInput() override;
|
||||
std::string GetName() const override { return m_name; }
|
||||
int GetId() const override { return m_id; }
|
||||
std::string GetSource() const override { return "Pipe"; }
|
||||
|
||||
private:
|
||||
class PipeInput : public Input
|
||||
{
|
||||
public:
|
||||
PipeInput(const std::string& name) : m_name(name), m_state(0.0) {}
|
||||
std::string GetName() const override { return m_name; }
|
||||
ControlState GetState() const override { return m_state; }
|
||||
void SetState(ControlState state) { m_state = state; }
|
||||
private:
|
||||
const std::string m_name;
|
||||
ControlState m_state;
|
||||
};
|
||||
|
||||
void AddAxis(const std::string& name, double value);
|
||||
void ParseCommand(const std::string& command);
|
||||
void SetAxis(const std::string& entry, double value);
|
||||
|
||||
const int m_fd;
|
||||
const std::string m_name;
|
||||
const int m_id;
|
||||
std::string m_buf;
|
||||
std::map<std::string, PipeInput*> m_buttons;
|
||||
std::map<std::string, PipeInput*> m_axes;
|
||||
};
|
||||
}
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <X11/XKBlib.h>
|
||||
|
||||
|
@@ -943,7 +943,7 @@ void CSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text
|
||||
|
||||
HRESULT hr;
|
||||
u32 numBlocksY = texture_entry->NumBlocksY();
|
||||
u32 cacheLinesPerRow = texture_entry->CacheLinesPerRow();
|
||||
u32 cacheLinesPerRow = texture_entry->BytesPerRow() / 32;
|
||||
if ((texture_entry->format & 0xF) == 0x6 && texture_entry->format != GX_TF_RGBA8)
|
||||
cacheLinesPerRow *= 2;
|
||||
// Reset API
|
||||
@@ -1020,7 +1020,7 @@ void CSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text
|
||||
if (hr == S_OK)
|
||||
{
|
||||
u8* src = (u8*)map.pData;
|
||||
u32 readStride = std::min(texture_entry->CacheLinesPerRow() * 32, map.RowPitch);
|
||||
u32 readStride = std::min(texture_entry->BytesPerRow(), map.RowPitch);
|
||||
for (u32 y = 0; y < numBlocksY; ++y)
|
||||
{
|
||||
memcpy(dst, src, readStride);
|
||||
|
@@ -20,7 +20,7 @@ public:
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void Encode(u8* dst, const TextureCache::TCacheEntryBase *texture_entry,
|
||||
void Encode(u8* dst, const TextureCacheBase::TCacheEntryBase *texture_entry,
|
||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf) override;
|
||||
private:
|
||||
|
@@ -1019,7 +1019,7 @@ void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text
|
||||
|
||||
HRESULT hr;
|
||||
u32 numBlocksY = texture_entry->NumBlocksY();
|
||||
u32 cacheLinesPerRow = texture_entry->CacheLinesPerRow();
|
||||
u32 cacheLinesPerRow = texture_entry->BytesPerRow() / 32;
|
||||
if ((texture_entry->format & 0xF) == 0x6 && texture_entry->format != GX_TF_RGBA8)
|
||||
cacheLinesPerRow *= 2;
|
||||
// Reset API
|
||||
@@ -1117,7 +1117,7 @@ void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text
|
||||
CHECK(SUCCEEDED(hr), "map staging buffer");
|
||||
|
||||
u8* src = (u8*)map.pData;
|
||||
u32 readStride = std::min(texture_entry->CacheLinesPerRow() * 32, map.RowPitch);
|
||||
u32 readStride = std::min(texture_entry->BytesPerRow(), map.RowPitch);
|
||||
for (u32 y = 0; y < numBlocksY; ++y)
|
||||
{
|
||||
memcpy(dst, src, readStride);
|
||||
|
@@ -20,7 +20,7 @@ namespace DX11
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void Encode(u8* dst, const TextureCache::TCacheEntryBase *texture_entry,
|
||||
void Encode(u8* dst, const TextureCacheBase::TCacheEntryBase *texture_entry,
|
||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf) override;
|
||||
|
||||
|
@@ -903,11 +903,11 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
|
||||
OSD::DrawMessages();
|
||||
D3D::EndFrame();
|
||||
|
||||
TextureCache::Cleanup(frameCount);
|
||||
TextureCacheBase::Cleanup(frameCount);
|
||||
|
||||
// Enable configuration changes
|
||||
UpdateActiveConfig();
|
||||
TextureCache::OnConfigChanged(g_ActiveConfig);
|
||||
TextureCacheBase::OnConfigChanged(g_ActiveConfig);
|
||||
|
||||
SetWindowSize(fbStride, fbHeight);
|
||||
|
||||
|
@@ -10,7 +10,7 @@
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class TextureCache : public ::TextureCache
|
||||
class TextureCache : public ::TextureCacheBase
|
||||
{
|
||||
public:
|
||||
TextureCache();
|
||||
|
@@ -116,7 +116,7 @@ namespace DX11
|
||||
|
||||
virtual void Init() = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
virtual void Encode(u8* dst, const TextureCache::TCacheEntryBase *texture_entry,
|
||||
virtual void Encode(u8* dst, const TextureCacheBase::TCacheEntryBase *texture_entry,
|
||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf) = 0;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class VertexManager : public ::VertexManager
|
||||
class VertexManager : public ::VertexManagerBase
|
||||
{
|
||||
public:
|
||||
VertexManager();
|
||||
@@ -39,8 +39,8 @@ private:
|
||||
u32 m_bufferCursor;
|
||||
enum { MAX_BUFFER_COUNT = 2 };
|
||||
// TODO: Find sensible values for these two
|
||||
const u32 MAX_IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * sizeof(u16);
|
||||
const u32 MAX_VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE;
|
||||
const u32 MAX_IBUFFER_SIZE = VertexManagerBase::MAXIBUFFERSIZE * sizeof(u16);
|
||||
const u32 MAX_VBUFFER_SIZE = VertexManagerBase::MAXVBUFFERSIZE;
|
||||
const u32 MAX_BUFFER_SIZE = MAX_IBUFFER_SIZE + MAX_VBUFFER_SIZE;
|
||||
D3D::BufferPtr m_buffers[MAX_BUFFER_COUNT];
|
||||
|
||||
|
@@ -88,7 +88,7 @@ void TeardownDeviceObjects()
|
||||
delete g_framebuffer_manager;
|
||||
((PerfQuery*)g_perf_query)->DestroyDeviceObjects();
|
||||
D3D::font.Shutdown();
|
||||
TextureCache::Invalidate();
|
||||
TextureCacheBase::Invalidate();
|
||||
VertexLoaderManager::Shutdown();
|
||||
VertexShaderCache::Shutdown();
|
||||
PixelShaderCache::Shutdown();
|
||||
@@ -840,12 +840,12 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_FRAME, true);
|
||||
|
||||
TextureCache::Cleanup(frameCount);
|
||||
TextureCacheBase::Cleanup(frameCount);
|
||||
// Flip/present backbuffer to frontbuffer here
|
||||
D3D::Present();
|
||||
// Enable configuration changes
|
||||
UpdateActiveConfig();
|
||||
TextureCache::OnConfigChanged(g_ActiveConfig);
|
||||
TextureCacheBase::OnConfigChanged(g_ActiveConfig);
|
||||
|
||||
SetWindowSize(fbStride, fbHeight);
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class TextureCache : public ::TextureCache
|
||||
class TextureCache : public ::TextureCacheBase
|
||||
{
|
||||
public:
|
||||
TextureCache();
|
||||
|
@@ -399,7 +399,7 @@ void EncodeToRamFromTexture(u8 *dest_ptr, const TextureCache::TCacheEntryBase *t
|
||||
if ((texture_entry->format & 0x0f) == 6)
|
||||
cacheBytes = 64;
|
||||
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(texture_entry->format);
|
||||
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, (expandedWidth / samples) * 4, expandedHeight, texture_entry->CacheLinesPerRow() * 32, readStride, bScaleByHalf > 0, 1.0f);
|
||||
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, (expandedWidth / samples) * 4, expandedHeight, texture_entry->BytesPerRow(), readStride, bScaleByHalf > 0, 1.0f);
|
||||
}
|
||||
|
||||
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, u8* destAddr, u32 dstwidth, u32 dstStride, u32 dstHeight, float Gamma)
|
||||
|
@@ -28,7 +28,7 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
|
||||
|
||||
// returns size of the encoded data (in bytes)
|
||||
void EncodeToRamFromTexture(u8 *dest_ptr, const TextureCache::TCacheEntryBase *texture_entry, u32 SourceW, u32 SourceH,
|
||||
void EncodeToRamFromTexture(u8 *dest_ptr, const TextureCacheBase::TCacheEntryBase *texture_entry, u32 SourceW, u32 SourceH,
|
||||
LPDIRECT3DTEXTURE9 source_texture, bool bFromZBuffer, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
|
||||
|
@@ -27,8 +27,8 @@ extern NativeVertexFormat *g_nativeVertexFmt;
|
||||
namespace DX9
|
||||
{
|
||||
// This are the initially requeted size for the buffers expresed in elements
|
||||
const u32 MAX_IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * sizeof(u16) * 8;
|
||||
const u32 MAX_VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE;
|
||||
const u32 MAX_IBUFFER_SIZE = VertexManagerBase::MAXIBUFFERSIZE * sizeof(u16) * 8;
|
||||
const u32 MAX_VBUFFER_SIZE = VertexManagerBase::MAXVBUFFERSIZE;
|
||||
const u32 MAX_VBUFFER_COUNT = 2;
|
||||
// Register count for line/point offset storage
|
||||
const u32 LINE_PT_OFFSETS_PARAMS_LEN = C_VENVCONST_END - C_PLOFFSETPARAMS;
|
||||
|
@@ -14,7 +14,7 @@
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class VertexManager : public ::VertexManager
|
||||
class VertexManager : public ::VertexManagerBase
|
||||
{
|
||||
public:
|
||||
VertexManager();
|
||||
|
@@ -369,9 +369,6 @@ GLuint ProgramShaderCache::CompileSingleShader(GLuint type, const char* code, co
|
||||
GLsizei length = 0;
|
||||
glGetShaderiv(result, GL_INFO_LOG_LENGTH, &length);
|
||||
|
||||
if (DriverDetails::HasBug(DriverDetails::BUG_BROKENINFOLOG))
|
||||
length = 1024;
|
||||
|
||||
if (compileStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
|
||||
{
|
||||
GLsizei charsWritten;
|
||||
|
@@ -753,128 +753,6 @@ void Renderer::Init()
|
||||
glVertexAttribPointer(SHADER_COLOR0_ATTRIB, 3, GL_FLOAT, 0, sizeof(GLfloat)*5, (GLfloat*)nullptr+2);
|
||||
}
|
||||
|
||||
// Create On-Screen-Messages
|
||||
void Renderer::ShowEfbCopyRegions()
|
||||
{
|
||||
if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL && g_ActiveConfig.bShowEFBCopyRegions)
|
||||
{
|
||||
// Set Line Size
|
||||
glLineWidth(3.0f);
|
||||
|
||||
// 2*Coords + 3*Color
|
||||
GLsizeiptr length = stats.efb_regions.size() * sizeof(GLfloat) * (2 + 3) * 2 * 6;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_ShowEFBCopyRegions_VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, length, nullptr, GL_STREAM_DRAW);
|
||||
GLfloat *Vertices = (GLfloat*)glMapBufferRange(GL_ARRAY_BUFFER, 0, length, GL_MAP_WRITE_BIT);
|
||||
|
||||
// Draw EFB copy regions rectangles
|
||||
int a = 0;
|
||||
GLfloat color[3] = {0.0f, 1.0f, 1.0f};
|
||||
|
||||
for (const EFBRectangle& rect : stats.efb_regions)
|
||||
{
|
||||
GLfloat halfWidth = EFB_WIDTH / 2.0f;
|
||||
GLfloat halfHeight = EFB_HEIGHT / 2.0f;
|
||||
GLfloat x = (GLfloat) -1.0f + ((GLfloat)rect.left / halfWidth);
|
||||
GLfloat y = (GLfloat) 1.0f - ((GLfloat)rect.top / halfHeight);
|
||||
GLfloat x2 = (GLfloat) -1.0f + ((GLfloat)rect.right / halfWidth);
|
||||
GLfloat y2 = (GLfloat) 1.0f - ((GLfloat)rect.bottom / halfHeight);
|
||||
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
// TO DO: build something nicer here
|
||||
GLfloat temp = color[0];
|
||||
color[0] = color[1];
|
||||
color[1] = color[2];
|
||||
color[2] = temp;
|
||||
}
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
|
||||
s_ShowEFBCopyRegions.Bind();
|
||||
glBindVertexArray(s_ShowEFBCopyRegions_VAO);
|
||||
GLsizei count = static_cast<GLsizei>(stats.efb_regions.size() * 2*6);
|
||||
glDrawArrays(GL_LINES, 0, count);
|
||||
|
||||
// Clear stored regions
|
||||
stats.efb_regions.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
|
||||
{
|
||||
const int nBackbufferWidth = (int)GLInterface->GetBackBufferWidth();
|
||||
@@ -1706,7 +1584,6 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
|
||||
// Reset viewport for drawing text
|
||||
glViewport(0, 0, GLInterface->GetBackBufferWidth(), GLInterface->GetBackBufferHeight());
|
||||
|
||||
ShowEfbCopyRegions();
|
||||
DrawDebugText();
|
||||
|
||||
// Do our OSD callbacks
|
||||
|
@@ -86,8 +86,7 @@ public:
|
||||
void ApplyState(bool bUseDstAlpha) override {}
|
||||
void RestoreState() override {}
|
||||
|
||||
void RenderText(const std::string& text, int left, int top, u32 color) override;
|
||||
void ShowEfbCopyRegions();
|
||||
void RenderText(const std::string& text, int left, int top, u32 color) override;
|
||||
void FlipImageData(u8 *data, int w, int h, int pixel_width = 3);
|
||||
|
||||
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;
|
||||
|
@@ -14,7 +14,7 @@
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
class TextureCache : public ::TextureCache
|
||||
class TextureCache : public ::TextureCacheBase
|
||||
{
|
||||
public:
|
||||
TextureCache();
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
static void SetStage();
|
||||
|
||||
private:
|
||||
struct TCacheEntry : TCacheEntryBase
|
||||
struct TCacheEntry : TextureCacheBase::TCacheEntryBase
|
||||
{
|
||||
GLuint texture;
|
||||
GLuint nrm_texture;
|
||||
|
@@ -280,7 +280,7 @@ void EncodeToRamFromTexture(u8 *dest_ptr, const TextureCache::TCacheEntryBase *t
|
||||
source.left, source.top, texture_entry->native_width, bScaleByHalf ? 2 : 1);
|
||||
|
||||
EncodeToRamUsingShader(source_texture,
|
||||
dest_ptr, texture_entry->CacheLinesPerRow() * 32, texture_entry->NumBlocksY(),
|
||||
dest_ptr, texture_entry->BytesPerRow(), texture_entry->NumBlocksY(),
|
||||
texture_entry->memory_stride, bScaleByHalf > 0 && !bFromZBuffer);
|
||||
}
|
||||
|
||||
|
@@ -25,7 +25,7 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
|
||||
|
||||
// returns size of the encoded data (in bytes)
|
||||
void EncodeToRamFromTexture(u8 *dest_ptr, const TextureCache::TCacheEntryBase *texture_entry,
|
||||
void EncodeToRamFromTexture(u8 *dest_ptr, const TextureCacheBase::TCacheEntryBase *texture_entry,
|
||||
GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ namespace OGL
|
||||
|
||||
// Handles the OpenGL details of drawing lots of vertices quickly.
|
||||
// Other functionality is moving out.
|
||||
class VertexManager : public ::VertexManager
|
||||
class VertexManager : public ::VertexManagerBase
|
||||
{
|
||||
public:
|
||||
VertexManager();
|
||||
|
@@ -27,7 +27,7 @@ namespace BPFunctions
|
||||
|
||||
void FlushPipeline()
|
||||
{
|
||||
VertexManager::Flush();
|
||||
VertexManagerBase::Flush();
|
||||
}
|
||||
|
||||
void SetGenerationMode()
|
||||
|
@@ -258,11 +258,8 @@ void BPWritten(const BPCmd& bp)
|
||||
// Check if we are to copy from the EFB or draw to the XFB
|
||||
if (PE_copy.copy_to_xfb == 0)
|
||||
{
|
||||
if (g_ActiveConfig.bShowEFBCopyRegions)
|
||||
stats.efb_regions.push_back(srcRect);
|
||||
|
||||
// bpmem.zcontrol.pixel_format to PEControl::Z24 is when the game wants to copy from ZBuffer (Zbuffer uses 24-bit Format)
|
||||
TextureCache::CopyRenderTargetToTexture(destAddr, PE_copy.tp_realFormat(), destStride,
|
||||
TextureCacheBase::CopyRenderTargetToTexture(destAddr, PE_copy.tp_realFormat(), destStride,
|
||||
bpmem.zcontrol.pixel_format, srcRect,
|
||||
!!PE_copy.intensity_fmt, !!PE_copy.half_scale);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user