Merge branch 'master' into wii-network
Conflicts: Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp
This commit is contained in:
commit
3d480c088f
|
@ -466,7 +466,7 @@ else(SDL2_FOUND)
|
|||
else(SDL_FOUND)
|
||||
# TODO: Use the prebuilt one on Windows
|
||||
message("Using static SDL from Externals")
|
||||
include_directories(Externals/SDL Externals/SDL/include)
|
||||
include_directories(Externals/SDL/SDL Externals/SDL Externals/SDL/include)
|
||||
add_subdirectory(Externals/SDL)
|
||||
endif(SDL_FOUND)
|
||||
endif(SDL2_FOUND)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# GSSE8P - Sega Soccer Slam
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
TLBHack = 0
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationIssues =
|
||||
EmulationIssues = Needs real xfb for the videos to display.
|
||||
EmulationStateId = 4
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
$Master Code
|
||||
|
@ -19,3 +19,14 @@ $SubZero Have Tons Of Cash
|
|||
0423C204 05F5E0FF
|
||||
$Volta Have Tons Of Cash
|
||||
0423CEA8 05F5E0FF
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Settings]
|
||||
UseXFB = True
|
||||
UseRealXFB = True
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# GSSJ8P - Sega Soccer Slam
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationIssues = Needs real xfb for the videos to display.
|
||||
EmulationStateId = 4
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Settings]
|
||||
UseXFB = True
|
||||
UseRealXFB = True
|
|
@ -0,0 +1,18 @@
|
|||
# GSSP70 - Sega Soccer Slam
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationIssues = Needs real xfb for the videos to display.
|
||||
EmulationStateId = 4
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Settings]
|
||||
UseXFB = True
|
||||
UseRealXFB = True
|
|
@ -0,0 +1,18 @@
|
|||
# GSSP8P - Sega Soccer Slam
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationIssues = Needs real xfb for the videos to display.
|
||||
EmulationStateId = 4
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Settings]
|
||||
UseXFB = True
|
||||
UseRealXFB = True
|
|
@ -0,0 +1,18 @@
|
|||
# GZPE70 - Zapper
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationStateId = 4
|
||||
EmulationIssues = Needs real xfb for the videos to display.
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Settings]
|
||||
UseXFB = True
|
||||
UseRealXFB = True
|
|
@ -0,0 +1,18 @@
|
|||
# GZPP70 - Zapper
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationStateId = 4
|
||||
EmulationIssues = Needs real xfb for the videos to display.
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Settings]
|
||||
UseXFB = True
|
||||
UseRealXFB = True
|
|
@ -33,8 +33,7 @@ PH_ExtraParam = 1
|
|||
|
||||
[5]
|
||||
Title = Tales of Symphonia GC
|
||||
PH_ZNear = 0.5
|
||||
PH_ZFar = 1
|
||||
PH_ZNear = 0.0002
|
||||
|
||||
|
||||
# ---------------------------------------------------
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# RH8E4F - Tomb Raider Underworld
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationStateId = 4
|
||||
EmulationIssues = Needs real Xfb for the videos to display.
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Settings]
|
||||
UseXFB = True
|
||||
UseRealXFB = True
|
|
@ -0,0 +1,18 @@
|
|||
# RH8JEL - Tomb Raider Underworld
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationStateId = 4
|
||||
EmulationIssues = Needs real Xfb for the videos to display.
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Settings]
|
||||
UseXFB = True
|
||||
UseRealXFB = True
|
|
@ -1,9 +1,18 @@
|
|||
# RH8P4F - Tomb Raider Eight
|
||||
# RH8P4F - Tomb Raider Underworld
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationStateId = 4
|
||||
EmulationIssues =
|
||||
EmulationIssues = Needs real Xfb for the videos to display.
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Settings]
|
||||
UseXFB = True
|
||||
UseRealXFB = True
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# RH8X4F - Tomb Raider Underworld
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationStateId = 4
|
||||
EmulationIssues = Needs real Xfb for the videos to display.
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Settings]
|
||||
UseXFB = True
|
||||
UseRealXFB = True
|
|
@ -0,0 +1,17 @@
|
|||
# RS5EC8 - SAMURAI WARRIORS KATANA
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationStateId = 4
|
||||
EmulationIssues =
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Hacks]
|
||||
EFBEmulateFormatChanges = True
|
|
@ -0,0 +1,17 @@
|
|||
# RS5JC8 - Sengoku Musou KATANA
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationStateId = 4
|
||||
EmulationIssues =
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Hacks]
|
||||
EFBEmulateFormatChanges = True
|
|
@ -0,0 +1,17 @@
|
|||
# RS5PC8 - SAMURAI WARRIORS KATANA
|
||||
[Core] Values set here will override the main dolphin settings.
|
||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||
EmulationStateId = 4
|
||||
EmulationIssues =
|
||||
[OnFrame] Add memory patches to be applied every frame here.
|
||||
[ActionReplay] Add action replay cheats here.
|
||||
[Video]
|
||||
ProjectionHack = 0
|
||||
PH_SZNear = 0
|
||||
PH_SZFar = 0
|
||||
PH_ExtraParam = 0
|
||||
PH_ZNear =
|
||||
PH_ZFar =
|
||||
[Gecko]
|
||||
[Video_Hacks]
|
||||
EFBEmulateFormatChanges = True
|
|
@ -7,7 +7,11 @@ CPP_FILE_LIST=$(find $SRCDIR \( -name '*.cpp' -o -name '*.h' -o -name '*.c' \) \
|
|||
xgettext -d dolphin-emu -s --keyword=_ --keyword=wxTRANSLATE --keyword=SuccessAlertT \
|
||||
--keyword=PanicAlertT --keyword=PanicYesNoT --keyword=AskYesNoT --keyword=_trans \
|
||||
--keyword=CriticalAlertT --add-comments=i18n -p ./Languages/po -o dolphin-emu.pot \
|
||||
$CPP_FILE_LIST --package-name="Dolphin Emu"
|
||||
$CPP_FILE_LIST --package-name="Dolphin Emulator"
|
||||
|
||||
sed -i "s/SOME DESCRIPTIVE TITLE\./Translation of dolphin-emu.pot to LANGUAGE/" Languages/po/dolphin-emu.pot
|
||||
sed -i "s/YEAR THE PACKAGE'S COPYRIGHT HOLDER/2003-2013/" Languages/po/dolphin-emu.pot
|
||||
sed -i "s/license as the PACKAGE package/license as the dolphin-emu package/" Languages/po/dolphin-emu.pot
|
||||
|
||||
POTFILE=./Languages/po/dolphin-emu.pot
|
||||
PO_FILES=$(find ./Languages/po -name '*.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
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
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
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
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
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
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
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
File diff suppressed because it is too large
Load Diff
|
@ -43,7 +43,8 @@ void MemArena::GrabLowMemSpace(size_t size)
|
|||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
fd = open(ram_temp_file, O_RDWR | O_CREAT, mode);
|
||||
unlink(ram_temp_file);
|
||||
ftruncate(fd, size);
|
||||
if (ftruncate(fd, size) < 0)
|
||||
ERROR_LOG(MEMMAP, "Failed to allocate low memory space");
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -117,7 +117,8 @@ void* AllocateAlignedMemory(size_t size,size_t alignment)
|
|||
void* ptr = _aligned_malloc(size,alignment);
|
||||
#else
|
||||
void* ptr = NULL;
|
||||
posix_memalign(&ptr, alignment, size);
|
||||
if (posix_memalign(&ptr, alignment, size) != 0)
|
||||
ERROR_LOG(MEMMAP, "Failed to allocate aligned memory");
|
||||
;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -69,7 +69,8 @@ std::string StringFromFormat(const char* format, ...)
|
|||
delete[] buf;
|
||||
#else
|
||||
va_start(args, format);
|
||||
vasprintf(&buf, format, args);
|
||||
if (vasprintf(&buf, format, args) < 0)
|
||||
ERROR_LOG(COMMON, "Unable to allocate memory for string");
|
||||
va_end(args);
|
||||
|
||||
std::string temp = buf;
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace BootManager
|
|||
struct ConfigCache
|
||||
{
|
||||
bool valid, bCPUThread, bSkipIdle, bEnableFPRF, bMMU, bDCBZOFF,
|
||||
bVBeam, bFastDiscSpeed, bMergeBlocks, bDSPHLE, bDisableWiimoteSpeaker, bHLE_BS2;
|
||||
bVBeam, bFastDiscSpeed, bMergeBlocks, bDSPHLE, bHLE_BS2;
|
||||
int iTLBHack, iCPUCore;
|
||||
std::string strBackend;
|
||||
};
|
||||
|
@ -98,7 +98,6 @@ bool BootCore(const std::string& _rFilename)
|
|||
config_cache.bFastDiscSpeed = StartUp.bFastDiscSpeed;
|
||||
config_cache.bMergeBlocks = StartUp.bMergeBlocks;
|
||||
config_cache.bDSPHLE = StartUp.bDSPHLE;
|
||||
config_cache.bDisableWiimoteSpeaker = StartUp.bDisableWiimoteSpeaker;
|
||||
config_cache.strBackend = StartUp.m_strVideoBackend;
|
||||
config_cache.bHLE_BS2 = StartUp.bHLE_BS2;
|
||||
|
||||
|
@ -113,7 +112,6 @@ bool BootCore(const std::string& _rFilename)
|
|||
game_ini.Get("Core", "FastDiscSpeed", &StartUp.bFastDiscSpeed, StartUp.bFastDiscSpeed);
|
||||
game_ini.Get("Core", "BlockMerging", &StartUp.bMergeBlocks, StartUp.bMergeBlocks);
|
||||
game_ini.Get("Core", "DSPHLE", &StartUp.bDSPHLE, StartUp.bDSPHLE);
|
||||
game_ini.Get("Wii", "DisableWiimoteSpeaker",&StartUp.bDisableWiimoteSpeaker, StartUp.bDisableWiimoteSpeaker);
|
||||
game_ini.Get("Core", "GFXBackend", &StartUp.m_strVideoBackend, StartUp.m_strVideoBackend.c_str());
|
||||
game_ini.Get("Core", "CPUCore", &StartUp.iCPUCore, StartUp.iCPUCore);
|
||||
game_ini.Get("Core", "HLE_BS2", &StartUp.bHLE_BS2, StartUp.bHLE_BS2);
|
||||
|
@ -173,7 +171,6 @@ void Stop()
|
|||
StartUp.bFastDiscSpeed = config_cache.bFastDiscSpeed;
|
||||
StartUp.bMergeBlocks = config_cache.bMergeBlocks;
|
||||
StartUp.bDSPHLE = config_cache.bDSPHLE;
|
||||
StartUp.bDisableWiimoteSpeaker = config_cache.bDisableWiimoteSpeaker;
|
||||
StartUp.m_strVideoBackend = config_cache.strBackend;
|
||||
VideoBackend::ActivateBackend(StartUp.m_strVideoBackend);
|
||||
StartUp.bHLE_BS2 = config_cache.bHLE_BS2;
|
||||
|
|
|
@ -51,7 +51,7 @@ SCoreStartupParameter::SCoreStartupParameter()
|
|||
bRunCompareServer(false), bRunCompareClient(false),
|
||||
bMMU(false), bDCBZOFF(false), iTLBHack(0), bVBeam(false),
|
||||
bFastDiscSpeed(false),
|
||||
SelectedLanguage(0), bWii(false), bDisableWiimoteSpeaker(false),
|
||||
SelectedLanguage(0), bWii(false),
|
||||
bConfirmStop(false), bHideCursor(false),
|
||||
bAutoHideCursor(false), bUsePanicHandlers(true), bOnScreenDisplayMessages(true),
|
||||
iRenderWindowXPos(-1), iRenderWindowYPos(-1),
|
||||
|
@ -102,8 +102,6 @@ void SCoreStartupParameter::LoadDefaults()
|
|||
bJITPairedOff = false;
|
||||
bJITSystemRegistersOff = false;
|
||||
|
||||
bDisableWiimoteSpeaker = false;
|
||||
|
||||
m_strName = "NONE";
|
||||
m_strUniqueID = "00000000";
|
||||
}
|
||||
|
|
|
@ -124,7 +124,6 @@ struct SCoreStartupParameter
|
|||
int SelectedLanguage;
|
||||
|
||||
bool bWii;
|
||||
bool bDisableWiimoteSpeaker;
|
||||
|
||||
// Interface settings
|
||||
bool bConfirmStop, bHideCursor, bAutoHideCursor, bUsePanicHandlers, bOnScreenDisplayMessages;
|
||||
|
|
|
@ -251,12 +251,11 @@ void Init()
|
|||
// Now the 1500 is a pure assumption
|
||||
// We need to figure out the real frequency though
|
||||
|
||||
// FIXME: does Wiimote Speaker support really require a different interval? (issue 4608)
|
||||
const int interval = SConfig::GetInstance().m_LocalCoreStartupParameter.
|
||||
bDisableWiimoteSpeaker ? 15000 : 4000;
|
||||
// FYI, WII_IPC_HLE_Interface::Update is also called in WII_IPCInterface::Write32
|
||||
const int freq = 1500;
|
||||
const int fields = SConfig::GetInstance().m_LocalCoreStartupParameter.
|
||||
bVBeam ? 2 : 1;
|
||||
IPC_HLE_PERIOD = GetTicksPerSecond() / (interval * fields);
|
||||
IPC_HLE_PERIOD = GetTicksPerSecond() / (freq * fields);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -221,6 +221,7 @@ void Write32(const u32 _Value, const u32 _Address)
|
|||
break;
|
||||
}
|
||||
|
||||
WII_IPC_HLE_Interface::Update();
|
||||
UpdateInterrupts();
|
||||
}
|
||||
|
||||
|
|
|
@ -184,7 +184,7 @@ int FindWiimotes(Wiimote** wm, int max_wiimotes)
|
|||
bool found = false;
|
||||
for(int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
if(wm[i] && strcmp(wm[i]->devicepath, detail_data->DevicePath) == 0)
|
||||
if(wm[i] && (wm[i]->devicepath == detail_data->DevicePath))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
|
@ -210,7 +210,7 @@ int FindWiimotes(Wiimote** wm, int max_wiimotes)
|
|||
for (; k < MAX_WIIMOTES && !(WIIMOTE_SRC_REAL & g_wiimote_sources[k] && !wm[k]); ++k);
|
||||
wm[k] = new Wiimote(k);
|
||||
wm[k]->dev_handle = dev;
|
||||
memcpy(wm[k]->devicepath, detail_data->DevicePath, 197);
|
||||
wm[k]->devicepath = detail_data->DevicePath;
|
||||
|
||||
if (!wm[k]->Connect())
|
||||
{
|
||||
|
@ -240,7 +240,7 @@ bool Wiimote::Connect()
|
|||
|
||||
if (!dev_handle)
|
||||
{
|
||||
dev_handle = CreateFile(devicepath,
|
||||
dev_handle = CreateFile(devicepath.c_str(),
|
||||
(GENERIC_READ | GENERIC_WRITE),
|
||||
(FILE_SHARE_READ | FILE_SHARE_WRITE),
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||
|
|
|
@ -181,23 +181,23 @@ bool Wiimote::Read()
|
|||
bool Wiimote::Write()
|
||||
{
|
||||
Report rpt;
|
||||
bool audio_written = false;
|
||||
|
||||
if (m_audio_reports.Pop(rpt))
|
||||
if (last_audio_report.GetTimeDifference() > 5 && m_audio_reports.Pop(rpt))
|
||||
{
|
||||
IOWrite(rpt.first, rpt.second);
|
||||
delete[] rpt.first;
|
||||
audio_written = true;
|
||||
}
|
||||
last_audio_report.Update();
|
||||
|
||||
if (m_write_reports.Pop(rpt))
|
||||
delete[] rpt.first;
|
||||
return true;
|
||||
}
|
||||
else if (m_write_reports.Pop(rpt))
|
||||
{
|
||||
IOWrite(rpt.first, rpt.second);
|
||||
delete[] rpt.first;
|
||||
return true;
|
||||
}
|
||||
|
||||
return audio_written;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the next report that should be sent
|
||||
|
@ -319,14 +319,9 @@ void Wiimote::ThreadFunc()
|
|||
while (Write()) {}
|
||||
Common::SleepCurrentThread(1);
|
||||
#else
|
||||
bool read = false;
|
||||
while (Write() || (read = true, IsOpen() && Read()))
|
||||
{
|
||||
if (m_audio_reports.Size() && !read)
|
||||
Read();
|
||||
Common::SleepCurrentThread(m_audio_reports.Size() ? 5 : 2);
|
||||
read = false;
|
||||
}
|
||||
bool const did_something = Write() || Read();
|
||||
if (!did_something)
|
||||
Common::SleepCurrentThread(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "ChunkFile.h"
|
||||
#include "Thread.h"
|
||||
#include "FifoQueue.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include "../Wiimote.h"
|
||||
#include "../WiimoteEmu/WiimoteEmu.h"
|
||||
|
@ -77,7 +78,7 @@ public:
|
|||
void Close();
|
||||
|
||||
#elif defined(_WIN32)
|
||||
char devicepath[255]; // Unique wiimote reference
|
||||
std::string devicepath; // Unique wiimote reference
|
||||
//ULONGLONG btaddr; // Bluetooth address
|
||||
HANDLE dev_handle; // HID handle
|
||||
OVERLAPPED hid_overlap; // Overlap handle
|
||||
|
@ -103,6 +104,8 @@ private:
|
|||
Common::FifoQueue<Report> m_read_reports;
|
||||
Common::FifoQueue<Report> m_write_reports;
|
||||
Common::FifoQueue<Report> m_audio_reports;
|
||||
|
||||
Common::Timer last_audio_report;
|
||||
};
|
||||
|
||||
extern std::mutex g_refresh_lock;
|
||||
|
|
|
@ -64,6 +64,8 @@ They will also generate a true or false return for UpdateInterrupts() in WII_IPC
|
|||
#include "../HW/WII_IPC.h"
|
||||
#include "../Debugger/Debugger_SymbolMap.h"
|
||||
#include "../PowerPC/PowerPC.h"
|
||||
#include "../HW/SystemTimers.h"
|
||||
#include "CoreTiming.h"
|
||||
|
||||
|
||||
namespace WII_IPC_HLE_Interface
|
||||
|
@ -87,8 +89,20 @@ static ipc_msg_queue request_queue; // ppc -> arm
|
|||
static ipc_msg_queue reply_queue; // arm -> ppc
|
||||
static std::mutex s_reply_queue;
|
||||
|
||||
static int enque_reply;
|
||||
|
||||
static u64 last_reply_time;
|
||||
|
||||
void EnqueReplyCallback(u64 userdata, int)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(s_reply_queue);
|
||||
reply_queue.push_back(userdata);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
enque_reply = CoreTiming::RegisterEvent("IPCReply", EnqueReplyCallback);
|
||||
|
||||
_dbg_assert_msg_(WII_IPC_HLE, g_DeviceMap.empty(), "DeviceMap isnt empty on init");
|
||||
CWII_IPC_HLE_Device_es::m_ContentFile = "";
|
||||
u32 i;
|
||||
|
@ -170,6 +184,7 @@ void Reset(bool _bHard)
|
|||
std::lock_guard<std::mutex> lk(s_reply_queue);
|
||||
reply_queue.clear();
|
||||
}
|
||||
last_reply_time = 0;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
|
@ -255,6 +270,7 @@ void DoState(PointerWrap &p)
|
|||
|
||||
p.Do(request_queue);
|
||||
p.Do(reply_queue);
|
||||
p.Do(last_reply_time);
|
||||
|
||||
TDeviceMap::const_iterator itr;
|
||||
|
||||
|
@ -402,18 +418,19 @@ void ExecuteCommand(u32 _Address)
|
|||
}
|
||||
else
|
||||
{
|
||||
IWII_IPC_HLE_Device* _pDevice = CreateFileIO(DeviceID, DeviceName);
|
||||
CmdSuccess = _pDevice->Open(_Address, Mode);
|
||||
pDevice = CreateFileIO(DeviceID, DeviceName);
|
||||
CmdSuccess = pDevice->Open(_Address, Mode);
|
||||
|
||||
INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)",
|
||||
_pDevice->GetDeviceName().c_str(), DeviceID, Mode);
|
||||
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
|
||||
if (Memory::Read_U32(_Address + 4) == (u32)DeviceID)
|
||||
{
|
||||
g_FdMap[DeviceID] = _pDevice;
|
||||
g_FdMap[DeviceID] = pDevice;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete _pDevice;
|
||||
delete pDevice;
|
||||
pDevice = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,7 +461,10 @@ void ExecuteCommand(u32 _Address)
|
|||
|
||||
// Don't delete hardware
|
||||
if (!pDevice->IsHardware())
|
||||
{
|
||||
delete pDevice;
|
||||
pDevice = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -523,8 +543,19 @@ void ExecuteCommand(u32 _Address)
|
|||
// IOS seems to write back the command that was responded to
|
||||
Memory::Write_U32(Command, _Address + 8);
|
||||
|
||||
// Ensure replies happen in order, fairly ugly
|
||||
// Without this, tons of games fail now that DI commads have different reply delays
|
||||
int reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0;
|
||||
|
||||
const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks();
|
||||
|
||||
if (ticks_til_last_reply > 0)
|
||||
reply_delay = ticks_til_last_reply;
|
||||
|
||||
last_reply_time = CoreTiming::GetTicks() + reply_delay;
|
||||
|
||||
// Generate a reply to the IPC command
|
||||
EnqReply(_Address);
|
||||
EnqReply(_Address, reply_delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -546,10 +577,9 @@ void EnqRequest(u32 _Address)
|
|||
}
|
||||
|
||||
// Called when IOS module has some reply
|
||||
void EnqReply(u32 _Address)
|
||||
void EnqReply(u32 _Address, int cycles_in_future)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(s_reply_queue);
|
||||
reply_queue.push_back(_Address);
|
||||
CoreTiming::ScheduleEvent(cycles_in_future, enque_reply, _Address);
|
||||
}
|
||||
|
||||
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
|
||||
|
|
|
@ -62,7 +62,7 @@ void UpdateDevices();
|
|||
void ExecuteCommand(u32 _Address);
|
||||
|
||||
void EnqRequest(u32 _Address);
|
||||
void EnqReply(u32 _Address);
|
||||
void EnqReply(u32 _Address, int cycles_in_future = 0);
|
||||
|
||||
enum ECommandType
|
||||
{
|
||||
|
|
|
@ -95,6 +95,8 @@ public:
|
|||
virtual bool IOCtlV (u32) { UNIMPLEMENTED_CMD(IOCtlV) }
|
||||
#undef UNIMPLEMENTED_CMD
|
||||
|
||||
virtual int GetCmdDelay(u32) { return 0; }
|
||||
|
||||
virtual u32 Update() { return 0; }
|
||||
|
||||
virtual bool IsHardware() { return m_Hardware; }
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "VolumeCreator.h"
|
||||
#include "Filesystem.h"
|
||||
#include "LogManager.h"
|
||||
#include "../HW/SystemTimers.h"
|
||||
|
||||
#include "../../DiscIO/Src/FileMonitor.h"
|
||||
|
||||
|
@ -460,3 +461,44 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
|
|||
// i dunno but prolly 1 is okay all the time :)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CWII_IPC_HLE_Device_di::GetCmdDelay(u32 _CommandAddress)
|
||||
{
|
||||
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
||||
u32 Command = Memory::Read_U32(BufferIn) >> 24;
|
||||
|
||||
// Hacks below
|
||||
|
||||
switch (Command)
|
||||
{
|
||||
case DVDLowRead:
|
||||
case DVDLowUnencryptedRead:
|
||||
{
|
||||
u32 const Size = Memory::Read_U32(BufferIn + 0x04);
|
||||
// Delay depends on size of read, that makes sense, right?
|
||||
// More than ~1150K "bytes / sec" hangs NSMBWii on boot.
|
||||
// Less than ~800K "bytes / sec" hangs DKCR randomly.
|
||||
return SystemTimers::GetTicksPerSecond() / 975000 * Size;
|
||||
break;
|
||||
}
|
||||
|
||||
case DVDLowClearCoverInterrupt:
|
||||
// Less than ~1/155th of a second hangs Oregon Trail at "loading wheel".
|
||||
// More than ~1/140th of a second hangs Resident Evil Archives: Resident Evil Zero.
|
||||
return SystemTimers::GetTicksPerSecond() / 146;
|
||||
break;
|
||||
|
||||
// case DVDLowAudioBufferConfig:
|
||||
// case DVDLowInquiry:
|
||||
// case DVDLowReadDiskID:
|
||||
// case DVDLowWaitForCoverClose:
|
||||
// case DVDLowGetCoverReg:
|
||||
// case DVDLowGetCoverStatus:
|
||||
// case DVDLowReset:
|
||||
// case DVDLowClosePartition:
|
||||
default:
|
||||
// ranom numbers here!
|
||||
return SystemTimers::GetTicksPerSecond() / 1500;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ public:
|
|||
bool IOCtl(u32 _CommandAddress);
|
||||
bool IOCtlV(u32 _CommandAddress);
|
||||
|
||||
int GetCmdDelay(u32);
|
||||
|
||||
private:
|
||||
|
||||
u32 ExecuteCommand(u32 BufferIn, u32 BufferInSize, u32 _BufferOut, u32 BufferOutSize);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "FileUtil.h"
|
||||
#include "NandPaths.h"
|
||||
#include "ChunkFile.h"
|
||||
#include "../HW/SystemTimers.h"
|
||||
|
||||
#include "../VolumeHandler.h"
|
||||
|
||||
|
@ -504,6 +505,13 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
|||
return FS_RESULT_FATAL;
|
||||
}
|
||||
|
||||
int CWII_IPC_HLE_Device_fs::GetCmdDelay(u32)
|
||||
{
|
||||
// ~1/1000th of a second is too short and causes hangs in Wii Party
|
||||
// Play it safe at 1/500th
|
||||
return SystemTimers::GetTicksPerSecond() / 500;
|
||||
}
|
||||
|
||||
void CWII_IPC_HLE_Device_fs::DoState(PointerWrap& p)
|
||||
{
|
||||
DoStateShared(p);
|
||||
|
|
|
@ -56,6 +56,8 @@ public:
|
|||
virtual bool IOCtl(u32 _CommandAddress);
|
||||
virtual bool IOCtlV(u32 _CommandAddress);
|
||||
|
||||
virtual int GetCmdDelay(u32);
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
|
|
|
@ -336,23 +336,23 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8
|
|||
pWiiMote->ExecuteL2capCmd(_pData, _Size);
|
||||
}
|
||||
|
||||
// Here we send ACL packets to CPU. They will consist of header + data.
|
||||
// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
|
||||
// ---------------------------------------------------
|
||||
// AyuanX: Basically, our WII_IPC_HLE is efficient enough to send the packet immediately
|
||||
// rather than enqueue it to some other memory
|
||||
// But...the only exception comes from the Wiimote_Plugin
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::IncDataPacket(u16 _ConnectionHandle)
|
||||
{
|
||||
m_PacketCount[_ConnectionHandle & 0xff]++;
|
||||
|
||||
// I don't think this makes sense or should be necessary
|
||||
// m_PacketCount refers to "completed" packets and is not related to some buffer size, yes?
|
||||
#if 0
|
||||
if (m_PacketCount[_ConnectionHandle & 0xff] > (unsigned int)m_acl_pkts_num)
|
||||
{
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL buffer overflow");
|
||||
m_PacketCount[_ConnectionHandle & 0xff] = m_acl_pkts_num;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Here we send ACL packets to CPU. They will consist of header + data.
|
||||
// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
||||
{
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet from %x ready to send to stack...", _ConnectionHandle);
|
||||
|
@ -374,8 +374,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u
|
|||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint not currently valid, "
|
||||
"queueing(%d)...", m_acl_pool.GetWritePos());
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint not currently valid, queueing...");
|
||||
m_acl_pool.Store(_pData, _Size, _ConnectionHandle);
|
||||
}
|
||||
}
|
||||
|
@ -486,18 +485,8 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||
}
|
||||
}
|
||||
|
||||
// The Real Wiimote sends report every ~6.66ms (150 Hz).
|
||||
// However, we don't actually reach here at dependable intervals, so we
|
||||
// instead just timeslice in such a way that makes the stack think we have
|
||||
// perfect "radio quality" (WPADGetRadioSensitivity) and yet still have some
|
||||
// idle time.
|
||||
// Somehow, Dolphin's Wiimote Speaker support requires using an update interval
|
||||
// of 5ms (200 Hz) for its output to work. This increased frequency tends to
|
||||
// fill the ACL queue (even) quicker than it can be processed by Dolphin,
|
||||
// especially during simultaneous requests involving many (emulated) Wiimotes...
|
||||
// Thus, we only use that interval when the option is enabled. See issue 4608.
|
||||
const u64 interval = SystemTimers::GetTicksPerSecond() / (SConfig::GetInstance().
|
||||
m_LocalCoreStartupParameter.bDisableWiimoteSpeaker ? 150 : 200);
|
||||
// The Real Wiimote sends report every ~5ms (200 Hz).
|
||||
const u64 interval = SystemTimers::GetTicksPerSecond() / 200;
|
||||
const u64 each_wiimote_interval = interval / m_WiiMotes.size();
|
||||
const u64 now = CoreTiming::GetTicks();
|
||||
|
||||
|
@ -518,25 +507,47 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||
return packet_transferred;
|
||||
}
|
||||
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::Store(const u8* data, const u16 size, const u16 conn_handle)
|
||||
{
|
||||
if (m_queue.size() >= 100)
|
||||
{
|
||||
// Many simultaneous exchanges of ACL packets tend to cause the queue to fill up.
|
||||
ERROR_LOG(WII_IPC_WIIMOTE, "ACL queue size reached 100 - current packet will be dropped!");
|
||||
return;
|
||||
}
|
||||
|
||||
_dbg_assert_msg_(WII_IPC_WIIMOTE,
|
||||
size < m_acl_pkt_size, "acl packet too large for pool");
|
||||
|
||||
m_queue.push_back(Packet());
|
||||
auto& packet = m_queue.back();
|
||||
|
||||
std::copy(data, data + size, packet.data);
|
||||
packet.size = size;
|
||||
packet.conn_handle = conn_handle;
|
||||
}
|
||||
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::WriteToEndpoint(CtrlBuffer& endpoint)
|
||||
{
|
||||
const u8 *data = m_pool + m_acl_pkt_size * m_read_ptr;
|
||||
const u16 size = m_info[m_read_ptr].size;
|
||||
const u16 conn_handle = m_info[m_read_ptr].conn_handle;
|
||||
auto& packet = m_queue.front();
|
||||
|
||||
const u8* const data = packet.data;
|
||||
const u16 size = packet.size;
|
||||
const u16 conn_handle = packet.conn_handle;
|
||||
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet being written from "
|
||||
"queue(%d) to %08x", GetReadPos(), endpoint.m_address);
|
||||
"queue to %08x", endpoint.m_address);
|
||||
|
||||
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.m_buffer);
|
||||
pHeader->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
||||
pHeader->length = size;
|
||||
|
||||
// Write the packet to the buffer
|
||||
memcpy((u8*)pHeader + sizeof(hci_acldata_hdr_t), data, pHeader->length);
|
||||
std::copy(data, data + size, (u8*)pHeader + sizeof(hci_acldata_hdr_t));
|
||||
|
||||
endpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + size);
|
||||
|
||||
m_read_ptr = (m_read_ptr + 1) % m_acl_pkts_num;
|
||||
m_queue.pop_front();
|
||||
|
||||
WII_IPC_HLE_Interface::EnqReply(endpoint.m_address);
|
||||
endpoint.Invalidate();
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "hci.h"
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
#include "hci.h"
|
||||
#include "WII_IPC_HLE.h"
|
||||
#include "WII_IPC_HLE_Device.h"
|
||||
#include "WII_IPC_HLE_WiiMote.h"
|
||||
|
@ -168,70 +170,33 @@ private:
|
|||
|
||||
class ACLPool
|
||||
{
|
||||
u8 m_pool[m_acl_pkt_size * m_acl_pkts_num];
|
||||
int m_read_ptr;
|
||||
int m_write_ptr;
|
||||
|
||||
struct
|
||||
struct Packet
|
||||
{
|
||||
u8 data[m_acl_pkt_size];
|
||||
u16 size;
|
||||
u16 conn_handle;
|
||||
} m_info[m_acl_pkts_num];
|
||||
};
|
||||
|
||||
std::deque<Packet> m_queue;
|
||||
|
||||
public:
|
||||
ACLPool()
|
||||
: m_read_ptr(0)
|
||||
, m_write_ptr(0)
|
||||
: m_queue()
|
||||
{}
|
||||
|
||||
void Store(const u8* data, const u16 size, const u16 conn_handle)
|
||||
{
|
||||
_dbg_assert_msg_(WII_IPC_WIIMOTE,
|
||||
size < m_acl_pkt_size, "acl packet too large for pool");
|
||||
|
||||
const int next_write_ptr = (m_write_ptr + 1) % m_acl_pkts_num;
|
||||
if (next_write_ptr == m_read_ptr)
|
||||
{
|
||||
// Many simultaneous exchanges of ACL packets tend to cause the
|
||||
// 10-packet limit to be exceeded. Typically, this occurs when
|
||||
// many emulated Wiimotes are requesting connections at once.
|
||||
// See issue 4608 for more info.
|
||||
ERROR_LOG(WII_IPC_WIIMOTE, "ACL queue is full - current packet will be "
|
||||
"dropped! (m_write_ptr(%d) was about to overlap m_read_ptr(%d))",
|
||||
m_write_ptr, m_read_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(m_pool + m_acl_pkt_size * m_write_ptr, data, size);
|
||||
m_info[m_write_ptr].size = size;
|
||||
m_info[m_write_ptr].conn_handle = conn_handle;
|
||||
m_write_ptr = next_write_ptr;
|
||||
}
|
||||
void Store(const u8* data, const u16 size, const u16 conn_handle);
|
||||
|
||||
void WriteToEndpoint(CtrlBuffer& endpoint);
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return m_write_ptr == m_read_ptr;
|
||||
}
|
||||
|
||||
int GetWritePos() const
|
||||
{
|
||||
return m_write_ptr;
|
||||
}
|
||||
|
||||
int GetReadPos() const
|
||||
{
|
||||
return m_read_ptr;
|
||||
return m_queue.empty();
|
||||
}
|
||||
|
||||
// For SaveStates
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(m_write_ptr);
|
||||
p.Do(m_read_ptr);
|
||||
p.DoArray((u8 *)m_pool, sizeof(m_pool));
|
||||
p.DoArray((u8 *)m_info, sizeof(m_info));
|
||||
p.Do(m_queue);
|
||||
}
|
||||
} m_acl_pool;
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
|
|||
static std::thread g_save_thread;
|
||||
|
||||
// Don't forget to increase this after doing changes on the savestate system
|
||||
static const u32 STATE_VERSION = 10;
|
||||
static const u32 STATE_VERSION = 12;
|
||||
|
||||
struct StateHeader
|
||||
{
|
||||
|
|
|
@ -222,7 +222,7 @@ bool CompressFileToBlob(const char* infile, const char* outfile, u32 sub_type,
|
|||
// u64 size = header.block_size;
|
||||
std::fill(in_buf, in_buf + header.block_size, 0);
|
||||
if (scrubbing)
|
||||
DiscScrubber::GetNextBlock(inf.GetHandle(), in_buf);
|
||||
DiscScrubber::GetNextBlock(inf, in_buf);
|
||||
else
|
||||
inf.ReadBytes(in_buf, header.block_size);
|
||||
z_stream z;
|
||||
|
|
|
@ -127,7 +127,7 @@ bool SetupScrub(const char* filename, int block_size)
|
|||
return success;
|
||||
}
|
||||
|
||||
void GetNextBlock(FILE* in, u8* buffer)
|
||||
void GetNextBlock(File::IOFile& in, u8* buffer)
|
||||
{
|
||||
u64 CurrentOffset = m_BlockCount * m_BlockSize;
|
||||
u64 i = CurrentOffset / CLUSTER_SIZE;
|
||||
|
@ -136,12 +136,12 @@ void GetNextBlock(FILE* in, u8* buffer)
|
|||
{
|
||||
DEBUG_LOG(DISCIO, "Freeing 0x%016llx", CurrentOffset);
|
||||
std::fill(buffer, buffer + m_BlockSize, 0xFF);
|
||||
fseeko(in, m_BlockSize, SEEK_CUR);
|
||||
in.Seek(m_BlockSize, SEEK_CUR);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(DISCIO, "Used 0x%016llx", CurrentOffset);
|
||||
fread(buffer, m_BlockSize, 1, in);
|
||||
in.ReadBytes(buffer, m_BlockSize);
|
||||
}
|
||||
|
||||
m_BlockCount++;
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace DiscScrubber
|
|||
{
|
||||
|
||||
bool SetupScrub(const char* filename, int block_size);
|
||||
void GetNextBlock(FILE* in, u8* buffer);
|
||||
void GetNextBlock(File::IOFile& in, u8* buffer);
|
||||
void Cleanup();
|
||||
|
||||
} // namespace DiscScrubber
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win32\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||
|
@ -151,6 +152,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
|||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||
|
@ -167,6 +169,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
|||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win32\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||
|
@ -181,6 +184,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
|||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win32\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||
|
@ -197,6 +201,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
|||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||
|
@ -213,6 +218,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
|||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||
|
|
|
@ -1566,6 +1566,8 @@ void CFrame::UpdateGUI()
|
|||
if (m_ToolBar)
|
||||
m_ToolBar->EnableTool(IDM_PLAY, true);
|
||||
GetMenuBar()->FindItem(IDM_PLAY)->Enable(true);
|
||||
GetMenuBar()->FindItem(IDM_RECORD)->Enable(true);
|
||||
GetMenuBar()->FindItem(IDM_PLAYRECORD)->Enable(true);
|
||||
}
|
||||
// Prepare to load last selected file, enable play button
|
||||
else if (!SConfig::GetInstance().m_LastFilename.empty()
|
||||
|
@ -1574,6 +1576,8 @@ void CFrame::UpdateGUI()
|
|||
if (m_ToolBar)
|
||||
m_ToolBar->EnableTool(IDM_PLAY, true);
|
||||
GetMenuBar()->FindItem(IDM_PLAY)->Enable(true);
|
||||
GetMenuBar()->FindItem(IDM_RECORD)->Enable(true);
|
||||
GetMenuBar()->FindItem(IDM_PLAYRECORD)->Enable(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1581,6 +1585,8 @@ void CFrame::UpdateGUI()
|
|||
if (m_ToolBar)
|
||||
m_ToolBar->EnableTool(IDM_PLAY, false);
|
||||
GetMenuBar()->FindItem(IDM_PLAY)->Enable(false);
|
||||
GetMenuBar()->FindItem(IDM_RECORD)->Enable(false);
|
||||
GetMenuBar()->FindItem(IDM_PLAYRECORD)->Enable(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1596,6 +1602,8 @@ void CFrame::UpdateGUI()
|
|||
if (m_ToolBar)
|
||||
m_ToolBar->EnableTool(IDM_PLAY, true);
|
||||
GetMenuBar()->FindItem(IDM_PLAY)->Enable(true);
|
||||
GetMenuBar()->FindItem(IDM_RECORD)->Enable(true);
|
||||
GetMenuBar()->FindItem(IDM_PLAYRECORD)->Enable(true);
|
||||
}
|
||||
}
|
||||
else if (Initialized)
|
||||
|
|
|
@ -57,6 +57,8 @@ size_t CGameListCtrl::m_numberItem = 0;
|
|||
std::string CGameListCtrl::m_currentFilename;
|
||||
bool sorted = false;
|
||||
|
||||
extern CFrame* main_frame;
|
||||
|
||||
static int CompareGameListItems(const GameListItem* iso1, const GameListItem* iso2,
|
||||
long sortData = CGameListCtrl::COLUMN_TITLE)
|
||||
{
|
||||
|
@ -373,7 +375,8 @@ void CGameListCtrl::Update()
|
|||
SetItemFont(index, *wxITALIC_FONT);
|
||||
SetColumnWidth(0, wxLIST_AUTOSIZE);
|
||||
}
|
||||
|
||||
if (GetSelectedISO() == NULL)
|
||||
main_frame->UpdateGUI();
|
||||
Show();
|
||||
|
||||
AutomaticColumnWidth();
|
||||
|
@ -975,7 +978,7 @@ const GameListItem * CGameListCtrl::GetSelectedISO()
|
|||
{
|
||||
long item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
||||
if (item == wxNOT_FOUND)
|
||||
return new GameListItem(""); // TODO: wtf is this
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
// Here is a little workaround for multiselections:
|
||||
|
|
|
@ -328,8 +328,6 @@ void CISOProperties::CreateGUIControls(bool IsWad)
|
|||
|
||||
// Wii Console
|
||||
EnableWideScreen = new wxCheckBox(m_GameConfig, ID_ENABLEWIDESCREEN, _("Enable WideScreen"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
|
||||
DisableWiimoteSpeaker = new wxCheckBox(m_GameConfig, ID_DISABLEWIIMOTESPEAKER, _("Alternate Wiimote Timing"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
|
||||
DisableWiimoteSpeaker->SetToolTip(_("Mutes the Wiimote speaker. Fixes random disconnections on real wiimotes. No effect on emulated wiimotes."));
|
||||
|
||||
// Video
|
||||
UseBBox = new wxCheckBox(m_GameConfig, ID_USE_BBOX, _("Enable Bounding Box Calculation"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER);
|
||||
|
@ -377,10 +375,8 @@ void CISOProperties::CreateGUIControls(bool IsWad)
|
|||
{
|
||||
sbWiiOverrides->ShowItems(false);
|
||||
EnableWideScreen->Hide();
|
||||
DisableWiimoteSpeaker->Hide();
|
||||
}
|
||||
sbWiiOverrides->Add(EnableWideScreen, 0, wxLEFT, 5);
|
||||
sbWiiOverrides->Add(DisableWiimoteSpeaker, 0, wxLEFT, 5);
|
||||
|
||||
wxStaticBoxSizer * const sbVideoOverrides =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_GameConfig, _("Video"));
|
||||
|
@ -966,11 +962,6 @@ void CISOProperties::LoadGameConfig()
|
|||
else
|
||||
EnableWideScreen->Set3StateValue(wxCHK_UNDETERMINED);
|
||||
|
||||
if (GameIni.Get("Wii", "DisableWiimoteSpeaker", &bTemp))
|
||||
DisableWiimoteSpeaker->Set3StateValue((wxCheckBoxState)bTemp);
|
||||
else
|
||||
DisableWiimoteSpeaker->Set3StateValue(wxCHK_UNDETERMINED);
|
||||
|
||||
if (GameIni.Get("Video", "UseBBox", &bTemp))
|
||||
UseBBox->Set3StateValue((wxCheckBoxState)bTemp);
|
||||
else
|
||||
|
@ -1059,11 +1050,6 @@ bool CISOProperties::SaveGameConfig()
|
|||
else
|
||||
GameIni.Set("Wii", "Widescreen", EnableWideScreen->Get3StateValue());
|
||||
|
||||
if (DisableWiimoteSpeaker->Get3StateValue() == wxCHK_UNDETERMINED)
|
||||
GameIni.DeleteKey("Wii", "DisableWiimoteSpeaker");
|
||||
else
|
||||
GameIni.Set("Wii", "DisableWiimoteSpeaker", DisableWiimoteSpeaker->Get3StateValue());
|
||||
|
||||
if (UseBBox->Get3StateValue() == wxCHK_UNDETERMINED)
|
||||
GameIni.DeleteKey("Video", "UseBBox");
|
||||
else
|
||||
|
|
|
@ -72,7 +72,7 @@ private:
|
|||
wxCheckBox *CPUThread, *SkipIdle, *MMU, *DCBZOFF, *TLBHack;
|
||||
wxCheckBox *VBeam, *FastDiscSpeed, *BlockMerging, *DSPHLE;
|
||||
// Wii
|
||||
wxCheckBox *EnableWideScreen, *DisableWiimoteSpeaker;
|
||||
wxCheckBox *EnableWideScreen;
|
||||
// Video
|
||||
wxCheckBox *UseZTPSpeedupHack, *PHackEnable, *UseBBox;
|
||||
wxButton *PHSettings;
|
||||
|
@ -139,7 +139,6 @@ private:
|
|||
ID_PHSETTINGS,
|
||||
ID_ENABLEPROGRESSIVESCAN,
|
||||
ID_ENABLEWIDESCREEN,
|
||||
ID_DISABLEWIIMOTESPEAKER,
|
||||
ID_EDITCONFIG,
|
||||
ID_EMUSTATE,
|
||||
ID_EMU_ISSUES,
|
||||
|
|
|
@ -121,7 +121,9 @@ Joystick::Axis::Axis(IOHIDElementRef element, IOHIDDeviceRef device, direction d
|
|||
// Need to parse the element a bit first
|
||||
std::string description("unk");
|
||||
|
||||
switch (IOHIDElementGetUsage(m_element)) {
|
||||
int const usage = IOHIDElementGetUsage(m_element);
|
||||
switch (usage)
|
||||
{
|
||||
case kHIDUsage_GD_X:
|
||||
description = "X";
|
||||
break;
|
||||
|
@ -146,6 +148,13 @@ Joystick::Axis::Axis(IOHIDElementRef element, IOHIDDeviceRef device, direction d
|
|||
case kHIDUsage_Csmr_ACPan:
|
||||
description = "Pan";
|
||||
break;
|
||||
default:
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << usage;
|
||||
description = s.str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_name = std::string("Axis ") + description;
|
||||
|
|
|
@ -18,6 +18,15 @@ namespace ciface
|
|||
namespace SDL
|
||||
{
|
||||
|
||||
std::string GetJoystickName(int index)
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
return SDL_JoystickNameForIndex(index);
|
||||
#else
|
||||
return SDL_JoystickName(index);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Init( std::vector<ControllerInterface::Device*>& devices )
|
||||
{
|
||||
// this is used to number the joysticks
|
||||
|
@ -32,7 +41,7 @@ void Init( std::vector<ControllerInterface::Device*>& devices )
|
|||
SDL_Joystick* dev = SDL_JoystickOpen(i);
|
||||
if (dev)
|
||||
{
|
||||
Joystick* js = new Joystick(dev, i, name_counts[SDL_JoystickName(i)]++);
|
||||
Joystick* js = new Joystick(dev, i, name_counts[GetJoystickName(i)]++);
|
||||
// only add if it has some inputs/outputs
|
||||
if (js->Inputs().size() || js->Outputs().size())
|
||||
devices.push_back( js );
|
||||
|
@ -325,7 +334,7 @@ bool Joystick::UpdateOutput()
|
|||
|
||||
std::string Joystick::GetName() const
|
||||
{
|
||||
return StripSpaces(SDL_JoystickName(m_sdl_index));
|
||||
return StripSpaces(GetJoystickName(m_sdl_index));
|
||||
}
|
||||
|
||||
std::string Joystick::GetSource() const
|
||||
|
|
|
@ -5,22 +5,14 @@
|
|||
|
||||
#include <list>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <SDL.h>
|
||||
#else
|
||||
#include <SDL/SDL.h>
|
||||
#endif
|
||||
#include <SDL.h>
|
||||
|
||||
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||
#define USE_SDL_HAPTIC
|
||||
#endif
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
#ifdef _WIN32
|
||||
#include <SDL_haptic.h>
|
||||
#else
|
||||
#include <SDL/SDL_haptic.h>
|
||||
#endif
|
||||
#include <SDL_haptic.h>
|
||||
#define SDL_INIT_FLAGS SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC
|
||||
#else
|
||||
#define SDL_INIT_FLAGS SDL_INIT_JOYSTICK
|
||||
|
|
|
@ -456,6 +456,7 @@ void BPWritten(const BPCmd& bp)
|
|||
|
||||
case BPMEM_ZCOMPARE: // Set the Z-Compare and EFB pixel format
|
||||
g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel
|
||||
g_renderer->SetBlendMode(true);
|
||||
OnPixelFormatChange();
|
||||
break;
|
||||
|
||||
|
|
|
@ -218,6 +218,9 @@ void TextureCache::ClearRenderTargets()
|
|||
|
||||
bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels)
|
||||
{
|
||||
if (levels == 1)
|
||||
return false;
|
||||
|
||||
// Just checking if the necessary files exist, if they can't be loaded or have incorrect dimensions LODs will be black
|
||||
char texBasePathTemp[MAX_PATH];
|
||||
char texPathTemp[MAX_PATH];
|
||||
|
@ -300,7 +303,7 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level)
|
|||
|
||||
TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||
u32 address, unsigned int width, unsigned int height, int texformat,
|
||||
unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem)
|
||||
unsigned int tlutaddr, int tlutfmt, bool use_mipmaps, unsigned int maxlevel, bool from_tmem)
|
||||
{
|
||||
if (0 == address)
|
||||
return NULL;
|
||||
|
@ -372,7 +375,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||
|
||||
// 2. b) For normal textures, all texture parameters need to match
|
||||
if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format &&
|
||||
entry->num_mipmaps == maxlevel && entry->native_width == nativeW && entry->native_height == nativeH)
|
||||
entry->num_mipmaps > maxlevel && entry->native_width == nativeW && entry->native_height == nativeH)
|
||||
{
|
||||
goto return_entry;
|
||||
}
|
||||
|
@ -382,7 +385,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||
//
|
||||
// TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies?
|
||||
// TODO: Actually, it should be enough if the internal texture format matches...
|
||||
if ((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height && full_format == entry->format && entry->num_mipmaps == maxlevel)
|
||||
if ((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height && full_format == entry->format && entry->num_mipmaps > maxlevel)
|
||||
|| (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height))
|
||||
{
|
||||
// reuse the texture
|
||||
|
@ -428,15 +431,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Cleanup. Plus, we still autogenerate mipmaps in certain cases (we shouldn't do that)
|
||||
bool isPow2;
|
||||
unsigned int texLevels;
|
||||
isPow2 = !((width & (width - 1)) || (height & (height - 1)));
|
||||
texLevels = (isPow2 && maxlevel) ? GetPow2(std::max(width, height)) : !isPow2;
|
||||
texLevels = maxlevel ? std::min(texLevels, maxlevel + 1) : texLevels;
|
||||
bool use_native_mips;
|
||||
texLevels = use_mipmaps ? (maxlevel + 1) : 1;
|
||||
using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels);
|
||||
UseNativeMips = UseNativeMips && !using_custom_lods && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions
|
||||
texLevels = (UseNativeMips || using_custom_lods) ? texLevels : !isPow2;
|
||||
use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions
|
||||
texLevels = (use_native_mips || using_custom_lods) ? texLevels : 1;
|
||||
|
||||
// create the entry/texture
|
||||
if (NULL == entry) {
|
||||
|
@ -445,9 +445,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||
// Sometimes, we can get around recreating a texture if only the number of mip levels changes
|
||||
// e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states
|
||||
// Thus, we don't update this member for every Load, but just whenever the texture gets recreated
|
||||
//
|
||||
// TODO: Won't we end up recreating textures all the time because maxlevel doesn't necessarily equal texLevels?
|
||||
entry->num_mipmaps = maxlevel; // TODO: Does this actually work? We can't really adjust mipmap settings per-stage...
|
||||
// TODO: D3D9 doesn't support min_lod. We should add a workaround for that here!
|
||||
entry->num_mipmaps = maxlevel + 1;
|
||||
entry->type = TCET_NORMAL;
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true);
|
||||
|
@ -460,13 +459,13 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||
else entry->type = TCET_NORMAL;
|
||||
|
||||
// load texture
|
||||
entry->Load(width, height, expandedWidth, 0, (texLevels == 0));
|
||||
entry->Load(width, height, expandedWidth, 0);
|
||||
|
||||
if (g_ActiveConfig.bDumpTextures && !using_custom_texture)
|
||||
DumpTexture(entry, 0);
|
||||
|
||||
// load mips - TODO: Loading mipmaps from tmem is untested!
|
||||
if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && UseNativeMips)
|
||||
if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && use_native_mips)
|
||||
{
|
||||
const unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(texformat);
|
||||
|
||||
|
@ -495,7 +494,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||
expandedHeight = (currentHeight + bsh) & (~bsh);
|
||||
|
||||
TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures);
|
||||
entry->Load(currentWidth, currentHeight, expandedWidth, level, false);
|
||||
entry->Load(currentWidth, currentHeight, expandedWidth, level);
|
||||
|
||||
if (g_ActiveConfig.bDumpTextures)
|
||||
DumpTexture(entry, level);
|
||||
|
@ -518,7 +517,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||
unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1;
|
||||
|
||||
LoadCustomTexture(tex_hash, texformat, level, currentWidth, currentHeight);
|
||||
entry->Load(currentWidth, currentHeight, currentWidth, level, false);
|
||||
entry->Load(currentWidth, currentHeight, currentWidth, level);
|
||||
|
||||
mipWidth >>= 1;
|
||||
mipHeight >>= 1;
|
||||
|
|
|
@ -89,7 +89,7 @@ public:
|
|||
virtual bool Save(const char filename[], unsigned int level) = 0;
|
||||
|
||||
virtual void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level, bool autogen_mips) = 0;
|
||||
unsigned int expanded_width, unsigned int level) = 0;
|
||||
virtual void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
||||
|
@ -116,7 +116,7 @@ public:
|
|||
virtual TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) = 0;
|
||||
|
||||
static TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width, unsigned int height,
|
||||
int format, unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem);
|
||||
int format, unsigned int tlutaddr, int tlutfmt, bool use_mipmaps, unsigned int maxlevel, bool from_tmem);
|
||||
static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
|
||||
const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf);
|
||||
|
||||
|
|
|
@ -54,8 +54,6 @@ static int s_fps = 0;
|
|||
|
||||
static u32 s_LastAA = 0;
|
||||
|
||||
static u32 s_blendMode;
|
||||
|
||||
static Television s_television;
|
||||
|
||||
ID3D11Buffer* access_efb_cbuf = NULL;
|
||||
|
@ -76,151 +74,6 @@ struct
|
|||
D3D11_RASTERIZER_DESC rastdc;
|
||||
} gx_state;
|
||||
|
||||
// State translation lookup tables
|
||||
static const D3D11_BLEND d3dSrcFactors[8] =
|
||||
{
|
||||
D3D11_BLEND_ZERO,
|
||||
D3D11_BLEND_ONE,
|
||||
D3D11_BLEND_DEST_COLOR,
|
||||
D3D11_BLEND_INV_DEST_COLOR,
|
||||
D3D11_BLEND_SRC_ALPHA,
|
||||
D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled!
|
||||
D3D11_BLEND_DEST_ALPHA,
|
||||
D3D11_BLEND_INV_DEST_ALPHA
|
||||
};
|
||||
|
||||
static const D3D11_BLEND d3dDestFactors[8] =
|
||||
{
|
||||
D3D11_BLEND_ZERO,
|
||||
D3D11_BLEND_ONE,
|
||||
D3D11_BLEND_SRC_COLOR,
|
||||
D3D11_BLEND_INV_SRC_COLOR,
|
||||
D3D11_BLEND_SRC_ALPHA,
|
||||
D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled!
|
||||
D3D11_BLEND_DEST_ALPHA,
|
||||
D3D11_BLEND_INV_DEST_ALPHA
|
||||
};
|
||||
|
||||
// 0 0x00
|
||||
// 1 Source & destination
|
||||
// 2 Source & ~destination
|
||||
// 3 Source
|
||||
// 4 ~Source & destination
|
||||
// 5 Destination
|
||||
// 6 Source ^ destination = Source & ~destination | ~Source & destination
|
||||
// 7 Source | destination
|
||||
|
||||
// 8 ~(Source | destination)
|
||||
// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination
|
||||
// 10 ~Destination
|
||||
// 11 Source | ~destination
|
||||
// 12 ~Source
|
||||
// 13 ~Source | destination
|
||||
// 14 ~(Source & destination)
|
||||
// 15 0xff
|
||||
|
||||
static const D3D11_BLEND_OP d3dLogicOps[16] =
|
||||
{
|
||||
D3D11_BLEND_OP_ADD,//0
|
||||
D3D11_BLEND_OP_ADD,//1
|
||||
D3D11_BLEND_OP_SUBTRACT,//2
|
||||
D3D11_BLEND_OP_ADD,//3
|
||||
D3D11_BLEND_OP_REV_SUBTRACT,//4
|
||||
D3D11_BLEND_OP_ADD,//5
|
||||
D3D11_BLEND_OP_MAX,//6
|
||||
D3D11_BLEND_OP_ADD,//7
|
||||
|
||||
D3D11_BLEND_OP_MAX,//8
|
||||
D3D11_BLEND_OP_MAX,//9
|
||||
D3D11_BLEND_OP_ADD,//10
|
||||
D3D11_BLEND_OP_ADD,//11
|
||||
D3D11_BLEND_OP_ADD,//12
|
||||
D3D11_BLEND_OP_ADD,//13
|
||||
D3D11_BLEND_OP_ADD,//14
|
||||
D3D11_BLEND_OP_ADD//15
|
||||
};
|
||||
|
||||
static const D3D11_BLEND d3dLogicOpSrcFactors[16] =
|
||||
{
|
||||
D3D11_BLEND_ZERO,//0
|
||||
D3D11_BLEND_DEST_COLOR,//1
|
||||
D3D11_BLEND_ONE,//2
|
||||
D3D11_BLEND_ONE,//3
|
||||
D3D11_BLEND_DEST_COLOR,//4
|
||||
D3D11_BLEND_ZERO,//5
|
||||
D3D11_BLEND_INV_DEST_COLOR,//6
|
||||
D3D11_BLEND_INV_DEST_COLOR,//7
|
||||
|
||||
D3D11_BLEND_INV_SRC_COLOR,//8
|
||||
D3D11_BLEND_INV_SRC_COLOR,//9
|
||||
D3D11_BLEND_INV_DEST_COLOR,//10
|
||||
D3D11_BLEND_ONE,//11
|
||||
D3D11_BLEND_INV_SRC_COLOR,//12
|
||||
D3D11_BLEND_INV_SRC_COLOR,//13
|
||||
D3D11_BLEND_INV_DEST_COLOR,//14
|
||||
D3D11_BLEND_ONE//15
|
||||
};
|
||||
|
||||
static const D3D11_BLEND d3dLogicOpDestFactors[16] =
|
||||
{
|
||||
D3D11_BLEND_ZERO,//0
|
||||
D3D11_BLEND_ZERO,//1
|
||||
D3D11_BLEND_INV_SRC_COLOR,//2
|
||||
D3D11_BLEND_ZERO,//3
|
||||
D3D11_BLEND_ONE,//4
|
||||
D3D11_BLEND_ONE,//5
|
||||
D3D11_BLEND_INV_SRC_COLOR,//6
|
||||
D3D11_BLEND_ONE,//7
|
||||
|
||||
D3D11_BLEND_INV_DEST_COLOR,//8
|
||||
D3D11_BLEND_SRC_COLOR,//9
|
||||
D3D11_BLEND_INV_DEST_COLOR,//10
|
||||
D3D11_BLEND_INV_DEST_COLOR,//11
|
||||
D3D11_BLEND_INV_SRC_COLOR,//12
|
||||
D3D11_BLEND_ONE,//13
|
||||
D3D11_BLEND_INV_SRC_COLOR,//14
|
||||
D3D11_BLEND_ONE//15
|
||||
};
|
||||
|
||||
static const D3D11_CULL_MODE d3dCullModes[4] =
|
||||
{
|
||||
D3D11_CULL_NONE,
|
||||
D3D11_CULL_BACK,
|
||||
D3D11_CULL_FRONT,
|
||||
D3D11_CULL_BACK
|
||||
};
|
||||
|
||||
static const D3D11_COMPARISON_FUNC d3dCmpFuncs[8] =
|
||||
{
|
||||
D3D11_COMPARISON_NEVER,
|
||||
D3D11_COMPARISON_LESS,
|
||||
D3D11_COMPARISON_EQUAL,
|
||||
D3D11_COMPARISON_LESS_EQUAL,
|
||||
D3D11_COMPARISON_GREATER,
|
||||
D3D11_COMPARISON_NOT_EQUAL,
|
||||
D3D11_COMPARISON_GREATER_EQUAL,
|
||||
D3D11_COMPARISON_ALWAYS
|
||||
};
|
||||
|
||||
#define TEXF_NONE 0
|
||||
#define TEXF_POINT 1
|
||||
#define TEXF_LINEAR 2
|
||||
static const unsigned int d3dMipFilters[4] =
|
||||
{
|
||||
TEXF_NONE,
|
||||
TEXF_POINT,
|
||||
TEXF_LINEAR,
|
||||
TEXF_NONE, //reserved
|
||||
};
|
||||
|
||||
static const D3D11_TEXTURE_ADDRESS_MODE d3dClamps[4] =
|
||||
{
|
||||
D3D11_TEXTURE_ADDRESS_CLAMP,
|
||||
D3D11_TEXTURE_ADDRESS_WRAP,
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR,
|
||||
D3D11_TEXTURE_ADDRESS_WRAP //reserved
|
||||
};
|
||||
|
||||
|
||||
void SetupDeviceObjects()
|
||||
{
|
||||
|
@ -338,7 +191,6 @@ void CreateScreenshotTexture()
|
|||
Renderer::Renderer()
|
||||
{
|
||||
int x, y, w_temp, h_temp;
|
||||
s_blendMode = 0;
|
||||
|
||||
InitFPSCounter();
|
||||
|
||||
|
@ -833,6 +685,32 @@ void SetBlendOp(D3D11_BLEND_OP val)
|
|||
|
||||
void Renderer::SetBlendMode(bool forceUpdate)
|
||||
{
|
||||
// Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
|
||||
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1.
|
||||
bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
const D3D11_BLEND d3dSrcFactors[8] =
|
||||
{
|
||||
D3D11_BLEND_ZERO,
|
||||
D3D11_BLEND_ONE,
|
||||
D3D11_BLEND_DEST_COLOR,
|
||||
D3D11_BLEND_INV_DEST_COLOR,
|
||||
D3D11_BLEND_SRC_ALPHA,
|
||||
D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled!
|
||||
(target_has_alpha) ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_ONE,
|
||||
(target_has_alpha) ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_ZERO
|
||||
};
|
||||
const D3D11_BLEND d3dDestFactors[8] =
|
||||
{
|
||||
D3D11_BLEND_ZERO,
|
||||
D3D11_BLEND_ONE,
|
||||
D3D11_BLEND_SRC_COLOR,
|
||||
D3D11_BLEND_INV_SRC_COLOR,
|
||||
D3D11_BLEND_SRC_ALPHA,
|
||||
D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled!
|
||||
(target_has_alpha) ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_ONE,
|
||||
(target_has_alpha) ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_ZERO
|
||||
};
|
||||
|
||||
if (bpmem.blendmode.logicopenable && !forceUpdate)
|
||||
return;
|
||||
|
||||
|
@ -845,8 +723,8 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
|||
}
|
||||
else
|
||||
{
|
||||
gx_state.blenddc.RenderTarget[0].BlendEnable = bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0));
|
||||
if (bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0)))
|
||||
gx_state.blenddc.RenderTarget[0].BlendEnable = bpmem.blendmode.blendenable;
|
||||
if (bpmem.blendmode.blendenable)
|
||||
{
|
||||
SetBlendOp(D3D11_BLEND_OP_ADD);
|
||||
SetSrcBlend(d3dSrcFactors[bpmem.blendmode.srcfactor]);
|
||||
|
@ -1331,12 +1209,32 @@ void Renderer::RestoreCull()
|
|||
|
||||
void Renderer::SetGenerationMode()
|
||||
{
|
||||
const D3D11_CULL_MODE d3dCullModes[4] =
|
||||
{
|
||||
D3D11_CULL_NONE,
|
||||
D3D11_CULL_BACK,
|
||||
D3D11_CULL_FRONT,
|
||||
D3D11_CULL_BACK
|
||||
};
|
||||
|
||||
// rastdc.FrontCounterClockwise must be false for this to work
|
||||
gx_state.rastdc.CullMode = d3dCullModes[bpmem.genMode.cullmode];
|
||||
}
|
||||
|
||||
void Renderer::SetDepthMode()
|
||||
{
|
||||
const D3D11_COMPARISON_FUNC d3dCmpFuncs[8] =
|
||||
{
|
||||
D3D11_COMPARISON_NEVER,
|
||||
D3D11_COMPARISON_LESS,
|
||||
D3D11_COMPARISON_EQUAL,
|
||||
D3D11_COMPARISON_LESS_EQUAL,
|
||||
D3D11_COMPARISON_GREATER,
|
||||
D3D11_COMPARISON_NOT_EQUAL,
|
||||
D3D11_COMPARISON_GREATER_EQUAL,
|
||||
D3D11_COMPARISON_ALWAYS
|
||||
};
|
||||
|
||||
if (bpmem.zmode.testenable)
|
||||
{
|
||||
gx_state.depthdc.DepthEnable = TRUE;
|
||||
|
@ -1353,9 +1251,85 @@ void Renderer::SetDepthMode()
|
|||
|
||||
void Renderer::SetLogicOpMode()
|
||||
{
|
||||
if (bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3)
|
||||
// D3D11 doesn't support logic blending, so this is a huge hack
|
||||
// TODO: Make use of D3D11.1's logic blending support
|
||||
|
||||
// 0 0x00
|
||||
// 1 Source & destination
|
||||
// 2 Source & ~destination
|
||||
// 3 Source
|
||||
// 4 ~Source & destination
|
||||
// 5 Destination
|
||||
// 6 Source ^ destination = Source & ~destination | ~Source & destination
|
||||
// 7 Source | destination
|
||||
// 8 ~(Source | destination)
|
||||
// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination
|
||||
// 10 ~Destination
|
||||
// 11 Source | ~destination
|
||||
// 12 ~Source
|
||||
// 13 ~Source | destination
|
||||
// 14 ~(Source & destination)
|
||||
// 15 0xff
|
||||
const D3D11_BLEND_OP d3dLogicOps[16] =
|
||||
{
|
||||
D3D11_BLEND_OP_ADD,//0
|
||||
D3D11_BLEND_OP_ADD,//1
|
||||
D3D11_BLEND_OP_SUBTRACT,//2
|
||||
D3D11_BLEND_OP_ADD,//3
|
||||
D3D11_BLEND_OP_REV_SUBTRACT,//4
|
||||
D3D11_BLEND_OP_ADD,//5
|
||||
D3D11_BLEND_OP_MAX,//6
|
||||
D3D11_BLEND_OP_ADD,//7
|
||||
D3D11_BLEND_OP_MAX,//8
|
||||
D3D11_BLEND_OP_MAX,//9
|
||||
D3D11_BLEND_OP_ADD,//10
|
||||
D3D11_BLEND_OP_ADD,//11
|
||||
D3D11_BLEND_OP_ADD,//12
|
||||
D3D11_BLEND_OP_ADD,//13
|
||||
D3D11_BLEND_OP_ADD,//14
|
||||
D3D11_BLEND_OP_ADD//15
|
||||
};
|
||||
const D3D11_BLEND d3dLogicOpSrcFactors[16] =
|
||||
{
|
||||
D3D11_BLEND_ZERO,//0
|
||||
D3D11_BLEND_DEST_COLOR,//1
|
||||
D3D11_BLEND_ONE,//2
|
||||
D3D11_BLEND_ONE,//3
|
||||
D3D11_BLEND_DEST_COLOR,//4
|
||||
D3D11_BLEND_ZERO,//5
|
||||
D3D11_BLEND_INV_DEST_COLOR,//6
|
||||
D3D11_BLEND_INV_DEST_COLOR,//7
|
||||
D3D11_BLEND_INV_SRC_COLOR,//8
|
||||
D3D11_BLEND_INV_SRC_COLOR,//9
|
||||
D3D11_BLEND_INV_DEST_COLOR,//10
|
||||
D3D11_BLEND_ONE,//11
|
||||
D3D11_BLEND_INV_SRC_COLOR,//12
|
||||
D3D11_BLEND_INV_SRC_COLOR,//13
|
||||
D3D11_BLEND_INV_DEST_COLOR,//14
|
||||
D3D11_BLEND_ONE//15
|
||||
};
|
||||
const D3D11_BLEND d3dLogicOpDestFactors[16] =
|
||||
{
|
||||
D3D11_BLEND_ZERO,//0
|
||||
D3D11_BLEND_ZERO,//1
|
||||
D3D11_BLEND_INV_SRC_COLOR,//2
|
||||
D3D11_BLEND_ZERO,//3
|
||||
D3D11_BLEND_ONE,//4
|
||||
D3D11_BLEND_ONE,//5
|
||||
D3D11_BLEND_INV_SRC_COLOR,//6
|
||||
D3D11_BLEND_ONE,//7
|
||||
D3D11_BLEND_INV_DEST_COLOR,//8
|
||||
D3D11_BLEND_SRC_COLOR,//9
|
||||
D3D11_BLEND_INV_DEST_COLOR,//10
|
||||
D3D11_BLEND_INV_DEST_COLOR,//11
|
||||
D3D11_BLEND_INV_SRC_COLOR,//12
|
||||
D3D11_BLEND_ONE,//13
|
||||
D3D11_BLEND_INV_SRC_COLOR,//14
|
||||
D3D11_BLEND_ONE//15
|
||||
};
|
||||
|
||||
if (bpmem.blendmode.logicopenable)
|
||||
{
|
||||
s_blendMode = 0;
|
||||
gx_state.blenddc.RenderTarget[0].BlendEnable = true;
|
||||
SetBlendOp(d3dLogicOps[bpmem.blendmode.logicmode]);
|
||||
SetSrcBlend(d3dLogicOpSrcFactors[bpmem.blendmode.logicmode]);
|
||||
|
@ -1379,18 +1353,32 @@ void Renderer::SetLineWidth()
|
|||
|
||||
void Renderer::SetSamplerState(int stage, int texindex)
|
||||
{
|
||||
#define TEXF_NONE 0
|
||||
#define TEXF_POINT 1
|
||||
#define TEXF_LINEAR 2
|
||||
const unsigned int d3dMipFilters[4] =
|
||||
{
|
||||
TEXF_NONE,
|
||||
TEXF_POINT,
|
||||
TEXF_LINEAR,
|
||||
TEXF_NONE, //reserved
|
||||
};
|
||||
const D3D11_TEXTURE_ADDRESS_MODE d3dClamps[4] =
|
||||
{
|
||||
D3D11_TEXTURE_ADDRESS_CLAMP,
|
||||
D3D11_TEXTURE_ADDRESS_WRAP,
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR,
|
||||
D3D11_TEXTURE_ADDRESS_WRAP //reserved
|
||||
};
|
||||
|
||||
const FourTexUnits &tex = bpmem.tex[texindex];
|
||||
const TexMode0 &tm0 = tex.texMode0[stage];
|
||||
const TexMode1 &tm1 = tex.texMode1[stage];
|
||||
|
||||
unsigned int mip;
|
||||
mip = (tm0.min_filter == 8) ? TEXF_NONE:d3dMipFilters[tm0.min_filter & 3];
|
||||
if ((tm0.min_filter & 3) && (tm0.min_filter != 8) && ((tm1.max_lod >> 4) == 0)) mip = TEXF_NONE;
|
||||
unsigned int mip = d3dMipFilters[tm0.min_filter & 3];
|
||||
|
||||
if (texindex) stage += 4;
|
||||
|
||||
// TODO: Clarify whether these values are correct
|
||||
// NOTE: since there's no "no filter" in DX11 we're using point filters in these cases
|
||||
if (g_ActiveConfig.bForceFiltering)
|
||||
{
|
||||
gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
|
@ -1432,7 +1420,7 @@ void Renderer::SetSamplerState(int stage, int texindex)
|
|||
// When mipfilter is set to "none", just disable mipmapping altogether
|
||||
gx_state.sampdc[stage].MaxLOD = (mip == TEXF_NONE) ? 0.0f : (float)tm1.max_lod/16.f;
|
||||
gx_state.sampdc[stage].MinLOD = (float)tm1.min_lod/16.f;
|
||||
gx_state.sampdc[stage].MipLODBias = (float)tm0.lod_bias/32.0f;
|
||||
gx_state.sampdc[stage].MipLODBias = (s32)tm0.lod_bias/32.0f;
|
||||
}
|
||||
|
||||
void Renderer::SetInterlacingMode()
|
||||
|
|
|
@ -59,12 +59,9 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
|
|||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level, bool autogen_mips)
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage);
|
||||
|
||||
if (autogen_mips)
|
||||
PD3DX11FilterTexture(D3D::context, texture->GetTex(), 0, D3DX11_DEFAULT);
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
||||
|
|
|
@ -41,7 +41,7 @@ private:
|
|||
~TCacheEntry();
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int levels, bool autogen_mips = false);
|
||||
unsigned int expanded_width, unsigned int levels);
|
||||
|
||||
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||
|
|
|
@ -237,8 +237,8 @@ void VertexManager::vFlush()
|
|||
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
||||
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
||||
tex.texTlut[i&3].tlut_format,
|
||||
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
|
||||
tex.texMode1[i&3].max_lod >> 4,
|
||||
(tex.texMode0[i&3].min_filter & 3),
|
||||
ceil(tex.texMode1[i&3].max_lod / 16.f),
|
||||
tex.texImage1[i&3].image_type);
|
||||
|
||||
if (tentry)
|
||||
|
|
|
@ -73,148 +73,6 @@ static char *st;
|
|||
static LPDIRECT3DSURFACE9 ScreenShootMEMSurface = NULL;
|
||||
|
||||
|
||||
// State translation lookup tables
|
||||
static const D3DBLEND d3dSrcFactors[8] =
|
||||
{
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_DESTCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_SRCALPHA,
|
||||
D3DBLEND_INVSRCALPHA,
|
||||
D3DBLEND_DESTALPHA,
|
||||
D3DBLEND_INVDESTALPHA
|
||||
};
|
||||
|
||||
static const D3DBLEND d3dDestFactors[8] =
|
||||
{
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_SRCCOLOR,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_SRCALPHA,
|
||||
D3DBLEND_INVSRCALPHA,
|
||||
D3DBLEND_DESTALPHA,
|
||||
D3DBLEND_INVDESTALPHA
|
||||
};
|
||||
|
||||
// 0 0x00
|
||||
// 1 Source & destination
|
||||
// 2 Source & ~destination
|
||||
// 3 Source
|
||||
// 4 ~Source & destination
|
||||
// 5 Destination
|
||||
// 6 Source ^ destination = Source & ~destination | ~Source & destination
|
||||
// 7 Source | destination
|
||||
|
||||
// 8 ~(Source | destination)
|
||||
// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination
|
||||
// 10 ~Destination
|
||||
// 11 Source | ~destination
|
||||
// 12 ~Source
|
||||
// 13 ~Source | destination
|
||||
// 14 ~(Source & destination)
|
||||
// 15 0xff
|
||||
|
||||
static const D3DBLENDOP d3dLogicOpop[16] =
|
||||
{
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_SUBTRACT,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_REVSUBTRACT,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_MAX,
|
||||
D3DBLENDOP_ADD,
|
||||
|
||||
D3DBLENDOP_MAX,
|
||||
D3DBLENDOP_MAX,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD
|
||||
};
|
||||
|
||||
static const D3DBLEND d3dLogicOpSrcFactors[16] =
|
||||
{
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_DESTCOLOR,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_DESTCOLOR,
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_ONE
|
||||
};
|
||||
|
||||
static const D3DBLEND d3dLogicOpDestFactors[16] =
|
||||
{
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_ONE,
|
||||
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_SRCCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_ONE
|
||||
};
|
||||
|
||||
static const D3DCULL d3dCullModes[4] =
|
||||
{
|
||||
D3DCULL_NONE,
|
||||
D3DCULL_CCW,
|
||||
D3DCULL_CW,
|
||||
D3DCULL_CCW
|
||||
};
|
||||
|
||||
static const D3DCMPFUNC d3dCmpFuncs[8] =
|
||||
{
|
||||
D3DCMP_NEVER,
|
||||
D3DCMP_LESS,
|
||||
D3DCMP_EQUAL,
|
||||
D3DCMP_LESSEQUAL,
|
||||
D3DCMP_GREATER,
|
||||
D3DCMP_NOTEQUAL,
|
||||
D3DCMP_GREATEREQUAL,
|
||||
D3DCMP_ALWAYS
|
||||
};
|
||||
|
||||
static const D3DTEXTUREFILTERTYPE d3dMipFilters[4] =
|
||||
{
|
||||
D3DTEXF_NONE,
|
||||
D3DTEXF_POINT,
|
||||
D3DTEXF_LINEAR,
|
||||
D3DTEXF_NONE, //reserved
|
||||
};
|
||||
|
||||
static const D3DTEXTUREADDRESS d3dClamps[4] =
|
||||
{
|
||||
D3DTADDRESS_CLAMP,
|
||||
D3DTADDRESS_WRAP,
|
||||
D3DTADDRESS_MIRROR,
|
||||
D3DTADDRESS_WRAP //reserved
|
||||
};
|
||||
|
||||
void SetupDeviceObjects()
|
||||
{
|
||||
D3D::font.Init();
|
||||
|
@ -796,6 +654,32 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
|
|||
|
||||
void Renderer::SetBlendMode(bool forceUpdate)
|
||||
{
|
||||
// Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
|
||||
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1.
|
||||
bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
const D3DBLEND d3dSrcFactors[8] =
|
||||
{
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_DESTCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_SRCALPHA,
|
||||
D3DBLEND_INVSRCALPHA,
|
||||
(target_has_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE,
|
||||
(target_has_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO
|
||||
};
|
||||
const D3DBLEND d3dDestFactors[8] =
|
||||
{
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_SRCCOLOR,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_SRCALPHA,
|
||||
D3DBLEND_INVSRCALPHA,
|
||||
(target_has_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE,
|
||||
(target_has_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO
|
||||
};
|
||||
|
||||
if (bpmem.blendmode.logicopenable && !forceUpdate)
|
||||
return;
|
||||
|
||||
|
@ -808,8 +692,8 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
|||
}
|
||||
else
|
||||
{
|
||||
D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0)));
|
||||
if (bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0)))
|
||||
D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable);
|
||||
if (bpmem.blendmode.blendenable)
|
||||
{
|
||||
D3D::SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
D3D::SetRenderState(D3DRS_SRCBLEND, d3dSrcFactors[bpmem.blendmode.srcfactor]);
|
||||
|
@ -1261,11 +1145,31 @@ void Renderer::RestoreAPIState()
|
|||
|
||||
void Renderer::SetGenerationMode()
|
||||
{
|
||||
const D3DCULL d3dCullModes[4] =
|
||||
{
|
||||
D3DCULL_NONE,
|
||||
D3DCULL_CCW,
|
||||
D3DCULL_CW,
|
||||
D3DCULL_CCW
|
||||
};
|
||||
|
||||
D3D::SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
|
||||
}
|
||||
|
||||
void Renderer::SetDepthMode()
|
||||
{
|
||||
const D3DCMPFUNC d3dCmpFuncs[8] =
|
||||
{
|
||||
D3DCMP_NEVER,
|
||||
D3DCMP_LESS,
|
||||
D3DCMP_EQUAL,
|
||||
D3DCMP_LESSEQUAL,
|
||||
D3DCMP_GREATER,
|
||||
D3DCMP_NOTEQUAL,
|
||||
D3DCMP_GREATEREQUAL,
|
||||
D3DCMP_ALWAYS
|
||||
};
|
||||
|
||||
if (bpmem.zmode.testenable)
|
||||
{
|
||||
D3D::SetRenderState(D3DRS_ZENABLE, TRUE);
|
||||
|
@ -1282,7 +1186,83 @@ void Renderer::SetDepthMode()
|
|||
|
||||
void Renderer::SetLogicOpMode()
|
||||
{
|
||||
if (bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3)
|
||||
// D3D9 doesn't support logic blending, so this is a huge hack
|
||||
|
||||
// 0 0x00
|
||||
// 1 Source & destination
|
||||
// 2 Source & ~destination
|
||||
// 3 Source
|
||||
// 4 ~Source & destination
|
||||
// 5 Destination
|
||||
// 6 Source ^ destination = Source & ~destination | ~Source & destination
|
||||
// 7 Source | destination
|
||||
// 8 ~(Source | destination)
|
||||
// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination
|
||||
// 10 ~Destination
|
||||
// 11 Source | ~destination
|
||||
// 12 ~Source
|
||||
// 13 ~Source | destination
|
||||
// 14 ~(Source & destination)
|
||||
// 15 0xff
|
||||
const D3DBLENDOP d3dLogicOpop[16] =
|
||||
{
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_SUBTRACT,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_REVSUBTRACT,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_MAX,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_MAX,
|
||||
D3DBLENDOP_MAX,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD,
|
||||
D3DBLENDOP_ADD
|
||||
};
|
||||
const D3DBLEND d3dLogicOpSrcFactors[16] =
|
||||
{
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_DESTCOLOR,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_DESTCOLOR,
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_ONE
|
||||
};
|
||||
const D3DBLEND d3dLogicOpDestFactors[16] =
|
||||
{
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_SRCCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_ONE
|
||||
};
|
||||
|
||||
if (bpmem.blendmode.logicopenable)
|
||||
{
|
||||
D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, true);
|
||||
D3D::SetRenderState(D3DRS_BLENDOP, d3dLogicOpop[bpmem.blendmode.logicmode]);
|
||||
|
@ -1310,6 +1290,21 @@ void Renderer::SetLineWidth()
|
|||
|
||||
void Renderer::SetSamplerState(int stage, int texindex)
|
||||
{
|
||||
const D3DTEXTUREFILTERTYPE d3dMipFilters[4] =
|
||||
{
|
||||
D3DTEXF_NONE,
|
||||
D3DTEXF_POINT,
|
||||
D3DTEXF_LINEAR,
|
||||
D3DTEXF_NONE, //reserved
|
||||
};
|
||||
const D3DTEXTUREADDRESS d3dClamps[4] =
|
||||
{
|
||||
D3DTADDRESS_CLAMP,
|
||||
D3DTADDRESS_WRAP,
|
||||
D3DTADDRESS_MIRROR,
|
||||
D3DTADDRESS_WRAP //reserved
|
||||
};
|
||||
|
||||
const FourTexUnits &tex = bpmem.tex[texindex];
|
||||
const TexMode0 &tm0 = tex.texMode0[stage];
|
||||
const TexMode1 &tm1 = tex.texMode1[stage];
|
||||
|
@ -1323,9 +1318,7 @@ void Renderer::SetSamplerState(int stage, int texindex)
|
|||
{
|
||||
min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
||||
mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
||||
mip = (tm0.min_filter == 8) ? D3DTEXF_NONE : d3dMipFilters[tm0.min_filter & 3];
|
||||
if((tm0.min_filter & 3) && (tm0.min_filter != 8) && ((tm1.max_lod >> 4) == 0))
|
||||
mip = D3DTEXF_NONE;
|
||||
mip = d3dMipFilters[tm0.min_filter & 3];
|
||||
}
|
||||
if (texindex)
|
||||
stage += 4;
|
||||
|
@ -1340,8 +1333,8 @@ void Renderer::SetSamplerState(int stage, int texindex)
|
|||
|
||||
D3D::SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]);
|
||||
D3D::SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]);
|
||||
//float SuperSampleCoeficient = (s_LastAA < 3)? s_LastAA + 1 : s_LastAA - 1;// uncoment this changes to conserve detail when incresing ssaa level
|
||||
float lodbias = (tm0.lod_bias / 32.0f);// + (s_LastAA)?(log(SuperSampleCoeficient) / log(2.0f)):0;
|
||||
|
||||
float lodbias = (s32)tm0.lod_bias / 32.0f;
|
||||
D3D::SetSamplerState(stage, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)&lodbias);
|
||||
D3D::SetSamplerState(stage, D3DSAMP_MAXMIPLEVEL, tm1.min_lod >> 4);
|
||||
}
|
||||
|
|
|
@ -72,10 +72,9 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
|
|||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level, bool autogen_mips)
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level);
|
||||
// D3D9 will automatically generate mip maps if necessary
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||
|
|
|
@ -44,7 +44,7 @@ private:
|
|||
~TCacheEntry();
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int levels, bool autogen_mips = false);
|
||||
unsigned int expanded_width, unsigned int levels);
|
||||
|
||||
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||
|
|
|
@ -333,8 +333,8 @@ void VertexManager::vFlush()
|
|||
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
||||
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
||||
tex.texTlut[i&3].tlut_format,
|
||||
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
|
||||
tex.texMode1[i&3].max_lod >> 4,
|
||||
(tex.texMode0[i&3].min_filter & 3),
|
||||
ceil(tex.texMode1[i&3].max_lod / 16.f),
|
||||
tex.texImage1[i&3].image_type);
|
||||
|
||||
if (tentry)
|
||||
|
|
|
@ -132,58 +132,6 @@ const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_
|
|||
static bool s_efbCacheValid[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT];
|
||||
static std::vector<u32> s_efbCache[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT]; // 2 for PEEK_Z and PEEK_COLOR
|
||||
|
||||
static const GLenum glSrcFactors[8] =
|
||||
{
|
||||
GL_ZERO,
|
||||
GL_ONE,
|
||||
GL_DST_COLOR,
|
||||
GL_ONE_MINUS_DST_COLOR,
|
||||
GL_SRC_ALPHA,
|
||||
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
||||
GL_DST_ALPHA,
|
||||
GL_ONE_MINUS_DST_ALPHA
|
||||
};
|
||||
|
||||
static const GLenum glDestFactors[8] = {
|
||||
GL_ZERO,
|
||||
GL_ONE,
|
||||
GL_SRC_COLOR,
|
||||
GL_ONE_MINUS_SRC_COLOR,
|
||||
GL_SRC_ALPHA,
|
||||
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
||||
GL_DST_ALPHA,
|
||||
GL_ONE_MINUS_DST_ALPHA
|
||||
};
|
||||
|
||||
static const GLenum glCmpFuncs[8] = {
|
||||
GL_NEVER,
|
||||
GL_LESS,
|
||||
GL_EQUAL,
|
||||
GL_LEQUAL,
|
||||
GL_GREATER,
|
||||
GL_NOTEQUAL,
|
||||
GL_GEQUAL,
|
||||
GL_ALWAYS
|
||||
};
|
||||
|
||||
static const GLenum glLogicOpCodes[16] = {
|
||||
GL_CLEAR,
|
||||
GL_AND,
|
||||
GL_AND_REVERSE,
|
||||
GL_COPY,
|
||||
GL_AND_INVERTED,
|
||||
GL_NOOP,
|
||||
GL_XOR,
|
||||
GL_OR,
|
||||
GL_NOR,
|
||||
GL_EQUIV,
|
||||
GL_INVERT,
|
||||
GL_OR_REVERSE,
|
||||
GL_COPY_INVERTED,
|
||||
GL_OR_INVERTED,
|
||||
GL_NAND,
|
||||
GL_SET
|
||||
};
|
||||
|
||||
#if defined HAVE_CG && HAVE_CG
|
||||
void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
|
||||
|
@ -908,6 +856,32 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
|
|||
|
||||
void Renderer::SetBlendMode(bool forceUpdate)
|
||||
{
|
||||
// Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
|
||||
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1.
|
||||
bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
const GLenum glSrcFactors[8] =
|
||||
{
|
||||
GL_ZERO,
|
||||
GL_ONE,
|
||||
GL_DST_COLOR,
|
||||
GL_ONE_MINUS_DST_COLOR,
|
||||
GL_SRC_ALPHA,
|
||||
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
||||
(target_has_alpha) ? GL_DST_ALPHA : (GLenum)GL_ONE,
|
||||
(target_has_alpha) ? GL_ONE_MINUS_DST_ALPHA : (GLenum)GL_ZERO
|
||||
};
|
||||
const GLenum glDestFactors[8] =
|
||||
{
|
||||
GL_ZERO,
|
||||
GL_ONE,
|
||||
GL_SRC_COLOR,
|
||||
GL_ONE_MINUS_SRC_COLOR,
|
||||
GL_SRC_ALPHA,
|
||||
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
||||
(target_has_alpha) ? GL_DST_ALPHA : (GLenum)GL_ONE,
|
||||
(target_has_alpha) ? GL_ONE_MINUS_DST_ALPHA : (GLenum)GL_ZERO
|
||||
};
|
||||
|
||||
// blend mode bit mask
|
||||
// 0 - blend enable
|
||||
// 2 - reverse subtract enable (else add)
|
||||
|
@ -951,10 +925,10 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
|||
|
||||
if (changes & 0x1F8)
|
||||
{
|
||||
#ifdef USE_DUAL_SOURCE_BLEND
|
||||
GLenum srcFactor = glSrcFactors[(newval >> 3) & 7];
|
||||
GLenum srcFactorAlpha = srcFactor;
|
||||
GLenum dstFactor = glDestFactors[(newval >> 6) & 7];
|
||||
#ifdef USE_DUAL_SOURCE_BLEND
|
||||
GLenum srcFactorAlpha = srcFactor;
|
||||
GLenum dstFactorAlpha = dstFactor;
|
||||
if (useDualSource)
|
||||
{
|
||||
|
@ -975,7 +949,7 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
|||
// blend RGB change
|
||||
glBlendFuncSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha);
|
||||
#else
|
||||
glBlendFunc(glSrcFactors[(newval >> 3) & 7], glDestFactors[(newval >> 6) & 7]);
|
||||
glBlendFunc(srcFactor, dstFactor);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1438,6 +1412,18 @@ void Renderer::SetGenerationMode()
|
|||
|
||||
void Renderer::SetDepthMode()
|
||||
{
|
||||
const GLenum glCmpFuncs[8] =
|
||||
{
|
||||
GL_NEVER,
|
||||
GL_LESS,
|
||||
GL_EQUAL,
|
||||
GL_LEQUAL,
|
||||
GL_GREATER,
|
||||
GL_NOTEQUAL,
|
||||
GL_GEQUAL,
|
||||
GL_ALWAYS
|
||||
};
|
||||
|
||||
if (bpmem.zmode.testenable)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
@ -1454,7 +1440,27 @@ void Renderer::SetDepthMode()
|
|||
|
||||
void Renderer::SetLogicOpMode()
|
||||
{
|
||||
if (bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3)
|
||||
const GLenum glLogicOpCodes[16] =
|
||||
{
|
||||
GL_CLEAR,
|
||||
GL_AND,
|
||||
GL_AND_REVERSE,
|
||||
GL_COPY,
|
||||
GL_AND_INVERTED,
|
||||
GL_NOOP,
|
||||
GL_XOR,
|
||||
GL_OR,
|
||||
GL_NOR,
|
||||
GL_EQUIV,
|
||||
GL_INVERT,
|
||||
GL_OR_REVERSE,
|
||||
GL_COPY_INVERTED,
|
||||
GL_OR_INVERTED,
|
||||
GL_NAND,
|
||||
GL_SET
|
||||
};
|
||||
|
||||
if (bpmem.blendmode.logicopenable)
|
||||
{
|
||||
glEnable(GL_COLOR_LOGIC_OP);
|
||||
glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]);
|
||||
|
|
|
@ -58,24 +58,6 @@ namespace OGL
|
|||
|
||||
static u32 s_TempFramebuffer = 0;
|
||||
|
||||
static const GLint c_MinLinearFilter[8] = {
|
||||
GL_NEAREST,
|
||||
GL_NEAREST_MIPMAP_NEAREST,
|
||||
GL_NEAREST_MIPMAP_LINEAR,
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
GL_LINEAR_MIPMAP_NEAREST,
|
||||
GL_LINEAR_MIPMAP_LINEAR,
|
||||
GL_LINEAR,
|
||||
};
|
||||
|
||||
static const GLint c_WrapSettings[4] = {
|
||||
GL_CLAMP_TO_EDGE,
|
||||
GL_REPEAT,
|
||||
GL_MIRRORED_REPEAT,
|
||||
GL_REPEAT,
|
||||
};
|
||||
|
||||
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level)
|
||||
{
|
||||
int width = std::max(virtual_width >> level, 1);
|
||||
|
@ -201,7 +183,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
|||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level, bool autogen_mips)
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
//glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
@ -212,16 +194,7 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
|||
if (expanded_width != width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
|
||||
|
||||
if (bHaveMipMaps && autogen_mips)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp);
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp);
|
||||
|
||||
if (expanded_width != width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
|
@ -357,35 +330,43 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
|||
|
||||
void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1)
|
||||
{
|
||||
// TODO: not used anywhere
|
||||
TexMode0 mode = newmode;
|
||||
//mode1 = newmode1;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
(newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
if (bHaveMipMaps)
|
||||
const GLint c_MinLinearFilter[8] =
|
||||
{
|
||||
// TODO: not used anywhere
|
||||
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
|
||||
mode.min_filter += 4; // take equivalent forced linear
|
||||
GL_NEAREST,
|
||||
GL_NEAREST_MIPMAP_NEAREST,
|
||||
GL_NEAREST_MIPMAP_LINEAR,
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
GL_LINEAR_MIPMAP_NEAREST,
|
||||
GL_LINEAR_MIPMAP_LINEAR,
|
||||
GL_LINEAR,
|
||||
};
|
||||
const GLint c_WrapSettings[4] =
|
||||
{
|
||||
GL_CLAMP_TO_EDGE,
|
||||
GL_REPEAT,
|
||||
GL_MIRRORED_REPEAT,
|
||||
GL_REPEAT,
|
||||
};
|
||||
|
||||
int filt = newmode.min_filter;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4);
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias / 32.0f));
|
||||
}
|
||||
else
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
(g_ActiveConfig.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
|
||||
int filt = newmode.min_filter;
|
||||
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
|
||||
filt += 4; // take equivalent forced linear
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod / 16.f);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod / 16.f);
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (s32)newmode.lod_bias / 32.0f);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]);
|
||||
|
||||
// TODO: Reset anisotrop when changed to 1
|
||||
if (g_Config.iMaxAnisotropy >= 1)
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
(float)(1 << g_ActiveConfig.iMaxAnisotropy));
|
||||
(float)(1 << g_ActiveConfig.iMaxAnisotropy));
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache()
|
||||
|
|
|
@ -54,7 +54,7 @@ private:
|
|||
~TCacheEntry();
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level, bool autogen_mips = false);
|
||||
unsigned int expanded_width, unsigned int level);
|
||||
|
||||
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||
|
|
|
@ -164,8 +164,8 @@ void VertexManager::vFlush()
|
|||
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
||||
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
||||
tex.texTlut[i&3].tlut_format,
|
||||
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
|
||||
tex.texMode1[i&3].max_lod >> 4,
|
||||
(tex.texMode0[i&3].min_filter & 3),
|
||||
ceil(tex.texMode1[i&3].max_lod / 16.f),
|
||||
tex.texImage1[i&3].image_type);
|
||||
|
||||
if (tentry)
|
||||
|
|
|
@ -431,7 +431,7 @@ static bool AlphaCompare(int alpha, int ref, int comp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool AlphaTest(int alpha)
|
||||
static bool TevAlphaTest(int alpha)
|
||||
{
|
||||
bool comp0 = AlphaCompare(alpha, bpmem.alpha_test.ref0, bpmem.alpha_test.comp0);
|
||||
bool comp1 = AlphaCompare(alpha, bpmem.alpha_test.ref1, bpmem.alpha_test.comp1);
|
||||
|
@ -700,7 +700,7 @@ void Tev::Draw()
|
|||
// convert to 8 bits per component
|
||||
u8 output[4] = {(u8)Reg[0][ALP_C], (u8)Reg[0][BLU_C], (u8)Reg[0][GRN_C], (u8)Reg[0][RED_C]};
|
||||
|
||||
if (!AlphaTest(output[ALP_C]))
|
||||
if (!TevAlphaTest(output[ALP_C]))
|
||||
return;
|
||||
|
||||
// z texture
|
||||
|
|
Loading…
Reference in New Issue