summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorskidau <skidau@gmail.com>2013-03-27 13:19:23 +1100
committerskidau <skidau@gmail.com>2013-03-27 13:19:23 +1100
commit7784fa4c67cc8d2545f45694d83805e7e89cd583 (patch)
tree7724133aabe971ec417d1dea0977a525bb8debfb /Source
parentd33c19b0cd2bae982c8d35e86a9d3551f9e5c72f (diff)
parent5cea0d9defeaa23e7af94adf7615a44fb2c9c173 (diff)
Merge branch 'master' into wii-network
# By Ryan Houdek (185) and others # Via degasus (12) and others * master: (625 commits) Revert "Don't open/close file for every file operation." as it was crashing PokePark in Windows builds. Array overrun fixed in VertexShaderCache for the DX11 plugin. Fixed DSPTool build. Windows build fix Go back to assuming every HID device is a wiimote on Windows. Fixed issue 6117. Unfixed issue 6031. VideoSoftware: Improve fog range adjustment by using less magic and more comments. revert RasterFont for VideoSoftware ogl: fix virtual xfb Windows build fix from web interface... Adjusted the audio loop criteria, using >= on the Wii and == on GC. This fixes the audio static that occurred in Wii games after hours of play. Forced the exception check only for ARAM DMA transfers. Removed the Eternal Darkness boot hack and replaced it with an exception check. VideoSoftware: Implement fog range adjustment, fixing issue 6147. implement 4xSSAA for OGL move ogl-only settings into backend Fix description of disable fog, and move it to enhancements tab. Reverted rd76ca5783743 as it was made obsolete by r1d550f4496e4. Removed the tracking of the FIFO Writes as it was made obsolete by r1d550f4496e4. Forced the external exception check to occur sooner by changing the downcount. Mark the Direct3D9 backend deprecated. Prefer D3D11 and OpenGL over D3D9 by default. ... Conflicts: CMakeLists.txt Source/Core/Common/Common.vcxproj.filters Source/Core/Common/Src/CommonPaths.h Source/Core/Core/Core.vcxproj.filters Source/Core/Core/Src/Core.cpp Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp Source/VSProps/Dolphin.Win32.props Source/VSProps/Dolphin.x64.props
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/AudioCommon/CMakeLists.txt5
-rw-r--r--Source/Core/AudioCommon/Src/AOSoundStream.cpp6
-rw-r--r--Source/Core/AudioCommon/Src/AOSoundStream.h12
-rw-r--r--Source/Core/AudioCommon/Src/AlsaSoundStream.cpp32
-rw-r--r--Source/Core/AudioCommon/Src/AudioCommon.cpp7
-rw-r--r--Source/Core/AudioCommon/Src/CoreAudioSoundStream.h6
-rw-r--r--Source/Core/AudioCommon/Src/DPL2Decoder.cpp52
-rw-r--r--Source/Core/AudioCommon/Src/DSoundStream.cpp2
-rw-r--r--Source/Core/AudioCommon/Src/DSoundStream.h52
-rw-r--r--Source/Core/AudioCommon/Src/Mixer.cpp11
-rw-r--r--Source/Core/AudioCommon/Src/NullSoundStream.h18
-rw-r--r--Source/Core/AudioCommon/Src/OpenALStream.cpp2
-rw-r--r--Source/Core/AudioCommon/Src/OpenSLESStream.cpp145
-rw-r--r--Source/Core/AudioCommon/Src/OpenSLESStream.h48
-rw-r--r--Source/Core/AudioCommon/Src/SoundStream.h10
-rw-r--r--Source/Core/AudioCommon/Src/WaveFile.cpp10
-rw-r--r--Source/Core/AudioCommon/Src/XAudio2Stream.cpp6
-rw-r--r--Source/Core/Common/CMakeLists.txt23
-rw-r--r--Source/Core/Common/Common.vcxproj13
-rw-r--r--Source/Core/Common/Common.vcxproj.filters9
-rw-r--r--Source/Core/Common/Src/ArmCPUDetect.cpp167
-rw-r--r--Source/Core/Common/Src/ArmEmitter.cpp1110
-rw-r--r--Source/Core/Common/Src/ArmEmitter.h637
-rw-r--r--Source/Core/Common/Src/BreakPoints.h8
-rw-r--r--Source/Core/Common/Src/CDUtils.cpp11
-rw-r--r--Source/Core/Common/Src/CPUDetect.h29
-rw-r--r--Source/Core/Common/Src/ChunkFile.h242
-rw-r--r--Source/Core/Common/Src/Common.h7
-rw-r--r--Source/Core/Common/Src/CommonFuncs.h59
-rw-r--r--Source/Core/Common/Src/CommonPaths.h9
-rw-r--r--Source/Core/Common/Src/ConsoleListener.cpp12
-rw-r--r--Source/Core/Common/Src/Crypto/md5.cpp9
-rw-r--r--Source/Core/Common/Src/Crypto/sha1.cpp9
-rw-r--r--Source/Core/Common/Src/ExtendedTrace.cpp52
-rw-r--r--Source/Core/Common/Src/ExtendedTrace.h19
-rw-r--r--Source/Core/Common/Src/FPURoundMode.h52
-rw-r--r--Source/Core/Common/Src/FileSearch.cpp5
-rw-r--r--Source/Core/Common/Src/FileUtil.cpp95
-rw-r--r--Source/Core/Common/Src/FileUtil.h12
-rw-r--r--Source/Core/Common/Src/GenericFPURoundMode.cpp41
-rw-r--r--Source/Core/Common/Src/Hash.cpp172
-rw-r--r--Source/Core/Common/Src/IniFile.cpp5
-rw-r--r--Source/Core/Common/Src/LinearDiskCache.h17
-rw-r--r--Source/Core/Common/Src/LogManager.cpp29
-rw-r--r--Source/Core/Common/Src/LogManager.h2
-rw-r--r--Source/Core/Common/Src/MathUtil.cpp148
-rw-r--r--Source/Core/Common/Src/MathUtil.h66
-rw-r--r--Source/Core/Common/Src/MemArena.cpp34
-rw-r--r--Source/Core/Common/Src/MemoryUtil.cpp9
-rw-r--r--Source/Core/Common/Src/Misc.cpp2
-rw-r--r--Source/Core/Common/Src/MsgHandler.cpp15
-rw-r--r--Source/Core/Common/Src/NandPaths.cpp6
-rw-r--r--Source/Core/Common/Src/SDCardUtil.cpp7
-rw-r--r--Source/Core/Common/Src/StdConditionVariable.h4
-rw-r--r--Source/Core/Common/Src/StdMutex.h2
-rw-r--r--Source/Core/Common/Src/StdThread.h4
-rw-r--r--Source/Core/Common/Src/StringUtil.cpp186
-rw-r--r--Source/Core/Common/Src/StringUtil.h24
-rw-r--r--Source/Core/Common/Src/Thread.cpp2
-rw-r--r--Source/Core/Common/Src/Thread.h4
-rw-r--r--Source/Core/Common/Src/Version.cpp2
-rw-r--r--Source/Core/Common/Src/VideoBackendBase.cpp25
-rw-r--r--Source/Core/Common/Src/VideoBackendBase.h8
-rw-r--r--Source/Core/Common/Src/x64ABI.cpp (renamed from Source/Core/Common/Src/ABI.cpp)98
-rw-r--r--Source/Core/Common/Src/x64ABI.h (renamed from Source/Core/Common/Src/ABI.h)0
-rw-r--r--Source/Core/Common/Src/x64Analyzer.cpp42
-rw-r--r--Source/Core/Common/Src/x64Analyzer.h2
-rw-r--r--Source/Core/Common/Src/x64CPUDetect.cpp (renamed from Source/Core/Common/Src/CPUDetect.cpp)8
-rw-r--r--Source/Core/Common/Src/x64Emitter.cpp218
-rw-r--r--Source/Core/Common/Src/x64Emitter.h4
-rw-r--r--Source/Core/Common/Src/x64FPURoundMode.cpp120
-rw-r--r--Source/Core/Common/Src/x64Thunk.cpp (renamed from Source/Core/Common/Src/Thunk.cpp)3
-rw-r--r--Source/Core/Core/CMakeLists.txt36
-rw-r--r--Source/Core/Core/Core.vcxproj16
-rw-r--r--Source/Core/Core/Core.vcxproj.filters11
-rw-r--r--Source/Core/Core/Src/ArmMemTools.cpp103
-rw-r--r--Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp4
-rw-r--r--Source/Core/Core/Src/BootManager.cpp5
-rw-r--r--Source/Core/Core/Src/ConfigManager.cpp37
-rw-r--r--Source/Core/Core/Src/ConfigManager.h9
-rw-r--r--Source/Core/Core/Src/Console.cpp4
-rw-r--r--Source/Core/Core/Src/Core.cpp21
-rw-r--r--Source/Core/Core/Src/Core.h2
-rw-r--r--Source/Core/Core/Src/CoreParameter.cpp3
-rw-r--r--Source/Core/Core/Src/CoreParameter.h1
-rw-r--r--Source/Core/Core/Src/CoreTiming.cpp10
-rw-r--r--Source/Core/Core/Src/CoreTiming.h2
-rw-r--r--Source/Core/Core/Src/DSP/DSPAccelerator.cpp6
-rw-r--r--Source/Core/Core/Src/DSP/DSPCore.cpp61
-rw-r--r--Source/Core/Core/Src/DSP/DSPEmitter.cpp2
-rw-r--r--Source/Core/Core/Src/DSP/DSPHWInterface.cpp2
-rw-r--r--Source/Core/Core/Src/DSP/DSPHost.h1
-rw-r--r--Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp2
-rw-r--r--Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp2
-rw-r--r--Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp2
-rw-r--r--Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp2
-rw-r--r--Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp2
-rw-r--r--Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp2
-rw-r--r--Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp2
-rw-r--r--Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp2
-rw-r--r--Source/Core/Core/Src/DSP/assemble.cpp3
-rw-r--r--Source/Core/Core/Src/HW/AudioInterface.cpp27
-rw-r--r--Source/Core/Core/Src/HW/AudioInterface.h2
-rw-r--r--Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp46
-rw-r--r--Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h14
-rw-r--r--Source/Core/Core/Src/HW/DSP.cpp15
-rw-r--r--Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp9
-rw-r--r--Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h7
-rw-r--r--Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp6
-rw-r--r--Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp17
-rw-r--r--Source/Core/Core/Src/HW/DVDInterface.cpp9
-rw-r--r--Source/Core/Core/Src/HW/EXI_Channel.cpp14
-rw-r--r--Source/Core/Core/Src/HW/EXI_Channel.h4
-rw-r--r--Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp38
-rw-r--r--Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.h11
-rw-r--r--Source/Core/Core/Src/HW/GCMemcard.cpp4
-rw-r--r--Source/Core/Core/Src/HW/GPFifo.cpp9
-rw-r--r--Source/Core/Core/Src/HW/Memmap.cpp126
-rw-r--r--Source/Core/Core/Src/HW/Memmap.h5
-rw-r--r--Source/Core/Core/Src/HW/ProcessorInterface.cpp2
-rw-r--r--Source/Core/Core/Src/HW/SI_DeviceGCController.cpp15
-rw-r--r--Source/Core/Core/Src/HW/SI_DeviceGCController.h1
-rw-r--r--Source/Core/Core/Src/HW/SystemTimers.cpp33
-rw-r--r--Source/Core/Core/Src/HW/WII_IPC.cpp11
-rw-r--r--Source/Core/Core/Src/HW/WII_IPC.h2
-rw-r--r--Source/Core/Core/Src/HW/Wiimote.cpp2
-rw-r--r--Source/Core/Core/Src/HW/Wiimote.h10
-rw-r--r--Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp9
-rw-r--r--Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp2
-rw-r--r--Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp2
-rw-r--r--Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h4
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp30
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp234
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp657
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm125
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp547
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h90
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h6
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp37
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h1
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp5
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp2
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp2
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp3
-rw-r--r--Source/Core/Core/Src/Movie.cpp2
-rw-r--r--Source/Core/Core/Src/NetPlay.h2
-rw-r--r--Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp4
-rw-r--r--Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp21
-rw-r--r--Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp52
-rw-r--r--Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp3
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp36
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit.h2
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp1
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp6
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h1
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp4
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp2
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp3
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp25
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp2
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/IR.h9
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp50
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp9
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h2
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp8
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp2
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp2
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp2
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp4
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp1
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp498
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/Jit.h186
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp46
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.h (renamed from Source/Core/DolphinWX/Src/GLInterface/WX.h)37
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArm_BackPatch.cpp164
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp356
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp80
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp308
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp414
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp72
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp104
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp502
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.h29
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp174
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.h43
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.cpp169
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.h62
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.cpp168
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.h92
-rw-r--r--Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp5
-rw-r--r--Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h25
-rw-r--r--Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp4
-rw-r--r--Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h4
-rw-r--r--Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h28
-rw-r--r--Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp94
-rw-r--r--Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h16
-rw-r--r--Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp2
-rw-r--r--Source/Core/Core/Src/PowerPC/JitInterface.cpp351
-rw-r--r--Source/Core/Core/Src/PowerPC/JitInterface.h53
-rw-r--r--Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp3
-rw-r--r--Source/Core/Core/Src/PowerPC/PPCCache.cpp7
-rw-r--r--Source/Core/Core/Src/PowerPC/PPCTables.cpp18
-rw-r--r--Source/Core/Core/Src/PowerPC/PowerPC.cpp79
-rw-r--r--Source/Core/Core/Src/PowerPC/Profiler.cpp78
-rw-r--r--Source/Core/Core/Src/PowerPC/Profiler.h9
-rw-r--r--Source/Core/Core/Src/State.cpp2
-rw-r--r--Source/Core/Core/Src/x64MemTools.cpp (renamed from Source/Core/Core/Src/MemTools.cpp)12
-rw-r--r--Source/Core/DiscIO/DiscIO.vcxproj4
-rw-r--r--Source/Core/DiscIO/Src/BannerLoader.cpp176
-rw-r--r--Source/Core/DiscIO/Src/BannerLoader.h24
-rw-r--r--Source/Core/DiscIO/Src/BannerLoaderGC.cpp143
-rw-r--r--Source/Core/DiscIO/Src/BannerLoaderGC.h36
-rw-r--r--Source/Core/DiscIO/Src/BannerLoaderWii.cpp76
-rw-r--r--Source/Core/DiscIO/Src/BannerLoaderWii.h13
-rw-r--r--Source/Core/DiscIO/Src/CISOBlob.cpp64
-rw-r--r--Source/Core/DiscIO/Src/CISOBlob.h44
-rw-r--r--Source/Core/DiscIO/Src/CompressedBlob.cpp3
-rw-r--r--Source/Core/DiscIO/Src/DriveBlob.cpp8
-rw-r--r--Source/Core/DiscIO/Src/FileHandlerARC.cpp24
-rw-r--r--Source/Core/DiscIO/Src/FileSystemGCWii.cpp32
-rw-r--r--Source/Core/DiscIO/Src/FileSystemGCWii.h6
-rw-r--r--Source/Core/DiscIO/Src/NANDContentLoader.cpp2
-rw-r--r--Source/Core/DiscIO/Src/NANDContentLoader.h64
-rw-r--r--Source/Core/DiscIO/Src/Volume.h6
-rw-r--r--Source/Core/DiscIO/Src/VolumeCommon.cpp10
-rw-r--r--Source/Core/DiscIO/Src/VolumeDirectory.cpp5
-rw-r--r--Source/Core/DiscIO/Src/VolumeDirectory.h4
-rw-r--r--Source/Core/DiscIO/Src/VolumeGC.cpp21
-rw-r--r--Source/Core/DiscIO/Src/VolumeGC.h6
-rw-r--r--Source/Core/DiscIO/Src/VolumeWad.cpp81
-rw-r--r--Source/Core/DiscIO/Src/VolumeWad.h3
-rw-r--r--Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp21
-rw-r--r--Source/Core/DiscIO/Src/VolumeWiiCrypted.h2
-rw-r--r--Source/Core/DiscIO/Src/WbfsBlob.cpp28
-rw-r--r--Source/Core/DiscIO/Src/WbfsBlob.h2
-rw-r--r--Source/Core/DiscIO/Src/WiiWad.cpp121
-rw-r--r--Source/Core/DiscIO/Src/WiiWad.h4
-rw-r--r--Source/Core/DolphinWX/CMakeLists.txt173
-rw-r--r--Source/Core/DolphinWX/Dolphin.vcxproj6
-rw-r--r--Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp11
-rw-r--r--Source/Core/DolphinWX/Src/AboutDolphin.cpp3
-rw-r--r--Source/Core/DolphinWX/Src/CheatsWindow.cpp13
-rw-r--r--Source/Core/DolphinWX/Src/ConfigMain.cpp74
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp5
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp19
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/CodeView.cpp39
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp35
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp23
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp6
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp4
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp17
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp5
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp26
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp17
-rw-r--r--Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp9
-rw-r--r--Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp7
-rw-r--r--Source/Core/DolphinWX/Src/Frame.cpp37
-rw-r--r--Source/Core/DolphinWX/Src/FrameAui.cpp11
-rw-r--r--Source/Core/DolphinWX/Src/FrameTools.cpp100
-rw-r--r--Source/Core/DolphinWX/Src/GLInterface.h21
-rw-r--r--Source/Core/DolphinWX/Src/GLInterface/AGL.cpp61
-rw-r--r--Source/Core/DolphinWX/Src/GLInterface/AGL.h5
-rw-r--r--Source/Core/DolphinWX/Src/GLInterface/EGL_X11.cpp (renamed from Source/Core/DolphinWX/Src/GLInterface/EGL.cpp)4
-rw-r--r--Source/Core/DolphinWX/Src/GLInterface/EGL_X11.h (renamed from Source/Core/DolphinWX/Src/GLInterface/EGL.h)1
-rw-r--r--Source/Core/DolphinWX/Src/GLInterface/GLX.cpp2
-rw-r--r--Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h10
-rw-r--r--Source/Core/DolphinWX/Src/GLInterface/WX.cpp96
-rw-r--r--Source/Core/DolphinWX/Src/GameListCtrl.cpp145
-rw-r--r--Source/Core/DolphinWX/Src/GameListCtrl.h8
-rw-r--r--Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp9
-rw-r--r--Source/Core/DolphinWX/Src/ISOFile.cpp166
-rw-r--r--Source/Core/DolphinWX/Src/ISOFile.h27
-rw-r--r--Source/Core/DolphinWX/Src/ISOProperties.cpp141
-rw-r--r--Source/Core/DolphinWX/Src/ISOProperties.h3
-rw-r--r--Source/Core/DolphinWX/Src/InputConfigDiag.cpp75
-rw-r--r--Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp11
-rw-r--r--Source/Core/DolphinWX/Src/LogConfigWindow.cpp3
-rw-r--r--Source/Core/DolphinWX/Src/LogWindow.cpp27
-rw-r--r--Source/Core/DolphinWX/Src/LogWindow.h2
-rw-r--r--Source/Core/DolphinWX/Src/Main.cpp101
-rw-r--r--Source/Core/DolphinWX/Src/Main.h2
-rw-r--r--Source/Core/DolphinWX/Src/MainAndroid.cpp149
-rw-r--r--Source/Core/DolphinWX/Src/MemcardManager.cpp63
-rw-r--r--Source/Core/DolphinWX/Src/NetWindow.cpp96
-rw-r--r--Source/Core/DolphinWX/Src/PHackSettings.cpp13
-rw-r--r--Source/Core/DolphinWX/Src/PatchAddEdit.cpp9
-rw-r--r--Source/Core/DolphinWX/Src/UDPConfigDiag.cpp8
-rw-r--r--Source/Core/DolphinWX/Src/VideoConfigDiag.cpp36
-rw-r--r--Source/Core/DolphinWX/Src/VideoConfigDiag.h5
-rw-r--r--Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp93
-rw-r--r--Source/Core/DolphinWX/Src/WiimoteConfigDiag.h20
-rw-r--r--Source/Core/DolphinWX/Src/WxUtils.cpp17
-rw-r--r--Source/Core/DolphinWX/Src/WxUtils.h9
-rw-r--r--Source/Core/DolphinWX/Src/X11Utils.cpp3
-rw-r--r--Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp16
-rw-r--r--Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm1
-rw-r--r--Source/Core/InputCommon/Src/X11InputBase.cpp508
-rw-r--r--Source/Core/VideoCommon/CMakeLists.txt11
-rw-r--r--Source/Core/VideoCommon/Src/AVIDump.cpp20
-rw-r--r--Source/Core/VideoCommon/Src/AVIDump.h6
-rw-r--r--Source/Core/VideoCommon/Src/BPFunctions.cpp3
-rw-r--r--Source/Core/VideoCommon/Src/BPMemory.h893
-rw-r--r--Source/Core/VideoCommon/Src/BPStructs.cpp32
-rw-r--r--Source/Core/VideoCommon/Src/CPMemory.h260
-rw-r--r--Source/Core/VideoCommon/Src/CommandProcessor.cpp153
-rw-r--r--Source/Core/VideoCommon/Src/CommandProcessor.h11
-rw-r--r--Source/Core/VideoCommon/Src/DataReader.h98
-rw-r--r--Source/Core/VideoCommon/Src/EmuWindow.cpp8
-rw-r--r--Source/Core/VideoCommon/Src/Fifo.cpp127
-rw-r--r--Source/Core/VideoCommon/Src/Fifo.h2
-rw-r--r--Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp16
-rw-r--r--Source/Core/VideoCommon/Src/GenericDLCache.cpp52
-rw-r--r--Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp2210
-rw-r--r--Source/Core/VideoCommon/Src/ImageWrite.cpp37
-rw-r--r--Source/Core/VideoCommon/Src/IndexGenerator.cpp364
-rw-r--r--Source/Core/VideoCommon/Src/IndexGenerator.h71
-rw-r--r--Source/Core/VideoCommon/Src/LightingShaderGen.cpp34
-rw-r--r--Source/Core/VideoCommon/Src/MainBase.cpp48
-rw-r--r--Source/Core/VideoCommon/Src/NativeVertexFormat.h2
-rw-r--r--Source/Core/VideoCommon/Src/OnScreenDisplay.h2
-rw-r--r--Source/Core/VideoCommon/Src/OpcodeDecoding.cpp473
-rw-r--r--Source/Core/VideoCommon/Src/OpcodeDecoding.h4
-rw-r--r--Source/Core/VideoCommon/Src/OpenCL.cpp30
-rw-r--r--Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp4
-rw-r--r--Source/Core/VideoCommon/Src/PerfQueryBase.cpp3
-rw-r--r--Source/Core/VideoCommon/Src/PerfQueryBase.h54
-rw-r--r--Source/Core/VideoCommon/Src/PixelEngine.cpp162
-rw-r--r--Source/Core/VideoCommon/Src/PixelEngine.h41
-rw-r--r--Source/Core/VideoCommon/Src/PixelShaderGen.cpp423
-rw-r--r--Source/Core/VideoCommon/Src/PixelShaderGen.h17
-rw-r--r--Source/Core/VideoCommon/Src/PixelShaderManager.cpp225
-rw-r--r--Source/Core/VideoCommon/Src/PixelShaderManager.h1
-rw-r--r--Source/Core/VideoCommon/Src/RenderBase.cpp5
-rw-r--r--Source/Core/VideoCommon/Src/RenderBase.h11
-rw-r--r--Source/Core/VideoCommon/Src/Statistics.cpp4
-rw-r--r--Source/Core/VideoCommon/Src/Statistics.h68
-rw-r--r--Source/Core/VideoCommon/Src/TextureCacheBase.cpp19
-rw-r--r--Source/Core/VideoCommon/Src/TextureConversionShader.cpp661
-rw-r--r--Source/Core/VideoCommon/Src/TextureDecoder.h62
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader.cpp267
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader.h12
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader_Color.cpp95
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp485
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader_Normal.h105
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader_Position.cpp244
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader_Position.h12
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp403
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader_TextCoord.h16
-rw-r--r--Source/Core/VideoCommon/Src/VertexManagerBase.cpp190
-rw-r--r--Source/Core/VideoCommon/Src/VertexManagerBase.h70
-rw-r--r--Source/Core/VideoCommon/Src/VertexShaderGen.cpp319
-rw-r--r--Source/Core/VideoCommon/Src/VertexShaderGen.h34
-rw-r--r--Source/Core/VideoCommon/Src/VertexShaderManager.cpp38
-rw-r--r--Source/Core/VideoCommon/Src/VertexShaderManager.h2
-rw-r--r--Source/Core/VideoCommon/Src/VideoCommon.h13
-rw-r--r--Source/Core/VideoCommon/Src/VideoConfig.cpp29
-rw-r--r--Source/Core/VideoCommon/Src/VideoConfig.h31
-rw-r--r--Source/Core/VideoCommon/Src/VideoState.cpp30
-rw-r--r--Source/Core/VideoCommon/Src/XFMemory.h196
-rw-r--r--Source/Core/VideoCommon/Src/XFStructs.cpp128
-rw-r--r--Source/Core/VideoCommon/Src/memcpy_amd.cpp4
-rw-r--r--Source/Core/VideoCommon/Src/x64DLCache.cpp (renamed from Source/Core/VideoCommon/Src/DLCache.cpp)38
-rw-r--r--Source/Core/VideoCommon/Src/x64TextureDecoder.cpp (renamed from Source/Core/VideoCommon/Src/TextureDecoder.cpp)129
-rw-r--r--Source/Core/VideoCommon/VideoCommon.vcxproj12
-rw-r--r--Source/Core/VideoCommon/VideoCommon.vcxproj.filters20
-rw-r--r--Source/DSPTool/Src/DSPTool.cpp1
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj2
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters6
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp2
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp9
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp4
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp150
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h46
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/Render.cpp26
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp122
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h24
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp2
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/VideoBackend.h1
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/main.cpp13
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp228
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h11
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp6
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp30
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp4
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp2
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/Render.cpp41
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp4
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp257
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/VertexManager.h25
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/VideoBackend.h2
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/main.cpp14
-rw-r--r--Source/Plugins/Plugin_VideoOGL/CMakeLists.txt10
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj34
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters17
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp199
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.h6
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp44
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h24
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp242
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp133
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h46
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp358
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h91
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp167
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.h8
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp553
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h137
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp235
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/RasterFont.h25
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/Render.cpp756
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/Render.h19
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.cpp129
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.h80
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp242
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.h72
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp308
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h8
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp305
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h2
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp208
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h25
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp268
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h76
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/VideoBackend.h1
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/main.cpp79
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt1
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj2
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj.filters2
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp15
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp7
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h3
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp16
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h1
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h13
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp21
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h3
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.cpp223
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.h42
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp35
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h9
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp15
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp6
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h77
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp11
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp13
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h3
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp44
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp47
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp30
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h2
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp62
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Tev.h3
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp6
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h7
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h3
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp6
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h11
-rw-r--r--Source/TestSuite/d.supp39
-rw-r--r--Source/VSProps/Dolphin.Win32.props4
-rw-r--r--Source/VSProps/Dolphin.x64.props4
460 files changed, 20821 insertions, 10613 deletions
diff --git a/Source/Core/AudioCommon/CMakeLists.txt b/Source/Core/AudioCommon/CMakeLists.txt
index 3b6d0cea4d..939956460d 100644
--- a/Source/Core/AudioCommon/CMakeLists.txt
+++ b/Source/Core/AudioCommon/CMakeLists.txt
@@ -6,6 +6,11 @@ set(SRCS Src/AudioCommon.cpp
set(LIBS "")
+if(ANDROID)
+ set(SRCS ${SRCS} Src/OpenSLESStream.cpp)
+ set(LIBS ${LIBS} OpenSLES)
+endif(ANDROID)
+
if(ALSA_FOUND)
set(SRCS ${SRCS} Src/AlsaSoundStream.cpp)
set(LIBS ${LIBS} ${ALSA_LIBRARIES})
diff --git a/Source/Core/AudioCommon/Src/AOSoundStream.cpp b/Source/Core/AudioCommon/Src/AOSoundStream.cpp
index 99ae2e661c..0ec6451666 100644
--- a/Source/Core/AudioCommon/Src/AOSoundStream.cpp
+++ b/Source/Core/AudioCommon/Src/AOSoundStream.cpp
@@ -34,7 +34,7 @@ void AOSound::SoundLoop()
format.channels = 2;
format.rate = m_mixer->GetSampleRate();
format.byte_format = AO_FMT_LITTLE;
-
+
device = ao_open_live(default_driver, &format, NULL /* no options */);
if (!device)
{
@@ -49,7 +49,7 @@ void AOSound::SoundLoop()
while (!threadData)
{
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
-
+
{
std::lock_guard<std::mutex> lk(soundCriticalSection);
ao_play(device, (char*)realtimeBuffer, numBytesToRender);
@@ -62,7 +62,7 @@ void AOSound::SoundLoop()
bool AOSound::Start()
{
memset(realtimeBuffer, 0, sizeof(realtimeBuffer));
-
+
thread = std::thread(std::mem_fun(&AOSound::SoundLoop), this);
return true;
}
diff --git a/Source/Core/AudioCommon/Src/AOSoundStream.h b/Source/Core/AudioCommon/Src/AOSoundStream.h
index a631596f02..0c11586b42 100644
--- a/Source/Core/AudioCommon/Src/AOSoundStream.h
+++ b/Source/Core/AudioCommon/Src/AOSoundStream.h
@@ -45,21 +45,21 @@ public:
AOSound(CMixer *mixer) : SoundStream(mixer) {}
virtual ~AOSound();
-
+
virtual bool Start();
-
+
virtual void SoundLoop();
-
+
virtual void Stop();
-
+
static bool isValid() {
return true;
}
-
+
virtual bool usesMixer() const {
return true;
}
-
+
virtual void Update();
#else
diff --git a/Source/Core/AudioCommon/Src/AlsaSoundStream.cpp b/Source/Core/AudioCommon/Src/AlsaSoundStream.cpp
index 710275d55a..d9b9016114 100644
--- a/Source/Core/AudioCommon/Src/AlsaSoundStream.cpp
+++ b/Source/Core/AudioCommon/Src/AlsaSoundStream.cpp
@@ -88,7 +88,7 @@ bool AlsaSound::AlsaInit()
snd_pcm_hw_params_t *hwparams;
snd_pcm_uframes_t buffer_size,buffer_size_max;
unsigned int periods;
-
+
err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0)
{
@@ -97,7 +97,7 @@ bool AlsaSound::AlsaInit()
}
snd_pcm_hw_params_alloca(&hwparams);
-
+
err = snd_pcm_hw_params_any(handle, hwparams);
if (err < 0)
{
@@ -111,8 +111,8 @@ bool AlsaSound::AlsaInit()
ERROR_LOG(AUDIO, "Access type not available: %s\n", snd_strerror(err));
return false;
}
-
- err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16_LE);
+
+ err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16_LE);
if (err < 0)
{
ERROR_LOG(AUDIO, "Sample format not available: %s\n", snd_strerror(err));
@@ -126,14 +126,14 @@ bool AlsaSound::AlsaInit()
ERROR_LOG(AUDIO, "Rate not available: %s\n", snd_strerror(err));
return false;
}
-
- err = snd_pcm_hw_params_set_channels(handle, hwparams, 2);
+
+ err = snd_pcm_hw_params_set_channels(handle, hwparams, 2);
if (err < 0)
{
ERROR_LOG(AUDIO, "Channels count not available: %s\n", snd_strerror(err));
return false;
}
-
+
periods = BUFFER_SIZE_MAX / FRAME_COUNT_MIN;
err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &periods, &dir);
if (err < 0)
@@ -153,10 +153,10 @@ bool AlsaSound::AlsaInit()
err = snd_pcm_hw_params(handle, hwparams);
if (err < 0)
{
- ERROR_LOG(AUDIO, "Unable to install hw params: %s\n", snd_strerror(err));
+ ERROR_LOG(AUDIO, "Unable to install hw params: %s\n", snd_strerror(err));
return false;
}
-
+
err = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
if (err < 0)
{
@@ -176,10 +176,10 @@ bool AlsaSound::AlsaInit()
frames_to_deliver = buffer_size / periods;
//limit the minimum size. pulseaudio advertises a minimum of 32 samples.
if (frames_to_deliver < FRAME_COUNT_MIN)
- frames_to_deliver = FRAME_COUNT_MIN;
+ frames_to_deliver = FRAME_COUNT_MIN;
//it is probably a bad idea to try to send more than one buffer of data
if ((unsigned int)frames_to_deliver > buffer_size)
- frames_to_deliver = buffer_size;
+ frames_to_deliver = buffer_size;
NOTICE_LOG(AUDIO, "ALSA gave us a %ld sample \"hardware\" buffer with %d periods. Will send %d samples per fragments.\n", buffer_size, periods, frames_to_deliver);
snd_pcm_sw_params_alloca(&swparams);
@@ -187,21 +187,21 @@ bool AlsaSound::AlsaInit()
err = snd_pcm_sw_params_current(handle, swparams);
if (err < 0)
{
- ERROR_LOG(AUDIO, "cannot init sw params: %s\n", snd_strerror(err));
+ ERROR_LOG(AUDIO, "cannot init sw params: %s\n", snd_strerror(err));
return false;
}
-
+
err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0U);
if (err < 0)
{
- ERROR_LOG(AUDIO, "cannot set start thresh: %s\n", snd_strerror(err));
+ ERROR_LOG(AUDIO, "cannot set start thresh: %s\n", snd_strerror(err));
return false;
}
-
+
err = snd_pcm_sw_params(handle, swparams);
if (err < 0)
{
- ERROR_LOG(AUDIO, "cannot set sw params: %s\n", snd_strerror(err));
+ ERROR_LOG(AUDIO, "cannot set sw params: %s\n", snd_strerror(err));
return false;
}
diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp
index e14b9ac45e..2f299d0edb 100644
--- a/Source/Core/AudioCommon/Src/AudioCommon.cpp
+++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp
@@ -26,6 +26,7 @@
#include "CoreAudioSoundStream.h"
#include "OpenALStream.h"
#include "PulseAudioStream.h"
+#include "OpenSLESStream.h"
#include "../../Core/Src/Movie.h"
#include "../../Core/Src/ConfigManager.h"
@@ -55,7 +56,8 @@ namespace AudioCommon
soundStream = new CoreAudioSound(mixer);
else if (backend == BACKEND_PULSEAUDIO && PulseAudio::isValid())
soundStream = new PulseAudio(mixer);
-
+ else if (backend == BACKEND_OPENSLES && OpenSLESStream::isValid())
+ soundStream = new OpenSLESStream(mixer);
if (soundStream != NULL)
{
UpdateSoundStream();
@@ -116,7 +118,8 @@ namespace AudioCommon
backends.push_back(BACKEND_PULSEAUDIO);
if (OpenALStream::isValid())
backends.push_back(BACKEND_OPENAL);
-
+ if (OpenSLESStream::isValid())
+ backends.push_back(BACKEND_OPENSLES);
return backends;
}
diff --git a/Source/Core/AudioCommon/Src/CoreAudioSoundStream.h b/Source/Core/AudioCommon/Src/CoreAudioSoundStream.h
index 581e4aabd8..34db5ac837 100644
--- a/Source/Core/AudioCommon/Src/CoreAudioSoundStream.h
+++ b/Source/Core/AudioCommon/Src/CoreAudioSoundStream.h
@@ -30,19 +30,19 @@ class CoreAudioSound : public SoundStream
public:
CoreAudioSound(CMixer *mixer);
virtual ~CoreAudioSound();
-
+
virtual bool Start();
virtual void SetVolume(int volume);
virtual void SoundLoop();
virtual void Stop();
-
+
static bool isValid() {
return true;
}
virtual bool usesMixer() const {
return true;
}
-
+
virtual void Update();
private:
diff --git a/Source/Core/AudioCommon/Src/DPL2Decoder.cpp b/Source/Core/AudioCommon/Src/DPL2Decoder.cpp
index 6a63f696de..c33333fb47 100644
--- a/Source/Core/AudioCommon/Src/DPL2Decoder.cpp
+++ b/Source/Core/AudioCommon/Src/DPL2Decoder.cpp
@@ -130,15 +130,15 @@ returns 0 if OK, -1 if fail
*/
float* design_fir(unsigned int *n, float* fc, float opt)
{
- unsigned int o = *n & 1; // Indicator for odd filter length
- unsigned int end = ((*n + 1) >> 1) - o; // Loop end
- unsigned int i; // Loop index
+ unsigned int o = *n & 1; // Indicator for odd filter length
+ unsigned int end = ((*n + 1) >> 1) - o; // Loop end
+ unsigned int i; // Loop index
- float k1 = 2 * float(M_PI); // 2*pi*fc1
- float k2 = 0.5f * (float)(1 - o);// Constant used if the filter has even length
- float g = 0.0f; // Gain
- float t1; // Temporary variables
- float fc1; // Cutoff frequencies
+ float k1 = 2 * float(M_PI); // 2*pi*fc1
+ float k2 = 0.5f * (float)(1 - o); // Constant used if the filter has even length
+ float g = 0.0f; // Gain
+ float t1; // Temporary variables
+ float fc1; // Cutoff frequencies
// Sanity check
if(*n==0) return NULL;
@@ -241,18 +241,18 @@ void matrix_decode(const float *in, const int k, const int il,
float *_rr, float *_cf)
{
static const float M9_03DB = 0.3535533906f;
- static const float MATAGCTRIG = 8.0f; /* (Fuzzy) AGC trigger */
- static const float MATAGCDECAY = 1.0f; /* AGC baseline decay rate (1/samp.) */
+ static const float MATAGCTRIG = 8.0f; /* (Fuzzy) AGC trigger */
+ static const float MATAGCDECAY = 1.0f; /* AGC baseline decay rate (1/samp.) */
static const float MATCOMPGAIN = 0.37f; /* Cross talk compensation gain, 0.50 - 0.55 is full cancellation. */
const int kr = (k + olddelay) % _dlbuflen;
float l_gain = (_l_fwr + _r_fwr) / (1 + _l_fwr + _l_fwr);
float r_gain = (_l_fwr + _r_fwr) / (1 + _r_fwr + _r_fwr);
- /* The 2nd axis has strong gain fluctuations, and therefore require
- limits. The factor corresponds to the 1 / amplification of (Lt
- - Rt) when (Lt, Rt) is strongly correlated. (e.g. during
- dialogues). It should be bigger than -12 dB to prevent
- distortion. */
+ // The 2nd axis has strong gain fluctuations, and therefore require
+ // limits. The factor corresponds to the 1 / amplification of (Lt
+ // - Rt) when (Lt, Rt) is strongly correlated. (e.g. during
+ // dialogues). It should be bigger than -12 dB to prevent
+ // distortion.
float lmr_lim_fwr = _lmr_fwr > M9_03DB * _lpr_fwr ? _lmr_fwr : M9_03DB * _lpr_fwr;
float lpr_gain = (_lpr_fwr + lmr_lim_fwr) / (1 + _lpr_fwr + _lpr_fwr);
float lmr_gain = (_lpr_fwr + lmr_lim_fwr) / (1 + lmr_lim_fwr + lmr_lim_fwr);
@@ -275,9 +275,9 @@ void matrix_decode(const float *in, const int k, const int il,
if (decode_rear)
{
_lr[kr] = _rr[kr] = (l_agc - r_agc) * (float)M_SQRT1_2;
- /* Stereo rear channel is steered with the same AGC steering as
- the decoding matrix. Note this requires a fast updating AGC
- at the order of 20 ms (which is the case here). */
+ // Stereo rear channel is steered with the same AGC steering as
+ // the decoding matrix. Note this requires a fast updating AGC
+ // at the order of 20 ms (which is the case here).
_lr[kr] *= (_l_fwr + _l_fwr) / (1 + _l_fwr + _r_fwr);
_rr[kr] *= (_r_fwr + _r_fwr) / (1 + _l_fwr + _r_fwr);
}
@@ -298,16 +298,16 @@ void matrix_decode(const float *in, const int k, const int il,
_rf[k] = (lpr_agc - lmr_agc) * (float)M_SQRT1_2;
/*** CENTER FRONT CANCELLATION ***/
- /* A heuristic approach exploits that Lt + Rt gain contains the
- information about Lt, Rt correlation. This effectively reshapes
- the front and rear "cones" to concentrate Lt + Rt to C and
- introduce Lt - Rt in L, R. */
+ // A heuristic approach exploits that Lt + Rt gain contains the
+ // information about Lt, Rt correlation. This effectively reshapes
+ // the front and rear "cones" to concentrate Lt + Rt to C and
+ // introduce Lt - Rt in L, R.
/* 0.67677 is the empirical lower bound for lpr_gain. */
c_gain = 8 * (*_adapt_lpr_gain - 0.67677f);
c_gain = c_gain > 0 ? c_gain : 0;
- /* c_gain should not be too high, not even reaching full
- cancellation (~ 0.50 - 0.55 at current AGC implementation), or
- the center will sound too narrow. */
+ // c_gain should not be too high, not even reaching full
+ // cancellation (~ 0.50 - 0.55 at current AGC implementation), or
+ // the center will sound too narrow. */
c_gain = MATCOMPGAIN / (1 + c_gain * c_gain);
c_agc_cfk = c_gain * _cf[k];
_lf[k] -= c_agc_cfk;
@@ -317,7 +317,7 @@ void matrix_decode(const float *in, const int k, const int il,
void dpl2decode(float *samples, int numsamples, float *out)
{
- static const unsigned int FWRDURATION = 240; /* FWR average duration (samples) */
+ static const unsigned int FWRDURATION = 240; // FWR average duration (samples)
static const int cfg_delay = 0;
static const unsigned int fmt_freq = 48000;
static const unsigned int fmt_nchannels = 2; // input channels
diff --git a/Source/Core/AudioCommon/Src/DSoundStream.cpp b/Source/Core/AudioCommon/Src/DSoundStream.cpp
index b252dc90c5..42c9f4f156 100644
--- a/Source/Core/AudioCommon/Src/DSoundStream.cpp
+++ b/Source/Core/AudioCommon/Src/DSoundStream.cpp
@@ -122,7 +122,7 @@ void DSound::SoundLoop()
bool DSound::Start()
{
if (FAILED(DirectSoundCreate8(0, &ds, 0)))
- return false;
+ return false;
if (hWnd)
{
HRESULT hr = ds->SetCooperativeLevel((HWND)hWnd, DSSCL_PRIORITY);
diff --git a/Source/Core/AudioCommon/Src/DSoundStream.h b/Source/Core/AudioCommon/Src/DSoundStream.h
index 2575a263bb..f2b8276114 100644
--- a/Source/Core/AudioCommon/Src/DSoundStream.h
+++ b/Source/Core/AudioCommon/Src/DSoundStream.h
@@ -31,33 +31,33 @@
class DSound : public SoundStream
{
#ifdef _WIN32
- std::thread thread;
- Common::Event soundSyncEvent;
- void *hWnd;
-
- IDirectSound8* ds;
- IDirectSoundBuffer* dsBuffer;
-
- int bufferSize; //i bytes
+ std::thread thread;
+ Common::Event soundSyncEvent;
+ void *hWnd;
+
+ IDirectSound8* ds;
+ IDirectSoundBuffer* dsBuffer;
+
+ int bufferSize; //i bytes
int m_volume;
-
- // playback position
- int currentPos;
- int lastPos;
- short realtimeBuffer[BUFSIZE / sizeof(short)];
-
- inline int FIX128(int x)
+
+ // playback position
+ int currentPos;
+ int lastPos;
+ short realtimeBuffer[BUFSIZE / sizeof(short)];
+
+ inline int FIX128(int x)
{
return x & (~127);
- }
+ }
- inline int ModBufferSize(int x)
+ inline int ModBufferSize(int x)
{
return (x + bufferSize) % bufferSize;
- }
+ }
- bool CreateBuffer();
- bool WriteDataToBuffer(DWORD dwOffset, char* soundData, DWORD dwSoundBytes);
+ bool CreateBuffer();
+ bool WriteDataToBuffer(DWORD dwOffset, char* soundData, DWORD dwSoundBytes);
public:
DSound(CMixer *mixer, void *_hWnd = NULL)
@@ -70,16 +70,16 @@ public:
, hWnd(_hWnd)
{}
- virtual ~DSound() {}
+ virtual ~DSound() {}
virtual bool Start();
- virtual void SoundLoop();
+ virtual void SoundLoop();
virtual void SetVolume(int volume);
- virtual void Stop();
+ virtual void Stop();
virtual void Clear(bool mute);
- static bool isValid() { return true; }
- virtual bool usesMixer() const { return true; }
- virtual void Update();
+ static bool isValid() { return true; }
+ virtual bool usesMixer() const { return true; }
+ virtual void Update();
#else
public:
diff --git a/Source/Core/AudioCommon/Src/Mixer.cpp b/Source/Core/AudioCommon/Src/Mixer.cpp
index b55fd56c97..6c5b6bcceb 100644
--- a/Source/Core/AudioCommon/Src/Mixer.cpp
+++ b/Source/Core/AudioCommon/Src/Mixer.cpp
@@ -67,7 +67,7 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
{
static const __m128i sr_mask =
_mm_set_epi32(0x0C0D0E0FL, 0x08090A0BL,
- 0x04050607L, 0x00010203L);
+ 0x04050607L, 0x00010203L);
for (unsigned int i = 0; i < numLeft * 2; i += 8)
{
@@ -99,12 +99,11 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
if ((m_indexR2 & INDEX_MASK) == (m_indexW & INDEX_MASK)) //..if it exists
m_indexR2 = m_indexR;
-
s16 l1 = Common::swap16(m_buffer[m_indexR & INDEX_MASK]); //current
s16 l2 = Common::swap16(m_buffer[m_indexR2 & INDEX_MASK]); //next
- int sampleL = ((l1 << 16) + (l2 - l1) * (u16)frac) >> 16;
- samples[i+1] = sampleL;
-
+ int sampleL = ((l1 << 16) + (l2 - l1) * (u16)frac) >> 16;
+ samples[i+1] = sampleL;
+
s16 r1 = Common::swap16(m_buffer[(m_indexR + 1) & INDEX_MASK]); //current
s16 r2 = Common::swap16(m_buffer[(m_indexR2 + 1) & INDEX_MASK]); //next
int sampleR = ((r1 << 16) + (r2 - r1) * (u16)frac) >> 16;
@@ -116,8 +115,6 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
}
}
-
-
} else {
numLeft = 0;
}
diff --git a/Source/Core/AudioCommon/Src/NullSoundStream.h b/Source/Core/AudioCommon/Src/NullSoundStream.h
index 5ce78cccec..c0a5e8cb7c 100644
--- a/Source/Core/AudioCommon/Src/NullSoundStream.h
+++ b/Source/Core/AudioCommon/Src/NullSoundStream.h
@@ -25,24 +25,24 @@
class NullSound : public SoundStream
{
- // playback position
- short realtimeBuffer[BUF_SIZE / sizeof(short)];
+ // playback position
+ short realtimeBuffer[BUF_SIZE / sizeof(short)];
public:
NullSound(CMixer *mixer, void *hWnd = NULL)
: SoundStream(mixer)
{}
- virtual ~NullSound() {}
-
+ virtual ~NullSound() {}
+
virtual bool Start();
- virtual void SoundLoop();
+ virtual void SoundLoop();
virtual void SetVolume(int volume);
- virtual void Stop();
+ virtual void Stop();
virtual void Clear(bool mute);
- static bool isValid() { return true; }
- virtual bool usesMixer() const { return true; }
- virtual void Update();
+ static bool isValid() { return true; }
+ virtual bool usesMixer() const { return true; }
+ virtual void Update();
};
#endif //_NULLSOUNDSTREAM_H_
diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp
index 7d1c45175b..83feb44364 100644
--- a/Source/Core/AudioCommon/Src/OpenALStream.cpp
+++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp
@@ -295,7 +295,6 @@ void OpenALStream::SoundLoop()
{
ERROR_LOG(AUDIO, "Error occurred while buffering float32 data: %08x", err);
}
-
}
#endif
if (!float32_capable)
@@ -308,7 +307,6 @@ void OpenALStream::SoundLoop()
stereo[i * 2 + 1] = (short)((float)sampleBuffer[i * 2 + 1] * (1 << 16));
}
alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, stereo, nSamples * 2 * 2, ulFrequency);
-
}
}
diff --git a/Source/Core/AudioCommon/Src/OpenSLESStream.cpp b/Source/Core/AudioCommon/Src/OpenSLESStream.cpp
new file mode 100644
index 0000000000..b0913a1895
--- /dev/null
+++ b/Source/Core/AudioCommon/Src/OpenSLESStream.cpp
@@ -0,0 +1,145 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifdef ANDROID
+#include "Common.h"
+#include <assert.h>
+#include "OpenSLESStream.h"
+
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+// engine interfaces
+static SLObjectItf engineObject;
+static SLEngineItf engineEngine;
+static SLObjectItf outputMixObject;
+
+// buffer queue player interfaces
+static SLObjectItf bqPlayerObject = NULL;
+static SLPlayItf bqPlayerPlay;
+static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
+static SLMuteSoloItf bqPlayerMuteSolo;
+static SLVolumeItf bqPlayerVolume;
+static CMixer *g_mixer;
+#define BUFFER_SIZE 512
+#define BUFFER_SIZE_IN_SAMPLES (BUFFER_SIZE / 2)
+
+// Double buffering.
+static short buffer[2][BUFFER_SIZE];
+static int curBuffer = 0;
+
+static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
+ assert(bq == bqPlayerBufferQueue);
+ assert(NULL == context);
+
+ short *nextBuffer = buffer[curBuffer];
+ int nextSize = sizeof(buffer[0]);
+
+ SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
+
+ // Comment from sample code:
+ // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
+ // which for this code example would indicate a programming error
+ assert(SL_RESULT_SUCCESS == result);
+
+ curBuffer ^= 1; // Switch buffer
+ // Render to the fresh buffer
+ g_mixer->Mix(reinterpret_cast<short *>(buffer[curBuffer]), BUFFER_SIZE_IN_SAMPLES);
+}
+bool OpenSLESStream::Start()
+{
+ SLresult result;
+ // create engine
+ result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
+ assert(SL_RESULT_SUCCESS == result);
+
+ SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
+ SLDataFormat_PCM format_pcm = {
+ SL_DATAFORMAT_PCM,
+ 2,
+ SL_SAMPLINGRATE_44_1,
+ SL_PCMSAMPLEFORMAT_FIXED_16,
+ SL_PCMSAMPLEFORMAT_FIXED_16,
+ SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
+ SL_BYTEORDER_LITTLEENDIAN
+ };
+
+ SLDataSource audioSrc = {&loc_bufq, &format_pcm};
+
+ // configure audio sink
+ SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
+ SLDataSink audioSnk = {&loc_outmix, NULL};
+
+ // create audio player
+ const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
+ const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
+ result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
+ assert(SL_RESULT_SUCCESS == result);
+
+ result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
+ &bqPlayerBufferQueue);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
+ assert(SL_RESULT_SUCCESS == result);
+
+ // Render and enqueue a first buffer. (or should we just play the buffer empty?)
+ curBuffer = 0;
+
+ result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[curBuffer]));
+ if (SL_RESULT_SUCCESS != result) {
+ return false;
+ }
+ curBuffer ^= 1;
+ g_mixer = m_mixer;
+ return true;
+}
+
+void OpenSLESStream::Stop()
+{
+ if (bqPlayerObject != NULL) {
+ (*bqPlayerObject)->Destroy(bqPlayerObject);
+ bqPlayerObject = NULL;
+ bqPlayerPlay = NULL;
+ bqPlayerBufferQueue = NULL;
+ bqPlayerMuteSolo = NULL;
+ bqPlayerVolume = NULL;
+ }
+ if (outputMixObject != NULL) {
+ (*outputMixObject)->Destroy(outputMixObject);
+ outputMixObject = NULL;
+ }
+ if (engineObject != NULL) {
+ (*engineObject)->Destroy(engineObject);
+ engineObject = NULL;
+ engineEngine = NULL;
+ }
+}
+#endif
diff --git a/Source/Core/AudioCommon/Src/OpenSLESStream.h b/Source/Core/AudioCommon/Src/OpenSLESStream.h
new file mode 100644
index 0000000000..f49160c4bc
--- /dev/null
+++ b/Source/Core/AudioCommon/Src/OpenSLESStream.h
@@ -0,0 +1,48 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef _OPENSLSTREAM_H_
+#define _OPENSLSTREAM_H_
+
+#include "Thread.h"
+#include "SoundStream.h"
+
+class OpenSLESStream : public SoundStream
+{
+#ifdef ANDROID
+public:
+ OpenSLESStream(CMixer *mixer, void *hWnd = NULL)
+ : SoundStream(mixer)
+ {};
+
+ virtual ~OpenSLESStream() {};
+
+ virtual bool Start();
+ virtual void Stop();
+ static bool isValid() { return true; }
+ virtual bool usesMixer() const { return true; }
+
+private:
+ std::thread thread;
+ Common::Event soundSyncEvent;
+#else
+public:
+ OpenSLESStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}
+#endif // HAVE_OPENSL
+};
+
+#endif
diff --git a/Source/Core/AudioCommon/Src/SoundStream.h b/Source/Core/AudioCommon/Src/SoundStream.h
index bb53c0f74d..1322cc19ac 100644
--- a/Source/Core/AudioCommon/Src/SoundStream.h
+++ b/Source/Core/AudioCommon/Src/SoundStream.h
@@ -27,17 +27,17 @@ class SoundStream
protected:
CMixer *m_mixer;
- // We set this to shut down the sound thread.
- // 0=keep playing, 1=stop playing NOW.
- volatile int threadData;
- bool m_logAudio;
+ // We set this to shut down the sound thread.
+ // 0=keep playing, 1=stop playing NOW.
+ volatile int threadData;
+ bool m_logAudio;
WaveFileWriter g_wave_writer;
bool m_muted;
public:
SoundStream(CMixer *mixer) : m_mixer(mixer), threadData(0), m_logAudio(false), m_muted(false) {}
virtual ~SoundStream() { delete m_mixer;}
-
+
static bool isValid() { return false; }
virtual CMixer *GetMixer() const { return m_mixer; }
virtual bool Start() { return false; }
diff --git a/Source/Core/AudioCommon/Src/WaveFile.cpp b/Source/Core/AudioCommon/Src/WaveFile.cpp
index d98348b8bf..3cab3cea68 100644
--- a/Source/Core/AudioCommon/Src/WaveFile.cpp
+++ b/Source/Core/AudioCommon/Src/WaveFile.cpp
@@ -104,21 +104,21 @@ void WaveFileWriter::AddStereoSamples(const short *sample_data, u32 count)
{
if (!file)
PanicAlertT("WaveFileWriter - file not open.");
-
+
if (skip_silence)
{
bool all_zero = true;
-
+
for (u32 i = 0; i < count * 2; i++)
{
if (sample_data[i])
all_zero = false;
}
-
+
if (all_zero)
return;
}
-
+
file.WriteBytes(sample_data, count * 4);
audio_size += count * 4;
}
@@ -134,7 +134,7 @@ void WaveFileWriter::AddStereoSamplesBE(const short *sample_data, u32 count)
if (skip_silence)
{
bool all_zero = true;
-
+
for (u32 i = 0; i < count * 2; i++)
{
if (sample_data[i])
diff --git a/Source/Core/AudioCommon/Src/XAudio2Stream.cpp b/Source/Core/AudioCommon/Src/XAudio2Stream.cpp
index f60842d960..0537f183c6 100644
--- a/Source/Core/AudioCommon/Src/XAudio2Stream.cpp
+++ b/Source/Core/AudioCommon/Src/XAudio2Stream.cpp
@@ -95,10 +95,10 @@ void StreamingVoiceContext::OnBufferEnd(void* context)
if (!m_source_voice || !context)
return;
-
+
//m_sound_sync_event->Wait(); // sync
//m_sound_sync_event->Spin(); // or tight sync
-
+
m_mixer->Mix(static_cast<short*>(context), SAMPLES_PER_BUFFER);
SubmitBuffer(static_cast<BYTE*>(context));
}
@@ -183,6 +183,6 @@ void XAudio2::Stop()
m_mastering_voice->DestroyVoice();
m_mastering_voice = nullptr;
}
-
+
m_xaudio2.reset(); // release interface
}
diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt
index 122f681085..361337e421 100644
--- a/Source/Core/Common/CMakeLists.txt
+++ b/Source/Core/Common/CMakeLists.txt
@@ -1,9 +1,7 @@
-set(SRCS Src/ABI.cpp
- Src/BreakPoints.cpp
+set(SRCS Src/BreakPoints.cpp
Src/CDUtils.cpp
Src/ColorUtil.cpp
Src/ConsoleListener.cpp
- Src/CPUDetect.cpp
Src/FileSearch.cpp
Src/FileUtil.cpp
Src/Hash.cpp
@@ -21,10 +19,10 @@ set(SRCS Src/ABI.cpp
Src/SymbolDB.cpp
Src/SysConf.cpp
Src/Thread.cpp
- Src/Thunk.cpp
Src/Timer.cpp
Src/Version.cpp
Src/VideoBackendBase.cpp
+ Src/x64ABI.cpp
Src/x64Analyzer.cpp
Src/x64Emitter.cpp
Src/Crypto/aes_cbc.cpp
@@ -34,6 +32,23 @@ set(SRCS Src/ABI.cpp
Src/Crypto/md5.cpp
Src/Crypto/sha1.cpp)
+if(_M_ARM) #ARM
+ set(SRCS ${SRCS}
+ Src/ArmCPUDetect.cpp
+ Src/ArmEmitter.cpp)
+else()
+ if(NOT _M_GENERIC) #X86
+ set(SRCS ${SRCS}
+ Src/x64FPURoundMode.cpp
+ Src/x64Thunk.cpp
+ )
+ endif()
+ set(SRCS ${SRCS} Src/x64CPUDetect.cpp)
+endif()
+if(_M_GENERIC) #Generic
+ set(SRCS ${SRCS}
+ Src/GenericFPURoundMode.cpp)
+endif()
if(WIN32)
set(SRCS ${SRCS} Src/ExtendedTrace.cpp)
endif(WIN32)
diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj
index 626204f344..373d274907 100644
--- a/Source/Core/Common/Common.vcxproj
+++ b/Source/Core/Common/Common.vcxproj
@@ -44,7 +44,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -54,7 +54,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -158,12 +158,10 @@
<Lib />
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="Src\ABI.cpp" />
<ClCompile Include="Src\BreakPoints.cpp" />
<ClCompile Include="Src\CDUtils.cpp" />
<ClCompile Include="Src\ColorUtil.cpp" />
<ClCompile Include="Src\ConsoleListener.cpp" />
- <ClCompile Include="Src\CPUDetect.cpp" />
<ClCompile Include="Src\Crypto\aes_cbc.cpp" />
<ClCompile Include="Src\Crypto\aes_core.cpp" />
<ClCompile Include="Src\Crypto\bn.cpp" />
@@ -196,15 +194,17 @@
<ClCompile Include="Src\SymbolDB.cpp" />
<ClCompile Include="Src\SysConf.cpp" />
<ClCompile Include="Src\Thread.cpp" />
- <ClCompile Include="Src\Thunk.cpp" />
<ClCompile Include="Src\Timer.cpp" />
<ClCompile Include="Src\Version.cpp" />
<ClCompile Include="Src\VideoBackendBase.cpp" />
+ <ClCompile Include="Src\x64ABI.cpp" />
<ClCompile Include="Src\x64Analyzer.cpp" />
+ <ClCompile Include="Src\x64CPUDetect.cpp" />
<ClCompile Include="Src\x64Emitter.cpp" />
+ <ClCompile Include="Src\x64FPURoundMode.cpp" />
+ <ClCompile Include="Src\x64Thunk.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="Src\ABI.h" />
<ClInclude Include="Src\Atomic.h" />
<ClInclude Include="Src\Atomic_GCC.h" />
<ClInclude Include="Src\Atomic_Win32.h" />
@@ -253,6 +253,7 @@
<ClInclude Include="Src\Thunk.h" />
<ClInclude Include="Src\Timer.h" />
<ClInclude Include="Src\VideoBackendBase.h" />
+ <ClInclude Include="Src\x64ABI.h" />
<ClInclude Include="Src\x64Analyzer.h" />
<ClInclude Include="Src\x64Emitter.h" />
</ItemGroup>
diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters
index 6ae75788ce..26f66b850a 100644
--- a/Source/Core/Common/Common.vcxproj.filters
+++ b/Source/Core/Common/Common.vcxproj.filters
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
- <ClCompile Include="Src\ABI.cpp" />
<ClCompile Include="Src\BreakPoints.cpp" />
<ClCompile Include="Src\CDUtils.cpp" />
<ClCompile Include="Src\ColorUtil.cpp" />
- <ClCompile Include="Src\CPUDetect.cpp" />
<ClCompile Include="Src\ExtendedTrace.cpp" />
<ClCompile Include="Src\FileSearch.cpp" />
<ClCompile Include="Src\FileUtil.cpp" />
@@ -23,7 +21,6 @@
<ClCompile Include="Src\SymbolDB.cpp" />
<ClCompile Include="Src\SysConf.cpp" />
<ClCompile Include="Src\Thread.cpp" />
- <ClCompile Include="Src\Thunk.cpp" />
<ClCompile Include="Src\Timer.cpp" />
<ClCompile Include="Src\Version.cpp" />
<ClCompile Include="Src\VideoBackendBase.cpp" />
@@ -54,9 +51,12 @@
<Filter>Crypto</Filter>
</ClCompile>
<ClCompile Include="Src\SettingsHandler.cpp" />
+ <ClCompile Include="Src\x64ABI.cpp" />
+ <ClCompile Include="Src\x64CPUDetect.cpp" />
+ <ClCompile Include="Src\x64FPURoundMode.cpp" />
+ <ClCompile Include="Src\x64Thunk.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="Src\ABI.h" />
<ClInclude Include="Src\Atomic.h" />
<ClInclude Include="Src\Atomic_GCC.h" />
<ClInclude Include="Src\Atomic_Win32.h" />
@@ -123,6 +123,7 @@
<ClInclude Include="Src\StdMutex.h" />
<ClInclude Include="Src\StdConditionVariable.h" />
<ClInclude Include="Src\SettingsHandler.h" />
+ <ClInclude Include="Src\x64ABI.h" />
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
diff --git a/Source/Core/Common/Src/ArmCPUDetect.cpp b/Source/Core/Common/Src/ArmCPUDetect.cpp
new file mode 100644
index 0000000000..33eee9f05e
--- /dev/null
+++ b/Source/Core/Common/Src/ArmCPUDetect.cpp
@@ -0,0 +1,167 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+#include "CPUDetect.h"
+#include "StringUtil.h"
+#include "FileUtil.h"
+
+const char procfile[] = "/proc/cpuinfo";
+
+char *GetCPUString()
+{
+ const char marker[] = "Hardware\t: ";
+ char *cpu_string = 0;
+ // Count the number of processor lines in /proc/cpuinfo
+ char buf[1024];
+
+ File::IOFile file(procfile, "r");
+ auto const fp = file.GetHandle();
+ if (!fp)
+ return 0;
+
+ while (fgets(buf, sizeof(buf), fp))
+ {
+ if (strncmp(buf, marker, sizeof(marker) - 1))
+ continue;
+ cpu_string = buf + sizeof(marker) - 1;
+ cpu_string = strndup(cpu_string, strlen(cpu_string) - 1); // Strip the newline
+ break;
+ }
+ return cpu_string;
+}
+bool CheckCPUFeature(const char *feature)
+{
+ const char marker[] = "Features\t: ";
+ char buf[1024];
+
+ File::IOFile file(procfile, "r");
+ auto const fp = file.GetHandle();
+ if (!fp)
+ return 0;
+
+ while (fgets(buf, sizeof(buf), fp))
+ {
+ if (strncmp(buf, marker, sizeof(marker) - 1))
+ continue;
+ char *featurestring = buf + sizeof(marker) - 1;
+ char *token = strtok(featurestring, " ");
+ while (token != NULL)
+ {
+ if (strstr(token, feature))
+ return true;
+ token = strtok(NULL, " ");
+ }
+ }
+ return false;
+}
+int GetCoreCount()
+{
+ const char marker[] = "processor\t: ";
+ int cores = 0;
+ char buf[1024];
+
+ File::IOFile file(procfile, "r");
+ auto const fp = file.GetHandle();
+ if (!fp)
+ return 0;
+
+ while (fgets(buf, sizeof(buf), fp))
+ {
+ if (strncmp(buf, marker, sizeof(marker) - 1))
+ continue;
+ ++cores;
+ }
+ return cores;
+}
+
+CPUInfo cpu_info;
+
+CPUInfo::CPUInfo() {
+ Detect();
+}
+
+// Detects the various cpu features
+void CPUInfo::Detect()
+{
+ // Set some defaults here
+ // When ARMv8 cpus come out, these need to be updated.
+ HTT = false;
+ OS64bit = false;
+ CPU64bit = false;
+ Mode64bit = false;
+ vendor = VENDOR_ARM;
+
+ // Get the information about the CPU
+ strncpy(cpu_string, GetCPUString(), sizeof(cpu_string));
+ num_cores = GetCoreCount();
+ bSwp = CheckCPUFeature("swp");
+ bHalf = CheckCPUFeature("half");
+ bThumb = CheckCPUFeature("thumb");
+ bFastMult = CheckCPUFeature("fastmult");
+ bVFP = CheckCPUFeature("vfp");
+ bEDSP = CheckCPUFeature("edsp");
+ bThumbEE = CheckCPUFeature("thumbee");
+ bNEON = CheckCPUFeature("neon");
+ bVFPv3 = CheckCPUFeature("vfpv3");
+ bTLS = CheckCPUFeature("tls");
+ bVFPv4 = CheckCPUFeature("vfpv4");
+ bIDIVa = CheckCPUFeature("idiva");
+ bIDIVt = CheckCPUFeature("idivt");
+
+ // On some buggy kernels(Qualcomm) they show that they support VFPv4 but not IDIVa
+ // All VFPv4 CPUs will support IDIVa
+ if (bVFPv4)
+ bIDIVa = bIDIVt = true;
+
+ // These two are ARMv8 specific.
+ bFP = CheckCPUFeature("fp");
+ bASIMD = CheckCPUFeature("asimd");
+
+
+#if defined(__ARM_ARCH_7A__)
+ bArmV7 = true;
+#else
+ bArmV7 = false;
+#endif
+}
+
+// Turn the cpu info into a string we can show
+std::string CPUInfo::Summarize()
+{
+ std::string sum;
+ if (num_cores == 1)
+ sum = StringFromFormat("%s, %i core", cpu_string, num_cores);
+ else
+ sum = StringFromFormat("%s, %i cores", cpu_string, num_cores);
+
+ if (bSwp) sum += ", SWP";
+ if (bHalf) sum += ", Half";
+ if (bThumb) sum += ", Thumb";
+ if (bFastMult) sum += ", FastMult";
+ if (bVFP) sum += ", VFP";
+ if (bEDSP) sum += ", EDSP";
+ if (bThumbEE) sum += ", ThumbEE";
+ if (bNEON) sum += ", NEON";
+ if (bVFPv3) sum += ", VFPv3";
+ if (bTLS) sum += ", TLS";
+ if (bVFPv4) sum += ", VFPv4";
+ if (bIDIVa) sum += ", IDIVa";
+ if (bIDIVt) sum += ", IDIVt";
+
+ return sum;
+}
diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp
new file mode 100644
index 0000000000..9b738be030
--- /dev/null
+++ b/Source/Core/Common/Src/ArmEmitter.cpp
@@ -0,0 +1,1110 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+#include "ArmEmitter.h"
+#include "CPUDetect.h"
+
+#include <assert.h>
+#include <stdarg.h>
+
+// For cache flushing on Symbian/iOS/Blackberry
+#ifdef __SYMBIAN32__
+#include <e32std.h>
+#endif
+
+#ifdef IOS
+#include <libkern/OSCacheControl.h>
+#include <sys/mman.h>
+#endif
+
+#ifdef BLACKBERRY
+#include <sys/mman.h>
+#endif
+
+namespace ArmGen
+{
+
+inline u32 RotR(u32 a, int amount) {
+ if (!amount) return a;
+ return (a >> amount) | (a << (32 - amount));
+}
+
+inline u32 RotL(u32 a, int amount) {
+ if (!amount) return a;
+ return (a << amount) | (a >> (32 - amount));
+}
+
+bool TryMakeOperand2(u32 imm, Operand2 &op2) {
+ // Just brute force it.
+ for (int i = 0; i < 16; i++) {
+ int mask = RotR(0xFF, i * 2);
+ if ((imm & mask) == imm) {
+ op2 = Operand2((u8)(RotL(imm, i * 2)), (u8)i);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse)
+{
+ if (!TryMakeOperand2(imm, op2)) {
+ *inverse = true;
+ return TryMakeOperand2(~imm, op2);
+ } else {
+ *inverse = false;
+ return true;
+ }
+}
+
+bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated)
+{
+ if (!TryMakeOperand2(imm, op2)) {
+ *negated = true;
+ return TryMakeOperand2(-imm, op2);
+ } else {
+ *negated = false;
+ return true;
+ }
+}
+
+void ARMXEmitter::MOVI2F(ARMReg dest, float val, ARMReg tempReg)
+{
+ union {float f; u32 u;} conv;
+ conv.f = val;
+ MOVI2R(tempReg, conv.u);
+ VMOV(dest, tempReg);
+ // TODO: VMOV an IMM directly if possible
+ // Otherwise, use a literal pool and VLDR directly (+- 1020)
+}
+
+void ARMXEmitter::ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
+{
+ Operand2 op2;
+ bool inverse;
+ if (TryMakeOperand2_AllowInverse(val, op2, &inverse)) {
+ if (!inverse) {
+ AND(rd, rs, op2);
+ } else {
+ BIC(rd, rs, op2);
+ }
+ } else {
+ MOVI2R(scratch, val);
+ AND(rd, rs, scratch);
+ }
+}
+
+void ARMXEmitter::ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
+{
+ Operand2 op2;
+ if (TryMakeOperand2(val, op2)) {
+ ORR(rd, rs, op2);
+ } else {
+ MOVI2R(scratch, val);
+ ORR(rd, rs, scratch);
+ }
+}
+
+void ARMXEmitter::FlushLitPool()
+{
+ for(std::vector<LiteralPool>::iterator it = currentLitPool.begin(); it != currentLitPool.end(); ++it) {
+ // Search for duplicates
+ for(std::vector<LiteralPool>::iterator old_it = currentLitPool.begin(); old_it != it; ++old_it) {
+ if ((*old_it).val == (*it).val)
+ (*it).loc = (*old_it).loc;
+ }
+
+ // Write the constant to Literal Pool
+ if (!(*it).loc)
+ {
+ (*it).loc = (s32)code;
+ Write32((*it).val);
+ }
+ s32 offset = (*it).loc - (s32)(*it).ldr_address - 8;
+
+ // Backpatch the LDR
+ *(u32*)(*it).ldr_address |= (offset >= 0) << 23 | abs(offset);
+ }
+ // TODO: Save a copy of previous pools in case they are still in range.
+ currentLitPool.clear();
+}
+
+void ARMXEmitter::AddNewLit(u32 val)
+{
+ LiteralPool pool_item;
+ pool_item.loc = 0;
+ pool_item.val = val;
+ pool_item.ldr_address = code;
+ currentLitPool.push_back(pool_item);
+}
+
+void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize)
+{
+ Operand2 op2;
+ bool inverse;
+
+ if (cpu_info.bArmV7 && !optimize)
+ {
+ // For backpatching on ARMv7
+ MOVW(reg, val & 0xFFFF);
+ MOVT(reg, val, true);
+ }
+ else if (TryMakeOperand2_AllowInverse(val, op2, &inverse)) {
+ inverse ? MVN(reg, op2) : MOV(reg, op2);
+ } else {
+ if (cpu_info.bArmV7)
+ {
+ // Use MOVW+MOVT for ARMv7+
+ MOVW(reg, val & 0xFFFF);
+ if(val & 0xFFFF0000)
+ MOVT(reg, val, true);
+ } else {
+ // Use literal pool for ARMv6.
+ AddNewLit(val);
+ LDR(reg, _PC); // To be backpatched later
+ }
+ }
+}
+
+void ARMXEmitter::QuickCallFunction(ARMReg reg, void *func) {
+ MOVI2R(reg, (u32)(func));
+ BL(reg);
+}
+
+void ARMXEmitter::SetCodePtr(u8 *ptr)
+{
+ code = ptr;
+ startcode = code;
+#ifdef IOS
+ lastCacheFlushEnd = ptr;
+#endif
+}
+
+const u8 *ARMXEmitter::GetCodePtr() const
+{
+ return code;
+}
+
+u8 *ARMXEmitter::GetWritableCodePtr()
+{
+ return code;
+}
+
+void ARMXEmitter::ReserveCodeSpace(u32 bytes)
+{
+ for (u32 i = 0; i < bytes/4; i++)
+ Write32(0xE1200070); //bkpt 0
+}
+
+const u8 *ARMXEmitter::AlignCode16()
+{
+ ReserveCodeSpace((-(s32)code) & 15);
+ return code;
+}
+
+const u8 *ARMXEmitter::AlignCodePage()
+{
+ ReserveCodeSpace((-(s32)code) & 4095);
+ return code;
+}
+
+void ARMXEmitter::FlushIcache()
+{
+ FlushIcacheSection(lastCacheFlushEnd, code);
+ lastCacheFlushEnd = code;
+}
+
+void ARMXEmitter::FlushIcacheSection(u8 *start, u8 *end)
+{
+#ifdef __SYMBIAN32__
+ User::IMB_Range(start, end);
+#elif defined(BLACKBERRY)
+ msync(start, end - start, MS_SYNC | MS_INVALIDATE_ICACHE);
+#elif defined(IOS)
+ if (start != NULL)
+ sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start);
+#elif !defined(_WIN32)
+#ifndef ANDROID
+ start = startcode; // Should be Linux Only
+#endif
+ __builtin___clear_cache(start, end);
+#endif
+}
+
+void ARMXEmitter::SetCC(CCFlags cond)
+{
+ condition = cond << 28;
+}
+
+void ARMXEmitter::NOP(int count)
+{
+ for (int i = 0; i < count; i++) {
+ Write32(condition | 0x01A00000);
+ }
+}
+
+void ARMXEmitter::SETEND(bool BE)
+{
+ //SETEND is non-conditional
+ Write32( 0xF1010000 | (BE << 9));
+}
+void ARMXEmitter::BKPT(u16 arg)
+{
+ Write32(condition | 0x01200070 | (arg << 4 & 0x000FFF00) | (arg & 0x0000000F));
+}
+void ARMXEmitter::YIELD()
+{
+ Write32(condition | 0x0320F001);
+}
+
+FixupBranch ARMXEmitter::B()
+{
+ FixupBranch branch;
+ branch.type = 0; // Zero for B
+ branch.ptr = code;
+ branch.condition = condition;
+ //We'll write NOP here for now.
+ Write32(condition | 0x01A00000);
+ return branch;
+}
+FixupBranch ARMXEmitter::BL()
+{
+ FixupBranch branch;
+ branch.type = 1; // Zero for B
+ branch.ptr = code;
+ branch.condition = condition;
+ //We'll write NOP here for now.
+ Write32(condition | 0x01A00000);
+ return branch;
+}
+
+FixupBranch ARMXEmitter::B_CC(CCFlags Cond)
+{
+ FixupBranch branch;
+ branch.type = 0; // Zero for B
+ branch.ptr = code;
+ branch.condition = Cond << 28;
+ //We'll write NOP here for now.
+ Write32(condition | 0x01A00000);
+ return branch;
+}
+void ARMXEmitter::B_CC(CCFlags Cond, const void *fnptr)
+{
+ s32 distance = (s32)fnptr - (s32(code) + 8);
+ _assert_msg_(DYNA_REC, distance > -33554432
+ && distance <= 33554432,
+ "B_CC out of range (%p calls %p)", code, fnptr);
+
+ Write32((Cond << 28) | 0x0A000000 | ((distance >> 2) & 0x00FFFFFF));
+}
+FixupBranch ARMXEmitter::BL_CC(CCFlags Cond)
+{
+ FixupBranch branch;
+ branch.type = 1; // Zero for B
+ branch.ptr = code;
+ branch.condition = Cond << 28;
+ //We'll write NOP here for now.
+ Write32(condition | 0x01A00000);
+ return branch;
+}
+void ARMXEmitter::SetJumpTarget(FixupBranch const &branch)
+{
+ s32 distance = (s32(code) - 8) - (s32)branch.ptr;
+ _assert_msg_(DYNA_REC, distance > -33554432
+ && distance <= 33554432,
+ "SetJumpTarget out of range (%p calls %p)", code,
+ branch.ptr);
+ if(branch.type == 0) // B
+ *(u32*)branch.ptr = (u32)(branch.condition | (10 << 24) | ((distance >> 2) &
+ 0x00FFFFFF));
+ else // BL
+ *(u32*)branch.ptr = (u32)(branch.condition | 0x0B000000 | ((distance >> 2)
+ & 0x00FFFFFF));
+}
+void ARMXEmitter::B (const void *fnptr)
+{
+ s32 distance = (s32)fnptr - (s32(code) + 8);
+ _assert_msg_(DYNA_REC, distance > -33554432
+ && distance <= 33554432,
+ "B out of range (%p calls %p)", code, fnptr);
+
+ Write32(condition | 0x0A000000 | ((distance >> 2) & 0x00FFFFFF));
+}
+
+void ARMXEmitter::B(ARMReg src)
+{
+ Write32(condition | 0x12FFF10 | src);
+}
+
+void ARMXEmitter::BL(const void *fnptr)
+{
+ s32 distance = (s32)fnptr - (s32(code) + 8);
+ _assert_msg_(DYNA_REC, distance > -33554432
+ && distance <= 33554432,
+ "BL out of range (%p calls %p)", code, fnptr);
+ Write32(condition | 0x0B000000 | ((distance >> 2) & 0x00FFFFFF));
+}
+void ARMXEmitter::BL(ARMReg src)
+{
+ Write32(condition | 0x12FFF30 | src);
+}
+void ARMXEmitter::PUSH(const int num, ...)
+{
+ u16 RegList = 0;
+ u8 Reg;
+ int i;
+ va_list vl;
+ va_start(vl, num);
+ for (i=0;i<num;i++)
+ {
+ Reg = va_arg(vl, u32);
+ RegList |= (1 << Reg);
+ }
+ va_end(vl);
+ Write32(condition | (2349 << 16) | RegList);
+}
+void ARMXEmitter::POP(const int num, ...)
+{
+ u16 RegList = 0;
+ u8 Reg;
+ int i;
+ va_list vl;
+ va_start(vl, num);
+ for (i=0;i<num;i++)
+ {
+ Reg = va_arg(vl, u32);
+ RegList |= (1 << Reg);
+ }
+ va_end(vl);
+ Write32(condition | (2237 << 16) | RegList);
+}
+
+void ARMXEmitter::WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2)
+{
+ Write32(condition | (13 << 21) | (SetFlags << 20) | (dest << 12) | op2.Imm5() | (op << 4) | src);
+}
+void ARMXEmitter::WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, ARMReg op2)
+{
+ Write32(condition | (13 << 21) | (SetFlags << 20) | (dest << 12) | (op2 << 8) | (op << 4) | src);
+}
+
+// IMM, REG, IMMSREG, RSR
+// -1 for invalid if the instruction doesn't support that
+const s32 InstOps[][4] = {{16, 0, 0, 0}, // AND(s)
+ {17, 1, 1, 1}, // EOR(s)
+ {18, 2, 2, 2}, // SUB(s)
+ {19, 3, 3, 3}, // RSB(s)
+ {20, 4, 4, 4}, // ADD(s)
+ {21, 5, 5, 5}, // ADC(s)
+ {22, 6, 6, 6}, // SBC(s)
+ {23, 7, 7, 7}, // RSC(s)
+ {24, 8, 8, 8}, // TST
+ {25, 9, 9, 9}, // TEQ
+ {26, 10, 10, 10}, // CMP
+ {27, 11, 11, 11}, // CMN
+ {28, 12, 12, 12}, // ORR(s)
+ {29, 13, 13, 13}, // MOV(s)
+ {30, 14, 14, 14}, // BIC(s)
+ {31, 15, 15, 15}, // MVN(s)
+ {24, -1, -1, -1}, // MOVW
+ {26, -1, -1, -1}, // MOVT
+ };
+
+const char *InstNames[] = { "AND",
+ "EOR",
+ "SUB",
+ "RSB",
+ "ADD",
+ "ADC",
+ "SBC",
+ "RSC",
+ "TST",
+ "TEQ",
+ "CMP",
+ "CMN",
+ "ORR",
+ "MOV",
+ "BIC",
+ "MVN"
+ };
+
+void ARMXEmitter::AND (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(0, Rd, Rn, Rm); }
+void ARMXEmitter::ANDS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(0, Rd, Rn, Rm, true); }
+void ARMXEmitter::EOR (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(1, Rd, Rn, Rm); }
+void ARMXEmitter::EORS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(1, Rd, Rn, Rm, true); }
+void ARMXEmitter::SUB (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(2, Rd, Rn, Rm); }
+void ARMXEmitter::SUBS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(2, Rd, Rn, Rm, true); }
+void ARMXEmitter::RSB (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(3, Rd, Rn, Rm); }
+void ARMXEmitter::RSBS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(3, Rd, Rn, Rm, true); }
+void ARMXEmitter::ADD (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(4, Rd, Rn, Rm); }
+void ARMXEmitter::ADDS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(4, Rd, Rn, Rm, true); }
+void ARMXEmitter::ADC (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(5, Rd, Rn, Rm); }
+void ARMXEmitter::ADCS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(5, Rd, Rn, Rm, true); }
+void ARMXEmitter::SBC (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(6, Rd, Rn, Rm); }
+void ARMXEmitter::SBCS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(6, Rd, Rn, Rm, true); }
+void ARMXEmitter::RSC (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(7, Rd, Rn, Rm); }
+void ARMXEmitter::RSCS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(7, Rd, Rn, Rm, true); }
+void ARMXEmitter::TST ( ARMReg Rn, Operand2 Rm) { WriteInstruction(8, R0, Rn, Rm, true); }
+void ARMXEmitter::TEQ ( ARMReg Rn, Operand2 Rm) { WriteInstruction(9, R0, Rn, Rm, true); }
+void ARMXEmitter::CMP ( ARMReg Rn, Operand2 Rm) { WriteInstruction(10, R0, Rn, Rm, true); }
+void ARMXEmitter::CMN ( ARMReg Rn, Operand2 Rm) { WriteInstruction(11, R0, Rn, Rm, true); }
+void ARMXEmitter::ORR (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(12, Rd, Rn, Rm); }
+void ARMXEmitter::ORRS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(12, Rd, Rn, Rm, true); }
+void ARMXEmitter::MOV (ARMReg Rd, Operand2 Rm) { WriteInstruction(13, Rd, R0, Rm); }
+void ARMXEmitter::MOVS(ARMReg Rd, Operand2 Rm) { WriteInstruction(13, Rd, R0, Rm, true); }
+void ARMXEmitter::BIC (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(14, Rd, Rn, Rm); }
+void ARMXEmitter::BICS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(14, Rd, Rn, Rm, true); }
+void ARMXEmitter::MVN (ARMReg Rd, Operand2 Rm) { WriteInstruction(15, Rd, R0, Rm); }
+void ARMXEmitter::MVNS(ARMReg Rd, Operand2 Rm) { WriteInstruction(15, Rd, R0, Rm, true); }
+void ARMXEmitter::MOVW(ARMReg Rd, Operand2 Rm) { WriteInstruction(16, Rd, R0, Rm); }
+void ARMXEmitter::MOVT(ARMReg Rd, Operand2 Rm, bool TopBits) { WriteInstruction(17, Rd, R0, TopBits ? Rm.Value >> 16 : Rm); }
+
+void ARMXEmitter::WriteInstruction (u32 Op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags) // This can get renamed later
+{
+ s32 op = InstOps[Op][Rm.GetType()]; // Type always decided by last operand
+ u32 Data = Rm.GetData();
+ if (Rm.GetType() == TYPE_IMM)
+ {
+ switch (Op)
+ {
+ // MOV cases that support IMM16
+ case 16:
+ case 17:
+ Data = Rm.Imm16();
+ break;
+ default:
+ break;
+ }
+ }
+ if (op == -1)
+ _assert_msg_(DYNA_REC, false, "%s not yet support %d", InstNames[Op], Rm.GetType());
+ Write32(condition | (op << 21) | (SetFlags ? (1 << 20) : 0) | Rn << 16 | Rd << 12 | Data);
+}
+
+// Data Operations
+void ARMXEmitter::WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2)
+{
+ Write32(condition | (0x7 << 24) | (Op << 20) | (dest << 16) | (Op2 << 12) | (r1 << 8) | (Op3 << 5) | (1 << 4) | r2);
+}
+void ARMXEmitter::UDIV(ARMReg dest, ARMReg dividend, ARMReg divisor)
+{
+ if (!cpu_info.bIDIVa)
+ PanicAlert("Trying to use integer divide on hardware that doesn't support it. Bad programmer.");
+ WriteSignedMultiply(3, 0xF, 0, dest, divisor, dividend);
+}
+void ARMXEmitter::SDIV(ARMReg dest, ARMReg dividend, ARMReg divisor)
+{
+ if (!cpu_info.bIDIVa)
+ PanicAlert("Trying to use integer divide on hardware that doesn't support it. Bad programmer.");
+ WriteSignedMultiply(1, 0xF, 0, dest, divisor, dividend);
+}
+void ARMXEmitter::LSL (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, false, dest, src, op2);}
+void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, true, dest, src, op2);}
+void ARMXEmitter::LSL (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, false, dest, src, op2);}
+void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, true, dest, src, op2);}
+void ARMXEmitter::LSR (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(3, false, dest, src, op2);}
+void ARMXEmitter::MUL (ARMReg dest, ARMReg src, ARMReg op2)
+{
+ Write32(condition | (dest << 16) | (src << 8) | (9 << 4) | op2);
+}
+void ARMXEmitter::MULS(ARMReg dest, ARMReg src, ARMReg op2)
+{
+ Write32(condition | (1 << 20) | (dest << 16) | (src << 8) | (9 << 4) | op2);
+}
+
+void ARMXEmitter::Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn) {
+ Write32(condition | (op << 20) | (destHi << 16) | (destLo << 12) | (rm << 8) | (9 << 4) | rn);
+}
+
+void ARMXEmitter::UMULL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn)
+{
+ Write4OpMultiply(0x8, destLo, destHi, rn, rm);
+}
+
+void ARMXEmitter::SMULL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn)
+{
+ Write4OpMultiply(0xC, destLo, destHi, rn, rm);
+}
+
+void ARMXEmitter::UMLAL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn)
+{
+ Write4OpMultiply(0xA, destLo, destHi, rn, rm);
+}
+
+void ARMXEmitter::SMLAL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn)
+{
+ Write4OpMultiply(0xE, destLo, destHi, rn, rm);
+}
+
+void ARMXEmitter::UBFX(ARMReg dest, ARMReg rn, u8 lsb, u8 width)
+{
+ Write32(condition | (0x7E0 << 16) | ((width - 1) << 16) | (dest << 12) | (lsb << 7) | (5 << 4) | rn);
+}
+
+void ARMXEmitter::CLZ(ARMReg rd, ARMReg rm)
+{
+ Write32(condition | (0x16F << 16) | (rd << 12) | (0xF1 << 4) | rm);
+}
+
+void ARMXEmitter::BFI(ARMReg rd, ARMReg rn, u8 lsb, u8 width)
+{
+ u32 msb = (lsb + width - 1);
+ if (msb > 31) msb = 31;
+ Write32(condition | (0x7C0 << 16) | (msb << 16) | (rd << 12) | (lsb << 7) | (1 << 4) | rn);
+}
+
+void ARMXEmitter::SXTB (ARMReg dest, ARMReg op2)
+{
+ Write32(condition | (0x6AF << 16) | (dest << 12) | (7 << 4) | op2);
+}
+
+void ARMXEmitter::SXTH (ARMReg dest, ARMReg op2, u8 rotation)
+{
+ SXTAH(dest, (ARMReg)15, op2, rotation);
+}
+void ARMXEmitter::SXTAH(ARMReg dest, ARMReg src, ARMReg op2, u8 rotation)
+{
+ // bits ten and 11 are the rotation amount, see 8.8.232 for more
+ // information
+ Write32(condition | (0x6B << 20) | (src << 16) | (dest << 12) | (rotation << 10) | (7 << 4) | op2);
+}
+void ARMXEmitter::RBIT(ARMReg dest, ARMReg src)
+{
+ Write32(condition | (0x6F << 20) | (0xF << 16) | (dest << 12) | (0xF3 << 4) | src);
+}
+void ARMXEmitter::REV (ARMReg dest, ARMReg src)
+{
+ Write32(condition | (0x6B << 20) | (0xF << 16) | (dest << 12) | (0xF3 << 4) | src);
+}
+void ARMXEmitter::REV16(ARMReg dest, ARMReg src)
+{
+ Write32(condition | (0x3DF << 16) | (dest << 12) | (0xFD << 4) | src);
+}
+
+void ARMXEmitter::_MSR (bool write_nzcvq, bool write_g, Operand2 op2)
+{
+ Write32(condition | (0x320F << 12) | (write_nzcvq << 19) | (write_g << 18) | op2.Imm12Mod());
+}
+void ARMXEmitter::_MSR (bool write_nzcvq, bool write_g, ARMReg src)
+{
+ Write32(condition | (0x120F << 12) | (write_nzcvq << 19) | (write_g << 18) | src);
+}
+void ARMXEmitter::MRS (ARMReg dest)
+{
+ Write32(condition | (16 << 20) | (15 << 16) | (dest << 12));
+}
+void ARMXEmitter::LDREX(ARMReg dest, ARMReg base)
+{
+ Write32(condition | (25 << 20) | (base << 16) | (dest << 12) | 0xF9F);
+}
+void ARMXEmitter::STREX(ARMReg result, ARMReg base, ARMReg op)
+{
+ _assert_msg_(DYNA_REC, (result != base && result != op), "STREX dest can't be other two registers");
+ Write32(condition | (24 << 20) | (base << 16) | (result << 12) | (0xF9 << 4) | op);
+}
+void ARMXEmitter::DMB ()
+{
+ Write32(0xF57FF05E);
+}
+void ARMXEmitter::SVC(Operand2 op)
+{
+ Write32(condition | (0x0F << 24) | op.Imm24());
+}
+
+// IMM, REG, IMMSREG, RSR
+// -1 for invalid if the instruction doesn't support that
+const s32 LoadStoreOps[][4] = { {0x40, 0x60, 0x60, -1}, // STR
+ {0x41, 0x61, 0x61, -1}, // LDR
+ {0x44, 0x64, 0x64, -1}, // STRB
+ {0x45, 0x65, 0x65, -1}, // LDRB
+ // Special encodings
+ { 0x4, 0x0, -1, -1}, // STRH
+ { 0x5, 0x1, -1, -1}, // LDRH
+ { 0x5, 0x1, -1, -1}, // LDRSB
+ { 0x5, 0x1, -1, -1}, // LDRSH
+ };
+const char *LoadStoreNames[] = { "STR",
+ "LDR",
+ "STRB",
+ "LDRB",
+ "STRH",
+ "LDRH",
+ "LDRSB",
+ "LDRSH",
+ };
+
+void ARMXEmitter::WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 Rm, bool RegAdd)
+{
+ s32 op = LoadStoreOps[Op][Rm.GetType()]; // Type always decided by last operand
+ u32 Data;
+
+ // Qualcomm chipsets get /really/ angry if you don't use index, even if the offset is zero.
+ // Some of these encodings require Index at all times anyway. Doesn't really matter.
+ // bool Index = op2 != 0 ? true : false;
+ bool Index = true;
+ bool Add = false;
+
+ // Special Encoding
+ bool SpecialOp = false;
+ bool Half = false;
+ bool SignedLoad = false;
+
+ if (op == -1)
+ _assert_msg_(DYNA_REC, false, "%s does not support %d", LoadStoreNames[Op], Rm.GetType());
+
+ switch (Op)
+ {
+ case 4: // STRH
+ SpecialOp = true;
+ Half = true;
+ SignedLoad = false;
+ break;
+ case 5: // LDRH
+ SpecialOp = true;
+ Half = true;
+ SignedLoad = false;
+ break;
+ case 6: // LDRSB
+ SpecialOp = true;
+ Half = false;
+ SignedLoad = true;
+ break;
+ case 7: // LDRSH
+ SpecialOp = true;
+ Half = true;
+ SignedLoad = true;
+ break;
+ }
+ switch (Rm.GetType())
+ {
+ case TYPE_IMM:
+ {
+ s32 Temp = (s32)Rm.Value;
+ Data = abs(Temp);
+ // The offset is encoded differently on this one.
+ if (SpecialOp)
+ Data = (Data & 0xF0 << 4) | (Data & 0xF);
+ if (Temp >= 0) Add = true;
+ }
+ break;
+ case TYPE_REG:
+ case TYPE_IMMSREG:
+ if (!SpecialOp)
+ {
+ Data = Rm.GetData();
+ Add = RegAdd;
+ break;
+ }
+ default:
+ // RSR not supported for any of these
+ // We already have the warning above
+ BKPT(0x2);
+ return;
+ break;
+ }
+ if (SpecialOp)
+ {
+ // Add SpecialOp things
+ Data = (0x5 << 4) | (SignedLoad << 6) | (Half << 5) | Data;
+ }
+ Write32(condition | (op << 20) | (Index << 24) | (Add << 23) | (Rn << 16) | (Rt << 12) | Data);
+}
+
+void ARMXEmitter::LDR (ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(1, dest, base, op2, RegAdd);}
+void ARMXEmitter::LDRB(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(3, dest, base, op2, RegAdd);}
+void ARMXEmitter::LDRH(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(5, dest, base, op2, RegAdd);}
+void ARMXEmitter::LDRSB(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(6, dest, base, op2, RegAdd);}
+void ARMXEmitter::LDRSH(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(7, dest, base, op2, RegAdd);}
+void ARMXEmitter::STR (ARMReg result, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(0, result, base, op2, RegAdd);}
+void ARMXEmitter::STRH (ARMReg result, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(4, result, base, op2, RegAdd);}
+void ARMXEmitter::STRB (ARMReg result, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(2, result, base, op2, RegAdd);}
+
+void ARMXEmitter::WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList)
+{
+ Write32(condition | (op << 20) | (WriteBack << 21) | (dest << 16) | RegList);
+}
+void ARMXEmitter::STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...)
+{
+ u16 RegList = 0;
+ u8 Reg;
+ int i;
+ va_list vl;
+ va_start(vl, Regnum);
+ for (i=0;i<Regnum;i++)
+ {
+ Reg = va_arg(vl, u32);
+ RegList |= (1 << Reg);
+ }
+ va_end(vl);
+ WriteRegStoreOp(0x90, dest, WriteBack, RegList);
+}
+void ARMXEmitter::LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...)
+{
+ u16 RegList = 0;
+ u8 Reg;
+ int i;
+ va_list vl;
+ va_start(vl, Regnum);
+ for (i=0;i<Regnum;i++)
+ {
+ Reg = va_arg(vl, u32);
+ RegList |= (1 << Reg);
+ }
+ va_end(vl);
+ WriteRegStoreOp(0x89, dest, WriteBack, RegList);
+}
+
+ARMReg ARMXEmitter::SubBase(ARMReg Reg)
+{
+ if (Reg >= S0)
+ {
+ if (Reg >= D0)
+ {
+ if (Reg >= Q0)
+ return (ARMReg)((Reg - Q0) * 2); // Always gets encoded as a double register
+ return (ARMReg)(Reg - D0);
+ }
+ return (ARMReg)(Reg - S0);
+ }
+ return Reg;
+}
+
+// NEON Specific
+void ARMXEmitter::VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to VADD(integer)");
+ _assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VADD(integer) when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+
+ // Gets encoded as a double register
+ Vd = SubBase(Vd);
+ Vn = SubBase(Vn);
+ Vm = SubBase(Vm);
+
+ Write32((0xF2 << 24) | ((Vd & 0x10) << 18) | (Size << 20) | ((Vn & 0xF) << 16) \
+ | ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (register_quad << 6) \
+ | ((Vm & 0x10) << 2) | (Vm & 0xF));
+
+}
+void ARMXEmitter::VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to VSUB(integer)");
+ _assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VSUB(integer) when CPU doesn't support it");
+
+ // Gets encoded as a double register
+ Vd = SubBase(Vd);
+ Vn = SubBase(Vn);
+ Vm = SubBase(Vm);
+
+ Write32((0xF3 << 24) | ((Vd & 0x10) << 18) | (Size << 20) | ((Vn & 0xF) << 16) \
+ | ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (1 << 6) \
+ | ((Vm & 0x10) << 2) | (Vm & 0xF));
+}
+
+// VFP Specific
+struct VFPEnc
+{
+ s16 opc1;
+ s16 opc2;
+};
+// Double/single, Neon
+const VFPEnc VFPOps[][2] = {
+ {{0xE0, 0xA0}, {0x20, 0xD1}}, // 0: VMLA
+ {{0xE0, 0xA4}, {0x22, 0xD1}}, // 1: VMLS
+ {{0xE3, 0xA0}, {0x20, 0xD0}}, // 2: VADD
+ {{0xE3, 0xA4}, {0x22, 0xD0}}, // 3: VSUB
+ {{0xE2, 0xA0}, {0x30, 0xD1}}, // 4: VMUL
+ {{0xEB, 0xAC}, { -1 /* 0x3B */, -1 /* 0x70 */}}, // 5: VABS(Vn(0x0) used for encoding)
+ {{0xE8, 0xA0}, { -1, -1}}, // 6: VDIV
+ {{0xEB, 0xA4}, { -1 /* 0x3B */, -1 /* 0x78 */}}, // 7: VNEG(Vn(0x1) used for encoding)
+ {{0xEB, 0xAC}, { -1, -1}}, // 8: VSQRT (Vn(0x1) used for encoding)
+ {{0xEB, 0xA4}, { -1, -1}}, // 9: VCMP (Vn(0x4 | #0 ? 1 : 0) used for encoding)
+ {{0xEB, 0xAC}, { -1, -1}}, // 10: VCMPE (Vn(0x4 | #0 ? 1 : 0) used for encoding)
+ {{ -1, -1}, {0x3B, 0x30}}, // 11: VABSi
+ };
+const char *VFPOpNames[] = {
+ "VMLA",
+ "VMLS",
+ "VADD",
+ "VSUB",
+ "VMUL",
+ "VABS",
+ "VDIV",
+ "VNEG",
+ "VSQRT",
+ "VCMP",
+ "VCMPE",
+ "VABSi",
+};
+
+u32 ARMXEmitter::EncodeVd(ARMReg Vd)
+{
+ bool quad_reg = Vd >= Q0;
+ bool double_reg = Vd >= D0;
+
+ ARMReg Reg = SubBase(Vd);
+
+ if (quad_reg)
+ return ((Reg & 0x10) << 18) | ((Reg & 0xF) << 12);
+ else
+ if (double_reg)
+ return ((Reg & 0x10) << 18) | ((Reg & 0xF) << 12);
+ else
+ return ((Reg & 0x1) << 22) | ((Reg & 0x1E) << 11);
+}
+u32 ARMXEmitter::EncodeVn(ARMReg Vn)
+{
+ bool quad_reg = Vn >= Q0;
+ bool double_reg = Vn >= D0;
+
+ ARMReg Reg = SubBase(Vn);
+ if (quad_reg)
+ return ((Reg & 0xF) << 16) | ((Reg & 0x10) << 3);
+ else
+ if (double_reg)
+ return ((Reg & 0xF) << 16) | ((Reg & 0x10) << 3);
+ else
+ return ((Reg & 0x1E) << 15) | ((Reg & 0x1) << 7);
+}
+u32 ARMXEmitter::EncodeVm(ARMReg Vm)
+{
+ bool quad_reg = Vm >= Q0;
+ bool double_reg = Vm >= D0;
+
+ ARMReg Reg = SubBase(Vm);
+
+ if (quad_reg)
+ return ((Reg & 0x10) << 2) | (Reg & 0xF);
+ else
+ if (double_reg)
+ return ((Reg & 0x10) << 2) | (Reg & 0xF);
+ else
+ return ((Reg & 0x1) << 5) | (Reg >> 1);
+}
+void ARMXEmitter::WriteVFPDataOp(u32 Op, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ bool quad_reg = Vd >= Q0;
+ bool double_reg = Vd >= D0 && Vd < Q0;
+
+ VFPEnc enc = VFPOps[Op][quad_reg];
+ if (enc.opc1 == -1 && enc.opc2 == -1)
+ _assert_msg_(DYNA_REC, false, "%s does not support %s", VFPOpNames[Op], quad_reg ? "NEON" : "VFP");
+ u32 VdEnc = EncodeVd(Vd);
+ u32 VnEnc = EncodeVn(Vn);
+ u32 VmEnc = EncodeVm(Vm);
+ u32 cond = quad_reg ? (0xF << 28) : condition;
+
+ Write32(cond | (enc.opc1 << 20) | VnEnc | VdEnc | (enc.opc2 << 4) | (quad_reg << 6) | (double_reg << 8) | VmEnc);
+}
+void ARMXEmitter::VMLA(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(0, Vd, Vn, Vm); }
+void ARMXEmitter::VMLS(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(1, Vd, Vn, Vm); }
+void ARMXEmitter::VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(2, Vd, Vn, Vm); }
+void ARMXEmitter::VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(3, Vd, Vn, Vm); }
+void ARMXEmitter::VMUL(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(4, Vd, Vn, Vm); }
+void ARMXEmitter::VABS(ARMReg Vd, ARMReg Vm){ WriteVFPDataOp(5, Vd, D0, Vm); }
+void ARMXEmitter::VDIV(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(6, Vd, Vn, Vm); }
+void ARMXEmitter::VNEG(ARMReg Vd, ARMReg Vm){ WriteVFPDataOp(7, Vd, D1, Vm); }
+void ARMXEmitter::VSQRT(ARMReg Vd, ARMReg Vm){ WriteVFPDataOp(8, Vd, D1, Vm); }
+void ARMXEmitter::VCMP(ARMReg Vd, ARMReg Vm){ WriteVFPDataOp(9, Vd, D4, Vm); }
+void ARMXEmitter::VCMPE(ARMReg Vd, ARMReg Vm){ WriteVFPDataOp(10, Vd, D4, Vm); }
+void ARMXEmitter::VCMP(ARMReg Vd){ WriteVFPDataOp(9, Vd, D5, D0); }
+void ARMXEmitter::VCMPE(ARMReg Vd){ WriteVFPDataOp(10, Vd, D5, D0); }
+
+void ARMXEmitter::VLDR(ARMReg Dest, ARMReg Base, s16 offset)
+{
+ _assert_msg_(DYNA_REC, Dest >= S0 && Dest <= D31, "Passed Invalid dest register to VLDR");
+ _assert_msg_(DYNA_REC, Base <= R15, "Passed invalid Base register to VLDR");
+
+ bool Add = offset >= 0 ? true : false;
+ u32 imm = abs(offset);
+
+ _assert_msg_(DYNA_REC, (imm & 0xC03) == 0, "VLDR: Offset needs to be word aligned and small enough");
+
+ if (imm & 0xC03)
+ ERROR_LOG(DYNA_REC, "VLDR: Bad offset %08x", imm);
+
+ bool single_reg = Dest < D0;
+
+ Dest = SubBase(Dest);
+
+ if (single_reg)
+ {
+ Write32(condition | (0xD << 24) | (Add << 23) | ((Dest & 0x1) << 22) | (1 << 20) | (Base << 16) \
+ | ((Dest & 0x1E) << 11) | (10 << 8) | (imm >> 2));
+
+ }
+ else
+ {
+ Write32(condition | (0xD << 24) | (Add << 23) | ((Dest & 0x10) << 18) | (1 << 20) | (Base << 16) \
+ | ((Dest & 0xF) << 12) | (11 << 8) | (imm >> 2));
+ }
+}
+void ARMXEmitter::VSTR(ARMReg Src, ARMReg Base, s16 offset)
+{
+ _assert_msg_(DYNA_REC, Src >= S0 && Src <= D31, "Passed invalid src register to VSTR");
+ _assert_msg_(DYNA_REC, Base <= R15, "Passed invalid base register to VSTR");
+
+ bool Add = offset >= 0 ? true : false;
+ u32 imm = abs(offset);
+
+ _assert_msg_(DYNA_REC, (imm & 0xC03) == 0, "VSTR: Offset needs to be word aligned and small enough");
+
+ if (imm & 0xC03)
+ ERROR_LOG(DYNA_REC, "VSTR: Bad offset %08x", imm);
+
+ bool single_reg = Src < D0;
+
+ Src = SubBase(Src);
+
+ if (single_reg)
+ {
+ Write32(condition | (0xD << 24) | (Add << 23) | ((Src & 0x1) << 22) | (Base << 16) \
+ | ((Src & 0x1E) << 11) | (10 << 8) | (imm >> 2));
+ }
+ else
+ {
+ Write32(condition | (0xD << 24) | (Add << 23) | ((Src & 0x10) << 18) | (Base << 16) \
+ | ((Src & 0xF) << 12) | (11 << 8) | (imm >> 2));
+ }
+}
+
+void ARMXEmitter::VMRS_APSR() {
+ Write32(condition | 0xEF10A10 | (15 << 12));
+}
+void ARMXEmitter::VMRS(ARMReg Rt) {
+ Write32(condition | (0xEF << 20) | (1 << 16) | (Rt << 12) | 0xA10);
+}
+void ARMXEmitter::VMSR(ARMReg Rt) {
+ Write32(condition | (0xEE << 20) | (1 << 16) | (Rt << 12) | 0xA10);
+}
+
+// VFP and ASIMD
+void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src, bool high)
+{
+ _assert_msg_(DYNA_REC, Src < S0, "This VMOV doesn't support SRC other than ARM Reg");
+ _assert_msg_(DYNA_REC, Dest >= D0, "This VMOV doesn't support DEST other than VFP");
+
+ Dest = SubBase(Dest);
+
+ Write32(condition | (0xE << 24) | (high << 21) | ((Dest & 0xF) << 16) | (Src << 12) \
+ | (11 << 8) | ((Dest & 0x10) << 3) | (1 << 4));
+}
+
+void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src)
+{
+ if (Dest > R15)
+ {
+ if (Src < S0)
+ {
+ if (Dest < D0)
+ {
+ // Moving to a Neon register FROM ARM Reg
+ Dest = (ARMReg)(Dest - S0);
+ Write32(condition | (0xE0 << 20) | ((Dest & 0x1E) << 15) | (Src << 12) \
+ | (0xA << 8) | ((Dest & 0x1) << 7) | (1 << 4));
+ return;
+ }
+ else
+ {
+ // Move 64bit from Arm reg
+ _assert_msg_(DYNA_REC, false, "This VMOV doesn't support moving 64bit ARM to NEON");
+ return;
+ }
+ }
+ }
+ else
+ {
+ if (Src > R15)
+ {
+ if (Src < D0)
+ {
+ // Moving to ARM Reg from Neon Register
+ Src = (ARMReg)(Src - S0);
+ Write32(condition | (0xE1 << 20) | ((Src & 0x1E) << 15) | (Dest << 12) \
+ | (0xA << 8) | ((Src & 0x1) << 7) | (1 << 4));
+ return;
+ }
+ else
+ {
+ // Move 64bit To Arm reg
+ _assert_msg_(DYNA_REC, false, "This VMOV doesn't support moving 64bit ARM From NEON");
+ return;
+ }
+ }
+ else
+ {
+ // Move Arm reg to Arm reg
+ _assert_msg_(DYNA_REC, false, "VMOV doesn't support moving ARM registers");
+ }
+ }
+ // Moving NEON registers
+ int SrcSize = Src < D0 ? 1 : Src < Q0 ? 2 : 4;
+ int DestSize = Dest < D0 ? 1 : Dest < Q0 ? 2 : 4;
+ bool Single = DestSize == 1;
+ bool Quad = DestSize == 4;
+
+ _assert_msg_(DYNA_REC, SrcSize == DestSize, "VMOV doesn't support moving different register sizes");
+
+ Dest = SubBase(Dest);
+ Src = SubBase(Src);
+
+ if (Single)
+ {
+ Write32(condition | (0x1D << 23) | ((Dest & 0x1) << 22) | (0x3 << 20) | ((Dest & 0x1E) << 11) \
+ | (0x5 << 9) | (1 << 6) | ((Src & 0x1) << 5) | ((Src & 0x1E) >> 1));
+ }
+ else
+ {
+ // Double and quad
+ if (Quad)
+ {
+ _assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use quad registers when you don't support ASIMD.");
+ // Gets encoded as a Double register
+ Write32((0xF2 << 24) | ((Dest & 0x10) << 18) | (2 << 20) | ((Src & 0xF) << 16) \
+ | ((Dest & 0xF) << 12) | (1 << 8) | ((Src & 0x10) << 3) | (1 << 6) \
+ | ((Src & 0x10) << 1) | (1 << 4) | (Src & 0xF));
+
+ }
+ else
+ {
+ Write32(condition | (0x1D << 23) | ((Dest & 0x10) << 18) | (0x3 << 20) | ((Dest & 0xF) << 12) \
+ | (0x2D << 6) | ((Src & 0x10) << 1) | (Src & 0xF));
+ }
+ }
+}
+
+void ARMXEmitter::VCVT(ARMReg Dest, ARMReg Source, int flags)
+{
+ bool single_reg = (Dest < D0) && (Source < D0);
+ int op = ((flags & TO_INT) ? (flags & ROUND_TO_ZERO) : (flags & IS_SIGNED)) ? 1 : 0;
+ int op2 = ((flags & TO_INT) ? (flags & IS_SIGNED) : 0) ? 1 : 0;
+ Dest = SubBase(Dest);
+ Source = SubBase(Source);
+
+ if (single_reg)
+ {
+ Write32(condition | (0x1D << 23) | ((Dest & 0x1) << 22) | (0x7 << 19) | ((flags & TO_INT) << 18) | (op2 << 16) \
+ | ((Dest & 0x1E) << 11) | (op << 7) | (0x29 << 6) | ((Source & 0x1) << 5) | (Source >> 1));
+ } else {
+ Write32(condition | (0x1D << 23) | ((Dest & 0x10) << 18) | (0x7 << 19) | ((flags & TO_INT) << 18) | (op2 << 16) \
+ | ((Dest & 0xF) << 12) | (1 << 8) | (op << 7) | (0x29 << 6) | ((Source & 0x10) << 1) | (Source & 0xF));
+ }
+}
+
+}
diff --git a/Source/Core/Common/Src/ArmEmitter.h b/Source/Core/Common/Src/ArmEmitter.h
new file mode 100644
index 0000000000..fe64584e0c
--- /dev/null
+++ b/Source/Core/Common/Src/ArmEmitter.h
@@ -0,0 +1,637 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+// WARNING - THIS LIBRARY IS NOT THREAD SAFE!!!
+
+#ifndef _DOLPHIN_ARM_CODEGEN_
+#define _DOLPHIN_ARM_CODEGEN_
+
+#include "Common.h"
+#include "MemoryUtil.h"
+#if defined(__SYMBIAN32__) || defined(PANDORA)
+#include <signal.h>
+#endif
+#include <vector>
+
+#undef _IP
+#undef R0
+#undef _SP
+#undef _LR
+#undef _PC
+
+// VCVT flags
+#define TO_FLOAT 0
+#define TO_INT 1 << 0
+#define IS_SIGNED 1 << 1
+#define ROUND_TO_ZERO 1 << 2
+
+namespace ArmGen
+{
+enum ARMReg
+{
+ // GPRs
+ R0 = 0, R1, R2, R3, R4, R5,
+ R6, R7, R8, R9, R10, R11,
+
+ // SPRs
+ // R13 - R15 are SP, LR, and PC.
+ // Almost always referred to by name instead of register number
+ R12 = 12, R13 = 13, R14 = 14, R15 = 15,
+ _IP = 12, _SP = 13, _LR = 14, _PC = 15,
+
+
+ // VFP single precision registers
+ S0, S1, S2, S3, S4, S5, S6,
+ S7, S8, S9, S10, S11, S12, S13,
+ S14, S15, S16, S17, S18, S19, S20,
+ S21, S22, S23, S24, S25, S26, S27,
+ S28, S29, S30, S31,
+
+ // VFP Double Precision registers
+ D0, D1, D2, D3, D4, D5, D6, D7,
+ D8, D9, D10, D11, D12, D13, D14, D15,
+ D16, D17, D18, D19, D20, D21, D22, D23,
+ D24, D25, D26, D27, D28, D29, D30, D31,
+
+ // ASIMD Quad-Word registers
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7,
+ Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15,
+ INVALID_REG = 0xFFFFFFFF
+};
+
+enum CCFlags
+{
+ CC_EQ = 0, // Equal
+ CC_NEQ, // Not equal
+ CC_CS, // Carry Set
+ CC_CC, // Carry Clear
+ CC_MI, // Minus (Negative)
+ CC_PL, // Plus
+ CC_VS, // Overflow
+ CC_VC, // No Overflow
+ CC_HI, // Unsigned higher
+ CC_LS, // Unsigned lower or same
+ CC_GE, // Signed greater than or equal
+ CC_LT, // Signed less than
+ CC_GT, // Signed greater than
+ CC_LE, // Signed less than or equal
+ CC_AL, // Always (unconditional) 14
+ CC_HS = CC_CS, // Alias of CC_CS Unsigned higher or same
+ CC_LO = CC_CC, // Alias of CC_CC Unsigned lower
+};
+const u32 NO_COND = 0xE0000000;
+
+enum ShiftType
+{
+ ST_LSL = 0,
+ ST_ASL = 0,
+ ST_LSR = 1,
+ ST_ASR = 2,
+ ST_ROR = 3,
+ ST_RRX = 4
+};
+enum IntegerSize
+{
+ I_I8 = 0,
+ I_I16,
+ I_I32,
+ I_I64
+};
+
+enum
+{
+ NUMGPRs = 13,
+};
+
+class ARMXEmitter;
+
+enum OpType
+{
+ TYPE_IMM = 0,
+ TYPE_REG,
+ TYPE_IMMSREG,
+ TYPE_RSR,
+ TYPE_MEM
+};
+
+// This is no longer a proper operand2 class. Need to split up.
+class Operand2
+{
+ friend class ARMXEmitter;
+protected:
+ u32 Value;
+
+private:
+ OpType Type;
+
+ // IMM types
+ u8 Rotation; // Only for u8 values
+
+ // Register types
+ u8 IndexOrShift;
+ ShiftType Shift;
+public:
+ OpType GetType()
+ {
+ return Type;
+ }
+ Operand2() {}
+ Operand2(u32 imm, OpType type = TYPE_IMM)
+ {
+ Type = type;
+ Value = imm;
+ Rotation = 0;
+ }
+
+ Operand2(ARMReg Reg)
+ {
+ Type = TYPE_REG;
+ Value = Reg;
+ Rotation = 0;
+ }
+ Operand2(u8 imm, u8 rotation)
+ {
+ Type = TYPE_IMM;
+ Value = imm;
+ Rotation = rotation;
+ }
+ Operand2(ARMReg base, ShiftType type, ARMReg shift) // RSR
+ {
+ Type = TYPE_RSR;
+ _assert_msg_(DYNA_REC, type != ST_RRX, "Invalid Operand2: RRX does not take a register shift amount");
+ IndexOrShift = shift;
+ Shift = type;
+ Value = base;
+ }
+
+ Operand2(ARMReg base, ShiftType type, u8 shift)// For IMM shifted register
+ {
+ if(shift == 32) shift = 0;
+ switch (type)
+ {
+ case ST_LSL:
+ _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: LSL %u", shift);
+ break;
+ case ST_LSR:
+ _assert_msg_(DYNA_REC, shift <= 32, "Invalid Operand2: LSR %u", shift);
+ if (!shift)
+ type = ST_LSL;
+ if (shift == 32)
+ shift = 0;
+ break;
+ case ST_ASR:
+ _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: LSR %u", shift);
+ if (!shift)
+ type = ST_LSL;
+ if (shift == 32)
+ shift = 0;
+ break;
+ case ST_ROR:
+ _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: ROR %u", shift);
+ if (!shift)
+ type = ST_LSL;
+ break;
+ case ST_RRX:
+ _assert_msg_(DYNA_REC, shift == 0, "Invalid Operand2: RRX does not take an immediate shift amount");
+ type = ST_ROR;
+ break;
+ }
+ IndexOrShift = shift;
+ Shift = type;
+ Value = base;
+ Type = TYPE_IMMSREG;
+ }
+ u32 GetData()
+ {
+ switch(Type)
+ {
+ case TYPE_IMM:
+ return Imm12Mod(); // This'll need to be changed later
+ case TYPE_REG:
+ return Rm();
+ case TYPE_IMMSREG:
+ return IMMSR();
+ case TYPE_RSR:
+ return RSR();
+ default:
+ _assert_msg_(DYNA_REC, false, "GetData with Invalid Type");
+ return 0;
+ }
+ }
+ u32 IMMSR() // IMM shifted register
+ {
+ _assert_msg_(DYNA_REC, Type == TYPE_IMMSREG, "IMMSR must be imm shifted register");
+ return ((IndexOrShift & 0x1f) << 7 | (Shift << 5) | Value);
+ }
+ u32 RSR() // Register shifted register
+ {
+ _assert_msg_(DYNA_REC, Type == TYPE_RSR, "RSR must be RSR Of Course");
+ return (IndexOrShift << 8) | (Shift << 5) | 0x10 | Value;
+ }
+ u32 Rm()
+ {
+ _assert_msg_(DYNA_REC, Type == TYPE_REG, "Rm must be with Reg");
+ return Value;
+ }
+
+ u32 Imm5()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm5 not IMM value");
+ return ((Value & 0x0000001F) << 7);
+ }
+ u32 Imm8()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value");
+ return Value & 0xFF;
+ }
+ u32 Imm8Rot() // IMM8 with Rotation
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value");
+ _assert_msg_(DYNA_REC, (Rotation & 0xE1) != 0, "Invalid Operand2: immediate rotation %u", Rotation);
+ return (1 << 25) | (Rotation << 7) | (Value & 0x000000FF);
+ }
+ u32 Imm12()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12 not IMM");
+ return (Value & 0x00000FFF);
+ }
+
+ u32 Imm12Mod()
+ {
+ // This is a IMM12 with the top four bits being rotation and the
+ // bottom eight being a IMM. This is for instructions that need to
+ // expand a 8bit IMM to a 32bit value and gives you some rotation as
+ // well.
+ // Each rotation rotates to the right by 2 bits
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12Mod not IMM");
+ return ((Rotation & 0xF) << 8) | (Value & 0xFF);
+ }
+ u32 Imm16()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
+ return ( (Value & 0xF000) << 4) | (Value & 0x0FFF);
+ }
+ u32 Imm16Low()
+ {
+ return Imm16();
+ }
+ u32 Imm16High() // Returns high 16bits
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
+ return ( ((Value >> 16) & 0xF000) << 4) | ((Value >> 16) & 0x0FFF);
+ }
+ u32 Imm24()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
+ return (Value & 0x0FFFFFFF);
+ }
+ // NEON and ASIMD specific
+ u32 Imm8ASIMD()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8ASIMD not IMM");
+ return ((Value & 0x80) << 17) | ((Value & 0x70) << 12) | (Value & 0xF);
+ }
+ u32 Imm8VFP()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8VFP not IMM");
+ return ((Value & 0xF0) << 12) | (Value & 0xF);
+ }
+};
+
+// Use these when you don't know if an imm can be represented as an operand2.
+// This lets you generate both an optimal and a fallback solution by checking
+// the return value, which will be false if these fail to find a Operand2 that
+// represents your 32-bit imm value.
+bool TryMakeOperand2(u32 imm, Operand2 &op2);
+bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse);
+bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated);
+
+inline Operand2 R(ARMReg Reg) { return Operand2(Reg, TYPE_REG); }
+inline Operand2 IMM(u32 Imm) { return Operand2(Imm, TYPE_IMM); }
+inline Operand2 Mem(void *ptr) { return Operand2((u32)ptr, TYPE_IMM); }
+//usage: struct {int e;} s; STRUCT_OFFSET(s,e)
+#define STRUCT_OFF(str,elem) ((u32)((u32)&(str).elem-(u32)&(str)))
+
+
+struct FixupBranch
+{
+ u8 *ptr;
+ u32 condition; // Remembers our codition at the time
+ int type; //0 = B 1 = BL
+};
+
+struct LiteralPool
+{
+ s32 loc;
+ u8* ldr_address;
+ u32 val;
+};
+
+typedef const u8* JumpTarget;
+
+class ARMXEmitter
+{
+ friend struct OpArg; // for Write8 etc
+private:
+ u8 *code, *startcode;
+ u8 *lastCacheFlushEnd;
+ u32 condition;
+ std::vector<LiteralPool> currentLitPool;
+
+ void WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 op2, bool RegAdd);
+ void WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList);
+ void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, ARMReg op2);
+ void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2);
+ void WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2);
+
+ u32 EncodeVd(ARMReg Vd);
+ u32 EncodeVn(ARMReg Vn);
+ u32 EncodeVm(ARMReg Vm);
+ void WriteVFPDataOp(u32 Op, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+
+ void Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
+
+ // New Ops
+ void WriteInstruction(u32 op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags = false);
+
+protected:
+ inline void Write32(u32 value) {*(u32*)code = value; code+=4;}
+
+public:
+ ARMXEmitter() : code(0), startcode(0), lastCacheFlushEnd(0) {
+ condition = CC_AL << 28;
+ }
+ ARMXEmitter(u8 *code_ptr) {
+ code = code_ptr;
+ lastCacheFlushEnd = code_ptr;
+ startcode = code_ptr;
+ condition = CC_AL << 28;
+ }
+ virtual ~ARMXEmitter() {}
+
+ void SetCodePtr(u8 *ptr);
+ void ReserveCodeSpace(u32 bytes);
+ const u8 *AlignCode16();
+ const u8 *AlignCodePage();
+ const u8 *GetCodePtr() const;
+ void FlushIcache();
+ void FlushIcacheSection(u8 *start, u8 *end);
+ u8 *GetWritableCodePtr();
+
+ void FlushLitPool();
+ void AddNewLit(u32 val);
+
+ CCFlags GetCC() { return CCFlags(condition >> 28); }
+ void SetCC(CCFlags cond = CC_AL);
+
+ // Special purpose instructions
+
+ // Dynamic Endian Switching
+ void SETEND(bool BE);
+ // Debug Breakpoint
+ void BKPT(u16 arg);
+
+ // Hint instruction
+ void YIELD();
+
+ // Do nothing
+ void NOP(int count = 1); //nop padding - TODO: fast nop slides, for amd and intel (check their manuals)
+
+#ifdef CALL
+#undef CALL
+#endif
+
+ // Branching
+ FixupBranch B();
+ FixupBranch B_CC(CCFlags Cond);
+ void B_CC(CCFlags Cond, const void *fnptr);
+ FixupBranch BL();
+ FixupBranch BL_CC(CCFlags Cond);
+ void SetJumpTarget(FixupBranch const &branch);
+
+ void B (const void *fnptr);
+ void B (ARMReg src);
+ void BL(const void *fnptr);
+ void BL(ARMReg src);
+
+ void PUSH(const int num, ...);
+ void POP(const int num, ...);
+
+ // New Data Ops
+ void AND (ARMReg Rd, ARMReg Rn, Operand2 Rm);
+ void ANDS(ARMReg Rd, ARMReg Rn, Operand2 Rm);
+ void EOR (ARMReg dest, ARMReg src, Operand2 op2);
+ void EORS(ARMReg dest, ARMReg src, Operand2 op2);
+ void SUB (ARMReg dest, ARMReg src, Operand2 op2);
+ void SUBS(ARMReg dest, ARMReg src, Operand2 op2);
+ void RSB (ARMReg dest, ARMReg src, Operand2 op2);
+ void RSBS(ARMReg dest, ARMReg src, Operand2 op2);
+ void ADD (ARMReg dest, ARMReg src, Operand2 op2);
+ void ADDS(ARMReg dest, ARMReg src, Operand2 op2);
+ void ADC (ARMReg dest, ARMReg src, Operand2 op2);
+ void ADCS(ARMReg dest, ARMReg src, Operand2 op2);
+ void LSL (ARMReg dest, ARMReg src, Operand2 op2);
+ void LSL (ARMReg dest, ARMReg src, ARMReg op2);
+ void LSLS(ARMReg dest, ARMReg src, Operand2 op2);
+ void LSLS(ARMReg dest, ARMReg src, ARMReg op2);
+ void LSR (ARMReg dest, ARMReg src, Operand2 op2);
+ void SBC (ARMReg dest, ARMReg src, Operand2 op2);
+ void SBCS(ARMReg dest, ARMReg src, Operand2 op2);
+ void RBIT(ARMReg dest, ARMReg src);
+ void REV (ARMReg dest, ARMReg src);
+ void REV16 (ARMReg dest, ARMReg src);
+ void RSC (ARMReg dest, ARMReg src, Operand2 op2);
+ void RSCS(ARMReg dest, ARMReg src, Operand2 op2);
+ void TST ( ARMReg src, Operand2 op2);
+ void TEQ ( ARMReg src, Operand2 op2);
+ void CMP ( ARMReg src, Operand2 op2);
+ void CMN ( ARMReg src, Operand2 op2);
+ void ORR (ARMReg dest, ARMReg src, Operand2 op2);
+ void ORRS(ARMReg dest, ARMReg src, Operand2 op2);
+ void MOV (ARMReg dest, Operand2 op2);
+ void MOVS(ARMReg dest, Operand2 op2);
+ void BIC (ARMReg dest, ARMReg src, Operand2 op2); // BIC = ANDN
+ void BICS(ARMReg dest, ARMReg src, Operand2 op2);
+ void MVN (ARMReg dest, Operand2 op2);
+ void MVNS(ARMReg dest, Operand2 op2);
+ void MOVW(ARMReg dest, Operand2 op2);
+ void MOVT(ARMReg dest, Operand2 op2, bool TopBits = false);
+
+ // UDIV and SDIV are only available on CPUs that have
+ // the idiva hardare capacity
+ void UDIV(ARMReg dest, ARMReg dividend, ARMReg divisor);
+ void SDIV(ARMReg dest, ARMReg dividend, ARMReg divisor);
+
+ void MUL (ARMReg dest, ARMReg src, ARMReg op2);
+ void MULS(ARMReg dest, ARMReg src, ARMReg op2);
+
+ void UMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
+ void SMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
+
+ void UMLAL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
+ void SMLAL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
+
+ void SXTB(ARMReg dest, ARMReg op2);
+ void SXTH(ARMReg dest, ARMReg op2, u8 rotation = 0);
+ void SXTAH(ARMReg dest, ARMReg src, ARMReg op2, u8 rotation = 0);
+ void BFI(ARMReg rd, ARMReg rn, u8 lsb, u8 width);
+ void UBFX(ARMReg dest, ARMReg op2, u8 lsb, u8 width);
+ void CLZ(ARMReg rd, ARMReg rm);
+
+ // Using just MSR here messes with our defines on the PPC side of stuff (when this code was in dolphin...)
+ // Just need to put an underscore here, bit annoying.
+ void _MSR (bool nzcvq, bool g, Operand2 op2);
+ void _MSR (bool nzcvq, bool g, ARMReg src);
+ void MRS (ARMReg dest);
+
+ // Memory load/store operations
+ void LDR (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void LDRB (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void LDRH (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void LDRSB(ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void LDRSH(ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void STR (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void STRB (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void STRH (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+
+ void STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);
+ void LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);
+
+ // Exclusive Access operations
+ void LDREX(ARMReg dest, ARMReg base);
+ // result contains the result if the instruction managed to store the value
+ void STREX(ARMReg result, ARMReg base, ARMReg op);
+ void DMB ();
+ void SVC(Operand2 op);
+
+ // NEON and ASIMD instructions
+ // None of these will be created with conditional since ARM
+ // is deprecating conditional execution of ASIMD instructions.
+ // ASIMD instructions don't even have a conditional encoding.
+
+ // Subtracts the base from the register to give us the real one
+ ARMReg SubBase(ARMReg Reg);
+ // NEON Only
+ void VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+
+ // VFP Only
+ void VLDR(ARMReg Dest, ARMReg Base, s16 offset);
+ void VSTR(ARMReg Src, ARMReg Base, s16 offset);
+ void VCMP(ARMReg Vd, ARMReg Vm);
+ void VCMPE(ARMReg Vd, ARMReg Vm);
+ // Compares against zero
+ void VCMP(ARMReg Vd);
+ void VCMPE(ARMReg Vd);
+ void VDIV(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VSQRT(ARMReg Vd, ARMReg Vm);
+
+ // NEON and VFP
+ void VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VABS(ARMReg Vd, ARMReg Vm);
+ void VNEG(ARMReg Vd, ARMReg Vm);
+ void VMUL(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMLA(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMLS(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMOV(ARMReg Dest, ARMReg Src, bool high);
+ void VMOV(ARMReg Dest, ARMReg Src);
+ void VCVT(ARMReg Dest, ARMReg Src, int flags);
+
+ void VMRS_APSR();
+ void VMRS(ARMReg Rt);
+ void VMSR(ARMReg Rt);
+
+ void QuickCallFunction(ARMReg scratchreg, void *func);
+
+ // Wrapper around MOVT/MOVW with fallbacks.
+ void MOVI2R(ARMReg reg, u32 val, bool optimize = true);
+ void MOVI2F(ARMReg dest, float val, ARMReg tempReg);
+
+ void ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
+ void ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
+
+
+}; // class ARMXEmitter
+
+
+// Everything that needs to generate X86 code should inherit from this.
+// You get memory management for free, plus, you can use all the MOV etc functions without
+// having to prefix them with gen-> or something similar.
+class ARMXCodeBlock : public ARMXEmitter
+{
+protected:
+ u8 *region;
+ size_t region_size;
+
+public:
+ ARMXCodeBlock() : region(NULL), region_size(0) {}
+ virtual ~ARMXCodeBlock() { if (region) FreeCodeSpace(); }
+
+ // Call this before you generate any code.
+ void AllocCodeSpace(int size)
+ {
+ region_size = size;
+ region = (u8*)AllocateExecutableMemory(region_size);
+ SetCodePtr(region);
+ }
+
+ // Always clear code space with breakpoints, so that if someone accidentally executes
+ // uninitialized, it just breaks into the debugger.
+ void ClearCodeSpace()
+ {
+ // x86/64: 0xCC = breakpoint
+ memset(region, 0xCC, region_size);
+ ResetCodePtr();
+ }
+
+ // Call this when shutting down. Don't rely on the destructor, even though it'll do the job.
+ void FreeCodeSpace()
+ {
+#ifndef __SYMBIAN32__
+ FreeMemoryPages(region, region_size);
+#endif
+ region = NULL;
+ region_size = 0;
+ }
+
+ bool IsInSpace(u8 *ptr)
+ {
+ return ptr >= region && ptr < region + region_size;
+ }
+
+ // Cannot currently be undone. Will write protect the entire code region.
+ // Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
+ void WriteProtect()
+ {
+ WriteProtectMemory(region, region_size, true);
+ }
+
+ void ResetCodePtr()
+ {
+ SetCodePtr(region);
+ }
+
+ size_t GetSpaceLeft() const
+ {
+ return region_size - (GetCodePtr() - region);
+ }
+};
+
+} // namespace
+
+#endif // _DOLPHIN_INTEL_CODEGEN_
diff --git a/Source/Core/Common/Src/BreakPoints.h b/Source/Core/Common/Src/BreakPoints.h
index c742f812a7..1268b4e80a 100644
--- a/Source/Core/Common/Src/BreakPoints.h
+++ b/Source/Core/Common/Src/BreakPoints.h
@@ -27,9 +27,9 @@ class DebugInterface;
struct TBreakPoint
{
- u32 iAddress;
+ u32 iAddress;
bool bOn;
- bool bTemporary;
+ bool bTemporary;
};
struct TMemCheck
@@ -96,9 +96,9 @@ public:
typedef std::vector<std::string> TMemChecksStr;
TMemChecks m_MemChecks;
-
+
const TMemChecks& GetMemChecks() { return m_MemChecks; }
-
+
TMemChecksStr GetStrings() const;
void AddFromStrings(const TMemChecksStr& mcs);
diff --git a/Source/Core/Common/Src/CDUtils.cpp b/Source/Core/Common/Src/CDUtils.cpp
index 42aa9bfe34..9a302b9189 100644
--- a/Source/Core/Common/Src/CDUtils.cpp
+++ b/Source/Core/Common/Src/CDUtils.cpp
@@ -6,6 +6,7 @@
#include <memory> // for std::unique_ptr
#ifdef _WIN32
#include <windows.h>
+#include "StringUtil.h"
#elif __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOBSD.h>
@@ -25,7 +26,7 @@
#ifdef _WIN32
// takes a root drive path, returns true if it is a cdrom drive
-bool is_cdrom(const char drive[])
+bool is_cdrom(const TCHAR* drive)
{
return (DRIVE_CDROM == GetDriveType(drive));
}
@@ -36,15 +37,15 @@ std::vector<std::string> cdio_get_devices()
std::vector<std::string> drives;
const DWORD buffsize = GetLogicalDriveStrings(0, NULL);
- std::unique_ptr<char[]> buff(new char[buffsize]);
- if (GetLogicalDriveStrings(buffsize, buff.get()) == buffsize - 1)
+ std::vector<TCHAR> buff(buffsize);
+ if (GetLogicalDriveStrings(buffsize, buff.data()) == buffsize - 1)
{
- const char* drive = buff.get();
+ auto drive = buff.data();
while (*drive)
{
if (is_cdrom(drive))
{
- std::string str(drive);
+ std::string str(TStrToUTF8(drive));
str.pop_back(); // we don't want the final backslash
drives.push_back(std::move(str));
}
diff --git a/Source/Core/Common/Src/CPUDetect.h b/Source/Core/Common/Src/CPUDetect.h
index 928b34c109..5c2b33b4b3 100644
--- a/Source/Core/Common/Src/CPUDetect.h
+++ b/Source/Core/Common/Src/CPUDetect.h
@@ -25,19 +25,20 @@ enum CPUVendor
{
VENDOR_INTEL = 0,
VENDOR_AMD = 1,
- VENDOR_OTHER = 2,
+ VENDOR_ARM = 2,
+ VENDOR_OTHER = 3,
};
struct CPUInfo
{
CPUVendor vendor;
-
+
char cpu_string[0x21];
char brand_string[0x41];
bool OS64bit;
bool CPU64bit;
bool Mode64bit;
-
+
bool HTT;
int num_cores;
int logical_cpu_count;
@@ -56,9 +57,29 @@ struct CPUInfo
bool bLAHFSAHF64;
bool bLongMode;
+ // ARM specific CPUInfo
+ bool bSwp;
+ bool bHalf;
+ bool bThumb;
+ bool bFastMult;
+ bool bVFP;
+ bool bEDSP;
+ bool bThumbEE;
+ bool bNEON;
+ bool bVFPv3;
+ bool bTLS;
+ bool bVFPv4;
+ bool bIDIVa;
+ bool bIDIVt;
+ bool bArmV7; // enable MOVT, MOVW etc
+
+ // ARMv8 specific
+ bool bFP;
+ bool bASIMD;
+
// Call Detect()
explicit CPUInfo();
-
+
// Turn the cpu info into a string we can show
std::string Summarize();
diff --git a/Source/Core/Common/Src/ChunkFile.h b/Source/Core/Common/Src/ChunkFile.h
index 38e1b2176c..ecf641a27b 100644
--- a/Source/Core/Common/Src/ChunkFile.h
+++ b/Source/Core/Common/Src/ChunkFile.h
@@ -29,6 +29,7 @@
#include <map>
#include <vector>
+#include <list>
#include <deque>
#include <string>
@@ -45,7 +46,8 @@ struct LinkedListItem : public T
class PointerWrap
{
public:
- enum Mode {
+ enum Mode
+ {
MODE_READ = 1, // load
MODE_WRITE, // save
MODE_MEASURE, // calculate size
@@ -57,124 +59,95 @@ public:
public:
PointerWrap(u8 **ptr_, Mode mode_) : ptr(ptr_), mode(mode_) {}
- PointerWrap(unsigned char **ptr_, int mode_) : ptr((u8**)ptr_), mode((Mode)mode_) {}
- void SetMode(Mode mode_) {mode = mode_;}
- Mode GetMode() const {return mode;}
- u8 **GetPPtr() {return ptr;}
+ void SetMode(Mode mode_) { mode = mode_; }
+ Mode GetMode() const { return mode; }
+ u8** GetPPtr() { return ptr; }
- void DoVoid(void *data, int size)
+ template <typename K, class V>
+ void Do(std::map<K, V>& x)
{
- switch (mode) {
- case MODE_READ: memcpy(data, *ptr, size); break;
- case MODE_WRITE: memcpy(*ptr, data, size); break;
- case MODE_MEASURE: break; // MODE_MEASURE - don't need to do anything
- case MODE_VERIFY: for(int i = 0; i < size; i++) _dbg_assert_msg_(COMMON, ((u8*)data)[i] == (*ptr)[i], "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n", ((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i], &(*ptr)[i]); break;
- default: break; // throw an error?
- }
- (*ptr) += size;
- }
+ u32 count = (u32)x.size();
+ Do(count);
- template<class T>
- void Do(std::map<unsigned int, T> &x)
- {
- unsigned int number = (unsigned int)x.size();
- Do(number);
- switch (mode) {
+ switch (mode)
+ {
case MODE_READ:
+ for (x.clear(); count != 0; --count)
{
- x.clear();
- while (number > 0)
- {
- unsigned int first = 0;
- Do(first);
- T second;
- Do(second);
- x[first] = second;
- --number;
- }
+ std::pair<K, V> pair;
+ Do(pair.first);
+ Do(pair.second);
+ x.insert(pair);
}
break;
+
case MODE_WRITE:
case MODE_MEASURE:
case MODE_VERIFY:
+ for (auto itr = x.begin(); itr != x.end(); ++itr)
{
- typename std::map<unsigned int, T>::iterator itr = x.begin();
- while (number > 0)
- {
- Do(itr->first);
- Do(itr->second);
- --number;
- ++itr;
- }
+ Do(itr->first);
+ Do(itr->second);
}
break;
}
}
- // Store vectors.
- template<class T>
- void Do(std::vector<T> &x)
+ template <typename T>
+ void DoContainer(T& x)
{
- u32 vec_size = (u32)x.size();
- Do(vec_size);
- x.resize(vec_size);
- DoArray(&x[0], vec_size);
+ u32 size = (u32)x.size();
+ Do(size);
+ x.resize(size);
+
+ for (auto itr = x.begin(); itr != x.end(); ++itr)
+ Do(*itr);
}
-
- // Store deques.
- template<class T>
- void Do(std::deque<T> &x)
+
+ template <typename T>
+ void Do(std::vector<T>& x)
{
- u32 deq_size = (u32)x.size();
- Do(deq_size);
- x.resize(deq_size);
- u32 i;
- for(i = 0; i < deq_size; i++)
- DoVoid(&x[i],sizeof(T));
+ DoContainer(x);
}
-
- // Store strings.
- void Do(std::string &x)
+
+ template <typename T>
+ void Do(std::list<T>& x)
{
- int stringLen = (int)x.length() + 1;
- Do(stringLen);
-
- switch (mode) {
- case MODE_READ: x = (char*)*ptr; break;
- case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
- case MODE_MEASURE: break;
- case MODE_VERIFY: _dbg_assert_msg_(COMMON, !strcmp(x.c_str(), (char*)*ptr), "Savestate verification failure: \"%s\" != \"%s\" (at %p).\n", x.c_str(), (char*)*ptr, ptr); break;
- }
- (*ptr) += stringLen;
+ DoContainer(x);
}
- void Do(std::wstring &x)
+ template <typename T>
+ void Do(std::deque<T>& x)
{
- int stringLen = sizeof(wchar_t)*((int)x.length() + 1);
- Do(stringLen);
-
- switch (mode) {
- case MODE_READ: x.assign((wchar_t*)*ptr, (stringLen / sizeof(wchar_t)) - 1); break;
- case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
- case MODE_MEASURE: break;
- case MODE_VERIFY: _dbg_assert_msg_(COMMON, x == (wchar_t*)*ptr, "Savestate verification failure: \"%ls\" != \"%ls\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); break;
- }
- (*ptr) += stringLen;
+ DoContainer(x);
}
- template<class T>
- void DoArray(T *x, int count) {
- DoVoid((void *)x, sizeof(T) * count);
- }
-
- template<class T>
- void Do(T &x) {
- DoVoid((void *)&x, sizeof(x));
+ template <typename T>
+ void Do(std::basic_string<T>& x)
+ {
+ DoContainer(x);
}
- template<class T>
- void DoPointer(T* &x, T*const base) {
+ template <typename T>
+ void DoArray(T* x, u32 count)
+ {
+ for (u32 i = 0; i != count; ++i)
+ Do(x[i]);
+ }
+
+ template <typename T>
+ void Do(T& x)
+ {
+ // TODO: Bad, Do(some_non_POD) will compile and fail at runtime
+ // type_traits are not fully supported everywhere yet
+
+ DoVoid((void*)&x, sizeof(x));
+ }
+
+ template <typename T>
+ void DoPointer(T*& x, T* const base)
+ {
// pointers can be more than 2^31 apart, but you're using this function wrong if you need that much range
s32 offset = x - base;
Do(offset);
@@ -182,7 +155,8 @@ public:
x = base + offset;
}
- template<class T, LinkedListItem<T>* (*TNew)(), void (*TFree)(LinkedListItem<T>*), void (*TDo)(PointerWrap&, T*)>
+ // Let's pretend std::list doesn't exist!
+ template <class T, LinkedListItem<T>* (*TNew)(), void (*TFree)(LinkedListItem<T>*), void (*TDo)(PointerWrap&, T*)>
void DoLinkedList(LinkedListItem<T>*& list_start, LinkedListItem<T>** list_end=0)
{
LinkedListItem<T>* list_cur = list_start;
@@ -242,25 +216,61 @@ public:
}
}
- void DoMarker(const char* prevName, u32 arbitraryNumber=0x42)
+ void DoMarker(const char* prevName, u32 arbitraryNumber = 0x42)
{
u32 cookie = arbitraryNumber;
Do(cookie);
- if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber)
+
+ if (mode == PointerWrap::MODE_READ && cookie != arbitraryNumber)
{
- PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber);
+ PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...",
+ prevName, cookie, cookie, arbitraryNumber, arbitraryNumber);
mode = PointerWrap::MODE_MEASURE;
}
}
-};
+private:
+ __forceinline void DoByte(u8& x)
+ {
+ switch (mode)
+ {
+ case MODE_READ:
+ x = **ptr;
+ break;
+
+ case MODE_WRITE:
+ **ptr = x;
+ break;
+
+ case MODE_MEASURE:
+ break;
+
+ case MODE_VERIFY:
+ _dbg_assert_msg_(COMMON, (x == **ptr),
+ "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n",
+ x, x, &x, **ptr, **ptr, *ptr);
+ break;
+
+ default:
+ break;
+ }
+
+ ++(*ptr);
+ }
+
+ void DoVoid(void *data, u32 size)
+ {
+ for(u32 i = 0; i != size; ++i)
+ DoByte(reinterpret_cast<u8*>(data)[i]);
+ }
+};
class CChunkFileReader
{
public:
// Load file template
template<class T>
- static bool Load(const std::string& _rFilename, int _Revision, T& _class)
+ static bool Load(const std::string& _rFilename, u32 _Revision, T& _class)
{
INFO_LOG(COMMON, "ChunkReader: Loading %s" , _rFilename.c_str());
@@ -290,7 +300,7 @@ public:
ERROR_LOG(COMMON,"ChunkReader: Bad header size");
return false;
}
-
+
// Check revision
if (header.Revision != _Revision)
{
@@ -298,36 +308,35 @@ public:
header.Revision, _Revision);
return false;
}
-
+
// get size
- const int sz = (int)(fileSize - headerSize);
+ const u32 sz = (u32)(fileSize - headerSize);
if (header.ExpectedSize != sz)
{
ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d",
sz, header.ExpectedSize);
return false;
}
-
+
// read the state
- u8* buffer = new u8[sz];
- if (!pFile.ReadBytes(buffer, sz))
+ std::vector<u8> buffer(sz);
+ if (!pFile.ReadArray(&buffer[0], sz))
{
ERROR_LOG(COMMON,"ChunkReader: Error reading file");
return false;
}
- u8 *ptr = buffer;
+ u8* ptr = &buffer[0];
PointerWrap p(&ptr, PointerWrap::MODE_READ);
_class.DoState(p);
- delete[] buffer;
INFO_LOG(COMMON, "ChunkReader: Done loading %s" , _rFilename.c_str());
return true;
}
-
+
// Save file template
template<class T>
- static bool Save(const std::string& _rFilename, int _Revision, T& _class)
+ static bool Save(const std::string& _rFilename, u32 _Revision, T& _class)
{
INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str());
File::IOFile pFile(_rFilename, "wb");
@@ -346,13 +355,12 @@ public:
ptr = &buffer[0];
p.SetMode(PointerWrap::MODE_WRITE);
_class.DoState(p);
-
+
// Create header
SChunkHeader header;
- header.Compress = 0;
header.Revision = _Revision;
- header.ExpectedSize = (int)sz;
-
+ header.ExpectedSize = (u32)sz;
+
// Write to file
if (!pFile.WriteArray(&header, 1))
{
@@ -360,23 +368,21 @@ public:
return false;
}
- if (!pFile.WriteBytes(&buffer[0], sz))
+ if (!pFile.WriteArray(&buffer[0], sz))
{
ERROR_LOG(COMMON,"ChunkReader: Failed writing data");
return false;
}
-
- INFO_LOG(COMMON,"ChunkReader: Done writing %s",
- _rFilename.c_str());
+
+ INFO_LOG(COMMON,"ChunkReader: Done writing %s", _rFilename.c_str());
return true;
}
-
+
private:
struct SChunkHeader
{
- int Revision;
- int Compress;
- int ExpectedSize;
+ u32 Revision;
+ u32 ExpectedSize;
};
};
diff --git a/Source/Core/Common/Src/Common.h b/Source/Core/Common/Src/Common.h
index c3cab37dd8..904095e255 100644
--- a/Source/Core/Common/Src/Common.h
+++ b/Source/Core/Common/Src/Common.h
@@ -133,7 +133,9 @@ private:
// wxWidgets does not have a true dummy macro for this.
#define _trans(a) a
-#if defined __GNUC__
+#if defined _M_GENERIC
+# define _M_SSE 0x0
+#elif defined __GNUC__
# if defined __SSE4_2__
# define _M_SSE 0x402
# elif defined __SSE4_1__
@@ -144,7 +146,7 @@ private:
# define _M_SSE 0x300
# endif
#elif (_MSC_VER >= 1500) || __INTEL_COMPILER // Visual Studio 2008
-# define _M_SSE 0x402
+# define _M_SSE 0x402
#endif
// Host communication.
@@ -155,7 +157,6 @@ enum HOST_COMM
WM_USER_CREATE,
WM_USER_SETCURSOR,
WM_USER_KEYDOWN,
- WIIMOTE_DISCONNECT // Disconnect Wiimote
};
// Used for notification on emulation state
diff --git a/Source/Core/Common/Src/CommonFuncs.h b/Source/Core/Common/Src/CommonFuncs.h
index 585fe0999a..f892769280 100644
--- a/Source/Core/Common/Src/CommonFuncs.h
+++ b/Source/Core/Common/Src/CommonFuncs.h
@@ -35,7 +35,7 @@ template<> struct CompileTimeAssert<true> {};
#define b32(x) (b16(x) | (b16(x) >>16) )
#define ROUND_UP_POW2(x) (b32(x - 1) + 1)
-#if defined __GNUC__ && !defined __SSSE3__
+#if defined __GNUC__ && !defined __SSSE3__ && !defined _M_GENERIC
#include <emmintrin.h>
static __inline __m128i __attribute__((__always_inline__))
_mm_shuffle_epi8(__m128i a, __m128i mask)
@@ -60,15 +60,17 @@ _mm_shuffle_epi8(__m128i a, __m128i mask)
// go to debugger mode
#ifdef GEKKO
#define Crash()
+ #elif defined _M_GENERIC
+ #define Crash() { exit(1); }
#else
#define Crash() {asm ("int $3");}
#endif
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
inline u32 _rotl(u32 x, int shift) {
- shift &= 31;
- if (!shift) return x;
- return (x << shift) | (x >> (32 - shift));
+ shift &= 31;
+ if (!shift) return x;
+ return (x << shift) | (x >> (32 - shift));
}
inline u64 _rotl64(u64 x, unsigned int shift){
@@ -77,9 +79,9 @@ inline u64 _rotl64(u64 x, unsigned int shift){
}
inline u32 _rotr(u32 x, int shift) {
- shift &= 31;
- if (!shift) return x;
- return (x >> shift) | (x << (32 - shift));
+ shift &= 31;
+ if (!shift) return x;
+ return (x >> shift) | (x << (32 - shift));
}
inline u64 _rotr64(u64 x, unsigned int shift){
@@ -136,6 +138,15 @@ inline u8 swap8(u8 _data) {return _data;}
inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);}
inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);}
inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);}
+#elif _M_ARM
+#ifdef ANDROID
+#undef swap16
+#undef swap32
+#undef swap64
+#endif
+inline u16 swap16 (u16 _data) { u32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (u16)data;}
+inline u32 swap32 (u32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;}
+inline u64 swap64(u64 _data) {return ((u64)swap32(_data) << 32) | swap32(_data >> 32);}
#elif __linux__
inline u16 swap16(u16 _data) {return bswap_16(_data);}
inline u32 swap32(u32 _data) {return bswap_32(_data);}
@@ -162,6 +173,40 @@ inline u16 swap16(const u8* _pData) {return swap16(*(const u16*)_pData);}
inline u32 swap32(const u8* _pData) {return swap32(*(const u32*)_pData);}
inline u64 swap64(const u8* _pData) {return swap64(*(const u64*)_pData);}
+template <int count>
+void swap(u8*);
+
+template <>
+inline void swap<1>(u8* data)
+{}
+
+template <>
+inline void swap<2>(u8* data)
+{
+ *reinterpret_cast<u16*>(data) = swap16(data);
+}
+
+template <>
+inline void swap<4>(u8* data)
+{
+ *reinterpret_cast<u32*>(data) = swap32(data);
+}
+
+template <>
+inline void swap<8>(u8* data)
+{
+ *reinterpret_cast<u64*>(data) = swap64(data);
+}
+
+template <typename T>
+inline T FromBigEndian(T data)
+{
+ //static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
+
+ swap<sizeof(data)>(reinterpret_cast<u8*>(&data));
+ return data;
+}
+
} // Namespace Common
#endif // _COMMONFUNCS_H_
diff --git a/Source/Core/Common/Src/CommonPaths.h b/Source/Core/Common/Src/CommonPaths.h
index 01180c67e3..ac6676cfcb 100644
--- a/Source/Core/Common/Src/CommonPaths.h
+++ b/Source/Core/Common/Src/CommonPaths.h
@@ -36,6 +36,9 @@
// You can use the File::GetUserPath() util for this
#define USERDATA_DIR "Contents/Resources/User"
#define DOLPHIN_DATA_DIR "Library/Application Support/Dolphin"
+#elif defined ANDROID
+ #define USERDATA_DIR "user"
+ #define DOLPHIN_DATA_DIR "/sdcard/dolphin-emu"
#else
#define USERDATA_DIR "user"
#ifdef USER_DIR
@@ -52,6 +55,8 @@
#define SYSDATA_DIR "Contents/Resources/Sys"
#define SHARED_USER_DIR File::GetBundleDirectory() + \
DIR_SEP USERDATA_DIR DIR_SEP
+#elif defined ANDROID
+ #define SYSDATA_DIR "/sdcard/dolphin-emu"
#else
#ifdef DATA_DIR
#define SYSDATA_DIR DATA_DIR "sys"
@@ -123,9 +128,9 @@
#define GC_MEMCARDA "MemoryCardA"
#define GC_MEMCARDB "MemoryCardB"
-#define WII_STATE "state.dat"
+#define WII_STATE "state.dat"
-#define WII_SETTING "setting.txt"
+#define WII_SETTING "setting.txt"
#define GECKO_CODE_HANDLER "codehandler.bin"
diff --git a/Source/Core/Common/Src/ConsoleListener.cpp b/Source/Core/Common/Src/ConsoleListener.cpp
index cf03581431..934300f777 100644
--- a/Source/Core/Common/Src/ConsoleListener.cpp
+++ b/Source/Core/Common/Src/ConsoleListener.cpp
@@ -61,7 +61,7 @@ void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title
// Save the window handle that AllocConsole() created
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Set the console window title
- SetConsoleTitle(Title);
+ SetConsoleTitle(UTF8ToTStr(Title).c_str());
// Set letter space
LetterSpace(80, 4000);
//MoveWindow(GetConsoleWindow(), 200,200, 800,800, true);
@@ -195,7 +195,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool
static const int MAX_BYTES = 1024 * 16;
- std::vector<std::array<CHAR, MAX_BYTES>> Str;
+ std::vector<std::array<TCHAR, MAX_BYTES>> Str;
std::vector<std::array<WORD, MAX_BYTES>> Attr;
// ReadConsoleOutputAttribute seems to have a limit at this level
@@ -227,7 +227,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool
LetterSpace(LBufWidth, LBufHeight);
- ClearScreen(true);
+ ClearScreen(true);
coordScreen.Y = 0;
coordScreen.X = 0;
DWORD cCharsWritten = 0;
@@ -270,7 +270,7 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
*/
DWORD cCharsWritten;
WORD Color;
-
+
switch (Level)
{
case NOTICE_LEVEL: // light green
@@ -334,9 +334,9 @@ void ConsoleListener::ClearScreen(bool Cursor)
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
-
+
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
-
+
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
// Write space to the entire console
diff --git a/Source/Core/Common/Src/Crypto/md5.cpp b/Source/Core/Common/Src/Crypto/md5.cpp
index 7fff7713da..7b8dc149f4 100644
--- a/Source/Core/Common/Src/Crypto/md5.cpp
+++ b/Source/Core/Common/Src/Crypto/md5.cpp
@@ -37,6 +37,8 @@
#include <string.h>
#include <stdio.h>
+#include "../FileUtil.h"
+
/*
* 32-bit integer manipulation macros (little endian)
*/
@@ -301,7 +303,10 @@ int md5_file( char *path, unsigned char output[16] )
md5_context ctx;
unsigned char buf[1024];
- if( ( f = fopen( path, "rb" ) ) == NULL )
+ File::IOFile file(path, "rb");
+ f = file.GetHandle();
+
+ if (f == NULL)
return( 1 );
md5_starts( &ctx );
@@ -315,11 +320,9 @@ int md5_file( char *path, unsigned char output[16] )
if( ferror( f ) != 0 )
{
- fclose( f );
return( 2 );
}
- fclose( f );
return( 0 );
}
diff --git a/Source/Core/Common/Src/Crypto/sha1.cpp b/Source/Core/Common/Src/Crypto/sha1.cpp
index 17ad930986..45b88b2b6e 100644
--- a/Source/Core/Common/Src/Crypto/sha1.cpp
+++ b/Source/Core/Common/Src/Crypto/sha1.cpp
@@ -36,6 +36,8 @@
#include <string.h>
#include <stdio.h>
+#include "../FileUtil.h"
+
/*
* 32-bit integer manipulation macros (big endian)
*/
@@ -335,7 +337,10 @@ int sha1_file( char *path, unsigned char output[20] )
sha1_context ctx;
unsigned char buf[1024];
- if( ( f = fopen( path, "rb" ) ) == NULL )
+ File::IOFile file(path, "rb");
+ f = file.GetHandle();
+
+ if (f == NULL)
return( 1 );
sha1_starts( &ctx );
@@ -349,11 +354,9 @@ int sha1_file( char *path, unsigned char output[20] )
if( ferror( f ) != 0 )
{
- fclose( f );
return( 2 );
}
- fclose( f );
return( 0 );
}
diff --git a/Source/Core/Common/Src/ExtendedTrace.cpp b/Source/Core/Common/Src/ExtendedTrace.cpp
index 3fe661f2e4..85057639a5 100644
--- a/Source/Core/Common/Src/ExtendedTrace.cpp
+++ b/Source/Core/Common/Src/ExtendedTrace.cpp
@@ -17,6 +17,7 @@
#include <windows.h>
#include <stdio.h>
#include "ExtendedTrace.h"
+#include "StringUtil.h"
using namespace std;
#include <tchar.h>
@@ -274,13 +275,21 @@ static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo )
return ret;
}
-void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
+void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack)
+{
+ TCHAR symInfo[BUFFERSIZE] = _T("?");
+ TCHAR srcInfo[BUFFERSIZE] = _T("?");
+
+ GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo);
+ GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo);
+ etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n");
+}
+
+void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file )
{
STACKFRAME callStack;
BOOL bResult;
CONTEXT context;
- TCHAR symInfo[BUFFERSIZE] = _T("?");
- TCHAR srcInfo[BUFFERSIZE] = _T("?");
HANDLE hProcess = GetCurrentProcess();
// If it's not this thread, let's suspend it, and resume it at the end
@@ -318,9 +327,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
etfprint(file, "Call stack info: \n");
etfprint(file, lpszMessage);
- GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
- GetSourceInfoFromAddress( (ULONG)callStack.AddrPC.Offset, srcInfo );
- etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
+ PrintFunctionAndSourceInfo(file, callStack);
for( ULONG index = 0; ; index++ )
{
@@ -341,9 +348,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
if( !bResult || callStack.AddrFrame.Offset == 0 )
break;
- GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
- GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
- etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
+ PrintFunctionAndSourceInfo(file, callStack);
}
@@ -351,19 +356,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
ResumeThread( hThread );
}
-void StackTrace( HANDLE hThread, wchar_t const*lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
-{
- // TODO: remove when Common builds as unicode
- size_t origsize = wcslen(lpszMessage) + 1;
- const size_t newsize = 100;
- size_t convertedChars = 0;
- char nstring[newsize];
- wcstombs_s(&convertedChars, nstring, origsize, lpszMessage, _TRUNCATE);
-
- StackTrace(hThread, nstring, file, eip, esp, ebp );
-}
-
-void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
+void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
{
STACKFRAME callStack;
BOOL bResult;
@@ -391,9 +384,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO
etfprint(file, "Call stack info: \n");
etfprint(file, lpszMessage);
- GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
- GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
- etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
+ PrintFunctionAndSourceInfo(file, callStack);
for( ULONG index = 0; ; index++ )
{
@@ -414,10 +405,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO
if( !bResult || callStack.AddrFrame.Offset == 0 )
break;
- GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
- GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
- etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
-
+ PrintFunctionAndSourceInfo(file, callStack);
}
if ( hThread != GetCurrentThread() )
@@ -426,7 +414,8 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO
char g_uefbuf[2048];
-void etfprintf(FILE *file, const char *format, ...) {
+void etfprintf(FILE *file, const char *format, ...)
+{
va_list ap;
va_start(ap, format);
int len = vsprintf(g_uefbuf, format, ap);
@@ -434,7 +423,8 @@ void etfprintf(FILE *file, const char *format, ...) {
va_end(ap);
}
-void etfprint(FILE *file, const std::string &text) {
+void etfprint(FILE *file, const std::string &text)
+{
size_t len = text.length();
fwrite(text.data(), 1, len, file);
}
diff --git a/Source/Core/Common/Src/ExtendedTrace.h b/Source/Core/Common/Src/ExtendedTrace.h
index 12e7ed41fa..6d33eb632d 100644
--- a/Source/Core/Common/Src/ExtendedTrace.h
+++ b/Source/Core/Common/Src/ExtendedTrace.h
@@ -25,16 +25,15 @@
#pragma comment( lib, "imagehlp.lib" )
#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) InitSymInfo( IniSymbolPath )
-#define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo()
-#define STACKTRACE(file) StackTrace( GetCurrentThread(), _T(""), file)
-#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), _T(""), file, eip, esp, ebp)
+#define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo()
+#define STACKTRACE(file) StackTrace( GetCurrentThread(), "", file)
+#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp)
// class File;
BOOL InitSymInfo( PCSTR );
BOOL UninitSymInfo();
-void StackTrace( HANDLE, LPCTSTR, FILE *file);
-void StackTrace( HANDLE, LPCTSTR, FILE *file, DWORD eip, DWORD esp, DWORD ebp);
-void StackTrace( HANDLE hThread, wchar_t const* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp);
+void StackTrace(HANDLE, char const* msg, FILE *file);
+void StackTrace(HANDLE, char const* msg, FILE *file, DWORD eip, DWORD esp, DWORD ebp);
// functions by Masken
void etfprintf(FILE *file, const char *format, ...);
@@ -44,10 +43,10 @@ extern char g_uefbuf[UEFBUFSIZE];
#else // not WIN32
-#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) ((void)0)
-#define EXTENDEDTRACEUNINITIALIZE() ((void)0)
-#define STACKTRACE(file) ((void)0)
-#define STACKTRACE2(file, eip, esp, ebp) ((void)0)
+#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) ((void)0)
+#define EXTENDEDTRACEUNINITIALIZE() ((void)0)
+#define STACKTRACE(file) ((void)0)
+#define STACKTRACE2(file, eip, esp, ebp) ((void)0)
#endif // WIN32
diff --git a/Source/Core/Common/Src/FPURoundMode.h b/Source/Core/Common/Src/FPURoundMode.h
new file mode 100644
index 0000000000..2e26047689
--- /dev/null
+++ b/Source/Core/Common/Src/FPURoundMode.h
@@ -0,0 +1,52 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+#ifndef FPU_ROUND_MODE_H_
+#define FPU_ROUND_MODE_H_
+#include "Common.h"
+
+namespace FPURoundMode
+{
+ enum RoundModes
+ {
+ ROUND_NEAR = 0,
+ ROUND_CHOP,
+ ROUND_UP,
+ ROUND_DOWN
+ };
+ enum PrecisionModes {
+ PREC_24 = 0,
+ PREC_53,
+ PREC_64
+ };
+ void SetRoundMode(u32 mode);
+
+ void SetPrecisionMode(u32 mode);
+
+ void SetSIMDMode(u32 mode);
+
+/*
+ * There are two different flavors of float to int conversion:
+ * _mm_cvtps_epi32() and _mm_cvttps_epi32().
+ *
+ * The first rounds according to the MXCSR rounding bits.
+ * The second one always uses round towards zero.
+ */
+ void SaveSIMDState();
+ void LoadSIMDState();
+ void LoadDefaultSIMDState();
+}
+#endif
diff --git a/Source/Core/Common/Src/FileSearch.cpp b/Source/Core/Common/Src/FileSearch.cpp
index 595dfe7000..674cf0e1d5 100644
--- a/Source/Core/Common/Src/FileSearch.cpp
+++ b/Source/Core/Common/Src/FileSearch.cpp
@@ -51,7 +51,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
BuildCompleteFilename(GCMSearchPath, _strPath, _searchString);
#ifdef _WIN32
WIN32_FIND_DATA findData;
- HANDLE FindFirst = FindFirstFile(GCMSearchPath.c_str(), &findData);
+ HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData);
if (FindFirst != INVALID_HANDLE_VALUE)
{
@@ -62,7 +62,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
if (findData.cFileName[0] != '.')
{
std::string strFilename;
- BuildCompleteFilename(strFilename, _strPath, findData.cFileName);
+ BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName));
m_FileNames.push_back(strFilename);
}
@@ -112,7 +112,6 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
#endif
}
-
const CFileSearch::XStringVector& CFileSearch::GetFileNames() const
{
return m_FileNames;
diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp
index b46b2498fe..bf7edb0844 100644
--- a/Source/Core/Common/Src/FileUtil.cpp
+++ b/Source/Core/Common/Src/FileUtil.cpp
@@ -41,10 +41,11 @@
#include <CoreFoundation/CFBundle.h>
#endif
-#include <fstream>
#include <algorithm>
#include <sys/stat.h>
+#include "StringUtil.h"
+
#ifndef S_ISDIR
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
#endif
@@ -81,7 +82,11 @@ bool Exists(const std::string &filename)
std::string copy(filename);
StripTailDirSlashes(copy);
+#ifdef _WIN32
+ int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info);
+#else
int result = stat64(copy.c_str(), &file_info);
+#endif
return (result == 0);
}
@@ -94,7 +99,11 @@ bool IsDirectory(const std::string &filename)
std::string copy(filename);
StripTailDirSlashes(copy);
+#ifdef _WIN32
+ int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info);
+#else
int result = stat64(copy.c_str(), &file_info);
+#endif
if (result < 0) {
WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s",
@@ -127,7 +136,7 @@ bool Delete(const std::string &filename)
}
#ifdef _WIN32
- if (!DeleteFile(filename.c_str()))
+ if (!DeleteFile(UTF8ToTStr(filename).c_str()))
{
WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s",
filename.c_str(), GetLastErrorMsg());
@@ -149,7 +158,7 @@ bool CreateDir(const std::string &path)
{
INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str());
#ifdef _WIN32
- if (::CreateDirectory(path.c_str(), NULL))
+ if (::CreateDirectory(UTF8ToTStr(path).c_str(), NULL))
return true;
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS)
@@ -181,7 +190,7 @@ bool CreateFullPath(const std::string &fullPath)
{
int panicCounter = 100;
INFO_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str());
-
+
if (File::Exists(fullPath))
{
INFO_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str());
@@ -197,7 +206,7 @@ bool CreateFullPath(const std::string &fullPath)
// we're done, yay!
if (position == fullPath.npos)
return true;
-
+
// Include the '/' so the first call is CreateDir("/") rather than CreateDir("")
std::string const subPath(fullPath.substr(0, position + 1));
if (!File::IsDirectory(subPath))
@@ -228,7 +237,7 @@ bool DeleteDir(const std::string &filename)
}
#ifdef _WIN32
- if (::RemoveDirectory(filename.c_str()))
+ if (::RemoveDirectory(UTF8ToTStr(filename).c_str()))
return true;
#else
if (rmdir(filename.c_str()) == 0)
@@ -257,7 +266,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
INFO_LOG(COMMON, "Copy: %s --> %s",
srcFilename.c_str(), destFilename.c_str());
#ifdef _WIN32
- if (CopyFile(srcFilename.c_str(), destFilename.c_str(), FALSE))
+ if (CopyFile(UTF8ToTStr(srcFilename).c_str(), UTF8ToTStr(destFilename).c_str(), FALSE))
return true;
ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s",
@@ -342,8 +351,13 @@ u64 GetSize(const std::string &filename)
WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str());
return 0;
}
+
struct stat64 buf;
+#ifdef _WIN32
+ if (_tstat64(UTF8ToTStr(filename).c_str(), &buf) == 0)
+#else
if (stat64(filename.c_str(), &buf) == 0)
+#endif
{
DEBUG_LOG(COMMON, "GetSize: %s: %lld",
filename.c_str(), (long long)buf.st_size);
@@ -391,13 +405,13 @@ bool CreateEmptyFile(const std::string &filename)
{
INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str());
- FILE *pFile = fopen(filename.c_str(), "wb");
- if (!pFile) {
+ if (!File::IOFile(filename, "wb"))
+ {
ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s",
filename.c_str(), GetLastErrorMsg());
return false;
}
- fclose(pFile);
+
return true;
}
@@ -413,7 +427,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
- HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd);
+ HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
FindClose(hFind);
@@ -423,7 +437,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
do
{
FSTEntry entry;
- const std::string virtualName(ffd.cFileName);
+ const std::string virtualName(TStrToUTF8(ffd.cFileName));
#else
struct dirent dirent, *result = NULL;
@@ -472,7 +486,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
return foundEntries;
}
-
+
// Deletes the given directory and anything under it. Returns true on success.
bool DeleteDirRecursively(const std::string &directory)
{
@@ -480,18 +494,18 @@ bool DeleteDirRecursively(const std::string &directory)
#ifdef _WIN32
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
- HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd);
+ HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
FindClose(hFind);
return false;
}
-
+
// windows loop
do
{
- const std::string virtualName = ffd.cFileName;
+ const std::string virtualName(TStrToUTF8(ffd.cFileName));
#else
struct dirent dirent, *result = NULL;
DIR *dirp = opendir(directory.c_str());
@@ -518,7 +532,7 @@ bool DeleteDirRecursively(const std::string &directory)
#ifndef _WIN32
closedir(dirp);
#endif
-
+
return false;
}
}
@@ -529,7 +543,7 @@ bool DeleteDirRecursively(const std::string &directory)
#ifndef _WIN32
closedir(dirp);
#endif
-
+
return false;
}
}
@@ -591,7 +605,7 @@ std::string GetCurrentDir()
if (!(dir = __getcwd(NULL, 0))) {
ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s",
- GetLastErrorMsg());
+ GetLastErrorMsg());
return NULL;
}
std::string strDir = dir;
@@ -622,14 +636,14 @@ std::string GetBundleDirectory()
#endif
#ifdef _WIN32
-std::string &GetExeDirectory()
+std::string& GetExeDirectory()
{
static std::string DolphinPath;
if (DolphinPath.empty())
{
- char Dolphin_exe_Path[2048];
- GetModuleFileNameA(NULL, Dolphin_exe_Path, 2048);
- DolphinPath = Dolphin_exe_Path;
+ TCHAR Dolphin_exe_Path[2048];
+ GetModuleFileName(NULL, Dolphin_exe_Path, 2048);
+ DolphinPath = TStrToUTF8(Dolphin_exe_Path);
DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\'));
}
return DolphinPath;
@@ -668,9 +682,10 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR))
paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
else
- paths[D_USER_IDX] = std::string(getenv("HOME") ? getenv("HOME") : getenv("PWD")) + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
+ paths[D_USER_IDX] = std::string(getenv("HOME") ?
+ getenv("HOME") : getenv("PWD") ?
+ getenv("PWD") : "") + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
#endif
- INFO_LOG(COMMON, "GetUserPath: Setting user directory to %s:", paths[D_USER_IDX].c_str());
paths[D_GCUSER_IDX] = paths[D_USER_IDX] + GC_USER_DIR DIR_SEP;
paths[D_WIIROOT_IDX] = paths[D_USER_IDX] + WII_USER_DIR;
@@ -731,31 +746,19 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
{
- FILE *f = fopen(filename, text_file ? "w" : "wb");
- if (!f)
- return false;
- size_t len = str.size();
- if (len != fwrite(str.data(), 1, str.size(), f)) // TODO: string::data() may not be contiguous
- {
- fclose(f);
- return false;
- }
- fclose(f);
- return true;
+ return File::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size());
}
bool ReadFileToString(bool text_file, const char *filename, std::string &str)
{
- FILE *f = fopen(filename, text_file ? "r" : "rb");
+ File::IOFile file(filename, text_file ? "r" : "rb");
+ auto const f = file.GetHandle();
+
if (!f)
return false;
- size_t len = (size_t)GetSize(f);
- char *buf = new char[len + 1];
- buf[fread(buf, 1, len, f)] = 0;
- str = std::string(buf, len);
- fclose(f);
- delete [] buf;
- return true;
+
+ str.resize(GetSize(f));
+ return file.ReadArray(&str[0], str.size());
}
IOFile::IOFile()
@@ -799,7 +802,7 @@ bool IOFile::Open(const std::string& filename, const char openmode[])
{
Close();
#ifdef _WIN32
- fopen_s(&m_file, filename.c_str(), openmode);
+ _tfopen_s(&m_file, UTF8ToTStr(filename).c_str(), UTF8ToTStr(openmode).c_str());
#else
m_file = fopen(filename.c_str(), openmode);
#endif
@@ -848,7 +851,7 @@ bool IOFile::Seek(s64 off, int origin)
}
u64 IOFile::Tell()
-{
+{
if (IsOpen())
return ftello(m_file);
else
diff --git a/Source/Core/Common/Src/FileUtil.h b/Source/Core/Common/Src/FileUtil.h
index 2bc55285ed..523e756307 100644
--- a/Source/Core/Common/Src/FileUtil.h
+++ b/Source/Core/Common/Src/FileUtil.h
@@ -25,6 +25,7 @@
#include <string.h>
#include "Common.h"
+#include "StringUtil.h"
// User directory indices for GetUserPath
enum {
@@ -227,4 +228,15 @@ private:
} // namespace
+// To deal with Windows being dumb at unicode:
+template <typename T>
+void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode)
+{
+#ifdef _WIN32
+ fstream.open(UTF8ToTStr(filename).c_str(), openmode);
+#else
+ fstream.open(filename.c_str(), openmode);
+#endif
+}
+
#endif
diff --git a/Source/Core/Common/Src/GenericFPURoundMode.cpp b/Source/Core/Common/Src/GenericFPURoundMode.cpp
new file mode 100644
index 0000000000..cc878291a1
--- /dev/null
+++ b/Source/Core/Common/Src/GenericFPURoundMode.cpp
@@ -0,0 +1,41 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "FPURoundMode.h"
+
+// Generic, do nothing
+namespace FPURoundMode
+{
+ void SetRoundMode(u32 mode)
+ {
+ }
+ void SetPrecisionMode(u32 mode)
+ {
+ }
+ void SetSIMDMode(u32 mode)
+ {
+ }
+ void SaveSIMDState()
+ {
+ }
+ void LoadSIMDState()
+ {
+ }
+ void LoadDefaultSIMDState()
+ {
+ }
+}
diff --git a/Source/Core/Common/Src/Hash.cpp b/Source/Core/Common/Src/Hash.cpp
index 8e8d6f85bd..bc72b16f2a 100644
--- a/Source/Core/Common/Src/Hash.cpp
+++ b/Source/Core/Common/Src/Hash.cpp
@@ -119,7 +119,7 @@ u32 HashEctor(const u8* ptr, int length)
inline u64 getblock(const u64 * p, int i)
{
- return p[i];
+ return p[i];
}
//----------
@@ -127,25 +127,25 @@ inline u64 getblock(const u64 * p, int i)
inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
{
- k1 *= c1;
- k1 = _rotl64(k1,23);
- k1 *= c2;
- h1 ^= k1;
- h1 += h2;
+ k1 *= c1;
+ k1 = _rotl64(k1,23);
+ k1 *= c2;
+ h1 ^= k1;
+ h1 += h2;
- h2 = _rotl64(h2,41);
+ h2 = _rotl64(h2,41);
- k2 *= c2;
- k2 = _rotl64(k2,23);
- k2 *= c1;
- h2 ^= k2;
- h2 += h1;
+ k2 *= c2;
+ k2 = _rotl64(k2,23);
+ k2 *= c1;
+ h2 ^= k2;
+ h2 += h1;
- h1 = h1*3+0x52dce729;
- h2 = h2*3+0x38495ab5;
+ h1 = h1*3+0x52dce729;
+ h2 = h2*3+0x38495ab5;
- c1 = c1*5+0x7b7d159c;
- c2 = c2*5+0x6bce6396;
+ c1 = c1*5+0x7b7d159c;
+ c2 = c2*5+0x6bce6396;
}
//----------
@@ -153,87 +153,87 @@ inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
inline u64 fmix64(u64 k)
{
- k ^= k >> 33;
- k *= 0xff51afd7ed558ccd;
- k ^= k >> 33;
- k *= 0xc4ceb9fe1a85ec53;
- k ^= k >> 33;
+ k ^= k >> 33;
+ k *= 0xff51afd7ed558ccd;
+ k ^= k >> 33;
+ k *= 0xc4ceb9fe1a85ec53;
+ k ^= k >> 33;
- return k;
+ return k;
}
u64 GetMurmurHash3(const u8 *src, int len, u32 samples)
{
- const u8 * data = (const u8*)src;
- const int nblocks = len / 16;
+ const u8 * data = (const u8*)src;
+ const int nblocks = len / 16;
u32 Step = (len / 8);
if(samples == 0) samples = max(Step, 1u);
Step = Step / samples;
if(Step < 1) Step = 1;
- u64 h1 = 0x9368e53c2f6af274;
- u64 h2 = 0x586dcd208f7cd3fd;
+ u64 h1 = 0x9368e53c2f6af274;
+ u64 h2 = 0x586dcd208f7cd3fd;
- u64 c1 = 0x87c37b91114253d5;
- u64 c2 = 0x4cf5ad432745937f;
+ u64 c1 = 0x87c37b91114253d5;
+ u64 c2 = 0x4cf5ad432745937f;
- //----------
- // body
-
- const u64 * blocks = (const u64 *)(data);
+ //----------
+ // body
- for(int i = 0; i < nblocks; i+=Step)
- {
- u64 k1 = getblock(blocks,i*2+0);
- u64 k2 = getblock(blocks,i*2+1);
+ const u64 * blocks = (const u64 *)(data);
- bmix64(h1,h2,k1,k2,c1,c2);
- }
+ for(int i = 0; i < nblocks; i+=Step)
+ {
+ u64 k1 = getblock(blocks,i*2+0);
+ u64 k2 = getblock(blocks,i*2+1);
- //----------
- // tail
+ bmix64(h1,h2,k1,k2,c1,c2);
+ }
- const u8 * tail = (const u8*)(data + nblocks*16);
+ //----------
+ // tail
- u64 k1 = 0;
- u64 k2 = 0;
+ const u8 * tail = (const u8*)(data + nblocks*16);
- switch(len & 15)
- {
- case 15: k2 ^= u64(tail[14]) << 48;
- case 14: k2 ^= u64(tail[13]) << 40;
- case 13: k2 ^= u64(tail[12]) << 32;
- case 12: k2 ^= u64(tail[11]) << 24;
- case 11: k2 ^= u64(tail[10]) << 16;
- case 10: k2 ^= u64(tail[ 9]) << 8;
- case 9: k2 ^= u64(tail[ 8]) << 0;
+ u64 k1 = 0;
+ u64 k2 = 0;
- case 8: k1 ^= u64(tail[ 7]) << 56;
- case 7: k1 ^= u64(tail[ 6]) << 48;
- case 6: k1 ^= u64(tail[ 5]) << 40;
- case 5: k1 ^= u64(tail[ 4]) << 32;
- case 4: k1 ^= u64(tail[ 3]) << 24;
- case 3: k1 ^= u64(tail[ 2]) << 16;
- case 2: k1 ^= u64(tail[ 1]) << 8;
- case 1: k1 ^= u64(tail[ 0]) << 0;
- bmix64(h1,h2,k1,k2,c1,c2);
- };
+ switch(len & 15)
+ {
+ case 15: k2 ^= u64(tail[14]) << 48;
+ case 14: k2 ^= u64(tail[13]) << 40;
+ case 13: k2 ^= u64(tail[12]) << 32;
+ case 12: k2 ^= u64(tail[11]) << 24;
+ case 11: k2 ^= u64(tail[10]) << 16;
+ case 10: k2 ^= u64(tail[ 9]) << 8;
+ case 9: k2 ^= u64(tail[ 8]) << 0;
+
+ case 8: k1 ^= u64(tail[ 7]) << 56;
+ case 7: k1 ^= u64(tail[ 6]) << 48;
+ case 6: k1 ^= u64(tail[ 5]) << 40;
+ case 5: k1 ^= u64(tail[ 4]) << 32;
+ case 4: k1 ^= u64(tail[ 3]) << 24;
+ case 3: k1 ^= u64(tail[ 2]) << 16;
+ case 2: k1 ^= u64(tail[ 1]) << 8;
+ case 1: k1 ^= u64(tail[ 0]) << 0;
+ bmix64(h1,h2,k1,k2,c1,c2);
+ };
- //----------
- // finalization
+ //----------
+ // finalization
- h2 ^= len;
+ h2 ^= len;
- h1 += h2;
- h2 += h1;
+ h1 += h2;
+ h2 += h1;
- h1 = fmix64(h1);
- h2 = fmix64(h2);
+ h1 = fmix64(h1);
+ h2 = fmix64(h2);
- h1 += h2;
+ h1 += h2;
- return h1;
+ return h1;
}
@@ -262,11 +262,13 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
}
-/* NOTE: This hash function is used for custom texture loading/dumping, so
- it should not be changed, which would require all custom textures to be
- recalculated for their new hash values. If the hashing function is
- changed, make sure this one is still used when the legacy parameter is
- true. */
+/*
+ * NOTE: This hash function is used for custom texture loading/dumping, so
+ * it should not be changed, which would require all custom textures to be
+ * recalculated for their new hash values. If the hashing function is
+ * changed, make sure this one is still used when the legacy parameter is
+ * true.
+ */
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{
const u64 m = 0xc6a4a7935bd1e995;
@@ -282,11 +284,11 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{
u64 k = data[0];
data+=Step;
- k *= m;
+ k *= m;
k ^= k >> r;
- k *= m;
+ k *= m;
h ^= k;
- h *= m;
+ h *= m;
}
const u8 * data2 = (const u8*)end;
@@ -453,9 +455,11 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples)
return *((u64 *)&out);
}
-/* FIXME: The old 32-bit version of this hash made different hashes than the
- 64-bit version. Until someone can make a new version of the 32-bit one that
- makes identical hashes, this is just a c/p of the 64-bit one. */
+/*
+ * FIXME: The old 32-bit version of this hash made different hashes than the
+ * 64-bit version. Until someone can make a new version of the 32-bit one that
+ * makes identical hashes, this is just a c/p of the 64-bit one.
+ */
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{
const u64 m = 0xc6a4a7935bd1e995ULL;
@@ -473,7 +477,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
data+=Step;
k *= m;
k ^= k >> r;
- k *= m;
+ k *= m;
h ^= k;
h *= m;
}
@@ -502,7 +506,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
u64 GetHash64(const u8 *src, int len, u32 samples)
{
- return ptrHashFunction(src, len, samples);
+ return ptrHashFunction(src, len, samples);
}
// sets the hash function used for the texture cache
diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp
index acad498106..da44855941 100644
--- a/Source/Core/Common/Src/IniFile.cpp
+++ b/Source/Core/Common/Src/IniFile.cpp
@@ -25,6 +25,7 @@
#include <fstream>
#include <algorithm>
+#include "FileUtil.h"
#include "StringUtil.h"
#include "IniFile.h"
@@ -400,7 +401,7 @@ bool IniFile::Load(const char* filename)
// Open file
std::ifstream in;
- in.open(filename, std::ios::in);
+ OpenFStream(in, filename, std::ios::in);
if (in.fail()) return false;
@@ -452,7 +453,7 @@ bool IniFile::Load(const char* filename)
bool IniFile::Save(const char* filename)
{
std::ofstream out;
- out.open(filename, std::ios::out);
+ OpenFStream(out, filename, std::ios::out);
if (out.fail())
{
diff --git a/Source/Core/Common/Src/LinearDiskCache.h b/Source/Core/Common/Src/LinearDiskCache.h
index 9755c996bd..b60c849c8e 100644
--- a/Source/Core/Common/Src/LinearDiskCache.h
+++ b/Source/Core/Common/Src/LinearDiskCache.h
@@ -21,11 +21,8 @@
#include "Common.h"
#include <fstream>
-// Increment this every time you change shader generation code.
-enum
-{
- LINEAR_DISKCACHE_VER = 6979
-};
+// defined in Version.cpp
+extern const char *scm_rev_git_str;
// On disk format:
//header{
@@ -74,7 +71,7 @@ public:
m_num_entries = 0;
// try opening for reading/writing
- m_file.open(filename, ios_base::in | ios_base::out | ios_base::binary);
+ OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary);
m_file.seekg(0, std::ios::end);
std::fstream::pos_type end_pos = m_file.tellg();
@@ -187,13 +184,15 @@ private:
{
Header()
: id(*(u32*)"DCAC")
- , ver(LINEAR_DISKCACHE_VER)
, key_t_size(sizeof(K))
, value_t_size(sizeof(V))
- {}
+ {
+ memcpy(ver, scm_rev_git_str, 40);
+ }
- const u32 id, ver;
+ const u32 id;
const u16 key_t_size, value_t_size;
+ char ver[40];
} m_header;
diff --git a/Source/Core/Common/Src/LogManager.cpp b/Source/Core/Common/Src/LogManager.cpp
index 26db5cbfc1..d5416fcd7d 100644
--- a/Source/Core/Common/Src/LogManager.cpp
+++ b/Source/Core/Common/Src/LogManager.cpp
@@ -17,6 +17,9 @@
#include <algorithm>
+#ifdef ANDROID
+#include "Host.h"
+#endif
#include "LogManager.h"
#include "ConsoleListener.h"
#include "Timer.h"
@@ -42,9 +45,9 @@ LogManager::LogManager()
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common");
- m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
+ m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor");
- m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
+ m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine");
m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc");
m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt");
@@ -61,15 +64,15 @@ LogManager::LogManager()
m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt");
m_Log[LogTypes::POWERPC] = new LogContainer("PowerPC", "IBM CPU");
m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE");
- m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
- m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
- m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
- m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
- m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
+ m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
+ m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
+ m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
+ m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
+ m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "Dynamic Recompiler");
m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console");
- m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
- m_Log[LogTypes::WIIMOTE] = new LogContainer("Wiimote", "Wiimote");
+ m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
+ m_Log[LogTypes::WIIMOTE] = new LogContainer("Wiimote", "Wiimote");
m_Log[LogTypes::WII_IOB] = new LogContainer("WII_IOB", "WII IO Bridge");
m_Log[LogTypes::WII_IPC] = new LogContainer("WII_IPC", "WII IPC");
m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID");
@@ -83,7 +86,7 @@ LogManager::LogManager()
m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24");
m_Log[LogTypes::WII_IPC_SSL] = new LogContainer("WII_IPC_SSL", "WII IPC SSL");
m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE","WII IPC WIIMOTE");
- m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
+ m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
@@ -136,7 +139,9 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
Common::Timer::GetTimeFormatted().c_str(),
file, line, level_to_char[(int)level],
log->GetShortName(), temp);
-
+#ifdef ANDROID
+ Host_SysMessage(msg);
+#endif
log->Trigger(level, msg);
}
@@ -185,7 +190,7 @@ void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg)
FileLogListener::FileLogListener(const char *filename)
{
- m_logfile.open(filename, std::ios::app);
+ OpenFStream(m_logfile, filename, std::ios::app);
SetEnable(true);
}
diff --git a/Source/Core/Common/Src/LogManager.h b/Source/Core/Common/Src/LogManager.h
index 1722c0b1bf..f7ccb15034 100644
--- a/Source/Core/Common/Src/LogManager.h
+++ b/Source/Core/Common/Src/LogManager.h
@@ -26,7 +26,7 @@
#include <set>
#include <string.h>
-#define MAX_MESSAGES 8000
+#define MAX_MESSAGES 8000
#define MAX_MSGLEN 1024
diff --git a/Source/Core/Common/Src/MathUtil.cpp b/Source/Core/Common/Src/MathUtil.cpp
index e078db2e9d..d5be1c3bb1 100644
--- a/Source/Core/Common/Src/MathUtil.cpp
+++ b/Source/Core/Common/Src/MathUtil.cpp
@@ -21,13 +21,6 @@
#include <cmath>
#include <numeric>
-namespace {
-
-static u32 saved_sse_state = _mm_getcsr();
-static const u32 default_sse_state = _mm_getcsr();
-
-}
-
namespace MathUtil
{
@@ -95,7 +88,7 @@ u32 ClassifyFloat(float fvalue)
else
{
// Denormalized number.
- return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
+ return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
}
}
else if (exp)
@@ -108,43 +101,26 @@ u32 ClassifyFloat(float fvalue)
//Zero
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
}
- }
+ }
}
} // namespace
-void LoadDefaultSSEState()
-{
- _mm_setcsr(default_sse_state);
-}
-
-
-void LoadSSEState()
-{
- _mm_setcsr(saved_sse_state);
-}
-
-
-void SaveSSEState()
-{
- saved_sse_state = _mm_getcsr();
-}
-
inline void MatrixMul(int n, const float *a, const float *b, float *result)
-{
- for (int i = 0; i < n; ++i)
+{
+ for (int i = 0; i < n; ++i)
{
- for (int j = 0; j < n; ++j)
+ for (int j = 0; j < n; ++j)
{
- float temp = 0;
- for (int k = 0; k < n; ++k)
+ float temp = 0;
+ for (int k = 0; k < n; ++k)
{
- temp += a[i * n + k] * b[k * n + j];
- }
- result[i * n + j] = temp;
- }
- }
+ temp += a[i * n + k] * b[k * n + j];
+ }
+ result[i * n + j] = temp;
+ }
+ }
}
// Calculate sum of a float list
@@ -155,94 +131,94 @@ float MathFloatVectorSum(const std::vector<float>& Vec)
void Matrix33::LoadIdentity(Matrix33 &mtx)
{
- memset(mtx.data, 0, sizeof(mtx.data));
- mtx.data[0] = 1.0f;
- mtx.data[4] = 1.0f;
- mtx.data[8] = 1.0f;
+ memset(mtx.data, 0, sizeof(mtx.data));
+ mtx.data[0] = 1.0f;
+ mtx.data[4] = 1.0f;
+ mtx.data[8] = 1.0f;
}
void Matrix33::RotateX(Matrix33 &mtx, float rad)
{
- float s = sin(rad);
- float c = cos(rad);
- memset(mtx.data, 0, sizeof(mtx.data));
- mtx.data[0] = 1;
- mtx.data[4] = c;
- mtx.data[5] = -s;
- mtx.data[7] = s;
- mtx.data[8] = c;
+ float s = sin(rad);
+ float c = cos(rad);
+ memset(mtx.data, 0, sizeof(mtx.data));
+ mtx.data[0] = 1;
+ mtx.data[4] = c;
+ mtx.data[5] = -s;
+ mtx.data[7] = s;
+ mtx.data[8] = c;
}
void Matrix33::RotateY(Matrix33 &mtx, float rad)
{
- float s = sin(rad);
- float c = cos(rad);
- memset(mtx.data, 0, sizeof(mtx.data));
- mtx.data[0] = c;
- mtx.data[2] = s;
- mtx.data[4] = 1;
- mtx.data[6] = -s;
- mtx.data[8] = c;
+ float s = sin(rad);
+ float c = cos(rad);
+ memset(mtx.data, 0, sizeof(mtx.data));
+ mtx.data[0] = c;
+ mtx.data[2] = s;
+ mtx.data[4] = 1;
+ mtx.data[6] = -s;
+ mtx.data[8] = c;
}
void Matrix33::Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result)
{
- MatrixMul(3, a.data, b.data, result.data);
+ MatrixMul(3, a.data, b.data, result.data);
}
void Matrix33::Multiply(const Matrix33 &a, const float vec[3], float result[3])
{
- for (int i = 0; i < 3; ++i) {
- result[i] = 0;
- for (int k = 0; k < 3; ++k) {
- result[i] += a.data[i * 3 + k] * vec[k];
- }
- }
+ for (int i = 0; i < 3; ++i) {
+ result[i] = 0;
+ for (int k = 0; k < 3; ++k) {
+ result[i] += a.data[i * 3 + k] * vec[k];
+ }
+ }
}
void Matrix44::LoadIdentity(Matrix44 &mtx)
{
- memset(mtx.data, 0, sizeof(mtx.data));
- mtx.data[0] = 1.0f;
- mtx.data[5] = 1.0f;
- mtx.data[10] = 1.0f;
- mtx.data[15] = 1.0f;
+ memset(mtx.data, 0, sizeof(mtx.data));
+ mtx.data[0] = 1.0f;
+ mtx.data[5] = 1.0f;
+ mtx.data[10] = 1.0f;
+ mtx.data[15] = 1.0f;
}
void Matrix44::LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33)
{
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 3; ++i)
{
- for (int j = 0; j < 3; ++j)
+ for (int j = 0; j < 3; ++j)
{
- mtx.data[i * 4 + j] = m33.data[i * 3 + j];
- }
- }
+ mtx.data[i * 4 + j] = m33.data[i * 3 + j];
+ }
+ }
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 3; ++i)
{
- mtx.data[i * 4 + 3] = 0;
- mtx.data[i + 12] = 0;
- }
- mtx.data[15] = 1.0f;
+ mtx.data[i * 4 + 3] = 0;
+ mtx.data[i + 12] = 0;
+ }
+ mtx.data[15] = 1.0f;
}
void Matrix44::Set(Matrix44 &mtx, const float mtxArray[16])
{
- for(int i = 0; i < 16; ++i) {
- mtx.data[i] = mtxArray[i];
- }
+ for(int i = 0; i < 16; ++i) {
+ mtx.data[i] = mtxArray[i];
+ }
}
void Matrix44::Translate(Matrix44 &mtx, const float vec[3])
{
- LoadIdentity(mtx);
- mtx.data[3] = vec[0];
- mtx.data[7] = vec[1];
- mtx.data[11] = vec[2];
+ LoadIdentity(mtx);
+ mtx.data[3] = vec[0];
+ mtx.data[7] = vec[1];
+ mtx.data[11] = vec[2];
}
void Matrix44::Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result)
{
- MatrixMul(4, a.data, b.data, result.data);
+ MatrixMul(4, a.data, b.data, result.data);
}
diff --git a/Source/Core/Common/Src/MathUtil.h b/Source/Core/Common/Src/MathUtil.h
index a6290ff602..ccb9a95e81 100644
--- a/Source/Core/Common/Src/MathUtil.h
+++ b/Source/Core/Common/Src/MathUtil.h
@@ -20,8 +20,8 @@
#include "Common.h"
-#include <xmmintrin.h>
#include <vector>
+#include "FPURoundMode.h"
namespace MathUtil
{
@@ -117,6 +117,8 @@ struct Rectangle
Rectangle(T theLeft, T theTop, T theRight, T theBottom)
: left(theLeft), top(theTop), right(theRight), bottom(theBottom)
{ }
+
+ bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; }
T GetWidth() const { return abs(right - left); }
T GetHeight() const { return abs(bottom - top); }
@@ -147,22 +149,32 @@ struct Rectangle
inline float pow2f(float x) {return x * x;}
inline double pow2(double x) {return x * x;}
-
-/*
- There are two different flavors of float to int conversion:
- _mm_cvtps_epi32() and _mm_cvttps_epi32(). The first rounds
- according to the MXCSR rounding bits. The second one always
- uses round towards zero.
- */
-
-void SaveSSEState();
-void LoadSSEState();
-void LoadDefaultSSEState();
float MathFloatVectorSum(const std::vector<float>&);
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ROUND_DOWN(x, a) ((x) & ~((a) - 1))
+// Rounds down. 0 -> undefined
+inline u64 Log2(u64 val)
+{
+#if defined(__GNUC__)
+ return 63 - __builtin_clzll(val);
+
+#elif defined(_MSC_VER) && defined(_M_X64)
+ unsigned long result = -1;
+ _BitScanReverse64(&result, val);
+ return result;
+
+#else
+ u64 result = -1;
+ while (val != 0)
+ {
+ val >>= 1;
+ ++result;
+ }
+ return result;
+#endif
+}
// Tiny matrix/vector library.
// Used for things like Free-Look in the gfx backend.
@@ -170,32 +182,32 @@ float MathFloatVectorSum(const std::vector<float>&);
class Matrix33
{
public:
- static void LoadIdentity(Matrix33 &mtx);
+ static void LoadIdentity(Matrix33 &mtx);
- // set mtx to be a rotation matrix around the x axis
- static void RotateX(Matrix33 &mtx, float rad);
- // set mtx to be a rotation matrix around the y axis
- static void RotateY(Matrix33 &mtx, float rad);
+ // set mtx to be a rotation matrix around the x axis
+ static void RotateX(Matrix33 &mtx, float rad);
+ // set mtx to be a rotation matrix around the y axis
+ static void RotateY(Matrix33 &mtx, float rad);
- // set result = a x b
- static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result);
- static void Multiply(const Matrix33 &a, const float vec[3], float result[3]);
+ // set result = a x b
+ static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result);
+ static void Multiply(const Matrix33 &a, const float vec[3], float result[3]);
- float data[9];
+ float data[9];
};
class Matrix44
{
public:
- static void LoadIdentity(Matrix44 &mtx);
- static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33);
- static void Set(Matrix44 &mtx, const float mtxArray[16]);
+ static void LoadIdentity(Matrix44 &mtx);
+ static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33);
+ static void Set(Matrix44 &mtx, const float mtxArray[16]);
- static void Translate(Matrix44 &mtx, const float vec[3]);
+ static void Translate(Matrix44 &mtx, const float vec[3]);
- static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result);
+ static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result);
- float data[16];
+ float data[16];
};
#endif // _MATH_UTIL_H_
diff --git a/Source/Core/Common/Src/MemArena.cpp b/Source/Core/Common/Src/MemArena.cpp
index 1dcdef6672..26ce81f578 100644
--- a/Source/Core/Common/Src/MemArena.cpp
+++ b/Source/Core/Common/Src/MemArena.cpp
@@ -27,6 +27,10 @@
#include <unistd.h>
#include <cerrno>
#include <cstring>
+#ifdef ANDROID
+#include <sys/ioctl.h>
+#include <linux/ashmem.h>
+#endif
#endif
#if defined(__APPLE__)
@@ -34,11 +38,41 @@ static const char* ram_temp_file = "/tmp/gc_mem.tmp";
#elif !defined(_WIN32) // non OSX unixes
static const char* ram_temp_file = "/dev/shm/gc_mem.tmp";
#endif
+#ifdef ANDROID
+#define ASHMEM_DEVICE "/dev/ashmem"
+
+int AshmemCreateFileMapping(const char *name, size_t size)
+{
+ int fd, ret;
+ fd = open(ASHMEM_DEVICE, O_RDWR);
+ if (fd < 0)
+ return fd;
+
+ // We don't really care if we can't set the name, it is optional
+ ret = ioctl(fd, ASHMEM_SET_NAME, name);
+
+ ret = ioctl(fd, ASHMEM_SET_SIZE, size);
+ if (ret < 0)
+ {
+ close(fd);
+ NOTICE_LOG(MEMMAP, "Ashmem returned error: 0x%08x", ret);
+ return ret;
+ }
+ return fd;
+}
+#endif
void MemArena::GrabLowMemSpace(size_t size)
{
#ifdef _WIN32
hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), NULL);
+#elif defined(ANDROID)
+ fd = AshmemCreateFileMapping("Dolphin-emu", size);
+ if (fd < 0)
+ {
+ NOTICE_LOG(MEMMAP, "Ashmem allocation failed");
+ return;
+ }
#else
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
fd = open(ram_temp_file, O_RDWR | O_CREAT, mode);
diff --git a/Source/Core/Common/Src/MemoryUtil.cpp b/Source/Core/Common/Src/MemoryUtil.cpp
index 0888746d42..d788783c5a 100644
--- a/Source/Core/Common/Src/MemoryUtil.cpp
+++ b/Source/Core/Common/Src/MemoryUtil.cpp
@@ -117,9 +117,12 @@ void* AllocateAlignedMemory(size_t size,size_t alignment)
void* ptr = _aligned_malloc(size,alignment);
#else
void* ptr = NULL;
+#ifdef ANDROID
+ ptr = memalign(alignment, size);
+#else
if (posix_memalign(&ptr, alignment, size) != 0)
ERROR_LOG(MEMMAP, "Failed to allocate aligned memory");
-;
+#endif
#endif
// printf("Mapped memory at %p (size %ld)\n", ptr,
@@ -152,9 +155,7 @@ void FreeAlignedMemory(void* ptr)
if (ptr)
{
#ifdef _WIN32
-
- _aligned_free(ptr);
-
+ _aligned_free(ptr);
#else
free(ptr);
#endif
diff --git a/Source/Core/Common/Src/Misc.cpp b/Source/Core/Common/Src/Misc.cpp
index aafe37886f..8364bda48d 100644
--- a/Source/Core/Common/Src/Misc.cpp
+++ b/Source/Core/Common/Src/Misc.cpp
@@ -31,7 +31,7 @@ const char* GetLastErrorMsg()
#ifdef _WIN32
static __declspec(thread) char err_str[buff_size] = {};
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err_str, buff_size, NULL);
#else
diff --git a/Source/Core/Common/Src/MsgHandler.cpp b/Source/Core/Common/Src/MsgHandler.cpp
index 7c666227aa..90369df1ae 100644
--- a/Source/Core/Common/Src/MsgHandler.cpp
+++ b/Source/Core/Common/Src/MsgHandler.cpp
@@ -102,15 +102,14 @@ bool MsgAlert(bool yes_no, int Style, const char* format, ...)
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style)
{
#ifdef _WIN32
- int STYLE = MB_ICONINFORMATION;
- if (Style == QUESTION) STYLE = MB_ICONQUESTION;
- if (Style == WARNING) STYLE = MB_ICONWARNING;
-
- return IDYES == MessageBox(0, text, caption, STYLE | (yes_no ? MB_YESNO : MB_OK));
-
+ int STYLE = MB_ICONINFORMATION;
+ if (Style == QUESTION) STYLE = MB_ICONQUESTION;
+ if (Style == WARNING) STYLE = MB_ICONWARNING;
+
+ return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK));
#else
- printf("%s\n", text);
- return true;
+ printf("%s\n", text);
+ return true;
#endif
}
diff --git a/Source/Core/Common/Src/NandPaths.cpp b/Source/Core/Common/Src/NandPaths.cpp
index cec79414a7..eb0673afe0 100644
--- a/Source/Core/Common/Src/NandPaths.cpp
+++ b/Source/Core/Common/Src/NandPaths.cpp
@@ -86,7 +86,8 @@ bool CheckTitleTIK(u64 _titleID)
static void CreateReplacementFile(std::string &filename)
{
- std::ofstream replace(filename.c_str());
+ std::ofstream replace;
+ OpenFStream(replace, filename, std::ios_base::out);
replace <<"\" __22__\n";
replace << "* __2a__\n";
//replace << "/ __2f__\n";
@@ -108,7 +109,8 @@ void ReadReplacements(replace_v& replacements)
if (!File::Exists(filename))
CreateReplacementFile(filename);
- std::ifstream f(filename.c_str());
+ std::ifstream f;
+ OpenFStream(f, filename, std::ios_base::in);
char letter;
std::string replacement;
diff --git a/Source/Core/Common/Src/SDCardUtil.cpp b/Source/Core/Common/Src/SDCardUtil.cpp
index 0f2ad08607..cf37ffff3e 100644
--- a/Source/Core/Common/Src/SDCardUtil.cpp
+++ b/Source/Core/Common/Src/SDCardUtil.cpp
@@ -29,6 +29,7 @@
// Modified for Dolphin.
#include "SDCardUtil.h"
+#include "FileUtil.h"
#include <time.h>
#include <stdio.h>
@@ -190,7 +191,6 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
{
u32 sectors_per_fat;
u32 sectors_per_disk;
- FILE* f;
// Convert MB to bytes
disk_size *= 1024 * 1024;
@@ -207,7 +207,8 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
boot_sector_init(s_boot_sector, s_fsinfo_sector, disk_size, nullptr);
fat_init(s_fat_head);
- f = fopen(filename, "wb");
+ File::IOFile file(filename, "wb");
+ FILE* const f = file.GetHandle();
if (!f)
{
ERROR_LOG(COMMON, "Could not create file '%s', aborting...\n", filename);
@@ -247,13 +248,11 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
if (write_empty(f, sectors_per_disk - RESERVED_SECTORS - 2*sectors_per_fat)) goto FailWrite;
- fclose(f);
return true;
FailWrite:
ERROR_LOG(COMMON, "Could not write to '%s', aborting...\n", filename);
if (unlink(filename) < 0)
ERROR_LOG(COMMON, "unlink(%s) failed\n%s", filename, GetLastErrorMsg());
- fclose(f);
return false;
}
diff --git a/Source/Core/Common/Src/StdConditionVariable.h b/Source/Core/Common/Src/StdConditionVariable.h
index 1b81766ee0..6530712c8f 100644
--- a/Source/Core/Common/Src/StdConditionVariable.h
+++ b/Source/Core/Common/Src/StdConditionVariable.h
@@ -5,7 +5,7 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
+#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <condition_variable>
#include <condition_variable>
#else
@@ -133,7 +133,7 @@ public:
// bool wait_for(unique_lock<mutex>& lock,
// const chrono::duration<Rep, Period>& rel_time,
// Predicate pred);
-
+
native_handle_type native_handle()
{
#ifdef USE_EVENTS
diff --git a/Source/Core/Common/Src/StdMutex.h b/Source/Core/Common/Src/StdMutex.h
index 8949e905ac..8a5d22f928 100644
--- a/Source/Core/Common/Src/StdMutex.h
+++ b/Source/Core/Common/Src/StdMutex.h
@@ -5,7 +5,7 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
+#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <mutex>
#include <mutex>
#else
diff --git a/Source/Core/Common/Src/StdThread.h b/Source/Core/Common/Src/StdThread.h
index fea058c874..8893c36204 100644
--- a/Source/Core/Common/Src/StdThread.h
+++ b/Source/Core/Common/Src/StdThread.h
@@ -5,7 +5,7 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
+#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <thread>
#ifndef _GLIBCXX_USE_SCHED_YIELD
#define _GLIBCXX_USE_SCHED_YIELD
@@ -88,7 +88,7 @@ public:
{
return !(*this == rhs);
}
-
+
bool operator<(const id& rhs) const
{
return m_thread < rhs.m_thread;
diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp
index e5c70b2c6b..43c4aebf12 100644
--- a/Source/Core/Common/Src/StringUtil.cpp
+++ b/Source/Core/Common/Src/StringUtil.cpp
@@ -17,11 +17,21 @@
#include <stdlib.h>
#include <stdio.h>
+#include <algorithm>
#include "Common.h"
#include "CommonPaths.h"
#include "StringUtil.h"
+#ifdef _WIN32
+ #include <Windows.h>
+#elif defined(ANDROID)
+
+#else
+ #include <iconv.h>
+ #include <errno.h>
+#endif
+
// faster than sscanf
bool AsciiToHex(const char* _szValue, u32& result)
{
@@ -263,25 +273,25 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
const char HEX2DEC[256] =
{
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
- /* 0 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 1 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 2 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1,
-
- /* 4 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 5 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 6 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 7 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-
- /* 8 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 9 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* A */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* B */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-
- /* C */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* D */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* E */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* F */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
+ /* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* 1 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* 2 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16, 16,16,16,16,
+
+ /* 4 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
+ /* 5 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* 6 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
+ /* 7 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+
+ /* 8 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* 9 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* A */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* B */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+
+ /* C */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* D */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* E */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* F */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16
};
std::string UriDecode(const std::string & sSrc)
@@ -303,8 +313,8 @@ std::string UriDecode(const std::string & sSrc)
if (*pSrc == '%')
{
char dec1, dec2;
- if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)])
- && -1 != (dec2 = HEX2DEC[*(pSrc + 2)]))
+ if (16 != (dec1 = HEX2DEC[*(pSrc + 1)])
+ && 16 != (dec2 = HEX2DEC[*(pSrc + 2)]))
{
*pEnd++ = (dec1 << 4) + dec2;
pSrc += 3;
@@ -375,3 +385,137 @@ std::string UriEncode(const std::string & sSrc)
delete [] pStart;
return sResult;
}
+
+#ifdef _WIN32
+
+std::string UTF16ToUTF8(const std::wstring& input)
+{
+ auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr);
+
+ std::string output;
+ output.resize(size);
+
+ if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr))
+ output.clear();
+
+ return output;
+}
+
+std::wstring CPToUTF16(u32 code_page, const std::string& input)
+{
+ auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0);
+
+ std::wstring output;
+ output.resize(size);
+
+ if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size()))
+ output.clear();
+
+ return output;
+}
+
+std::wstring UTF8ToUTF16(const std::string& input)
+{
+ return CPToUTF16(CP_UTF8, input);
+}
+
+std::string SHIFTJISToUTF8(const std::string& input)
+{
+ return UTF16ToUTF8(CPToUTF16(932, input));
+}
+
+std::string CP1252ToUTF8(const std::string& input)
+{
+ return UTF16ToUTF8(CPToUTF16(1252, input));
+}
+
+#else
+
+template <typename T>
+std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
+{
+ std::string result;
+
+#if defined(ANDROID)
+ result = "Not implemented on Android!";
+
+#else
+ iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
+ if ((iconv_t)-1 == conv_desc)
+ {
+ ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
+ }
+ else
+ {
+ size_t const in_bytes = sizeof(T) * input.size();
+ size_t const out_buffer_size = 4 * in_bytes;
+
+ std::string out_buffer;
+ out_buffer.resize(out_buffer_size);
+
+ auto src_buffer = &input[0];
+ size_t src_bytes = in_bytes;
+ auto dst_buffer = &out_buffer[0];
+ size_t dst_bytes = out_buffer.size();
+
+ while (src_bytes != 0)
+ {
+ size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes,
+ &dst_buffer, &dst_bytes);
+
+ if ((size_t)-1 == iconv_result)
+ {
+ if (EILSEQ == errno || EINVAL == errno)
+ {
+ // Try to skip the bad character
+ if (src_bytes != 0)
+ {
+ --src_bytes;
+ ++src_buffer;
+ }
+ }
+ else
+ {
+ ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
+ break;
+ }
+ }
+ }
+
+ out_buffer.resize(out_buffer_size - dst_bytes);
+ out_buffer.swap(result);
+
+ iconv_close(conv_desc);
+ }
+
+#endif
+ return result;
+}
+
+std::string CP1252ToUTF8(const std::string& input)
+{
+ //return CodeToUTF8("CP1252//TRANSLIT", input);
+ //return CodeToUTF8("CP1252//IGNORE", input);
+ return CodeToUTF8("CP1252", input);
+}
+
+std::string SHIFTJISToUTF8(const std::string& input)
+{
+ //return CodeToUTF8("CP932", input);
+ return CodeToUTF8("SJIS", input);
+}
+
+std::string UTF16ToUTF8(const std::wstring& input)
+{
+ std::string result =
+ // CodeToUTF8("UCS-2", input);
+ // CodeToUTF8("UCS-2LE", input);
+ // CodeToUTF8("UTF-16", input);
+ CodeToUTF8("UTF-16LE", input);
+
+ // TODO: why is this needed?
+ result.erase(std::remove(result.begin(), result.end(), 0x00), result.end());
+ return result;
+}
+
+#endif
diff --git a/Source/Core/Common/Src/StringUtil.h b/Source/Core/Common/Src/StringUtil.h
index 102ae2d5fb..9463db5bb1 100644
--- a/Source/Core/Common/Src/StringUtil.h
+++ b/Source/Core/Common/Src/StringUtil.h
@@ -97,4 +97,28 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
std::string UriDecode(const std::string & sSrc);
std::string UriEncode(const std::string & sSrc);
+std::string CP1252ToUTF8(const std::string& str);
+std::string SHIFTJISToUTF8(const std::string& str);
+std::string UTF16ToUTF8(const std::wstring& str);
+
+#ifdef _WIN32
+
+std::wstring UTF8ToUTF16(const std::string& str);
+
+#ifdef _UNICODE
+inline std::string TStrToUTF8(const std::wstring& str)
+{ return UTF16ToUTF8(str); }
+
+inline std::wstring UTF8ToTStr(const std::string& str)
+{ return UTF8ToUTF16(str); }
+#else
+inline std::string TStrToUTF8(const std::string& str)
+{ return str; }
+
+inline std::string UTF8ToTStr(const std::string& str)
+{ return str; }
+#endif
+
+#endif
+
#endif // _STRINGUTIL_H_
diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp
index 73f83c204f..3e8440b74f 100644
--- a/Source/Core/Common/Src/Thread.cpp
+++ b/Source/Core/Common/Src/Thread.cpp
@@ -105,7 +105,7 @@ void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
#ifdef __APPLE__
thread_policy_set(pthread_mach_thread_np(thread),
THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1);
-#elif defined __linux__ || defined BSD4_4
+#elif (defined __linux__ || defined BSD4_4) && !(defined ANDROID)
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h
index e711fcab5c..b5f899c43b 100644
--- a/Source/Core/Common/Src/Thread.h
+++ b/Source/Core/Common/Src/Thread.h
@@ -33,8 +33,6 @@
#define INFINITE 0xffffffff
#endif
-#include <xmmintrin.h>
-
//for gettimeofday and struct time(spec|val)
#include <time.h>
#include <sys/time.h>
@@ -64,7 +62,7 @@ public:
m_condvar.notify_one();
}
}
-
+
void Wait()
{
std::unique_lock<std::mutex> lk(m_mutex);
diff --git a/Source/Core/Common/Src/Version.cpp b/Source/Core/Common/Src/Version.cpp
index 97e232785d..a668d24e1b 100644
--- a/Source/Core/Common/Src/Version.cpp
+++ b/Source/Core/Common/Src/Version.cpp
@@ -50,3 +50,5 @@ const char *netplay_dolphin_ver = SCM_DESC_STR " M" NP_ARCH;
#else
const char *netplay_dolphin_ver = SCM_DESC_STR " L" NP_ARCH;
#endif
+
+const char *scm_rev_git_str = SCM_REV_STR;
diff --git a/Source/Core/Common/Src/VideoBackendBase.cpp b/Source/Core/Common/Src/VideoBackendBase.cpp
index 62bb42997f..a5aa572039 100644
--- a/Source/Core/Common/Src/VideoBackendBase.cpp
+++ b/Source/Core/Common/Src/VideoBackendBase.cpp
@@ -29,6 +29,7 @@
std::vector<VideoBackend*> g_available_video_backends;
VideoBackend* g_video_backend = NULL;
+static VideoBackend* s_default_backend = NULL;
#ifdef _WIN32
// http://msdn.microsoft.com/en-us/library/ms725491.aspx
@@ -49,17 +50,27 @@ static bool IsGteVista()
void VideoBackend::PopulateList()
{
+ VideoBackend* backends[4] = { NULL };
+
+ // D3D11 > OGL > D3D9 > SW
#ifdef _WIN32
- g_available_video_backends.push_back(new DX9::VideoBackend);
+ g_available_video_backends.push_back(backends[2] = new DX9::VideoBackend);
if (IsGteVista())
- g_available_video_backends.push_back(new DX11::VideoBackend);
+ g_available_video_backends.push_back(backends[0] = new DX11::VideoBackend);
#endif
#ifndef USE_GLES
- g_available_video_backends.push_back(new OGL::VideoBackend);
+ g_available_video_backends.push_back(backends[1] = new OGL::VideoBackend);
#endif
- g_available_video_backends.push_back(new SW::VideoSoftware);
+ g_available_video_backends.push_back(backends[3] = new SW::VideoSoftware);
- g_video_backend = g_available_video_backends.front();
+ for (int i = 0; i < 4; ++i)
+ {
+ if (backends[i])
+ {
+ s_default_backend = g_video_backend = backends[i];
+ break;
+ }
+ }
}
void VideoBackend::ClearList()
@@ -73,8 +84,8 @@ void VideoBackend::ClearList()
void VideoBackend::ActivateBackend(const std::string& name)
{
- if (name.length() == 0) // If NULL, set it to the first one in the list. Expected behavior
- g_video_backend = g_available_video_backends.front();
+ if (name.length() == 0) // If NULL, set it to the default backend (expected behavior)
+ g_video_backend = s_default_backend;
for (std::vector<VideoBackend*>::const_iterator it = g_available_video_backends.begin(); it != g_available_video_backends.end(); ++it)
if (name == (*it)->GetName())
diff --git a/Source/Core/Common/Src/VideoBackendBase.h b/Source/Core/Common/Src/VideoBackendBase.h
index 311fa66104..c4455b3234 100644
--- a/Source/Core/Common/Src/VideoBackendBase.h
+++ b/Source/Core/Common/Src/VideoBackendBase.h
@@ -22,6 +22,7 @@
#include <vector>
#include "ChunkFile.h"
+#include "../../VideoCommon/Src/PerfQueryBase.h"
typedef void (*writeFn16)(const u16,const u32);
typedef void (*writeFn32)(const u32,const u32);
@@ -96,17 +97,20 @@ public:
virtual void RunLoop(bool enable) = 0;
virtual std::string GetName() = 0;
+ virtual std::string GetDisplayName() { return GetName(); }
virtual void ShowConfig(void*) {}
virtual void Video_Prepare() = 0;
virtual void Video_EnterLoop() = 0;
virtual void Video_ExitLoop() = 0;
+ virtual void Video_Cleanup() = 0; // called from gl/d3d thread
virtual void Video_BeginField(u32, FieldType, u32, u32) = 0;
virtual void Video_EndField() = 0;
virtual u32 Video_AccessEFB(EFBAccessType, u32, u32, u32) = 0;
+ virtual u32 Video_GetQueryResult(PerfQueryType type) = 0;
virtual void Video_AddMessage(const char* pstr, unsigned int milliseconds) = 0;
virtual void Video_ClearMessages() = 0;
@@ -156,8 +160,10 @@ class VideoBackendHardware : public VideoBackend
void Video_ExitLoop();
void Video_BeginField(u32, FieldType, u32, u32);
void Video_EndField();
- u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
+ u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
+ u32 Video_GetQueryResult(PerfQueryType type);
+
void Video_AddMessage(const char* pstr, unsigned int milliseconds);
void Video_ClearMessages();
bool Video_Screenshot(const char* filename);
diff --git a/Source/Core/Common/Src/ABI.cpp b/Source/Core/Common/Src/x64ABI.cpp
index 63a8e76934..468d02d9b9 100644
--- a/Source/Core/Common/Src/ABI.cpp
+++ b/Source/Core/Common/Src/x64ABI.cpp
@@ -17,7 +17,7 @@
#include "Common.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
using namespace Gen;
@@ -226,11 +226,11 @@ void XEmitter::ABI_CallFunction(void *func) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -239,11 +239,11 @@ void XEmitter::ABI_CallFunctionC16(void *func, u16 param1) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -266,11 +266,11 @@ void XEmitter::ABI_CallFunctionC(void *func, u32 param1) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -280,11 +280,11 @@ void XEmitter::ABI_CallFunctionCC(void *func, u32 param1, u32 param2) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -295,11 +295,11 @@ void XEmitter::ABI_CallFunctionCCC(void *func, u32 param1, u32 param2, u32 param
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -310,11 +310,11 @@ void XEmitter::ABI_CallFunctionCCP(void *func, u32 param1, u32 param2, void *par
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -326,11 +326,11 @@ void XEmitter::ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2, u32 para
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -341,11 +341,11 @@ void XEmitter::ABI_CallFunctionPPC(void *func, void *param1, void *param2, u32 p
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -356,11 +356,11 @@ void XEmitter::ABI_CallFunctionR(void *func, X64Reg reg1) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -380,11 +380,11 @@ void XEmitter::ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -396,11 +396,11 @@ void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -411,11 +411,11 @@ void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1)
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
diff --git a/Source/Core/Common/Src/ABI.h b/Source/Core/Common/Src/x64ABI.h
index 7226870e58..7226870e58 100644
--- a/Source/Core/Common/Src/ABI.h
+++ b/Source/Core/Common/Src/x64ABI.h
diff --git a/Source/Core/Common/Src/x64Analyzer.cpp b/Source/Core/Common/Src/x64Analyzer.cpp
index 66a2fe217f..37a9030a4b 100644
--- a/Source/Core/Common/Src/x64Analyzer.cpp
+++ b/Source/Core/Common/Src/x64Analyzer.cpp
@@ -60,18 +60,18 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
codeByte = *codePtr++;
- // Skip two-byte opcode byte
- bool twoByte = false;
- if(codeByte == 0x0F)
- {
- twoByte = true;
+ // Skip two-byte opcode byte
+ bool twoByte = false;
+ if(codeByte == 0x0F)
+ {
+ twoByte = true;
codeByte2 = *codePtr++;
- }
+ }
if (!twoByte)
{
- if ((codeByte & 0xF0) == 0x80 ||
- ((codeByte & 0xF8) == 0xC0 && (codeByte & 0x0E) != 0x02))
+ if ((codeByte & 0xF0) == 0x80 ||
+ ((codeByte & 0xF8) == 0xC0 && (codeByte & 0x0E) != 0x02))
{
modRMbyte = *codePtr++;
hasModRM = true;
@@ -79,20 +79,20 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
}
else
{
- if (((codeByte2 & 0xF0) == 0x00 && (codeByte2 & 0x0F) >= 0x04 && (codeByte2 & 0x0D) != 0x0D) ||
- (codeByte2 & 0xF0) == 0x30 ||
- codeByte2 == 0x77 ||
- (codeByte2 & 0xF0) == 0x80 ||
- ((codeByte2 & 0xF0) == 0xA0 && (codeByte2 & 0x07) <= 0x02) ||
- (codeByte2 & 0xF8) == 0xC8)
- {
- // No mod R/M byte
- }
- else
- {
+ if (((codeByte2 & 0xF0) == 0x00 && (codeByte2 & 0x0F) >= 0x04 && (codeByte2 & 0x0D) != 0x0D) ||
+ (codeByte2 & 0xF0) == 0x30 ||
+ codeByte2 == 0x77 ||
+ (codeByte2 & 0xF0) == 0x80 ||
+ ((codeByte2 & 0xF0) == 0xA0 && (codeByte2 & 0x07) <= 0x02) ||
+ (codeByte2 & 0xF8) == 0xC8)
+ {
+ // No mod R/M byte
+ }
+ else
+ {
modRMbyte = *codePtr++;
hasModRM = true;
- }
+ }
}
if (hasModRM)
@@ -130,7 +130,7 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
info.displacement = *((s32 *)codePtr);
codePtr += displacementSize;
-
+
if (accessType == 1)
{
info.isMemoryWrite = true;
diff --git a/Source/Core/Common/Src/x64Analyzer.h b/Source/Core/Common/Src/x64Analyzer.h
index 8b13ca94aa..e9676ec250 100644
--- a/Source/Core/Common/Src/x64Analyzer.h
+++ b/Source/Core/Common/Src/x64Analyzer.h
@@ -51,7 +51,7 @@ enum{
MOVZX_SHORT = 0xB7, //movzx on short
MOVSX_BYTE = 0xBE, //movsx on byte
MOVSX_SHORT = 0xBF, //movsx on short
- MOVE_8BIT = 0xC6, //move 8-bit immediate
+ MOVE_8BIT = 0xC6, //move 8-bit immediate
MOVE_16_32BIT = 0xC7, //move 16 or 32-bit immediate
MOVE_REG_TO_MEM = 0x89, //move reg to memory
};
diff --git a/Source/Core/Common/Src/CPUDetect.cpp b/Source/Core/Common/Src/x64CPUDetect.cpp
index 282929e7b2..dcde313630 100644
--- a/Source/Core/Common/Src/CPUDetect.cpp
+++ b/Source/Core/Common/Src/x64CPUDetect.cpp
@@ -30,16 +30,20 @@
#else
//#include <config/i386/cpuid.h>
+#ifndef _M_GENERIC
#include <xmmintrin.h>
+#endif
#if defined __FreeBSD__
#include <sys/types.h>
#include <machine/cpufunc.h>
#else
static inline void do_cpuid(unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
+ unsigned int *ecx, unsigned int *edx)
{
-#ifdef _LP64
+#if defined _M_GENERIC
+ (*eax) = (*ebx) = (*ecx) = (*edx) = 0;
+#elif defined _LP64
// Note: EBX is reserved on Mac OS X and in PIC on Linux, so it has to
// restored at the end of the asm block.
__asm__ (
diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp
index 5f8d0a66f1..1a74eaef80 100644
--- a/Source/Core/Common/Src/x64Emitter.cpp
+++ b/Source/Core/Common/Src/x64Emitter.cpp
@@ -17,7 +17,7 @@
#include "Common.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "CPUDetect.h"
namespace Gen
@@ -51,13 +51,13 @@ static const NormalOpDef nops[11] =
enum NormalSSEOps
{
- sseCMP = 0xC2,
- sseADD = 0x58, //ADD
+ sseCMP = 0xC2,
+ sseADD = 0x58, //ADD
sseSUB = 0x5C, //SUB
sseAND = 0x54, //AND
sseANDN = 0x55, //ANDN
- sseOR = 0x56,
- sseXOR = 0x57,
+ sseOR = 0x56,
+ sseXOR = 0x57,
sseMUL = 0x59, //MUL,
sseDIV = 0x5E, //DIV
sseMIN = 0x5D, //MIN
@@ -143,18 +143,18 @@ void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const
if (indexReg & 8) op |= 2;
if (offsetOrBaseReg & 8) op |= 1; //TODO investigate if this is dangerous
if (op != 0x40 ||
- (bits == 8 && (offsetOrBaseReg & 0x10c) == 4) ||
- (opBits == 8 && (customOp & 0x10c) == 4)) {
+ (bits == 8 && (offsetOrBaseReg & 0x10c) == 4) ||
+ (opBits == 8 && (customOp & 0x10c) == 4)) {
emit->Write8(op);
_dbg_assert_(DYNA_REC, (offsetOrBaseReg & 0x100) == 0 || bits != 8);
_dbg_assert_(DYNA_REC, (customOp & 0x100) == 0 || opBits != 8);
} else {
_dbg_assert_(DYNA_REC, (offsetOrBaseReg & 0x10c) == 0 ||
- (offsetOrBaseReg & 0x10c) == 0x104 ||
- bits != 8);
+ (offsetOrBaseReg & 0x10c) == 0x104 ||
+ bits != 8);
_dbg_assert_(DYNA_REC, (customOp & 0x10c) == 0 ||
- (customOp & 0x10c) == 0x104 ||
- opBits != 8);
+ (customOp & 0x10c) == 0x104 ||
+ opBits != 8);
}
#else
@@ -969,15 +969,15 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &o
immToWrite = 8;
}
else if ((operand.scale == SCALE_IMM16 && bits == 16) ||
- (operand.scale == SCALE_IMM32 && bits == 32) ||
- (operand.scale == SCALE_IMM32 && bits == 64))
+ (operand.scale == SCALE_IMM32 && bits == 32) ||
+ (operand.scale == SCALE_IMM32 && bits == 64))
{
emit->Write8(nops[op].imm32);
immToWrite = bits == 16 ? 16 : 32;
}
else if ((operand.scale == SCALE_IMM8 && bits == 16) ||
- (operand.scale == SCALE_IMM8 && bits == 32) ||
- (operand.scale == SCALE_IMM8 && bits == 64))
+ (operand.scale == SCALE_IMM8 && bits == 32) ||
+ (operand.scale == SCALE_IMM8 && bits == 64))
{
emit->Write8(nops[op].simm8);
immToWrite = 8;
@@ -1471,142 +1471,142 @@ void XEmitter::RTDSC() { Write8(0x0F); Write8(0x31); }
// helper routines for setting pointers
void XEmitter::CallCdeclFunction3(void* fnptr, u32 arg0, u32 arg1, u32 arg2)
{
- using namespace Gen;
+ using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- CALL(fnptr);
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ CALL(fnptr);
#else
- MOV(32, R(RDI), Imm32(arg0));
- MOV(32, R(RSI), Imm32(arg1));
- MOV(32, R(RDX), Imm32(arg2));
- CALL(fnptr);
+ MOV(32, R(RDI), Imm32(arg0));
+ MOV(32, R(RSI), Imm32(arg1));
+ MOV(32, R(RDX), Imm32(arg2));
+ CALL(fnptr);
#endif
#else
- ABI_AlignStack(3 * 4);
- PUSH(32, Imm32(arg2));
- PUSH(32, Imm32(arg1));
- PUSH(32, Imm32(arg0));
- CALL(fnptr);
+ ABI_AlignStack(3 * 4);
+ PUSH(32, Imm32(arg2));
+ PUSH(32, Imm32(arg1));
+ PUSH(32, Imm32(arg0));
+ CALL(fnptr);
#ifdef _WIN32
- // don't inc stack
+ // don't inc stack
#else
- ABI_RestoreStack(3 * 4);
+ ABI_RestoreStack(3 * 4);
#endif
#endif
}
void XEmitter::CallCdeclFunction4(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3)
{
- using namespace Gen;
+ using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
- CALL(fnptr);
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
+ CALL(fnptr);
#else
- MOV(32, R(RDI), Imm32(arg0));
- MOV(32, R(RSI), Imm32(arg1));
- MOV(32, R(RDX), Imm32(arg2));
- MOV(32, R(RCX), Imm32(arg3));
- CALL(fnptr);
+ MOV(32, R(RDI), Imm32(arg0));
+ MOV(32, R(RSI), Imm32(arg1));
+ MOV(32, R(RDX), Imm32(arg2));
+ MOV(32, R(RCX), Imm32(arg3));
+ CALL(fnptr);
#endif
#else
- ABI_AlignStack(4 * 4);
- PUSH(32, Imm32(arg3));
- PUSH(32, Imm32(arg2));
- PUSH(32, Imm32(arg1));
- PUSH(32, Imm32(arg0));
- CALL(fnptr);
+ ABI_AlignStack(4 * 4);
+ PUSH(32, Imm32(arg3));
+ PUSH(32, Imm32(arg2));
+ PUSH(32, Imm32(arg1));
+ PUSH(32, Imm32(arg0));
+ CALL(fnptr);
#ifdef _WIN32
- // don't inc stack
+ // don't inc stack
#else
- ABI_RestoreStack(4 * 4);
+ ABI_RestoreStack(4 * 4);
#endif
#endif
}
void XEmitter::CallCdeclFunction5(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
{
- using namespace Gen;
+ using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
- CALL(fnptr);
+ CALL(fnptr);
#else
- MOV(32, R(RDI), Imm32(arg0));
- MOV(32, R(RSI), Imm32(arg1));
- MOV(32, R(RDX), Imm32(arg2));
- MOV(32, R(RCX), Imm32(arg3));
- MOV(32, R(R8), Imm32(arg4));
- CALL(fnptr);
+ MOV(32, R(RDI), Imm32(arg0));
+ MOV(32, R(RSI), Imm32(arg1));
+ MOV(32, R(RDX), Imm32(arg2));
+ MOV(32, R(RCX), Imm32(arg3));
+ MOV(32, R(R8), Imm32(arg4));
+ CALL(fnptr);
#endif
#else
- ABI_AlignStack(5 * 4);
- PUSH(32, Imm32(arg4));
- PUSH(32, Imm32(arg3));
- PUSH(32, Imm32(arg2));
- PUSH(32, Imm32(arg1));
- PUSH(32, Imm32(arg0));
- CALL(fnptr);
+ ABI_AlignStack(5 * 4);
+ PUSH(32, Imm32(arg4));
+ PUSH(32, Imm32(arg3));
+ PUSH(32, Imm32(arg2));
+ PUSH(32, Imm32(arg1));
+ PUSH(32, Imm32(arg0));
+ CALL(fnptr);
#ifdef _WIN32
- // don't inc stack
+ // don't inc stack
#else
- ABI_RestoreStack(5 * 4);
+ ABI_RestoreStack(5 * 4);
#endif
#endif
}
void XEmitter::CallCdeclFunction6(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
{
- using namespace Gen;
+ using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
MOV(32, MDisp(RSP, 0x28), Imm32(arg5));
- CALL(fnptr);
+ CALL(fnptr);
#else
- MOV(32, R(RDI), Imm32(arg0));
- MOV(32, R(RSI), Imm32(arg1));
- MOV(32, R(RDX), Imm32(arg2));
- MOV(32, R(RCX), Imm32(arg3));
- MOV(32, R(R8), Imm32(arg4));
- MOV(32, R(R9), Imm32(arg5));
- CALL(fnptr);
+ MOV(32, R(RDI), Imm32(arg0));
+ MOV(32, R(RSI), Imm32(arg1));
+ MOV(32, R(RDX), Imm32(arg2));
+ MOV(32, R(RCX), Imm32(arg3));
+ MOV(32, R(R8), Imm32(arg4));
+ MOV(32, R(R9), Imm32(arg5));
+ CALL(fnptr);
#endif
#else
- ABI_AlignStack(6 * 4);
- PUSH(32, Imm32(arg5));
- PUSH(32, Imm32(arg4));
- PUSH(32, Imm32(arg3));
- PUSH(32, Imm32(arg2));
- PUSH(32, Imm32(arg1));
- PUSH(32, Imm32(arg0));
- CALL(fnptr);
+ ABI_AlignStack(6 * 4);
+ PUSH(32, Imm32(arg5));
+ PUSH(32, Imm32(arg4));
+ PUSH(32, Imm32(arg3));
+ PUSH(32, Imm32(arg2));
+ PUSH(32, Imm32(arg1));
+ PUSH(32, Imm32(arg0));
+ CALL(fnptr);
#ifdef _WIN32
- // don't inc stack
+ // don't inc stack
#else
- ABI_RestoreStack(6 * 4);
+ ABI_RestoreStack(6 * 4);
#endif
#endif
}
@@ -1615,31 +1615,31 @@ void XEmitter::CallCdeclFunction6(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32
// See header
void XEmitter::___CallCdeclImport3(void* impptr, u32 arg0, u32 arg1, u32 arg2) {
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
CALLptr(M(impptr));
}
void XEmitter::___CallCdeclImport4(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3) {
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
CALLptr(M(impptr));
}
void XEmitter::___CallCdeclImport5(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4) {
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
CALLptr(M(impptr));
}
void XEmitter::___CallCdeclImport6(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 arg5) {
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
MOV(32, MDisp(RSP, 0x28), Imm32(arg5));
CALLptr(M(impptr));
diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h
index 3b699c81a0..97ba080790 100644
--- a/Source/Core/Common/Src/x64Emitter.h
+++ b/Source/Core/Common/Src/x64Emitter.h
@@ -757,7 +757,7 @@ public:
region_size = 0;
}
- bool IsInCodeSpace(u8 *ptr)
+ bool IsInSpace(u8 *ptr)
{
return ptr >= region && ptr < region + region_size;
}
@@ -766,7 +766,7 @@ public:
// Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
void WriteProtect()
{
- WriteProtectMemory(region, region_size, true);
+ WriteProtectMemory(region, region_size, true);
}
void ResetCodePtr()
diff --git a/Source/Core/Common/Src/x64FPURoundMode.cpp b/Source/Core/Common/Src/x64FPURoundMode.cpp
new file mode 100644
index 0000000000..41363f7999
--- /dev/null
+++ b/Source/Core/Common/Src/x64FPURoundMode.cpp
@@ -0,0 +1,120 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+#include "FPURoundMode.h"
+
+#ifndef _WIN32
+static const unsigned short FPU_ROUND_NEAR = 0 << 10;
+static const unsigned short FPU_ROUND_DOWN = 1 << 10;
+static const unsigned short FPU_ROUND_UP = 2 << 10;
+static const unsigned short FPU_ROUND_CHOP = 3 << 10;
+static const unsigned short FPU_ROUND_MASK = 3 << 10;
+#include <xmmintrin.h>
+#endif
+
+const u32 MASKS = 0x1F80; // mask away the interrupts.
+const u32 DAZ = 0x40;
+const u32 FTZ = 0x8000;
+
+namespace FPURoundMode
+{
+ // Get the default SSE states here.
+ static u32 saved_sse_state = _mm_getcsr();
+ static const u32 default_sse_state = _mm_getcsr();
+
+ void SetRoundMode(u32 mode)
+ {
+ // Set FPU rounding mode to mimic the PowerPC's
+ #ifdef _M_IX86
+ // This shouldn't really be needed anymore since we use SSE
+ #ifdef _WIN32
+ const int table[4] =
+ {
+ _RC_NEAR,
+ _RC_CHOP,
+ _RC_UP,
+ _RC_DOWN
+ };
+ _set_controlfp(_MCW_RC, table[mode]);
+ #else
+ const unsigned short table[4] =
+ {
+ FPU_ROUND_NEAR,
+ FPU_ROUND_CHOP,
+ FPU_ROUND_UP,
+ FPU_ROUND_DOWN
+ };
+ unsigned short _mode;
+ asm ("fstcw %0" : "=m" (_mode) : );
+ _mode = (_mode & ~FPU_ROUND_MASK) | table[mode];
+ asm ("fldcw %0" : : "m" (_mode));
+ #endif
+ #endif
+ }
+
+ void SetPrecisionMode(u32 mode)
+ {
+ #ifdef _M_IX86
+ // sets the floating-point lib to 53-bit
+ // PowerPC has a 53bit floating pipeline only
+ // eg: sscanf is very sensitive
+ #ifdef _WIN32
+ _control87(_PC_53, MCW_PC);
+ #else
+ const unsigned short table[4] = {
+ 0 << 8, // FPU_PREC_24
+ 2 << 8, // FPU_PREC_53
+ 3 << 8, // FPU_PREC_64
+ 3 << 8, // FPU_PREC_MASK
+ };
+ unsigned short _mode;
+ asm ("fstcw %0" : : "m" (_mode));
+ _mode = (_mode & ~table[3]) | table[mode];
+ asm ("fldcw %0" : : "m" (_mode));
+ #endif
+ #else
+ //x64 doesn't need this - fpu is done with SSE
+ //but still - set any useful sse options here
+ #endif
+ }
+ void SetSIMDMode(u32 mode)
+ {
+ static const u32 ssetable[4] =
+ {
+ (0 << 13) | MASKS,
+ (3 << 13) | MASKS,
+ (2 << 13) | MASKS,
+ (1 << 13) | MASKS,
+ };
+ u32 csr = ssetable[mode];
+ _mm_setcsr(csr);
+ }
+
+ void SaveSIMDState()
+ {
+ saved_sse_state = _mm_getcsr();
+ }
+ void LoadSIMDState()
+ {
+ _mm_setcsr(saved_sse_state);
+ }
+ void LoadDefaultSIMDState()
+ {
+ _mm_setcsr(default_sse_state);
+ }
+}
diff --git a/Source/Core/Common/Src/Thunk.cpp b/Source/Core/Common/Src/x64Thunk.cpp
index 1792df3e77..b9fd54f354 100644
--- a/Source/Core/Common/Src/Thunk.cpp
+++ b/Source/Core/Common/Src/x64Thunk.cpp
@@ -18,9 +18,8 @@
#include <map>
#include "Common.h"
-#include "x64Emitter.h"
#include "MemoryUtil.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Thunk.h"
#define THUNK_ARENA_SIZE 1024*1024*1
diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 862a9b30ad..db6d3dca80 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -10,7 +10,6 @@ set(SRCS Src/ActionReplay.cpp
Src/ec_wii.cpp
Src/GeckoCodeConfig.cpp
Src/GeckoCode.cpp
- Src/MemTools.cpp
Src/Movie.cpp
Src/NetPlay.cpp
Src/NetPlayClient.cpp
@@ -156,6 +155,7 @@ set(SRCS Src/ActionReplay.cpp
Src/PowerPC/PPCTables.cpp
Src/PowerPC/Profiler.cpp
Src/PowerPC/SignatureDB.cpp
+ Src/PowerPC/JitInterface.cpp
Src/PowerPC/Interpreter/Interpreter_Branch.cpp
Src/PowerPC/Interpreter/Interpreter.cpp
Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp
@@ -165,6 +165,15 @@ set(SRCS Src/ActionReplay.cpp
Src/PowerPC/Interpreter/Interpreter_Paired.cpp
Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
Src/PowerPC/Interpreter/Interpreter_Tables.cpp
+ Src/PowerPC/JitCommon/JitAsmCommon.cpp
+ Src/PowerPC/JitCommon/JitBackpatch.cpp
+ Src/PowerPC/JitCommon/JitBase.cpp
+ Src/PowerPC/JitCommon/JitCache.cpp
+ Src/PowerPC/JitCommon/Jit_Util.cpp)
+
+if(NOT _M_GENERIC)
+ set(SRCS ${SRCS}
+ Src/x64MemTools.cpp
Src/PowerPC/Jit64IL/IR.cpp
Src/PowerPC/Jit64IL/IR_X86.cpp
Src/PowerPC/Jit64IL/JitILAsm.cpp
@@ -189,12 +198,25 @@ set(SRCS Src/ActionReplay.cpp
Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp
Src/PowerPC/Jit64/Jit_Paired.cpp
Src/PowerPC/Jit64/JitRegCache.cpp
- Src/PowerPC/Jit64/Jit_SystemRegisters.cpp
- Src/PowerPC/JitCommon/JitAsmCommon.cpp
- Src/PowerPC/JitCommon/JitBackpatch.cpp
- Src/PowerPC/JitCommon/JitBase.cpp
- Src/PowerPC/JitCommon/JitCache.cpp
- Src/PowerPC/JitCommon/Jit_Util.cpp)
+ Src/PowerPC/Jit64/Jit_SystemRegisters.cpp)
+endif()
+if(_M_ARM)
+ set(SRCS ${SRCS}
+ Src/ArmMemTools.cpp
+ Src/PowerPC/JitArm32/Jit.cpp
+ Src/PowerPC/JitArm32/JitAsm.cpp
+ Src/PowerPC/JitArm32/JitArm_BackPatch.cpp
+ Src/PowerPC/JitArm32/JitArm_Tables.cpp
+ Src/PowerPC/JitArm32/JitArmCache.cpp
+ Src/PowerPC/JitArm32/JitRegCache.cpp
+ Src/PowerPC/JitArm32/JitFPRCache.cpp
+ Src/PowerPC/JitArm32/JitArm_Branch.cpp
+ Src/PowerPC/JitArm32/JitArm_Integer.cpp
+ Src/PowerPC/JitArm32/JitArm_LoadStore.cpp
+ Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp
+ Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp
+ Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp)
+endif()
set(LIBS bdisasm inputcommon videosoftware sfml-network ${OPENSSL_LIBRARIES})
diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index f0520955c6..4c2a3a2747 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -44,7 +44,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -54,7 +54,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -335,7 +335,7 @@
<ClCompile Include="Src\IPC_HLE\WII_IPC_HLE_Device_usb.cpp" />
<ClCompile Include="Src\IPC_HLE\WII_IPC_HLE_Device_usb_kbd.cpp" />
<ClCompile Include="Src\IPC_HLE\WII_IPC_HLE_WiiMote.cpp" />
- <ClCompile Include="Src\MemTools.cpp" />
+ <ClCompile Include="Src\x64MemTools.cpp" />
<ClCompile Include="Src\Movie.cpp" />
<ClCompile Include="Src\NetPlay.cpp" />
<ClCompile Include="Src\NetPlayClient.cpp" />
@@ -382,6 +382,7 @@
<ClCompile Include="Src\PowerPC\JitCommon\JitBase.cpp" />
<ClCompile Include="Src\PowerPC\JitCommon\JitCache.cpp" />
<ClCompile Include="Src\PowerPC\JitCommon\Jit_Util.cpp" />
+ <ClCompile Include="Src\PowerPC\JitInterface.cpp" />
<ClCompile Include="Src\PowerPC\LUT_frsqrtex.cpp" />
<ClCompile Include="Src\PowerPC\PowerPC.cpp" />
<ClCompile Include="Src\PowerPC\PPCAnalyst.cpp" />
@@ -391,10 +392,10 @@
<ClCompile Include="Src\PowerPC\Profiler.cpp" />
<ClCompile Include="Src\PowerPC\SignatureDB.cpp" />
<ClCompile Include="Src\State.cpp">
- <OpenMPSupport Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">false</OpenMPSupport>
- <OpenMPSupport Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</OpenMPSupport>
- <OpenMPSupport Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</OpenMPSupport>
- </ClCompile>
+ <OpenMPSupport Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">false</OpenMPSupport>
+ <OpenMPSupport Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</OpenMPSupport>
+ <OpenMPSupport Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</OpenMPSupport>
+ </ClCompile>
<ClCompile Include="Src\stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
@@ -572,6 +573,7 @@
<ClInclude Include="Src\PowerPC\JitCommon\JitBase.h" />
<ClInclude Include="Src\PowerPC\JitCommon\JitCache.h" />
<ClInclude Include="Src\PowerPC\JitCommon\Jit_Util.h" />
+ <ClInclude Include="Src\PowerPC\JitInterface.h" />
<ClInclude Include="Src\PowerPC\LUT_frsqrtex.h" />
<ClInclude Include="Src\PowerPC\PowerPC.h" />
<ClInclude Include="Src\PowerPC\PPCAnalyst.h" />
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index deb707ba68..b21361634b 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -5,9 +5,8 @@
<ClCompile Include="Src\Console.cpp" />
<ClCompile Include="Src\Core.cpp" />
<ClCompile Include="Src\CoreParameter.cpp" />
- <ClCompile Include="Src\CoreRerecording.cpp" />
<ClCompile Include="Src\CoreTiming.cpp" />
- <ClCompile Include="Src\MemTools.cpp" />
+ <ClCompile Include="Src\x64MemTools.cpp" />
<ClCompile Include="Src\PatchEngine.cpp" />
<ClCompile Include="Src\DSPEmulator.cpp" />
<ClCompile Include="Src\State.cpp" />
@@ -568,7 +567,9 @@
<ClCompile Include="Src\HW\GCMemcard.cpp">
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
</ClCompile>
- <ClCompile Include="Src\IPC_HLE\ICMPWin.cpp">
+ <ClCompile Include="Src\PowerPC\JitInterface.cpp">
+ <Filter>PowerPC</Filter>
+ </ClCompile> <ClCompile Include="Src\IPC_HLE\ICMPWin.cpp">
<Filter>IPC HLE %28IOS/Starlet%29\Net</Filter>
</ClCompile>
<ClCompile Include="Src\IPC_HLE\WII_IPC_HLE_Device_hid.cpp">
@@ -1063,7 +1064,9 @@
<ClInclude Include="Src\HW\GCMemcard.h">
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
</ClInclude>
- <ClInclude Include="Src\IPC_HLE\WII_IPC_HLE_Device_net_ssl.h">
+ <ClInclude Include="Src\PowerPC\JitInterface.h">
+ <Filter>PowerPC</Filter>
+ </ClInclude> <ClInclude Include="Src\IPC_HLE\WII_IPC_HLE_Device_net_ssl.h">
<Filter>IPC HLE %28IOS/Starlet%29\Net</Filter>
</ClInclude>
<ClInclude Include="Src\IPC_HLE\fakepoll.h">
diff --git a/Source/Core/Core/Src/ArmMemTools.cpp b/Source/Core/Core/Src/ArmMemTools.cpp
new file mode 100644
index 0000000000..34a0c34b7d
--- /dev/null
+++ b/Source/Core/Core/Src/ArmMemTools.cpp
@@ -0,0 +1,103 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+
+#include <stdio.h>
+#include <signal.h>
+#ifdef ANDROID
+#include <asm/sigcontext.h>
+#else
+#include <sys/ucontext.h> // Look in here for the context definition.
+#include <execinfo.h>
+#endif
+
+#include "Common.h"
+#include "MemTools.h"
+#include "HW/Memmap.h"
+#include "PowerPC/PowerPC.h"
+#include "PowerPC/JitInterface.h"
+#include "PowerPC/JitCommon/JitBase.h"
+
+namespace EMM
+{
+#ifdef ANDROID
+typedef struct sigcontext mcontext_t;
+typedef struct ucontext {
+ uint32_t uc_flags;
+ struct ucontext* uc_link;
+ stack_t uc_stack;
+ mcontext_t uc_mcontext;
+ // Other fields are not used by Google Breakpad. Don't define them.
+} ucontext_t;
+#endif
+
+void sigsegv_handler(int signal, siginfo_t *info, void *raw_context)
+{
+ if (signal != SIGSEGV)
+ {
+ // We are not interested in other signals - handle it as usual.
+ return;
+ }
+ ucontext_t *context = (ucontext_t *)raw_context;
+ int sicode = info->si_code;
+ if (sicode != SEGV_MAPERR && sicode != SEGV_ACCERR)
+ {
+ // Huh? Return.
+ return;
+ }
+
+
+ // Get all the information we can out of the context.
+ mcontext_t *ctx = &context->uc_mcontext;
+
+ void *fault_memory_ptr = (void*)ctx->arm_r10;
+ u8 *fault_instruction_ptr = (u8 *)ctx->arm_pc;
+
+ if (!JitInterface::IsInCodeSpace(fault_instruction_ptr)) {
+ // Let's not prevent debugging.
+ return;
+ }
+
+ u64 bad_address = (u64)fault_memory_ptr;
+ u64 memspace_bottom = (u64)Memory::base;
+ if (bad_address < memspace_bottom) {
+ PanicAlertT("Exception handler - access below memory space. %08llx%08llx",
+ bad_address >> 32, bad_address);
+ }
+
+ u32 em_address = (u32)(bad_address - memspace_bottom);
+
+ int access_type = 0;
+
+ CONTEXT fake_ctx;
+ fake_ctx.reg_pc = ctx->arm_pc;
+ const u8 *new_rip = jit->BackPatch(fault_instruction_ptr, access_type, em_address, &fake_ctx);
+ if (new_rip) {
+ ctx->arm_pc = fake_ctx.reg_pc;
+ }
+}
+
+void InstallExceptionHandler()
+{
+ struct sigaction sa;
+ sa.sa_handler = 0;
+ sa.sa_sigaction = &sigsegv_handler;
+ sa.sa_flags = SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGSEGV, &sa, NULL);
+}
+} // namespace
diff --git a/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp
index d3fa172621..a86c38286d 100644
--- a/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp
+++ b/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp
@@ -90,9 +90,7 @@ bool CBoot::Boot_WiiWAD(const char* _pFilename)
u64 titleID = ContentLoader.GetTitleID();
// create data directory
File::CreateFullPath(Common::GetTitleDataPath(titleID));
-
- if (titleID == TITLEID_SYSMENU)
- HLE_IPC_CreateVirtualFATFilesystem();
+
// setup wii mem
if (!SetupWiiMemory(ContentLoader.GetCountry()))
return false;
diff --git a/Source/Core/Core/Src/BootManager.cpp b/Source/Core/Core/Src/BootManager.cpp
index 1e9e612fe0..88e0cebcb6 100644
--- a/Source/Core/Core/Src/BootManager.cpp
+++ b/Source/Core/Core/Src/BootManager.cpp
@@ -55,7 +55,7 @@ namespace BootManager
struct ConfigCache
{
bool valid, bCPUThread, bSkipIdle, bEnableFPRF, bMMU, bDCBZOFF,
- bVBeam, bFastDiscSpeed, bMergeBlocks, bDSPHLE, bHLE_BS2;
+ bVBeam, bSyncGPU, bFastDiscSpeed, bMergeBlocks, bDSPHLE, bHLE_BS2;
int iTLBHack, iCPUCore;
std::string strBackend;
};
@@ -95,6 +95,7 @@ bool BootCore(const std::string& _rFilename)
config_cache.bDCBZOFF = StartUp.bDCBZOFF;
config_cache.iTLBHack = StartUp.iTLBHack;
config_cache.bVBeam = StartUp.bVBeam;
+ config_cache.bSyncGPU = StartUp.bSyncGPU;
config_cache.bFastDiscSpeed = StartUp.bFastDiscSpeed;
config_cache.bMergeBlocks = StartUp.bMergeBlocks;
config_cache.bDSPHLE = StartUp.bDSPHLE;
@@ -109,6 +110,7 @@ bool BootCore(const std::string& _rFilename)
game_ini.Get("Core", "TLBHack", &StartUp.iTLBHack, StartUp.iTLBHack);
game_ini.Get("Core", "DCBZ", &StartUp.bDCBZOFF, StartUp.bDCBZOFF);
game_ini.Get("Core", "VBeam", &StartUp.bVBeam, StartUp.bVBeam);
+ game_ini.Get("Core", "SyncGPU", &StartUp.bSyncGPU, StartUp.bSyncGPU);
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);
@@ -168,6 +170,7 @@ void Stop()
StartUp.bDCBZOFF = config_cache.bDCBZOFF;
StartUp.iTLBHack = config_cache.iTLBHack;
StartUp.bVBeam = config_cache.bVBeam;
+ StartUp.bSyncGPU = config_cache.bSyncGPU;
StartUp.bFastDiscSpeed = config_cache.bFastDiscSpeed;
StartUp.bMergeBlocks = config_cache.bMergeBlocks;
StartUp.bDSPHLE = config_cache.bDSPHLE;
diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp
index e67effd607..4470b294a4 100644
--- a/Source/Core/Core/Src/ConfigManager.cpp
+++ b/Source/Core/Core/Src/ConfigManager.cpp
@@ -100,9 +100,6 @@ SConfig::SConfig()
{
// Make sure we have log manager
LoadSettings();
- //Make sure we load any extra settings
- LoadSettingsWii();
-
}
void SConfig::Init()
@@ -140,7 +137,7 @@ void SConfig::SaveSettings()
ini.Get("General", "GCMPathes", &oldPaths, 0);
for (int i = numPaths; i < oldPaths; i++)
{
- TCHAR tmp[16];
+ char tmp[16];
sprintf(tmp, "GCMPath%i", i);
ini.DeleteKey("General", tmp);
}
@@ -149,7 +146,7 @@ void SConfig::SaveSettings()
for (int i = 0; i < numPaths; i++)
{
- TCHAR tmp[16];
+ char tmp[16];
sprintf(tmp, "GCMPath%i", i);
ini.Set("General", tmp, m_ISOFolder[i]);
}
@@ -247,6 +244,8 @@ void SConfig::SaveSettings()
ini.Set("Core", "WiiSDCard", m_WiiSDCard);
ini.Set("Core", "WiiKeyboard", m_WiiKeyboard);
ini.Set("Core", "WiimoteReconnectOnLoad", m_WiimoteReconnectOnLoad);
+ ini.Set("Core", "WiimoteContinuousScanning", m_WiimoteContinuousScanning);
+ ini.Set("Core", "WiimoteEnableSpeaker", m_WiimoteEnableSpeaker);
ini.Set("Core", "RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer);
ini.Set("Core", "RunCompareClient", m_LocalCoreStartupParameter.bRunCompareClient);
ini.Set("Core", "FrameLimit", m_Framelimit);
@@ -291,7 +290,7 @@ void SConfig::LoadSettings()
{
for (int i = 0; i < numGCMPaths; i++)
{
- TCHAR tmp[16];
+ char tmp[16];
sprintf(tmp, "GCMPath%i", i);
std::string tmpPath;
ini.Get("General", tmp, &tmpPath, "");
@@ -369,7 +368,11 @@ void SConfig::LoadSettings()
// Core
ini.Get("Core", "HLE_BS2", &m_LocalCoreStartupParameter.bHLE_BS2, false);
+#ifdef _M_ARM
+ ini.Get("Core", "CPUCore", &m_LocalCoreStartupParameter.iCPUCore, 3);
+#else
ini.Get("Core", "CPUCore", &m_LocalCoreStartupParameter.iCPUCore, 1);
+#endif
ini.Get("Core", "DSPThread", &m_LocalCoreStartupParameter.bDSPThread, false);
ini.Get("Core", "DSPHLE", &m_LocalCoreStartupParameter.bDSPHLE, true);
ini.Get("Core", "CPUThread", &m_LocalCoreStartupParameter.bCPUThread, true);
@@ -399,12 +402,15 @@ void SConfig::LoadSettings()
ini.Get("Core", "WiiSDCard", &m_WiiSDCard, false);
ini.Get("Core", "WiiKeyboard", &m_WiiKeyboard, false);
- ini.Get("Core", "WiimoteReconnectOnLoad", &m_WiimoteReconnectOnLoad, true);
+ ini.Get("Core", "WiimoteReconnectOnLoad", &m_WiimoteReconnectOnLoad, true);
+ ini.Get("Core", "WiimoteContinuousScanning", &m_WiimoteContinuousScanning, false);
+ ini.Get("Core", "WiimoteEnableSpeaker", &m_WiimoteEnableSpeaker, true);
ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false);
ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false);
ini.Get("Core", "MMU", &m_LocalCoreStartupParameter.bMMU, false);
ini.Get("Core", "TLBHack", &m_LocalCoreStartupParameter.iTLBHack, 0);
ini.Get("Core", "VBeam", &m_LocalCoreStartupParameter.bVBeam, false);
+ ini.Get("Core", "SyncGPU", &m_LocalCoreStartupParameter.bSyncGPU, false);
ini.Get("Core", "FastDiscSpeed", &m_LocalCoreStartupParameter.bFastDiscSpeed, false);
ini.Get("Core", "DCBZ", &m_LocalCoreStartupParameter.bDCBZOFF, false);
ini.Get("Core", "FrameLimit", &m_Framelimit, 1); // auto frame limit by default
@@ -414,7 +420,7 @@ void SConfig::LoadSettings()
ini.Get("Core", "GFXBackend", &m_LocalCoreStartupParameter.m_strVideoBackend, "");
// Movie
- ini.Get("General", "PauseMovie", &m_PauseMovie, false);
+ ini.Get("Movie", "PauseMovie", &m_PauseMovie, false);
ini.Get("Movie", "Author", &m_strMovieAuthor, "");
// DSP
@@ -434,18 +440,3 @@ void SConfig::LoadSettings()
m_SYSCONF = new SysConf();
}
-void SConfig::LoadSettingsWii()
-{
- IniFile ini;
- //Wiimote configs
- ini.Load((File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini"));
- for (int i = 0; i < 4; i++)
- {
- char SectionName[32];
- sprintf(SectionName, "Wiimote%i", i + 1);
- ini.Get(SectionName, "AutoReconnectRealWiimote", &m_WiiAutoReconnect[i], false);
- }
- ini.Load((File::GetUserPath(D_CONFIG_IDX) + "wiimote.ini"));
- ini.Get("Real", "Unpair", &m_WiiAutoUnpair, false);
-
-}
diff --git a/Source/Core/Core/Src/ConfigManager.h b/Source/Core/Core/Src/ConfigManager.h
index e92d29ee65..4a36b37335 100644
--- a/Source/Core/Core/Src/ConfigManager.h
+++ b/Source/Core/Core/Src/ConfigManager.h
@@ -35,15 +35,15 @@
#define BACKEND_OPENAL "OpenAL"
#define BACKEND_PULSEAUDIO "Pulse"
#define BACKEND_XAUDIO2 "XAudio2"
-
+#define BACKEND_OPENSLES "OpenSLES"
struct SConfig : NonCopyable
{
// Wii Devices
bool m_WiiSDCard;
bool m_WiiKeyboard;
- bool m_WiiAutoReconnect[4];
- bool m_WiiAutoUnpair;
bool m_WiimoteReconnectOnLoad;
+ bool m_WiimoteContinuousScanning;
+ bool m_WiimoteEnableSpeaker;
// name of the last used filename
std::string m_LastFilename;
@@ -107,9 +107,6 @@ struct SConfig : NonCopyable
// load settings
void LoadSettings();
- //Special load settings
- void LoadSettingsWii();
-
// Return the permanent and somewhat globally used instance of this struct
static SConfig& GetInstance() {return(*m_Instance);}
diff --git a/Source/Core/Core/Src/Console.cpp b/Source/Core/Core/Src/Console.cpp
index 759dc46bc5..b0ef416a84 100644
--- a/Source/Core/Core/Src/Console.cpp
+++ b/Source/Core/Core/Src/Console.cpp
@@ -98,8 +98,8 @@ void Console_Submit(const char *cmd)
}
CASE("dump")
{
- TCHAR temp[256];
- TCHAR filename[256];
+ char temp[256];
+ char filename[256];
u32 start;
u32 end;
sscanf(cmd, "%s %08x %08x %s", temp, &start, &end, filename);
diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp
index a9e6c87329..fa989409dc 100644
--- a/Source/Core/Core/Src/Core.cpp
+++ b/Source/Core/Core/Src/Core.cpp
@@ -54,7 +54,6 @@
#include "IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "PowerPC/PowerPC.h"
-#include "PowerPC/JitCommon/JitBase.h"
#ifdef USE_GDBSTUB
#include "PowerPC/GDBStub.h"
#endif
@@ -108,6 +107,7 @@ static bool g_requestRefreshInfo = false;
static int g_pauseAndLockDepth = 0;
SCoreStartupParameter g_CoreStartupParameter;
+bool isTabPressed = false;
std::string GetStateFileName() { return g_stateFileName; }
void SetStateFileName(std::string val) { g_stateFileName = val; }
@@ -143,7 +143,7 @@ void DisplayMessage(const char *message, int time_in_ms)
if (_CoreParameter.bRenderToMain &&
SConfig::GetInstance().m_InterfaceStatusbar)
{
- Host_UpdateStatusBar(message);
+ Host_UpdateStatusBar(message);
}
else
Host_UpdateTitle(message);
@@ -192,7 +192,7 @@ bool IsGPUThread()
return IsCPUThread();
}
}
-
+
// This is called from the GUI thread. See the booting call schedule in
// BootManager.cpp
bool Init()
@@ -313,7 +313,7 @@ void CpuThread()
g_video_backend->Video_Prepare();
}
- #if defined(_M_X64)
+ #if defined(_M_X64) || _M_ARM
EMM::InstallExceptionHandler(); // Let's run under memory watch
#endif
@@ -336,6 +336,9 @@ void CpuThread()
CCPU::Run();
g_bStarted = false;
+
+ if (!_CoreParameter.bCPUThread)
+ g_video_backend->Video_Cleanup();
return;
}
@@ -364,6 +367,9 @@ void FifoPlayerThread()
}
g_bStarted = false;
+
+ if(!_CoreParameter.bCPUThread)
+ g_video_backend->Video_Cleanup();
return;
}
@@ -497,6 +503,9 @@ void EmuThread()
INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str());
+ if(_CoreParameter.bCPUThread)
+ g_video_backend->Video_Cleanup();
+
VolumeHandler::EjectVolume();
FileMon::Close();
@@ -614,9 +623,13 @@ void VideoThrottle()
u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 2) ?
(SConfig::GetInstance().m_Framelimit - 1) * 5 : VideoInterface::TargetRefreshRate;
+ if (Host_GetKeyState('\t'))
+ isTabPressed = true;
+
// Disable the frame-limiter when the throttle (Tab) key is held down. Audio throttle: m_Framelimit = 2
if (SConfig::GetInstance().m_Framelimit && SConfig::GetInstance().m_Framelimit != 2 && !Host_GetKeyState('\t'))
{
+ isTabPressed = false;
u32 frametime = ((SConfig::GetInstance().b_UseFPS)? Common::AtomicLoad(DrawnFrame) : DrawnVideo) * 1000 / TargetVPS;
u32 timeDifference = (u32)Timer.GetTimeDifference();
diff --git a/Source/Core/Core/Src/Core.h b/Source/Core/Core/Src/Core.h
index ac55419db3..2b88b16510 100644
--- a/Source/Core/Core/Src/Core.h
+++ b/Source/Core/Core/Src/Core.h
@@ -38,6 +38,8 @@ namespace Core
// TODO: kill, use SConfig instead
extern SCoreStartupParameter g_CoreStartupParameter;
+extern bool isTabPressed;
+
void Callback_VideoCopiedToXFB(bool video_update);
enum EState
diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp
index d00625963c..4b1364c400 100644
--- a/Source/Core/Core/Src/CoreParameter.cpp
+++ b/Source/Core/Core/Src/CoreParameter.cpp
@@ -50,7 +50,7 @@ SCoreStartupParameter::SCoreStartupParameter()
bDPL2Decoder(false), iLatency(14),
bRunCompareServer(false), bRunCompareClient(false),
bMMU(false), bDCBZOFF(false), iTLBHack(0), bVBeam(false),
- bFastDiscSpeed(false),
+ bSyncGPU(false), bFastDiscSpeed(false),
SelectedLanguage(0), bWii(false),
bConfirmStop(false), bHideCursor(false),
bAutoHideCursor(false), bUsePanicHandlers(true), bOnScreenDisplayMessages(true),
@@ -81,6 +81,7 @@ void SCoreStartupParameter::LoadDefaults()
bDCBZOFF = false;
iTLBHack = 0;
bVBeam = false;
+ bSyncGPU = false;
bFastDiscSpeed = false;
bMergeBlocks = false;
SelectedLanguage = 0;
diff --git a/Source/Core/Core/Src/CoreParameter.h b/Source/Core/Core/Src/CoreParameter.h
index c9352a91d7..2f92d58604 100644
--- a/Source/Core/Core/Src/CoreParameter.h
+++ b/Source/Core/Core/Src/CoreParameter.h
@@ -119,6 +119,7 @@ struct SCoreStartupParameter
bool bDCBZOFF;
int iTLBHack;
bool bVBeam;
+ bool bSyncGPU;
bool bFastDiscSpeed;
int SelectedLanguage;
diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp
index 525f7165f2..ff9488b4fe 100644
--- a/Source/Core/Core/Src/CoreTiming.cpp
+++ b/Source/Core/Core/Src/CoreTiming.cpp
@@ -413,6 +413,15 @@ void SetMaximumSlice(int maximumSliceLength)
maxSliceLength = maximumSliceLength;
}
+void ForceExceptionCheck(int cycles)
+{
+ if (downcount > cycles)
+ {
+ slicelength -= (downcount - cycles); // Account for cycles already executed by adjusting the slicelength
+ downcount = cycles;
+ }
+}
+
void ResetSliceLength()
{
maxSliceLength = MAX_SLICE_LENGTH;
@@ -468,7 +477,6 @@ void MoveEvents()
void Advance()
{
-
MoveEvents();
int cyclesExecuted = slicelength - downcount;
diff --git a/Source/Core/Core/Src/CoreTiming.h b/Source/Core/Core/Src/CoreTiming.h
index db8dcecfc1..8e00b303f0 100644
--- a/Source/Core/Core/Src/CoreTiming.h
+++ b/Source/Core/Core/Src/CoreTiming.h
@@ -92,6 +92,8 @@ void SetFakeTBStartValue(u64 val);
u64 GetFakeTBStartTicks();
void SetFakeTBStartTicks(u64 val);
+void ForceExceptionCheck(int cycles);
+
extern int downcount;
extern int slicelength;
diff --git a/Source/Core/Core/Src/DSP/DSPAccelerator.cpp b/Source/Core/Core/Src/DSP/DSPAccelerator.cpp
index dcb79b7ac5..f625f1ddf6 100644
--- a/Source/Core/Core/Src/DSP/DSPAccelerator.cpp
+++ b/Source/Core/Core/Src/DSP/DSPAccelerator.cpp
@@ -168,9 +168,11 @@ u16 dsp_read_accelerator()
if (Address >= EndAddress)
{
// Set address back to start address.
- if ((Address & ~0x1f) == (EndAddress & ~0x1f))
+ if (DSPHost_Wii() || (Address == EndAddress))
+ {
Address = (g_dsp.ifx_regs[DSP_ACSAH] << 16) | g_dsp.ifx_regs[DSP_ACSAL];
- DSPCore_SetException(EXP_ACCOV);
+ DSPCore_SetException(EXP_ACCOV);
+ }
}
g_dsp.ifx_regs[DSP_ACCAH] = Address >> 16;
diff --git a/Source/Core/Core/Src/DSP/DSPCore.cpp b/Source/Core/Core/Src/DSP/DSPCore.cpp
index 972eb53858..2594a27eef 100644
--- a/Source/Core/Core/Src/DSP/DSPCore.cpp
+++ b/Source/Core/Core/Src/DSP/DSPCore.cpp
@@ -77,37 +77,50 @@ static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
// Returns false iff the hash fails and the user hits "Yes"
static bool VerifyRoms(const char *irom_filename, const char *coef_filename)
{
- static const u32 hash[] = { 0x66f334fe, 0xf3b93527 };
- static const u32 hash_mini[] = { 0x9c8f593c, 0x10000001 };
- static const int size[] = { DSP_IROM_BYTE_SIZE, DSP_COEF_BYTE_SIZE };
- const u16 *data[] = { g_dsp.irom, g_dsp.coef };
- u32 h = 0;
- u8 count = 0;
-
- for (int i = 0; i < 2; i++)
+ struct DspRomHashes
{
- h = HashAdler32((u8*)data[i], size[i]);
+ u32 hash_irom; // dsp_rom.bin
+ u32 hash_drom; // dsp_coef.bin
+ } KNOWN_ROMS[] = {
+ // Official Nintendo ROM
+ { 0x66f334fe, 0xf3b93527 },
- if (h == hash_mini[i])
- {
- count++;
- }
- else if (h != hash[i])
- {
- if (AskYesNoT("%s has an incorrect hash.\n"
- "Would you like to stop now to fix the problem?\n"
- "If you select \"No\", audio will be garbled.",
- (i == 0) ? irom_filename : coef_filename))
- return false;
- }
+ // LM1234 replacement ROM (Zelda UCode only)
+ { 0x9c8f593c, 0x10000001 },
+
+ // delroth's improvement on LM1234 replacement ROM (Zelda and AX only,
+ // IPL/Card/GBA still broken)
+ { 0xd9907f71, 0xb019c2fb }
+ };
+
+ u32 hash_irom = HashAdler32((u8*)g_dsp.irom, DSP_IROM_BYTE_SIZE);
+ u32 hash_drom = HashAdler32((u8*)g_dsp.coef, DSP_COEF_BYTE_SIZE);
+ int rom_idx = -1;
+
+ for (u32 i = 0; i < sizeof (KNOWN_ROMS) / sizeof (KNOWN_ROMS[0]); ++i)
+ {
+ DspRomHashes& rom = KNOWN_ROMS[i];
+ if (hash_irom == rom.hash_irom && hash_drom == rom.hash_drom)
+ rom_idx = i;
}
- if (count == 2)
+ if (rom_idx < 0)
{
- PanicAlertT("You are using free dsp roms made by Dolphin Team.\n"
- "Only Zelda ucode games will work correctly with them.\n");
+ if (AskYesNoT("Your DSP ROMs have incorrect hashes.\n"
+ "Would you like to stop now to fix the problem?\n"
+ "If you select \"No\", audio might be garbled."))
+ return false;
}
+ if (rom_idx == 1)
+ PanicAlertT("You are using an old free DSP ROM made by the Dolphin Team.\n"
+ "Only games using the Zelda UCode will work correctly.\n");
+
+ if (rom_idx == 2)
+ PanicAlertT("You are using a free DSP ROM made by the Dolphin Team.\n"
+ "All Wii games will work correctly, and most GC games should "
+ "also work fine, but the GBA/IPL/CARD UCodes will not work.\n");
+
return true;
}
diff --git a/Source/Core/Core/Src/DSP/DSPEmitter.cpp b/Source/Core/Core/Src/DSP/DSPEmitter.cpp
index 2ce441bf31..12dac52e31 100644
--- a/Source/Core/Core/Src/DSP/DSPEmitter.cpp
+++ b/Source/Core/Core/Src/DSP/DSPEmitter.cpp
@@ -25,7 +25,7 @@
#include "DSPAnalyzer.h"
#include "Jit/DSPJitUtil.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#define MAX_BLOCK_SIZE 250
#define DSP_IDLE_SKIP_CYCLES 0x1000
diff --git a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp
index f2cbbc2b9f..e4c81e4a7a 100644
--- a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp
+++ b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp
@@ -252,7 +252,9 @@ static void gdsp_idma_out(u16 dsp_addr, u32 addr, u32 size)
ERROR_LOG(DSPLLE, "*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)", dsp_addr / 2, addr, size);
}
+#if _M_SSE >= 0x301
static const __m128i s_mask = _mm_set_epi32(0x0E0F0C0DL, 0x0A0B0809L, 0x06070405L, 0x02030001L);
+#endif
// TODO: These should eat clock cycles.
static void gdsp_ddma_in(u16 dsp_addr, u32 addr, u32 size)
diff --git a/Source/Core/Core/Src/DSP/DSPHost.h b/Source/Core/Core/Src/DSP/DSPHost.h
index c28ce80a9a..8ee90477d6 100644
--- a/Source/Core/Core/Src/DSP/DSPHost.h
+++ b/Source/Core/Core/Src/DSP/DSPHost.h
@@ -26,6 +26,7 @@
u8 DSPHost_ReadHostMemory(u32 addr);
void DSPHost_WriteHostMemory(u8 value, u32 addr);
bool DSPHost_OnThread();
+bool DSPHost_Wii();
void DSPHost_InterruptRequest();
u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
void DSPHost_UpdateDebugger();
diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp
index 0b75431de6..185ada8ba3 100644
--- a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp
+++ b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp
@@ -25,7 +25,7 @@
#include "DSPJitUtil.h"
#endif
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
using namespace Gen;
// CLR $acR
diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp
index 8ca770e35d..252550b84c 100644
--- a/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp
+++ b/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp
@@ -21,7 +21,7 @@
#include "../DSPAnalyzer.h"
#include "DSPJitUtil.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
using namespace Gen;
diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp
index e382b6114a..be7675378d 100644
--- a/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp
+++ b/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp
@@ -24,7 +24,7 @@
#include "../DSPEmitter.h"
#include "DSPJitUtil.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
using namespace Gen;
// In: RAX: s64 _Value
diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp
index 8203f7cde1..40e39a89e9 100644
--- a/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp
+++ b/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp
@@ -18,7 +18,7 @@
#include "../DSPEmitter.h"
#include "DSPJitUtil.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
using namespace Gen;
diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp
index a784e2dd2d..248ed8f945 100644
--- a/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp
+++ b/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp
@@ -22,7 +22,7 @@
#include "../DSPEmitter.h"
#include "DSPJitUtil.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
using namespace Gen;
// SRS @M, $(0x18+S)
diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp
index 8d8a635536..d0bf7a3822 100644
--- a/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp
+++ b/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp
@@ -20,7 +20,7 @@
#include "../DSPEmitter.h"
#include "DSPJitUtil.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
using namespace Gen;
//clobbers:
diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp
index 1323de002d..0dcbf41877 100644
--- a/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp
+++ b/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp
@@ -27,7 +27,7 @@
#include "DSPJitUtil.h"
#endif
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
using namespace Gen;
// Returns s64 in RAX
diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp
index b9e166f698..2fb18f83da 100644
--- a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp
+++ b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp
@@ -20,7 +20,7 @@
#include "../DSPEmitter.h"
#include "DSPJitUtil.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
using namespace Gen;
diff --git a/Source/Core/Core/Src/DSP/assemble.cpp b/Source/Core/Core/Src/DSP/assemble.cpp
index dd394ab82c..248b0d8ba8 100644
--- a/Source/Core/Core/Src/DSP/assemble.cpp
+++ b/Source/Core/Core/Src/DSP/assemble.cpp
@@ -754,7 +754,8 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass)
{
int disable_text = 0; // modified by Hermes
- std::ifstream fsrc(fname);
+ std::ifstream fsrc;
+ OpenFStream(fsrc, fname, std::ios_base::in);
if (fsrc.fail())
{
diff --git a/Source/Core/Core/Src/HW/AudioInterface.cpp b/Source/Core/Core/Src/HW/AudioInterface.cpp
index 0a33e7c773..15e1f0bb29 100644
--- a/Source/Core/Core/Src/HW/AudioInterface.cpp
+++ b/Source/Core/Core/Src/HW/AudioInterface.cpp
@@ -145,6 +145,8 @@ static void GenerateAudioInterrupt();
static void UpdateInterrupts();
static void IncreaseSampleCount(const u32 _uAmount);
void ReadStreamBlock(s16* _pPCM);
+u64 GetAIPeriod();
+int et_AI;
void Init()
{
@@ -159,6 +161,8 @@ void Init()
g_AISSampleRate = 48000;
g_AIDSampleRate = 32000;
+
+ et_AI = CoreTiming::RegisterEvent("AICallback", Update);
}
void Shutdown()
@@ -178,11 +182,8 @@ void Read32(u32& _rReturnValue, const u32 _Address)
break;
case AI_SAMPLE_COUNTER:
+ Update(0, 0);
_rReturnValue = m_SampleCounter;
- // HACK - AI SRC init will do while (oldval == sample_counter) {}
- // in order to pass this, we need to increment the counter whenever read
- if (m_Control.PSTAT)
- m_SampleCounter++;
break;
case AI_INTERRUPT_TIMING:
@@ -236,6 +237,9 @@ void Write32(const u32 _Value, const u32 _Address)
// Tell Drive Interface to start/stop streaming
DVDInterface::g_bStream = tmpAICtrl.PSTAT;
+
+ CoreTiming::RemoveEvent(et_AI);
+ CoreTiming::ScheduleEvent(((int)GetAIPeriod() / 2), et_AI);
}
// AI Interrupt
@@ -271,6 +275,8 @@ void Write32(const u32 _Value, const u32 _Address)
case AI_INTERRUPT_TIMING:
m_InterruptTiming = _Value;
+ CoreTiming::RemoveEvent(et_AI);
+ CoreTiming::ScheduleEvent(((int)GetAIPeriod() / 2), et_AI);
DEBUG_LOG(AUDIO_INTERFACE, "Set interrupt: %08x samples", m_InterruptTiming);
break;
@@ -448,7 +454,7 @@ unsigned int GetAIDSampleRate()
return g_AIDSampleRate;
}
-void Update()
+void Update(u64 userdata, int cyclesLate)
{
if (m_Control.PSTAT)
{
@@ -458,8 +464,17 @@ void Update()
const u32 Samples = static_cast<u32>(Diff / g_CPUCyclesPerSample);
g_LastCPUTime += Samples * g_CPUCyclesPerSample;
IncreaseSampleCount(Samples);
- }
+ }
+ CoreTiming::ScheduleEvent(((int)GetAIPeriod() / 2) - cyclesLate, et_AI);
}
}
+u64 GetAIPeriod()
+{
+ u64 period = g_CPUCyclesPerSample * m_InterruptTiming;
+ if (period == 0)
+ period = 32000 * g_CPUCyclesPerSample;
+ return period;
+}
+
} // end of namespace AudioInterface
diff --git a/Source/Core/Core/Src/HW/AudioInterface.h b/Source/Core/Core/Src/HW/AudioInterface.h
index 1504198621..06fd3aec79 100644
--- a/Source/Core/Core/Src/HW/AudioInterface.h
+++ b/Source/Core/Core/Src/HW/AudioInterface.h
@@ -31,7 +31,7 @@ void Init();
void Shutdown();
void DoState(PointerWrap &p);
-void Update();
+void Update(u64 userdata, int cyclesLate);
// Called by DSP emulator
void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DACSampleRate);
diff --git a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp
index 87ebd90344..03332d3012 100644
--- a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp
+++ b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp
@@ -25,7 +25,7 @@
namespace Win32TAPHelper
{
-bool IsTAPDevice(const char *guid)
+bool IsTAPDevice(const TCHAR *guid)
{
HKEY netcard_key;
LONG status;
@@ -39,13 +39,13 @@ bool IsTAPDevice(const char *guid)
for (;;)
{
- char enum_name[256];
- char unit_string[256];
+ TCHAR enum_name[256];
+ TCHAR unit_string[256];
HKEY unit_key;
- char component_id_string[] = "ComponentId";
- char component_id[256];
- char net_cfg_instance_id_string[] = "NetCfgInstanceId";
- char net_cfg_instance_id[256];
+ TCHAR component_id_string[] = _T("ComponentId");
+ TCHAR component_id[256];
+ TCHAR net_cfg_instance_id_string[] = _T("NetCfgInstanceId");
+ TCHAR net_cfg_instance_id[256];
DWORD data_type;
len = sizeof(enum_name);
@@ -56,7 +56,7 @@ bool IsTAPDevice(const char *guid)
else if (status != ERROR_SUCCESS)
return false;
- snprintf(unit_string, sizeof(unit_string), "%s\\%s", ADAPTER_KEY, enum_name);
+ _sntprintf(unit_string, sizeof(unit_string), _T("%s\\%s"), ADAPTER_KEY, enum_name);
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit_string, 0, KEY_READ, &unit_key);
@@ -78,8 +78,8 @@ bool IsTAPDevice(const char *guid)
if (status == ERROR_SUCCESS && data_type == REG_SZ)
{
- if (!strcmp(component_id, TAP_COMPONENT_ID) &&
- !strcmp(net_cfg_instance_id, guid))
+ if (!_tcscmp(component_id, TAP_COMPONENT_ID) &&
+ !_tcscmp(net_cfg_instance_id, guid))
{
RegCloseKey(unit_key);
RegCloseKey(netcard_key);
@@ -96,7 +96,7 @@ bool IsTAPDevice(const char *guid)
return false;
}
-bool GetGUIDs(std::vector<std::string>& guids)
+bool GetGUIDs(std::vector<std::basic_string<TCHAR>>& guids)
{
LONG status;
HKEY control_net_key;
@@ -111,12 +111,12 @@ bool GetGUIDs(std::vector<std::string>& guids)
while (!found_all)
{
- char enum_name[256];
- char connection_string[256];
+ TCHAR enum_name[256];
+ TCHAR connection_string[256];
HKEY connection_key;
- char name_data[256];
+ TCHAR name_data[256];
DWORD name_type;
- const char name_string[] = "Name";
+ const TCHAR name_string[] = _T("Name");
len = sizeof(enum_name);
status = RegEnumKeyEx(control_net_key, i, enum_name,
@@ -127,8 +127,8 @@ bool GetGUIDs(std::vector<std::string>& guids)
else if (status != ERROR_SUCCESS)
return false;
- snprintf(connection_string, sizeof(connection_string),
- "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, enum_name);
+ _sntprintf(connection_string, sizeof(connection_string),
+ _T("%s\\%s\\Connection"), NETWORK_CONNECTIONS_KEY, enum_name);
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, connection_string,
0, KEY_READ, &connection_key);
@@ -165,15 +165,11 @@ bool GetGUIDs(std::vector<std::string>& guids)
return true;
}
-bool OpenTAP(HANDLE& adapter, const std::string device_guid)
+bool OpenTAP(HANDLE& adapter, const std::basic_string<TCHAR>& device_guid)
{
- char device_path[256];
+ auto const device_path = USERMODEDEVICEDIR + device_guid + TAPSUFFIX;
- /* Open Windows TAP-Win32 adapter */
- snprintf(device_path, sizeof(device_path), "%s%s%s",
- USERMODEDEVICEDIR, device_guid.c_str(), TAPSUFFIX);
-
- adapter = CreateFile(device_path, GENERIC_READ | GENERIC_WRITE, 0, 0,
+ adapter = CreateFile(device_path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
if (adapter == INVALID_HANDLE_VALUE)
@@ -192,7 +188,7 @@ bool CEXIETHERNET::Activate()
return true;
DWORD len;
- std::vector<std::string> device_guids;
+ std::vector<std::basic_string<TCHAR>> device_guids;
if (!Win32TAPHelper::GetGUIDs(device_guids))
{
diff --git a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h
index 2676a3fc7e..2a5bc52ffa 100644
--- a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h
+++ b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h
@@ -65,18 +65,18 @@
// Registry keys
//=================
-#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
+#define ADAPTER_KEY _T("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}")
-#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
+#define NETWORK_CONNECTIONS_KEY _T("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}")
//======================
// Filesystem prefixes
//======================
-#define USERMODEDEVICEDIR "\\\\.\\Global\\"
-#define SYSDEVICEDIR "\\Device\\"
-#define USERDEVICEDIR "\\DosDevices\\Global\\"
-#define TAPSUFFIX ".tap"
+#define USERMODEDEVICEDIR _T("\\\\.\\Global\\")
+#define SYSDEVICEDIR _T("\\Device\\")
+#define USERDEVICEDIR _T("\\DosDevices\\Global\\")
+#define TAPSUFFIX _T(".tap")
//=========================================================
// TAP_COMPONENT_ID -- This string defines the TAP driver
@@ -84,4 +84,4 @@
// simultaneously.
//=========================================================
-#define TAP_COMPONENT_ID "tap0901"
+#define TAP_COMPONENT_ID _T("tap0901")
diff --git a/Source/Core/Core/Src/HW/DSP.cpp b/Source/Core/Core/Src/HW/DSP.cpp
index 5945cb7141..a9acf6aedc 100644
--- a/Source/Core/Core/Src/HW/DSP.cpp
+++ b/Source/Core/Core/Src/HW/DSP.cpp
@@ -436,10 +436,6 @@ void Write16(const u16 _Value, const u32 _Address)
if (tmpControl.ARAM) g_dspState.DSPControl.ARAM = 0;
if (tmpControl.DSP) g_dspState.DSPControl.DSP = 0;
- // Tracking DMAState fixes Knockout Kings 2003 in DSP HLE mode
- if (GetDSPEmulator()->IsLLE())
- g_dspState.DSPControl.DMAState = 0; // keep g_ARAM DMA State zero
-
// unknown
g_dspState.DSPControl.unk3 = tmpControl.unk3;
g_dspState.DSPControl.pad = tmpControl.pad;
@@ -691,17 +687,18 @@ void UpdateAudioDMA()
{
// Send silence. Yeah, it's a bit of a waste to sample rate convert
// silence. or hm. Maybe we shouldn't do this :)
- //dsp_emulator->DSP_SendAIBuffer(0, AudioInterface::GetAIDSampleRate());
+ dsp_emulator->DSP_SendAIBuffer(0, AudioInterface::GetAIDSampleRate());
}
}
void Do_ARAM_DMA()
{
- // Emulating the DMA wait time fixes Knockout Kings 2003 in DSP HLE mode
- if (!GetDSPEmulator()->IsLLE())
- g_dspState.DSPControl.DMAState = 1;
+ g_dspState.DSPControl.DMAState = 1;
+ CoreTiming::ScheduleEvent_Threadsafe(0, et_GenerateDSPInterrupt, INT_ARAM | (1<<16));
- GenerateDSPInterrupt(INT_ARAM, true);
+ // Force an early exception check. Fixes RE2 audio.
+ if (g_arDMA.Cnt.count == 4096)
+ CoreTiming::ForceExceptionCheck(100);
// Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks
if (g_arDMA.Cnt.dir)
diff --git a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp
index b22be91104..6d2a1f9097 100644
--- a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp
+++ b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp
@@ -27,6 +27,7 @@
#include "UCodes/UCodes.h"
#include "../AudioInterface.h"
#include "ConfigManager.h"
+#include "Core.h"
DSPHLE::DSPHLE() {
m_InitMixer = false;
@@ -130,6 +131,14 @@ void DSPHLE::SwapUCode(u32 _crc)
void DSPHLE::DoState(PointerWrap &p)
{
+ bool isHLE = true;
+ p.Do(isHLE);
+ if (isHLE != true && p.GetMode() == PointerWrap::MODE_READ)
+ {
+ Core::DisplayMessage("State is incompatible with current DSP engine. Aborting load state.", 3000);
+ p.SetMode(PointerWrap::MODE_VERIFY);
+ return;
+ }
bool prevInitMixer = m_InitMixer;
p.Do(m_InitMixer);
if (prevInitMixer != m_InitMixer && p.GetMode() == PointerWrap::MODE_READ)
diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h
index 349dc7e03b..76c67d0952 100644
--- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h
+++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h
@@ -29,6 +29,8 @@
#include "Common.h"
#include "UCode_AX_Structs.h"
#include "../../DSP.h"
+#include "CoreTiming.h"
+#include "Core.h"
#ifdef AX_GC
# define PB_TYPE AXPB
@@ -205,9 +207,8 @@ u16 AcceleratorGetSample()
// UCode. We simulate what this interrupt does here.
if (*acc_cur_addr >= acc_end_addr)
{
- // If we are really at the end (and we don't simply have cur_addr >
- // end_addr all the time), loop back to loop_addr.
- if ((*acc_cur_addr & ~0x1F) == (acc_end_addr & ~0x1F))
+ // loop back to loop_addr.
+ if (Core::g_CoreStartupParameter.bWii || *acc_cur_addr == acc_end_addr)
*acc_cur_addr = acc_loop_addr;
if (acc_pb->audio_addr.looping)
diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp
index 35fc88eeb8..c3bbeb3afb 100644
--- a/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp
+++ b/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp
@@ -46,6 +46,12 @@ bool DSPHost_OnThread()
return _CoreParameter.bDSPThread;
}
+bool DSPHost_Wii()
+{
+ const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
+ return _CoreParameter.bWii;
+}
+
void DSPHost_InterruptRequest()
{
// Fire an interrupt on the PPC ASAP.
diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp
index 92053053de..0b1dfe524d 100644
--- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp
+++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp
@@ -26,6 +26,7 @@
#include "IniFile.h"
#include "ConfigManager.h"
#include "CPUDetect.h"
+#include "Core.h"
#include "DSPLLEGlobals.h" // Local
#include "DSP/DSPInterpreter.h"
@@ -56,6 +57,14 @@ Common::Event ppcEvent;
void DSPLLE::DoState(PointerWrap &p)
{
+ bool isHLE = false;
+ p.Do(isHLE);
+ if (isHLE != false && p.GetMode() == PointerWrap::MODE_READ)
+ {
+ Core::DisplayMessage("State is incompatible with current DSP engine. Aborting load state.", 3000);
+ p.SetMode(PointerWrap::MODE_VERIFY);
+ return;
+ }
p.Do(g_dsp.r);
p.Do(g_dsp.pc);
#if PROFILE
@@ -135,13 +144,13 @@ bool DSPLLE::Initialize(void *hWnd, bool bWii, bool bDSPThread)
m_bDSPThread = bDSPThread;
m_InitMixer = false;
- std::string irom_file = File::GetSysDirectory() + GC_SYS_DIR DIR_SEP DSP_IROM;
- std::string coef_file = File::GetSysDirectory() + GC_SYS_DIR DIR_SEP DSP_COEF;
+ std::string irom_file = File::GetUserPath(D_GCUSER_IDX) + DSP_IROM;
+ std::string coef_file = File::GetUserPath(D_GCUSER_IDX) + DSP_COEF;
if (!File::Exists(irom_file))
- irom_file = File::GetUserPath(D_GCUSER_IDX) + DSP_IROM;
+ irom_file = File::GetSysDirectory() + GC_SYS_DIR DIR_SEP DSP_IROM;
if (!File::Exists(coef_file))
- coef_file = File::GetUserPath(D_GCUSER_IDX) + DSP_COEF;
+ coef_file = File::GetSysDirectory() + GC_SYS_DIR DIR_SEP DSP_COEF;
if (!DSPCore_Init(irom_file.c_str(), coef_file.c_str(), AudioCommon::UseJIT()))
return false;
diff --git a/Source/Core/Core/Src/HW/DVDInterface.cpp b/Source/Core/Core/Src/HW/DVDInterface.cpp
index 214fb5dc02..57c85a82ed 100644
--- a/Source/Core/Core/Src/HW/DVDInterface.cpp
+++ b/Source/Core/Core/Src/HW/DVDInterface.cpp
@@ -32,11 +32,7 @@
#include "../Movie.h"
// Disc transfer rate measured in bytes per second
-static const u32 DISC_TRANSFER_RATE_GC = 3125 * 1024;
-static const u32 DISC_TRANSFER_RATE_WII = 7926 * 1024;
-
-// Disc access time measured in milliseconds
-static const u32 DISC_ACCESS_TIME_MS = 128;
+static const u32 DISC_TRANSFER_RATE_GC = 4 * 1024 * 1024;
namespace DVDInterface
{
@@ -501,8 +497,7 @@ void Write32(const u32 _iValue, const u32 _iAddress)
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bFastDiscSpeed)
{
u64 ticksUntilTC = m_DILENGTH.Length *
- (SystemTimers::GetTicksPerSecond() / (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii?DISC_TRANSFER_RATE_WII:DISC_TRANSFER_RATE_GC)) +
- (SystemTimers::GetTicksPerSecond() * DISC_ACCESS_TIME_MS / 1000);
+ (SystemTimers::GetTicksPerSecond() / (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii ? 1 : DISC_TRANSFER_RATE_GC));
CoreTiming::ScheduleEvent((int)ticksUntilTC, tc);
}
else
diff --git a/Source/Core/Core/Src/HW/EXI_Channel.cpp b/Source/Core/Core/Src/HW/EXI_Channel.cpp
index b38009f0b1..f31fc59b3f 100644
--- a/Source/Core/Core/Src/HW/EXI_Channel.cpp
+++ b/Source/Core/Core/Src/HW/EXI_Channel.cpp
@@ -25,9 +25,9 @@
#define EXI_WRITE 1
#define EXI_READWRITE 2
-
#include "ProcessorInterface.h"
#include "../PowerPC/PowerPC.h"
+#include "CoreTiming.h"
CEXIChannel::CEXIChannel(u32 ChannelId) :
m_DMAMemoryAddress(0),
@@ -45,6 +45,8 @@ CEXIChannel::CEXIChannel(u32 ChannelId) :
for (int i = 0; i < NUM_DEVICES; i++)
m_pDevices[i] = EXIDevice_Create(EXIDEVICE_NONE, m_ChannelId);
+
+ updateInterrupts = CoreTiming::RegisterEvent("EXIInterrupt", UpdateInterrupts);
}
CEXIChannel::~CEXIChannel()
@@ -88,12 +90,12 @@ void CEXIChannel::AddDevice(IEXIDevice* pDevice, const int device_num, bool noti
if (m_ChannelId != 2)
{
m_Status.EXTINT = 1;
- UpdateInterrupts();
+ CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0);
}
}
}
-void CEXIChannel::UpdateInterrupts()
+void CEXIChannel::UpdateInterrupts(u64 userdata, int cyclesLate)
{
ExpansionInterface::UpdateInterrupts();
}
@@ -149,7 +151,9 @@ void CEXIChannel::Read32(u32& _uReturnValue, const u32 _iRegister)
if (m_ChannelId == 2)
m_Status.EXT = 0;
else
+ {
m_Status.EXT = GetDevice(1)->IsPresent() ? 1 : 0;
+ }
_uReturnValue = m_Status.Hex;
break;
@@ -213,7 +217,7 @@ void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister)
if (pDevice != NULL)
pDevice->SetCS(m_Status.CHIP_SELECT);
- UpdateInterrupts();
+ CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0);
}
break;
@@ -264,7 +268,7 @@ void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister)
if(!m_Control.TSTART) // completed !
{
m_Status.TCINT = 1;
- UpdateInterrupts();
+ CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0);
}
}
break;
diff --git a/Source/Core/Core/Src/HW/EXI_Channel.h b/Source/Core/Core/Src/HW/EXI_Channel.h
index ef6c0a4e0f..dfbd8558f9 100644
--- a/Source/Core/Core/Src/HW/EXI_Channel.h
+++ b/Source/Core/Core/Src/HW/EXI_Channel.h
@@ -110,6 +110,9 @@ private:
// Since channels operate a bit differently from each other
u32 m_ChannelId;
+ int updateInterrupts;
+
+ static void UpdateInterrupts(u64 userdata, int cyclesLate);
public:
// get device
IEXIDevice* GetDevice(const u8 _CHIP_SELECT);
@@ -129,7 +132,6 @@ public:
void Update();
bool IsCausingInterrupt();
- void UpdateInterrupts();
void DoState(PointerWrap &p);
void PauseAndLock(bool doLock, bool unpauseOnUnlock);
diff --git a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp
index c157e55d1b..8307c8c3bc 100644
--- a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp
+++ b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp
@@ -47,6 +47,14 @@ void CEXIMemoryCard::FlushCallback(u64 userdata, int cyclesLate)
pThis->Flush();
}
+void CEXIMemoryCard::CmdDoneCallback(u64 userdata, int cyclesLate)
+{
+ int card_index = (int)userdata;
+ CEXIMemoryCard* pThis = (CEXIMemoryCard*)ExpansionInterface::FindDevice(EXIDEVICE_MEMORYCARD, card_index);
+ if (pThis)
+ pThis->CmdDone();
+}
+
CEXIMemoryCard::CEXIMemoryCard(const int index)
: card_index(index)
, m_bDirty(false)
@@ -56,7 +64,8 @@ CEXIMemoryCard::CEXIMemoryCard(const int index)
m_strFilename = "Movie.raw";
// we're potentially leaking events here, since there's no UnregisterEvent until emu shutdown, but I guess it's inconsequential
- et_this_card = CoreTiming::RegisterEvent((card_index == 0) ? "memcardA" : "memcardB", FlushCallback);
+ et_this_card = CoreTiming::RegisterEvent((card_index == 0) ? "memcardFlushA" : "memcardFlushB", FlushCallback);
+ et_cmd_done = CoreTiming::RegisterEvent((card_index == 0) ? "memcardDoneA" : "memcardDoneB", CmdDoneCallback);
interruptSwitch = 0;
m_bInterruptSet = 0;
@@ -178,6 +187,21 @@ bool CEXIMemoryCard::IsPresent()
return true;
}
+void CEXIMemoryCard::CmdDone()
+{
+ status |= MC_STATUS_READY;
+ status &= ~MC_STATUS_BUSY;
+
+ m_bInterruptSet = 1;
+ m_bDirty = true;
+}
+
+void CEXIMemoryCard::CmdDoneLater(u64 cycles)
+{
+ CoreTiming::RemoveEvent(et_cmd_done);
+ CoreTiming::ScheduleEvent(cycles, et_cmd_done, (u64)card_index);
+}
+
void CEXIMemoryCard::SetCS(int cs)
{
// So that memory card won't be invalidated during flushing
@@ -201,11 +225,7 @@ void CEXIMemoryCard::SetCS(int cs)
//???
- status |= MC_STATUS_READY;
- status &= ~MC_STATUS_BUSY;
-
- m_bInterruptSet = 1;
- m_bDirty = true;
+ CmdDoneLater(5000);
}
break;
@@ -232,11 +252,7 @@ void CEXIMemoryCard::SetCS(int cs)
address = (address & ~0x1FF) | ((address+1) & 0x1FF);
}
- status |= MC_STATUS_READY;
- status &= ~MC_STATUS_BUSY;
-
- m_bInterruptSet = 1;
- m_bDirty = true;
+ CmdDoneLater(5000);
}
// Page written to memory card, not just to buffer - let's schedule a flush 0.5b cycles into the future (1 sec)
diff --git a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.h b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.h
index dfdc6349aa..33b94ca530 100644
--- a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.h
+++ b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.h
@@ -47,9 +47,18 @@ private:
// through the userdata parameter, so that it can then call Flush on the right card.
static void FlushCallback(u64 userdata, int cyclesLate);
+ // Scheduled when a command that required delayed end signaling is done.
+ static void CmdDoneCallback(u64 userdata, int cyclesLate);
+
// Flushes the memory card contents to disk.
void Flush(bool exiting = false);
+ // Signals that the command that was previously executed is now done.
+ void CmdDone();
+
+ // Variant of CmdDone which schedules an event later in the future to complete the command.
+ void CmdDoneLater(u64 cycles);
+
enum
{
cmdNintendoID = 0x00,
@@ -71,7 +80,7 @@ private:
std::string m_strFilename;
int card_index;
- int et_this_card;
+ int et_this_card, et_cmd_done;
//! memory card state
// STATE_TO_SAVE
diff --git a/Source/Core/Core/Src/HW/GCMemcard.cpp b/Source/Core/Core/Src/HW/GCMemcard.cpp
index dd15a32914..a2c9690b4e 100644
--- a/Source/Core/Core/Src/HW/GCMemcard.cpp
+++ b/Source/Core/Core/Src/HW/GCMemcard.cpp
@@ -432,7 +432,6 @@ std::string GCMemcard::DEntry_BIFlags(u8 index) const
flags.push_back((x & 0x80) ? '1' : '0');
x = x << 1;
}
- flags.push_back(0);
return flags;
}
@@ -469,7 +468,6 @@ std::string GCMemcard::DEntry_IconFmt(u8 index) const
format.push_back((x & 0x80) ? '1' : '0');
x = x << 1;
}
- format.push_back(0);
return format;
}
@@ -485,7 +483,6 @@ std::string GCMemcard::DEntry_AnimSpeed(u8 index) const
speed.push_back((x & 0x80) ? '1' : '0');
x = x << 1;
}
- speed.push_back(0);
return speed;
}
@@ -498,7 +495,6 @@ std::string GCMemcard::DEntry_Permissions(u8 index) const
permissionsString.push_back((Permissions & 16) ? 'x' : 'M');
permissionsString.push_back((Permissions & 8) ? 'x' : 'C');
permissionsString.push_back((Permissions & 4) ? 'P' : 'x');
- permissionsString.push_back(0);
return permissionsString;
}
diff --git a/Source/Core/Core/Src/HW/GPFifo.cpp b/Source/Core/Core/Src/HW/GPFifo.cpp
index 3af387792f..ab3058bd8d 100644
--- a/Source/Core/Core/Src/HW/GPFifo.cpp
+++ b/Source/Core/Core/Src/HW/GPFifo.cpp
@@ -96,15 +96,6 @@ void STACKALIGN CheckGatherPipe()
// move back the spill bytes
memmove(m_gatherPipe, m_gatherPipe + cnt, m_gatherPipeCount);
-
- // Profile where the FIFO writes are occurring.
- if (jit && (jit->js.fifoWriteAddresses.find(PC)) == (jit->js.fifoWriteAddresses.end()))
- {
- jit->js.fifoWriteAddresses.insert(PC);
-
- // Invalidate the JIT block so that it gets recompiled with the external exception check included.
- jit->GetBlockCache()->InvalidateICache(PC, 4);
- }
}
}
diff --git a/Source/Core/Core/Src/HW/Memmap.cpp b/Source/Core/Core/Src/HW/Memmap.cpp
index 88f6b2c358..6a6fb14212 100644
--- a/Source/Core/Core/Src/HW/Memmap.cpp
+++ b/Source/Core/Core/Src/HW/Memmap.cpp
@@ -419,132 +419,6 @@ u32 Read_Instruction(const u32 em_address)
return inst.hex;
}
-u32 Read_Opcode_JIT_Uncached(const u32 _Address)
-{
- u8* iCache;
- u32 addr;
- if (_Address & JIT_ICACHE_VMEM_BIT)
- {
- iCache = jit->GetBlockCache()->GetICacheVMEM();
- addr = _Address & JIT_ICACHE_MASK;
- }
- else if (_Address & JIT_ICACHE_EXRAM_BIT)
- {
- iCache = jit->GetBlockCache()->GetICacheEx();
- addr = _Address & JIT_ICACHEEX_MASK;
- }
- else
- {
- iCache = jit->GetBlockCache()->GetICache();
- addr = _Address & JIT_ICACHE_MASK;
- }
- u32 inst = *(u32*)(iCache + addr);
- if (inst == JIT_ICACHE_INVALID_WORD)
- {
- u32 cache_block_start = addr & ~0x1f;
- u32 mem_block_start = _Address & ~0x1f;
- u8 *pMem = Memory::GetPointer(mem_block_start);
- memcpy(iCache + cache_block_start, pMem, 32);
- inst = *(u32*)(iCache + addr);
- }
- inst = Common::swap32(inst);
-
- if ((inst & 0xfc000000) == 0)
- {
- inst = jit->GetBlockCache()->GetOriginalFirstOp(inst);
- }
-
- return inst;
-}
-
-u32 Read_Opcode_JIT(u32 _Address)
-{
-#ifdef FAST_ICACHE
- if (bMMU && !bFakeVMEM && (_Address & ADDR_MASK_MEM1))
- {
- _Address = Memory::TranslateAddress(_Address, FLAG_OPCODE);
- if (_Address == 0)
- {
- return 0;
- }
- }
- u32 inst = 0;
-
- // Bypass the icache for the external interrupt exception handler
- if ( (_Address & 0x0FFFFF00) == 0x00000500 )
- inst = Read_Opcode_JIT_Uncached(_Address);
- else
- inst = PowerPC::ppcState.iCache.ReadInstruction(_Address);
-#else
- u32 inst = Memory::ReadUnchecked_U32(_Address);
-#endif
- return inst;
-}
-
-// The following function is deprecated in favour of FAST_ICACHE
-u32 Read_Opcode_JIT_LC(const u32 _Address)
-{
-#ifdef JIT_UNLIMITED_ICACHE
- if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 &&
- (_Address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area
- (_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000)
- {
- PanicAlertT("iCacheJIT: Reading Opcode from %x. Please report.", _Address);
- ERROR_LOG(MEMMAP, "iCacheJIT: Reading Opcode from %x. Please report.", _Address);
- return 0;
- }
- u8* iCache;
- u32 addr;
- if (_Address & JIT_ICACHE_VMEM_BIT)
- {
- iCache = jit->GetBlockCache()->GetICacheVMEM();
- addr = _Address & JIT_ICACHE_MASK;
- }
- else if (_Address & JIT_ICACHE_EXRAM_BIT)
- {
- iCache = jit->GetBlockCache()->GetICacheEx();
- addr = _Address & JIT_ICACHEEX_MASK;
- }
- else
- {
- iCache = jit->GetBlockCache()->GetICache();
- addr = _Address & JIT_ICACHE_MASK;
- }
- u32 inst = *(u32*)(iCache + addr);
- if (inst == JIT_ICACHE_INVALID_WORD)
- inst = Memory::ReadUnchecked_U32(_Address);
- else
- inst = Common::swap32(inst);
-#else
- u32 inst = Memory::ReadUnchecked_U32(_Address);
-#endif
- if ((inst & 0xfc000000) == 0)
- {
- inst = jit->GetBlockCache()->GetOriginalFirstOp(inst);
- }
- return inst;
-}
-
-// WARNING! No checks!
-// We assume that _Address is cached
-void Write_Opcode_JIT(const u32 _Address, const u32 _Value)
-{
-#ifdef JIT_UNLIMITED_ICACHE
- if (_Address & JIT_ICACHE_VMEM_BIT)
- {
- *(u32*)(jit->GetBlockCache()->GetICacheVMEM() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value);
- }
- else if (_Address & JIT_ICACHE_EXRAM_BIT)
- {
- *(u32*)(jit->GetBlockCache()->GetICacheEx() + (_Address & JIT_ICACHEEX_MASK)) = Common::swap32(_Value);
- }
- else
- *(u32*)(jit->GetBlockCache()->GetICache() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value);
-#else
- Memory::WriteUnchecked_U32(_Value, _Address);
-#endif
-}
-
void WriteBigEData(const u8 *_pData, const u32 _Address, const u32 _iSize)
{
memcpy(GetPointer(_Address), _pData, _iSize);
diff --git a/Source/Core/Core/Src/HW/Memmap.h b/Source/Core/Core/Src/HW/Memmap.h
index 42ceb737ca..8662804185 100644
--- a/Source/Core/Core/Src/HW/Memmap.h
+++ b/Source/Core/Core/Src/HW/Memmap.h
@@ -119,11 +119,6 @@ inline u32 ReadFast32(const u32 _Address)
// used by interpreter to read instructions, uses iCache
u32 Read_Opcode(const u32 _Address);
-// used by JIT to read instructions
-u32 Read_Opcode_JIT(const u32 _Address);
-// used by JIT. uses iCacheJIT. Reads in the "Locked cache" mode
-u32 Read_Opcode_JIT_LC(const u32 _Address);
-void Write_Opcode_JIT(const u32 _Address, const u32 _Value);
// this is used by Debugger a lot.
// For now, just reads from memory!
u32 Read_Instruction(const u32 _Address);
diff --git a/Source/Core/Core/Src/HW/ProcessorInterface.cpp b/Source/Core/Core/Src/HW/ProcessorInterface.cpp
index 9e72cc2169..d4142efaae 100644
--- a/Source/Core/Core/Src/HW/ProcessorInterface.cpp
+++ b/Source/Core/Core/Src/HW/ProcessorInterface.cpp
@@ -99,7 +99,7 @@ void Init()
m_ResetCode = 0x80000000; // Cold reset
m_InterruptCause = INT_CAUSE_RST_BUTTON | INT_CAUSE_VI;
- toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", &ToggleResetButtonCallback);
+ toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", ToggleResetButtonCallback);
}
void Read16(u16& _uReturnValue, const u32 _iAddress)
diff --git a/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp b/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp
index 8c4c562b82..f6af63da53 100644
--- a/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp
+++ b/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp
@@ -69,6 +69,19 @@ int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
*(u32*)&_pBuffer[0] = SI_GC_CONTROLLER;
break;
+ case CMD_DIRECT:
+ {
+ INFO_LOG(SERIALINTERFACE, "PAD - Direct (Length: %d)", _iLength);
+ u32 high, low;
+ GetData(high, low);
+ for (int i = 0; i < (_iLength - 1) / 2; i++)
+ {
+ _pBuffer[0 + i] = (high >> (i * 8)) & 0xff;
+ _pBuffer[4 + i] = (low >> (i * 8)) & 0xff;
+ }
+ }
+ break;
+
case CMD_ORIGIN:
{
INFO_LOG(SERIALINTERFACE, "PAD - Get Origin");
@@ -96,7 +109,7 @@ int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
default:
{
ERROR_LOG(SERIALINTERFACE, "unknown SI command (0x%x)", command);
- PanicAlert("SI: Unknown command");
+ PanicAlert("SI: Unknown command (0x%x)", command);
}
break;
}
diff --git a/Source/Core/Core/Src/HW/SI_DeviceGCController.h b/Source/Core/Core/Src/HW/SI_DeviceGCController.h
index 058dde3582..b89f433331 100644
--- a/Source/Core/Core/Src/HW/SI_DeviceGCController.h
+++ b/Source/Core/Core/Src/HW/SI_DeviceGCController.h
@@ -31,6 +31,7 @@ private:
enum EBufferCommands
{
CMD_RESET = 0x00,
+ CMD_DIRECT = 0x40,
CMD_ORIGIN = 0x41,
CMD_RECALIBRATE = 0x42,
};
diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp
index a041a3b0ad..27ba4a62f9 100644
--- a/Source/Core/Core/Src/HW/SystemTimers.cpp
+++ b/Source/Core/Core/Src/HW/SystemTimers.cpp
@@ -74,6 +74,7 @@ IPC_HLE_PERIOD: For the Wiimote this is the call schedule:
#include "Thread.h"
#include "Timer.h"
#include "VideoBackendBase.h"
+#include "CommandProcessor.h"
namespace SystemTimers
@@ -109,7 +110,7 @@ enum
int et_Dec;
int et_VI;
int et_SI;
-int et_AI;
+int et_CP;
int et_AudioDMA;
int et_DSP;
int et_IPC_HLE;
@@ -118,15 +119,15 @@ int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default
// These are badly educated guesses
// Feel free to experiment. Set these in Init below.
int
- // This one should simply be determined by the increasing counter in AI.
- AI_PERIOD,
-
// These shouldn't be period controlled either, most likely.
DSP_PERIOD,
// This is a fixed value, don't change it
AUDIO_DMA_PERIOD,
+ // Regulates the speed of the Command Processor
+ CP_PERIOD,
+
// This is completely arbitrary. If we find that we need lower latency, we can just
// increase this number.
IPC_HLE_PERIOD;
@@ -143,12 +144,6 @@ u32 ConvertMillisecondsToTicks(u32 _Milliseconds)
return GetTicksPerSecond() / 1000 * _Milliseconds;
}
-void AICallback(u64 userdata, int cyclesLate)
-{
- AudioInterface::Update();
- CoreTiming::ScheduleEvent(AI_PERIOD - cyclesLate, et_AI);
-}
-
// DSP/CPU timeslicing.
void DSPCallback(u64 userdata, int cyclesLate)
{
@@ -187,6 +182,12 @@ void SICallback(u64 userdata, int cyclesLate)
CoreTiming::ScheduleEvent(SerialInterface::GetTicksToNextSIPoll() - cyclesLate, et_SI);
}
+void CPCallback(u64 userdata, int cyclesLate)
+{
+ CommandProcessor::Update();
+ CoreTiming::ScheduleEvent(CP_PERIOD - cyclesLate, et_CP);
+}
+
void DecrementerCallback(u64 userdata, int cyclesLate)
{
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
@@ -266,12 +267,12 @@ void Init()
if (DSP::GetDSPEmulator()->IsLLE())
DSP_PERIOD = 12000; // TO BE TWEAKED
- // This is the biggest question mark.
- AI_PERIOD = GetTicksPerSecond() / 80;
-
// System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA
AUDIO_DMA_PERIOD = CPU_CORE_CLOCK / (AudioInterface::GetAIDSampleRate() * 4 / 32);
+ // Emulated gekko <-> flipper bus speed ratio (cpu clock / flipper clock)
+ CP_PERIOD = GetTicksPerSecond() / 10000;
+
Common::Timer::IncreaseResolution();
// store and convert localtime at boot to timebase ticks
CoreTiming::SetFakeTBStartValue((u64)(CPU_CORE_CLOCK / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime());
@@ -281,19 +282,21 @@ void Init()
CoreTiming::SetFakeDecStartTicks(CoreTiming::GetTicks());
et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback);
- et_AI = CoreTiming::RegisterEvent("AICallback", AICallback);
et_VI = CoreTiming::RegisterEvent("VICallback", VICallback);
et_SI = CoreTiming::RegisterEvent("SICallback", SICallback);
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU)
+ et_CP = CoreTiming::RegisterEvent("CPCallback", CPCallback);
et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback);
et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback);
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
- CoreTiming::ScheduleEvent(AI_PERIOD, et_AI);
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI);
CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP);
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_SI);
CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA);
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU)
+ CoreTiming::ScheduleEvent(CP_PERIOD, et_CP);
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_PatchEngine);
diff --git a/Source/Core/Core/Src/HW/WII_IPC.cpp b/Source/Core/Core/Src/HW/WII_IPC.cpp
index 3651eef8ab..3d269d0fcd 100644
--- a/Source/Core/Core/Src/HW/WII_IPC.cpp
+++ b/Source/Core/Core/Src/HW/WII_IPC.cpp
@@ -28,6 +28,7 @@
#include "../IPC_HLE/WII_IPC_HLE.h"
#include "WII_IPC.h"
+#include "CoreTiming.h"
// This is the intercommunication between ARM and PPC. Currently only PPC actually uses it, because of the IOS HLE
@@ -104,6 +105,8 @@ static u32 arm_irq_masks;
static u32 sensorbar_power; // do we need to care about this?
+int updateInterrupts;
+
void DoState(PointerWrap &p)
{
p.Do(ppc_msg);
@@ -130,6 +133,8 @@ void Init()
sensorbar_power = 0;
ppc_irq_masks |= INT_CAUSE_IPC_BROADWAY;
+
+ updateInterrupts = CoreTiming::RegisterEvent("IPCInterrupt", UpdateInterrupts);
}
void Reset()
@@ -222,10 +227,10 @@ void Write32(const u32 _Value, const u32 _Address)
}
WII_IPC_HLE_Interface::Update();
- UpdateInterrupts();
+ CoreTiming::ScheduleEvent_Threadsafe(0, updateInterrupts, 0);
}
-void UpdateInterrupts()
+void UpdateInterrupts(u64 userdata, int cyclesLate)
{
if ((ctrl.Y1 & ctrl.IY1) || (ctrl.Y2 & ctrl.IY2))
{
@@ -247,7 +252,7 @@ void GenerateAck(u32 _Address)
ctrl.Y2 = 1;
INFO_LOG(WII_IPC, "GenerateAck: %08x | %08x [R:%i A:%i E:%i]",
ppc_msg,_Address, ctrl.Y1, ctrl.Y2, ctrl.X1);
- UpdateInterrupts();
+ CoreTiming::ScheduleEvent_Threadsafe(0, updateInterrupts, 0);
}
void GenerateReply(u32 _Address)
diff --git a/Source/Core/Core/Src/HW/WII_IPC.h b/Source/Core/Core/Src/HW/WII_IPC.h
index cb79a4f700..3d4e416c42 100644
--- a/Source/Core/Core/Src/HW/WII_IPC.h
+++ b/Source/Core/Core/Src/HW/WII_IPC.h
@@ -52,7 +52,7 @@ void DoState(PointerWrap &p);
void Read32(u32& _rReturnValue, const u32 _Address);
void Write32(const u32 _Value, const u32 _Address);
-void UpdateInterrupts();
+void UpdateInterrupts(u64 userdata = 0, int cyclesLate = 0);
void GenerateAck(u32 _Address);
void GenerateReply(u32 _Address);
diff --git a/Source/Core/Core/Src/HW/Wiimote.cpp b/Source/Core/Core/Src/HW/Wiimote.cpp
index 59fe8b7fa5..e45856f5f5 100644
--- a/Source/Core/Core/Src/HW/Wiimote.cpp
+++ b/Source/Core/Core/Src/HW/Wiimote.cpp
@@ -133,7 +133,7 @@ unsigned int GetAttached()
// input/output: ptr
// input: mode
//
-void DoState(unsigned char **ptr, int mode)
+void DoState(u8 **ptr, PointerWrap::Mode mode)
{
// TODO:
diff --git a/Source/Core/Core/Src/HW/Wiimote.h b/Source/Core/Core/Src/HW/Wiimote.h
index 5e0ab8d05e..6b758abb5a 100644
--- a/Source/Core/Core/Src/HW/Wiimote.h
+++ b/Source/Core/Core/Src/HW/Wiimote.h
@@ -3,6 +3,7 @@
#define _WIIMOTE_H_
#include "../../InputCommon/Src/InputConfig.h"
+#include "ChunkFile.h"
#define MAX_WIIMOTES 4
@@ -25,7 +26,7 @@ void Shutdown();
void Initialize(void* const hwnd);
unsigned int GetAttached();
-void DoState(unsigned char **ptr, int mode);
+void DoState(u8 **ptr, PointerWrap::Mode mode);
void EmuStateChange(EMUSTATE_CHANGE newState);
InputPlugin *GetPlugin();
@@ -38,17 +39,12 @@ void Update(int _number);
namespace WiimoteReal
{
-unsigned int Initialize();
+void Initialize();
void Shutdown();
void Refresh();
void LoadSettings();
-#ifdef _WIN32
-int PairUp(bool unpair = false);
-int UnPair();
-#endif
-
}
#endif
diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp
index 5c34fff9ac..5710fd4f25 100644
--- a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp
@@ -248,13 +248,12 @@ void Wiimote::RequestStatus(const wm_request_status* const rs)
{
using namespace WiimoteReal;
- std::lock_guard<std::mutex> lk(g_refresh_lock);
+ std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
if (g_wiimotes[m_index])
{
- wm_request_status rpt;
- rpt.rumble = 0;
- g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt));
+ wm_request_status rpt = {};
+ g_wiimotes[m_index]->QueueReport(WM_REQUEST_STATUS, &rpt, sizeof(rpt));
}
return;
@@ -298,7 +297,7 @@ void Wiimote::WriteData(const wm_write_data* const wd)
{
// writing the whole mii block each write :/
std::ofstream file;
- file.open((File::GetUserPath(D_WIIUSER_IDX) + "mii.bin").c_str(), std::ios::binary | std::ios::out);
+ OpenFStream(file, File::GetUserPath(D_WIIUSER_IDX) + "mii.bin", std::ios::binary | std::ios::out);
file.write((char*)m_eeprom + 0x0FCA, 0x02f0);
file.close();
}
diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp
index ba01239bf2..c743c80294 100644
--- a/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp
@@ -106,7 +106,7 @@ void Wiimote::SpeakerData(wm_speaker_data* sd)
File::Delete("rmtdump.wav");
File::Delete("rmtdump.bin");
atexit(stopdamnwav);
- ofile.open("rmtdump.bin", ofile.binary | ofile.out);
+ OpenFStream(ofile, "rmtdump.bin", ofile.binary | ofile.out);
wav.Start("rmtdump.wav", 6000/*Common::swap16(m_reg_speaker.sample_rate)*/);
}
wav.AddMonoSamples(samples, sd->length*2);
diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp
index 6fe6b81613..92018f7c21 100644
--- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp
@@ -704,7 +704,7 @@ void Wiimote::Update()
{
using namespace WiimoteReal;
- std::lock_guard<std::mutex> lk(g_refresh_lock);
+ std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
if (g_wiimotes[m_index])
{
Report rpt = g_wiimotes[m_index]->ProcessReadQueue();
diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h
index fd7c549e8d..9d1a2092a0 100644
--- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h
+++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h
@@ -201,6 +201,7 @@ struct wm_report
#define WM_LEDS 0x11
struct wm_leds {
u8 rumble : 1;
+ // real wii also sets bit 0x2 (unknown purpose)
u8 : 3;
u8 leds : 4;
};
@@ -208,8 +209,9 @@ struct wm_leds {
#define WM_REPORT_MODE 0x12
struct wm_report_mode {
u8 rumble : 1;
- u8 continuous : 1; // these 2 seem to be named wrong
+ // unsure what "all_the_time" actually is, the real wii does set it (bit 0x2)
u8 all_the_time : 1;
+ u8 continuous : 1;
u8 : 5;
u8 mode;
};
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp
index 49afee8ad1..3a017354eb 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp
@@ -21,9 +21,25 @@
namespace WiimoteReal
{
-int FindWiimotes(Wiimote **wm, int max_wiimotes)
+WiimoteScanner::WiimoteScanner()
{
- return 0;
+ return;
+}
+
+WiimoteScanner::~WiimoteScanner()
+{}
+
+void WiimoteScanner::Update()
+{}
+
+std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
+{
+ return std::vector<Wiimote*>();
+}
+
+bool WiimoteScanner::IsReady() const
+{
+ return false;
}
bool Wiimote::Connect()
@@ -31,22 +47,22 @@ bool Wiimote::Connect()
return 0;
}
-void Wiimote::RealDisconnect()
+void Wiimote::Disconnect()
{
return;
}
-bool Wiimote::IsOpen() const
+bool Wiimote::IsConnected() const
{
- return IsConnected();
+ return false;
}
-int Wiimote::IORead(unsigned char* buf)
+int Wiimote::IORead(u8* buf)
{
return 0;
}
-int Wiimote::IOWrite(unsigned char* buf, int len)
+int Wiimote::IOWrite(const u8* buf, int len)
{
return 0;
}
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp
index ec838d9313..87ddc5086b 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp
@@ -15,16 +15,6 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-#include <sys/time.h>
-#include <errno.h>
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
@@ -32,114 +22,116 @@
#include "Common.h"
#include "WiimoteReal.h"
-#include "Host.h"
namespace WiimoteReal
{
-// Find wiimotes.
-// Does not replace already found wiimotes even if they are disconnected.
-// wm is an array of max_wiimotes wiimotes
-// Returns the total number of found wiimotes.
-int FindWiimotes(Wiimote** wm, int max_wiimotes)
+WiimoteScanner::WiimoteScanner()
+ : m_run_thread()
+ , m_want_wiimotes()
+ , device_id(-1)
+ , device_sock(-1)
{
- int device_id;
- int device_sock;
- int found_devices;
- int found_wiimotes = 0;
- int i;
-
- // Count the number of already found wiimotes
- for (i = 0; i < MAX_WIIMOTES; ++i)
- {
- if (wm[i])
- found_wiimotes++;
- }
-
// Get the id of the first bluetooth device.
- if ((device_id = hci_get_route(NULL)) < 0)
+ device_id = hci_get_route(NULL);
+ if (device_id < 0)
{
NOTICE_LOG(WIIMOTE, "Bluetooth not found.");
- return found_wiimotes;
+ return;
}
// Create a socket to the device
- if ((device_sock = hci_open_dev(device_id)) < 0)
+ device_sock = hci_open_dev(device_id);
+ if (device_sock < 0)
{
ERROR_LOG(WIIMOTE, "Unable to open bluetooth.");
- return found_wiimotes;
+ return;
}
+}
- int try_num = 0;
- while ((try_num < 5) && (found_wiimotes < max_wiimotes))
+bool WiimoteScanner::IsReady() const
+{
+ return device_sock > 0;
+}
+
+WiimoteScanner::~WiimoteScanner()
+{
+ if (IsReady())
+ close(device_sock);
+}
+
+void WiimoteScanner::Update()
+{}
+
+std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
+{
+ std::vector<Wiimote*> found_wiimotes;
+
+ // supposedly 1.28 seconds
+ int const wait_len = 1;
+
+ int const max_infos = 255;
+ inquiry_info scan_infos[max_infos] = {};
+ auto* scan_infos_ptr = scan_infos;
+
+ // Scan for bluetooth devices
+ int const found_devices = hci_inquiry(device_id, wait_len, max_infos, NULL, &scan_infos_ptr, IREQ_CACHE_FLUSH);
+ if (found_devices < 0)
{
- inquiry_info scan_info_arr[128];
- inquiry_info* scan_info = scan_info_arr;
- memset(&scan_info_arr, 0, sizeof(scan_info_arr));
+ ERROR_LOG(WIIMOTE, "Error searching for bluetooth devices.");
+ return found_wiimotes;
+ }
+
+ DEBUG_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices);
- // Scan for bluetooth devices for approximately one second
- found_devices = hci_inquiry(device_id, 1, 128, NULL, &scan_info, IREQ_CACHE_FLUSH);
- if (found_devices < 0)
+ // Display discovered devices
+ for (int i = 0; i < found_devices; ++i)
+ {
+ ERROR_LOG(WIIMOTE, "found a device...");
+
+ // BT names are a maximum of 248 bytes apparently
+ char name[255] = {};
+ if (hci_read_remote_name(device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 0) < 0)
{
- ERROR_LOG(WIIMOTE, "Error searching for bluetooth devices.");
- return found_wiimotes;
+ ERROR_LOG(WIIMOTE, "name request failed");
+ continue;
}
- DEBUG_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices);
-
- // Display discovered devices
- for (i = 0; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i)
+ ERROR_LOG(WIIMOTE, "device name %s", name);
+ if (IsValidBluetoothName(name))
{
- char name[1000];
- memset(name, 0, sizeof(name));
- ERROR_LOG(WIIMOTE, "found a device...");
- if (hci_read_remote_name(device_sock, &scan_info[i].bdaddr, sizeof(name), name, 0) < 0) {
- ERROR_LOG(WIIMOTE, "name request failed");
- continue;
- }
- ERROR_LOG(WIIMOTE, "device name %s", name);
- if (IsValidBluetoothName(name))
+ bool new_wiimote = true;
+
+ // TODO: do this
+
+ // Determine if this wiimote has already been found.
+ //for (int j = 0; j < MAX_WIIMOTES && new_wiimote; ++j)
+ //{
+ // if (wm[j] && bacmp(&scan_infos[i].bdaddr,&wm[j]->bdaddr) == 0)
+ // new_wiimote = false;
+ //}
+
+ if (new_wiimote)
{
- bool new_wiimote = true;
- // Determine if this wiimote has already been found.
- for (int j = 0; j < MAX_WIIMOTES && new_wiimote; ++j)
- {
- if (wm[j] && bacmp(&scan_info[i].bdaddr,&wm[j]->bdaddr) == 0)
- new_wiimote = false;
- }
-
- if (new_wiimote)
- {
- // Find an unused slot
- unsigned int k = 0;
- for (; k < MAX_WIIMOTES && !(WIIMOTE_SRC_REAL & g_wiimote_sources[k] && !wm[k]); ++k);
- wm[k] = new Wiimote(k);
-
- // Found a new device
- char bdaddr_str[18];
- ba2str(&scan_info[i].bdaddr, bdaddr_str);
-
- NOTICE_LOG(WIIMOTE, "Found wiimote %i, (%s).",
- wm[k]->index + 1, bdaddr_str);
-
- wm[k]->bdaddr = scan_info[i].bdaddr;
- ++found_wiimotes;
- }
+ // Found a new device
+ char bdaddr_str[18] = {};
+ ba2str(&scan_infos[i].bdaddr, bdaddr_str);
+
+ auto* const wm = new Wiimote;
+ wm->bdaddr = scan_infos[i].bdaddr;
+ found_wiimotes.push_back(wm);
+
+ NOTICE_LOG(WIIMOTE, "Found wiimote (%s).", bdaddr_str);
}
}
- try_num++;
}
- close(device_sock);
return found_wiimotes;
}
// Connect to a wiimote with a known address.
bool Wiimote::Connect()
{
- if (IsConnected())
- return false;
-
sockaddr_l2 addr;
addr.l2_family = AF_BLUETOOTH;
addr.l2_bdaddr = bdaddr;
@@ -148,7 +140,7 @@ bool Wiimote::Connect()
// Output channel
addr.l2_psm = htobs(WM_OUTPUT_CHANNEL);
if ((cmd_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 ||
- connect(cmd_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
+ connect(cmd_sock, (sockaddr*)&addr, sizeof(addr)) < 0)
{
DEBUG_LOG(WIIMOTE, "Unable to open output socket to wiimote.");
close(cmd_sock);
@@ -159,7 +151,7 @@ bool Wiimote::Connect()
// Input channel
addr.l2_psm = htobs(WM_INPUT_CHANNEL);
if ((int_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 ||
- connect(int_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
+ connect(int_sock, (sockaddr*)&addr, sizeof(addr)) < 0)
{
DEBUG_LOG(WIIMOTE, "Unable to open input socket from wiimote.");
close(int_sock);
@@ -168,57 +160,27 @@ bool Wiimote::Connect()
return false;
}
- NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", index + 1);
-
- m_connected = true;
-
- // Do the handshake
- Handshake();
-
- // Set LEDs
- SetLEDs(WIIMOTE_LED_1 << index);
-
- m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this);
-
return true;
}
-// Disconnect a wiimote.
-void Wiimote::RealDisconnect()
-{
- if (!IsConnected())
- return;
-
- NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i.", index + 1);
-
- m_connected = false;
-
- if (m_wiimote_thread.joinable())
- m_wiimote_thread.join();
-
- Close();
-}
-
-void Wiimote::Close()
+void Wiimote::Disconnect()
{
- if (IsOpen())
- {
- Host_ConnectWiimote(index, false);
+ close(cmd_sock);
+ close(int_sock);
- close(cmd_sock);
- close(int_sock);
-
- cmd_sock = -1;
- int_sock = -1;
- }
+ cmd_sock = -1;
+ int_sock = -1;
}
-bool Wiimote::IsOpen() const
+bool Wiimote::IsConnected() const
{
- return IsConnected() && cmd_sock != -1 && int_sock != -1;
+ return cmd_sock != -1;// && int_sock != -1;
}
-int Wiimote::IORead(unsigned char *buf)
+// positive = read packet
+// negative = didn't read packet
+// zero = error
+int Wiimote::IORead(u8* buf)
{
// Block select for 1/2000th of a second
timeval tv;
@@ -232,11 +194,11 @@ int Wiimote::IORead(unsigned char *buf)
if (select(int_sock + 1, &fds, NULL, NULL, &tv) == -1)
{
ERROR_LOG(WIIMOTE, "Unable to select wiimote %i input socket.", index + 1);
- return 0;
+ return -1;
}
if (!FD_ISSET(int_sock, &fds))
- return 0;
+ return -1;
// Read the pending message into the buffer
int r = read(int_sock, buf, MAX_PAYLOAD);
@@ -250,21 +212,15 @@ int Wiimote::IORead(unsigned char *buf)
// This can happen if the bluetooth dongle is disconnected
ERROR_LOG(WIIMOTE, "Bluetooth appears to be disconnected. "
"Wiimote %i will be disconnected.", index + 1);
- Close();
}
- return 0;
- }
- else if (!r)
- {
- // Disconnect
- Close();
+ r = 0;
}
return r;
}
-int Wiimote::IOWrite(unsigned char* buf, int len)
+int Wiimote::IOWrite(u8 const* buf, int len)
{
return write(int_sock, buf, len);
}
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
index 529a48d15d..b80bbc2315 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
@@ -17,7 +17,10 @@
#include <stdio.h>
#include <stdlib.h>
-#include <regex>
+#include <algorithm>
+#include <unordered_map>
+#include <ctime>
+#include <unordered_set>
#include <windows.h>
#include <dbt.h>
@@ -25,6 +28,7 @@
#include "Common.h"
#include "WiimoteReal.h"
+#include "StringUtil.h"
// Used for pair up
#undef NTDDI_VERSION
@@ -32,6 +36,9 @@
#include <bthdef.h>
#include <BluetoothAPIs.h>
+//#define AUTHENTICATE_WIIMOTES
+#define SHARE_WRITE_WIIMOTES
+
typedef struct _HIDD_ATTRIBUTES
{
ULONG Size;
@@ -43,6 +50,7 @@ typedef struct _HIDD_ATTRIBUTES
typedef VOID (__stdcall *PHidD_GetHidGuid)(LPGUID);
typedef BOOLEAN (__stdcall *PHidD_GetAttributes)(HANDLE, PHIDD_ATTRIBUTES);
typedef BOOLEAN (__stdcall *PHidD_SetOutputReport)(HANDLE, PVOID, ULONG);
+typedef BOOLEAN (__stdcall *PHidD_GetProductString)(HANDLE, PVOID, ULONG);
typedef BOOL (__stdcall *PBth_BluetoothFindDeviceClose)(HBLUETOOTH_DEVICE_FIND);
typedef HBLUETOOTH_DEVICE_FIND (__stdcall *PBth_BluetoothFindFirstDevice)(const BLUETOOTH_DEVICE_SEARCH_PARAMS*, BLUETOOTH_DEVICE_INFO*);
@@ -53,10 +61,13 @@ typedef BOOL (__stdcall *PBth_BluetoothFindRadioClose)(HBLUETOOTH_RADIO_FIND);
typedef DWORD (__stdcall *PBth_BluetoothGetRadioInfo)(HANDLE, PBLUETOOTH_RADIO_INFO);
typedef DWORD (__stdcall *PBth_BluetoothRemoveDevice)(const BLUETOOTH_ADDRESS*);
typedef DWORD (__stdcall *PBth_BluetoothSetServiceState)(HANDLE, const BLUETOOTH_DEVICE_INFO*, const GUID*, DWORD);
+typedef DWORD (__stdcall *PBth_BluetoothAuthenticateDevice)(HWND, HANDLE, BLUETOOTH_DEVICE_INFO*, PWCHAR, ULONG);
+typedef DWORD (__stdcall *PBth_BluetoothEnumerateInstalledServices)(HANDLE, BLUETOOTH_DEVICE_INFO*, DWORD*, GUID*);
PHidD_GetHidGuid HidD_GetHidGuid = NULL;
PHidD_GetAttributes HidD_GetAttributes = NULL;
PHidD_SetOutputReport HidD_SetOutputReport = NULL;
+PHidD_GetProductString HidD_GetProductString = NULL;
PBth_BluetoothFindDeviceClose Bth_BluetoothFindDeviceClose = NULL;
PBth_BluetoothFindFirstDevice Bth_BluetoothFindFirstDevice = NULL;
@@ -67,12 +78,21 @@ PBth_BluetoothFindRadioClose Bth_BluetoothFindRadioClose = NULL;
PBth_BluetoothGetRadioInfo Bth_BluetoothGetRadioInfo = NULL;
PBth_BluetoothRemoveDevice Bth_BluetoothRemoveDevice = NULL;
PBth_BluetoothSetServiceState Bth_BluetoothSetServiceState = NULL;
+PBth_BluetoothAuthenticateDevice Bth_BluetoothAuthenticateDevice = NULL;
+PBth_BluetoothEnumerateInstalledServices Bth_BluetoothEnumerateInstalledServices = NULL;
HINSTANCE hid_lib = NULL;
HINSTANCE bthprops_lib = NULL;
static int initialized = 0;
+std::unordered_map<BTH_ADDR, std::time_t> g_connect_times;
+
+#ifdef SHARE_WRITE_WIIMOTES
+std::unordered_set<std::basic_string<TCHAR>> g_connected_wiimotes;
+std::mutex g_connected_wiimotes_lock;
+#endif
+
inline void init_lib()
{
if (!initialized)
@@ -87,7 +107,9 @@ inline void init_lib()
HidD_GetHidGuid = (PHidD_GetHidGuid)GetProcAddress(hid_lib, "HidD_GetHidGuid");
HidD_GetAttributes = (PHidD_GetAttributes)GetProcAddress(hid_lib, "HidD_GetAttributes");
HidD_SetOutputReport = (PHidD_SetOutputReport)GetProcAddress(hid_lib, "HidD_SetOutputReport");
- if (!HidD_GetHidGuid || !HidD_GetAttributes || !HidD_SetOutputReport)
+ HidD_GetProductString = (PHidD_GetProductString)GetProcAddress(hid_lib, "HidD_GetProductString");
+ if (!HidD_GetHidGuid || !HidD_GetAttributes ||
+ !HidD_SetOutputReport || !HidD_GetProductString)
{
PanicAlertT("Failed to load hid.dll");
exit(EXIT_FAILURE);
@@ -109,12 +131,15 @@ inline void init_lib()
Bth_BluetoothGetRadioInfo = (PBth_BluetoothGetRadioInfo)GetProcAddress(bthprops_lib, "BluetoothGetRadioInfo");
Bth_BluetoothRemoveDevice = (PBth_BluetoothRemoveDevice)GetProcAddress(bthprops_lib, "BluetoothRemoveDevice");
Bth_BluetoothSetServiceState = (PBth_BluetoothSetServiceState)GetProcAddress(bthprops_lib, "BluetoothSetServiceState");
+ Bth_BluetoothAuthenticateDevice = (PBth_BluetoothAuthenticateDevice)GetProcAddress(bthprops_lib, "BluetoothAuthenticateDevice");
+ Bth_BluetoothEnumerateInstalledServices = (PBth_BluetoothEnumerateInstalledServices)GetProcAddress(bthprops_lib, "BluetoothEnumerateInstalledServices");
if (!Bth_BluetoothFindDeviceClose || !Bth_BluetoothFindFirstDevice ||
!Bth_BluetoothFindFirstRadio || !Bth_BluetoothFindNextDevice ||
!Bth_BluetoothFindNextRadio || !Bth_BluetoothFindRadioClose ||
!Bth_BluetoothGetRadioInfo || !Bth_BluetoothRemoveDevice ||
- !Bth_BluetoothSetServiceState)
+ !Bth_BluetoothSetServiceState || !Bth_BluetoothAuthenticateDevice ||
+ !Bth_BluetoothEnumerateInstalledServices)
{
PanicAlertT("Failed to load bthprops.cpl");
exit(EXIT_FAILURE);
@@ -127,312 +152,369 @@ inline void init_lib()
namespace WiimoteReal
{
+template <typename T>
+void ProcessWiimotes(bool new_scan, T& callback);
+
+bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT&);
+void RemoveWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&);
+bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&);
+
+WiimoteScanner::WiimoteScanner()
+ : m_run_thread()
+ , m_want_wiimotes()
+{
+ init_lib();
+}
+
+WiimoteScanner::~WiimoteScanner()
+{
+ // TODO: what do we want here?
+#if 0
+ ProcessWiimotes(false, [](HANDLE, BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
+ {
+ RemoveWiimote(btdi);
+ });
+#endif
+}
+
+void WiimoteScanner::Update()
+{
+ bool forgot_some = false;
+
+ ProcessWiimotes(false, [&](HANDLE, BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
+ {
+ forgot_some |= ForgetWiimote(btdi);
+ });
+
+ // Some hacks that allows disconnects to be detected before connections are handled
+ // workaround for wiimote 1 moving to slot 2 on temporary disconnect
+ if (forgot_some)
+ SLEEP(100);
+}
+
// Find and connect wiimotes.
// Does not replace already found wiimotes even if they are disconnected.
// wm is an array of max_wiimotes wiimotes
// Returns the total number of found and connected wiimotes.
-int FindWiimotes(Wiimote** wm, int max_wiimotes)
+std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
{
- GUID device_id;
- HANDLE dev;
- HDEVINFO device_info;
- int found_wiimotes = 0;
- DWORD len;
- SP_DEVICE_INTERFACE_DATA device_data;
- PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL;
- HIDD_ATTRIBUTES attr;
-
- init_lib();
-
- // Count the number of already found wiimotes
- for (int i = 0; i < MAX_WIIMOTES; ++i)
+ ProcessWiimotes(true, [](HANDLE hRadio, const BLUETOOTH_RADIO_INFO& rinfo, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{
- if (wm[i])
- found_wiimotes++;
- }
-
- device_data.cbSize = sizeof(device_data);
+ ForgetWiimote(btdi);
+ AttachWiimote(hRadio, rinfo, btdi);
+ });
// Get the device id
+ GUID device_id;
HidD_GetHidGuid(&device_id);
// Get all hid devices connected
- device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
+ HDEVINFO const device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
- for (int index = 0; found_wiimotes < max_wiimotes; ++index)
- {
- if (detail_data)
- {
- free(detail_data);
- detail_data = NULL;
- }
+ std::vector<Wiimote*> wiimotes;
- // Query the next hid device info
- if (!SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data))
- break;
+ SP_DEVICE_INTERFACE_DATA device_data;
+ device_data.cbSize = sizeof(device_data);
+ PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL;
+ for (int index = 0; SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data); ++index)
+ {
// Get the size of the data block required
+ DWORD len;
SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL);
detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(len);
detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
// Query the data for this device
- if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL))
- continue;
-
- // Determine if this wiimote has already been found.
- bool found = false;
- for(int i = 0; i < MAX_WIIMOTES; i++)
+ if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL))
{
- if(wm[i] && (wm[i]->devicepath == detail_data->DevicePath))
- {
- found = true;
- break;
- }
+ auto const wm = new Wiimote;
+ wm->devicepath = detail_data->DevicePath;
+ wiimotes.push_back(wm);
}
- if (found)
- continue;
-
- // Open new device
- dev = CreateFile(detail_data->DevicePath,
- (GENERIC_READ | GENERIC_WRITE),
- (FILE_SHARE_READ | FILE_SHARE_WRITE),
- NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- if (dev == INVALID_HANDLE_VALUE)
- continue;
-
- // Get device attributes
- attr.Size = sizeof(attr);
- HidD_GetAttributes(dev, &attr);
-
- // Find an unused slot
- unsigned int k = 0;
- for (; k < MAX_WIIMOTES && !(WIIMOTE_SRC_REAL & g_wiimote_sources[k] && !wm[k]); ++k);
- wm[k] = new Wiimote(k);
- wm[k]->dev_handle = dev;
- wm[k]->devicepath = detail_data->DevicePath;
-
- if (!wm[k]->Connect())
- {
- ERROR_LOG(WIIMOTE, "Unable to connect to wiimote %i.", wm[k]->index + 1);
- delete wm[k];
- wm[k] = NULL;
- CloseHandle(dev);
- }
- else
- {
- ++found_wiimotes;
- }
- }
- if (detail_data)
free(detail_data);
+ }
SetupDiDestroyDeviceInfoList(device_info);
- return found_wiimotes;
+ // Don't mind me, just a random sleep to fix stuff on Windows
+ //if (!wiimotes.empty())
+ // SLEEP(2000);
+
+ return wiimotes;
+}
+
+bool WiimoteScanner::IsReady() const
+{
+ // TODO: don't search for a radio each time
+
+ BLUETOOTH_FIND_RADIO_PARAMS radioParam;
+ radioParam.dwSize = sizeof(radioParam);
+
+ HANDLE hRadio;
+ HBLUETOOTH_RADIO_FIND hFindRadio = Bth_BluetoothFindFirstRadio(&radioParam, &hRadio);
+
+ if (NULL != hFindRadio)
+ {
+ Bth_BluetoothFindRadioClose(hFindRadio);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
// Connect to a wiimote with a known device path.
bool Wiimote::Connect()
{
- if (IsConnected()) return false;
+ if (IsConnected())
+ return false;
- if (!dev_handle)
+#ifdef SHARE_WRITE_WIIMOTES
+ std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
+ if (g_connected_wiimotes.count(devicepath) != 0)
+ return false;
+
+ auto const open_flags = FILE_SHARE_READ | FILE_SHARE_WRITE;
+#else
+ // Having no FILE_SHARE_WRITE disallows us from connecting to the same wiimote twice.
+ // (And disallows using wiimotes in use by other programs)
+ // This is what "WiiYourself" does.
+ // Apparently this doesn't work for everyone. It might be their fault.
+ auto const open_flags = FILE_SHARE_READ;
+#endif
+
+ dev_handle = CreateFile(devicepath.c_str(),
+ GENERIC_READ | GENERIC_WRITE, open_flags,
+ NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+
+ if (dev_handle == INVALID_HANDLE_VALUE)
{
- dev_handle = CreateFile(devicepath.c_str(),
- (GENERIC_READ | GENERIC_WRITE),
- (FILE_SHARE_READ | FILE_SHARE_WRITE),
- NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- if (dev_handle == INVALID_HANDLE_VALUE)
- return false;
+ dev_handle = 0;
+ return false;
}
- hid_overlap.hEvent = CreateEvent(NULL, 1, 1, _T(""));
- hid_overlap.Offset = 0;
- hid_overlap.OffsetHigh = 0;
+#if 0
+ TCHAR name[128] = {};
+ HidD_GetProductString(dev_handle, name, 128);
+
+ //ERROR_LOG(WIIMOTE, "product string: %s", TStrToUTF8(name).c_str());
- m_connected = true;
+ if (!IsValidBluetoothName(TStrToUTF8(name)))
+ {
+ CloseHandle(dev_handle);
+ dev_handle = 0;
+ return false;
+ }
+#endif
- // Try a handshake to see if the device is actually connected
- if (!Handshake())
+#if 0
+ HIDD_ATTRIBUTES attr;
+ attr.Size = sizeof(attr);
+ if (!HidD_GetAttributes(dev_handle, &attr))
{
- m_connected = false;
+ CloseHandle(dev_handle);
+ dev_handle = 0;
return false;
}
+#endif
- // Set LEDs
- SetLEDs(WIIMOTE_LED_1 << index);
+ hid_overlap_read = OVERLAPPED();
+ hid_overlap_read.hEvent = CreateEvent(NULL, true, false, NULL);
- m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this);
+ hid_overlap_write = OVERLAPPED();
+ hid_overlap_write.hEvent = CreateEvent(NULL, true, false, NULL);
+ // TODO: thread isn't started here now, do this elsewhere
// This isn't as drastic as it sounds, since the process in which the threads
// reside is normal priority. Needed for keeping audio reports at a decent rate
+/*
if (!SetThreadPriority(m_wiimote_thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL))
{
ERROR_LOG(WIIMOTE, "Failed to set wiimote thread priority");
}
-
- NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", index + 1);
+*/
+#ifdef SHARE_WRITE_WIIMOTES
+ g_connected_wiimotes.insert(devicepath);
+#endif
return true;
}
-void Wiimote::RealDisconnect()
+void Wiimote::Disconnect()
{
if (!IsConnected())
return;
- m_connected = false;
-
- if (m_wiimote_thread.joinable())
- m_wiimote_thread.join();
-
CloseHandle(dev_handle);
dev_handle = 0;
- ResetEvent(&hid_overlap);
+ CloseHandle(hid_overlap_read.hEvent);
+ CloseHandle(hid_overlap_write.hEvent);
+
+#ifdef SHARE_WRITE_WIIMOTES
+ std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
+ g_connected_wiimotes.erase(devicepath);
+#endif
}
-bool Wiimote::IsOpen() const
+bool Wiimote::IsConnected() const
{
- return IsConnected();
+ return dev_handle != 0;
}
-int Wiimote::IORead(unsigned char* buf)
+// positive = read packet
+// negative = didn't read packet
+// zero = error
+int Wiimote::IORead(u8* buf)
{
- DWORD b, r;
-
- init_lib();
-
- if (!IsConnected())
- return 0;
-
+ // used below for a warning
*buf = 0;
- if (!ReadFile(dev_handle, buf, MAX_PAYLOAD, &b, &hid_overlap))
+
+ DWORD bytes;
+ ResetEvent(hid_overlap_read.hEvent);
+ if (!ReadFile(dev_handle, buf, MAX_PAYLOAD - 1, &bytes, &hid_overlap_read))
{
- // Partial read
- b = GetLastError();
+ auto const err = GetLastError();
- if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED))
+ if (ERROR_IO_PENDING == err)
{
- // Remote disconnect
- RealDisconnect();
- return 0;
- }
+ auto const r = WaitForSingleObject(hid_overlap_read.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
+ if (WAIT_TIMEOUT == r)
+ {
+ // Timeout - cancel and continue
+ if (*buf)
+ WARN_LOG(WIIMOTE, "Packet ignored. This may indicate a problem (timeout is %i ms).",
+ WIIMOTE_DEFAULT_TIMEOUT);
- r = WaitForSingleObject(hid_overlap.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
- if (r == WAIT_TIMEOUT)
+ CancelIo(dev_handle);
+ bytes = -1;
+ }
+ else if (WAIT_FAILED == r)
+ {
+ WARN_LOG(WIIMOTE, "A wait error occured on reading from wiimote %i.", index + 1);
+ bytes = 0;
+ }
+ else if (WAIT_OBJECT_0 == r)
+ {
+ if (!GetOverlappedResult(dev_handle, &hid_overlap_read, &bytes, TRUE))
+ {
+ WARN_LOG(WIIMOTE, "GetOverlappedResult failed on wiimote %i.", index + 1);
+ bytes = 0;
+ }
+ }
+ else
+ {
+ bytes = 0;
+ }
+ }
+ else if (ERROR_HANDLE_EOF == err)
{
- // Timeout - cancel and continue
-
- if (*buf)
- WARN_LOG(WIIMOTE, "Packet ignored. This may indicate a problem (timeout is %i ms).",
- WIIMOTE_DEFAULT_TIMEOUT);
-
- CancelIo(dev_handle);
- ResetEvent(hid_overlap.hEvent);
- return 0;
+ // Remote disconnect
+ bytes = 0;
}
- else if (r == WAIT_FAILED)
+ else if (ERROR_DEVICE_NOT_CONNECTED == err)
{
- WARN_LOG(WIIMOTE, "A wait error occured on reading from wiimote %i.", index + 1);
- return 0;
+ // Remote disconnect
+ bytes = 0;
}
-
- if (!GetOverlappedResult(dev_handle, &hid_overlap, &b, 0))
+ else
{
- return 0;
+ bytes = 0;
}
}
- // This needs to be done even if ReadFile fails, essential during init
- // Move the data over one, so we can add back in data report indicator byte (here, 0xa1)
- memmove(buf + 1, buf, MAX_PAYLOAD - 1);
- buf[0] = 0xa1;
+ if (bytes > 0)
+ {
+ // Move the data over one, so we can add back in data report indicator byte (here, 0xa1)
+ std::copy_n(buf, MAX_PAYLOAD - 1, buf + 1);
+ buf[0] = 0xa1;
+
+ // TODO: is this really needed?
+ bytes = MAX_PAYLOAD;
+ }
- ResetEvent(hid_overlap.hEvent);
- return MAX_PAYLOAD; // XXX
+ return bytes;
}
-int Wiimote::IOWrite(unsigned char* buf, int len)
+int Wiimote::IOWrite(const u8* buf, int len)
{
- DWORD bytes, dw;
- int i;
-
- init_lib();
-
- if (!IsConnected())
- return 0;
-
switch (stack)
{
- case MSBT_STACK_UNKNOWN:
- {
- // Try to auto-detect the stack type
- if (i = WriteFile(dev_handle, buf + 1, 22, &bytes, &hid_overlap))
- {
- // Bluesoleil will always return 1 here, even if it's not connected
- stack = MSBT_STACK_BLUESOLEIL;
- return i;
- }
-
- if (i = HidD_SetOutputReport(dev_handle, buf + 1, len - 1))
- {
- stack = MSBT_STACK_MS;
- return i;
- }
+ case MSBT_STACK_UNKNOWN:
+ {
+ // Try to auto-detect the stack type
+ stack = MSBT_STACK_BLUESOLEIL;
+ if (IOWrite(buf, len))
+ return 1;
- dw = GetLastError();
- // Checking for 121 = timeout on semaphore/device off/disconnected to
- // avoid trouble with other stacks toshiba/widcomm
- if (dw == 121)
- {
- NOTICE_LOG(WIIMOTE, "IOWrite[MSBT_STACK_UNKNOWN]: Timeout");
- RealDisconnect();
- }
- else ERROR_LOG(WIIMOTE,
- "IOWrite[MSBT_STACK_UNKNOWN]: ERROR: %08x", dw);
- return 0;
- }
+ stack = MSBT_STACK_MS;
+ if (IOWrite(buf, len))
+ return 1;
- case MSBT_STACK_MS:
- i = HidD_SetOutputReport(dev_handle, buf + 1, len - 1);
- dw = GetLastError();
+ stack = MSBT_STACK_UNKNOWN;
+ break;
+ }
+ case MSBT_STACK_MS:
+ {
+ auto result = HidD_SetOutputReport(dev_handle, const_cast<u8*>(buf) + 1, len - 1);
+ //FlushFileBuffers(dev_handle);
- if (dw == 121)
+ if (!result)
+ {
+ auto err = GetLastError();
+ if (err == 121)
{
// Semaphore timeout
NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to wiimote");
- RealDisconnect();
- return 0;
}
- return i;
+ else
+ {
+ WARN_LOG(WIIMOTE, "IOWrite[MSBT_STACK_MS]: ERROR: %08x", err);
+ }
+ }
- case MSBT_STACK_BLUESOLEIL:
- return WriteFile(dev_handle, buf + 1, 22, &bytes, &hid_overlap);
+ return result;
+ break;
}
+ case MSBT_STACK_BLUESOLEIL:
+ {
+ u8 big_buf[MAX_PAYLOAD];
+ if (len < MAX_PAYLOAD)
+ {
+ std::copy(buf, buf + len, big_buf);
+ std::fill(big_buf + len, big_buf + MAX_PAYLOAD, 0);
+ buf = big_buf;
+ }
- return 0;
-}
+ ResetEvent(hid_overlap_write.hEvent);
+ DWORD bytes = 0;
+ if (WriteFile(dev_handle, buf + 1, MAX_PAYLOAD - 1, &bytes, &hid_overlap_write))
+ {
+ // WriteFile always returns true with bluesoleil.
+ return 1;
+ }
+ else
+ {
+ auto const err = GetLastError();
+ if (ERROR_IO_PENDING == err)
+ {
+ CancelIo(dev_handle);
+ }
+ }
+ break;
+ }
+ }
-int UnPair()
-{
- // TODO:
return 0;
}
-// WiiMote Pair-Up, function will return amount of either new paired or unpaired devices
-// negative number on failure
-int PairUp(bool unpair)
+// invokes callback for each found wiimote bluetooth device
+template <typename T>
+void ProcessWiimotes(bool new_scan, T& callback)
{
- init_lib();
-
- // match strings like "Nintendo RVL-WBC-01", "Nintendo RVL-CNT-01", "Nintendo RVL-CNT-01-TR"
- const std::wregex wiimote_device_name(L"Nintendo RVL-\\w{3}-\\d{2}(-\\w{2})?");
-
- int nPaired = 0;
-
BLUETOOTH_DEVICE_SEARCH_PARAMS srch;
srch.dwSize = sizeof(srch);
srch.fReturnAuthenticated = true;
@@ -441,84 +523,51 @@ int PairUp(bool unpair)
// fConnected BT Devices
srch.fReturnConnected = true;
srch.fReturnUnknown = true;
- srch.fIssueInquiry = true;
- srch.cTimeoutMultiplier = 2; // == (2 * 1.28) seconds
+ srch.fIssueInquiry = new_scan;
+ // multiple of 1.28 seconds
+ srch.cTimeoutMultiplier = 2;
BLUETOOTH_FIND_RADIO_PARAMS radioParam;
radioParam.dwSize = sizeof(radioParam);
HANDLE hRadio;
+
+ // TODO: save radio(s) in the WiimoteScanner constructor?
// Enumerate BT radios
HBLUETOOTH_RADIO_FIND hFindRadio = Bth_BluetoothFindFirstRadio(&radioParam, &hRadio);
-
- if (NULL == hFindRadio)
- return -1;
-
while (hFindRadio)
{
BLUETOOTH_RADIO_INFO radioInfo;
radioInfo.dwSize = sizeof(radioInfo);
- // TODO: check for SUCCEEDED()
- Bth_BluetoothGetRadioInfo(hRadio, &radioInfo);
-
- srch.hRadio = hRadio;
-
- BLUETOOTH_DEVICE_INFO btdi;
- btdi.dwSize = sizeof(btdi);
-
- // Enumerate BT devices
- HBLUETOOTH_DEVICE_FIND hFindDevice = Bth_BluetoothFindFirstDevice(&srch, &btdi);
- while (hFindDevice)
+ auto const rinfo_result = Bth_BluetoothGetRadioInfo(hRadio, &radioInfo);
+ if (ERROR_SUCCESS == rinfo_result)
{
- // btdi.szName is sometimes missings it's content - it's a bt feature..
- DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ",
- btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered);
+ srch.hRadio = hRadio;
+
+ BLUETOOTH_DEVICE_INFO btdi;
+ btdi.dwSize = sizeof(btdi);
- if (std::regex_match(btdi.szName, wiimote_device_name))
+ // Enumerate BT devices
+ HBLUETOOTH_DEVICE_FIND hFindDevice = Bth_BluetoothFindFirstDevice(&srch, &btdi);
+ while (hFindDevice)
{
- if (unpair)
+ // btdi.szName is sometimes missings it's content - it's a bt feature..
+ DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ",
+ btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered);
+
+ if (IsValidBluetoothName(UTF16ToUTF8(btdi.szName)))
{
- if (SUCCEEDED(Bth_BluetoothRemoveDevice(&btdi.Address)))
- {
- NOTICE_LOG(WIIMOTE,
- "Pair-Up: Automatically removed BT Device on shutdown: %08x",
- GetLastError());
- ++nPaired;
- }
+ callback(hRadio, radioInfo, btdi);
}
- else
+
+ if (false == Bth_BluetoothFindNextDevice(hFindDevice, &btdi))
{
- if (false == btdi.fConnected)
- {
- // TODO: improve the read of the BT driver, esp. when batteries
- // of the wiimote are removed while being fConnected
- if (btdi.fRemembered)
- {
- // Make Windows forget old expired pairing. We can pretty
- // much ignore the return value here. It either worked
- // (ERROR_SUCCESS), or the device did not exist
- // (ERROR_NOT_FOUND). In both cases, there is nothing left.
- Bth_BluetoothRemoveDevice(&btdi.Address);
- }
-
- // Activate service
- const DWORD hr = Bth_BluetoothSetServiceState(hRadio, &btdi,
- &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE);
- if (SUCCEEDED(hr))
- ++nPaired;
- else
- ERROR_LOG(WIIMOTE, "Pair-Up: BluetoothSetServiceState() returned %08x", hr);
- }
+ Bth_BluetoothFindDeviceClose(hFindDevice);
+ hFindDevice = NULL;
}
}
-
- if (false == Bth_BluetoothFindNextDevice(hFindDevice, &btdi))
- {
- Bth_BluetoothFindDeviceClose(hFindDevice);
- hFindDevice = NULL;
- }
}
if (false == Bth_BluetoothFindNextRadio(hFindRadio, &hRadio))
@@ -527,8 +576,84 @@ int PairUp(bool unpair)
hFindRadio = NULL;
}
}
+}
+
+void RemoveWiimote(BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
+{
+ //if (btdi.fConnected)
+ {
+ if (SUCCEEDED(Bth_BluetoothRemoveDevice(&btdi.Address)))
+ {
+ NOTICE_LOG(WIIMOTE, "Removed BT Device", GetLastError());
+ }
+ }
+}
+
+bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO& radio_info, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
+{
+ // We don't want "remembered" devices.
+ // SetServiceState will just fail with them..
+ if (!btdi.fConnected && !btdi.fRemembered)
+ {
+ auto const& wm_addr = btdi.Address.rgBytes;
+
+ NOTICE_LOG(WIIMOTE, "Found wiimote (%02x:%02x:%02x:%02x:%02x:%02x). Enabling HID service.",
+ wm_addr[0], wm_addr[1], wm_addr[2], wm_addr[3], wm_addr[4], wm_addr[5]);
+
+#if defined(AUTHENTICATE_WIIMOTES)
+ // Authenticate
+ auto const& radio_addr = radio_info.address.rgBytes;
+ const DWORD auth_result = Bth_BluetoothAuthenticateDevice(NULL, hRadio, &btdi,
+ std::vector<WCHAR>(radio_addr, radio_addr + 6).data(), 6);
+
+ if (ERROR_SUCCESS != auth_result)
+ ERROR_LOG(WIIMOTE, "AttachWiimote: BluetoothAuthenticateDevice returned %08x", auth_result);
+
+ DWORD pcServices = 16;
+ GUID guids[16];
+ // If this is not done, the Wii device will not remember the pairing
+ const DWORD srv_result = Bth_BluetoothEnumerateInstalledServices(hRadio, &btdi, &pcServices, guids);
+
+ if (ERROR_SUCCESS != srv_result)
+ ERROR_LOG(WIIMOTE, "AttachWiimote: BluetoothEnumerateInstalledServices returned %08x", srv_result);
+#endif
+ // Activate service
+ const DWORD hr = Bth_BluetoothSetServiceState(hRadio, &btdi,
+ &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE);
+
+ g_connect_times[btdi.Address.ullLong] = std::time(nullptr);
+
+ if (FAILED(hr))
+ ERROR_LOG(WIIMOTE, "AttachWiimote: BluetoothSetServiceState returned %08x", hr);
+ else
+ return true;
+ }
+
+ return false;
+}
+
+// Removes remembered non-connected devices
+bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
+{
+ if (!btdi.fConnected && btdi.fRemembered)
+ {
+ // Time to avoid RemoveDevice after SetServiceState.
+ // Sometimes SetServiceState takes a while..
+ auto const avoid_forget_seconds = 5.0;
+
+ auto pair_time = g_connect_times.find(btdi.Address.ullLong);
+ if (pair_time == g_connect_times.end()
+ || std::difftime(time(nullptr), pair_time->second) >= avoid_forget_seconds)
+ {
+ // Make Windows forget about device so it will re-find it if visible.
+ // This is also required to detect a disconnect for some reason..
+ NOTICE_LOG(WIIMOTE, "Removing remembered wiimote.");
+ Bth_BluetoothRemoveDevice(&btdi.Address);
+ return true;
+ }
+ }
- return nPaired;
+ return false;
}
};
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm
index 64de880180..cec18ed63a 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm
@@ -40,8 +40,11 @@
{
IOBluetoothDevice *device = [l2capChannel getDevice];
WiimoteReal::Wiimote *wm = NULL;
+
+ std::lock_guard<std::recursive_mutex> lk(WiimoteReal::g_refresh_lock);
- for (int i = 0; i < MAX_WIIMOTES; i++) {
+ for (int i = 0; i < MAX_WIIMOTES; i++)
+ {
if (WiimoteReal::g_wiimotes[i] == NULL)
continue;
if ([device isEqual: WiimoteReal::g_wiimotes[i]->btd] == TRUE)
@@ -77,8 +80,11 @@
{
IOBluetoothDevice *device = [l2capChannel getDevice];
WiimoteReal::Wiimote *wm = NULL;
+
+ std::lock_guard<std::recursive_mutex> lk(WiimoteReal::g_refresh_lock);
- for (int i = 0; i < MAX_WIIMOTES; i++) {
+ for (int i = 0; i < MAX_WIIMOTES; i++)
+ {
if (WiimoteReal::g_wiimotes[i] == NULL)
continue;
if ([device isEqual: WiimoteReal::g_wiimotes[i]->btd] == TRUE)
@@ -92,41 +98,47 @@
WARN_LOG(WIIMOTE, "Lost channel to wiimote %i", wm->index + 1);
- wm->RealDisconnect();
+ wm->Disconnect();
}
@end
namespace WiimoteReal
{
-// Find wiimotes.
-// wm is an array of max_wiimotes wiimotes
-// Returns the total number of found wiimotes.
-int FindWiimotes(Wiimote **wm, int max_wiimotes)
+WiimoteScanner::WiimoteScanner()
+ : m_run_thread()
+ , m_want_wiimotes()
+{}
+
+WiimoteScanner::~WiimoteScanner()
+{}
+
+void WiimoteScanner::Update()
+{}
+
+std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
{
+ // TODO: find the device in the constructor and save it for later
+
+ std::vector<Wiimote*> wiimotes;
IOBluetoothHostController *bth;
IOBluetoothDeviceInquiry *bti;
SearchBT *sbt;
NSEnumerator *en;
- int found_devices = 0, found_wiimotes = 0;
-
- // Count the number of already found wiimotes
- for (int i = 0; i < MAX_WIIMOTES; ++i)
- if (wm[i])
- found_wiimotes++;
bth = [[IOBluetoothHostController alloc] init];
- if ([bth addressAsString] == nil) {
+ if ([bth addressAsString] == nil)
+ {
WARN_LOG(WIIMOTE, "No bluetooth host controller");
[bth release];
- return found_wiimotes;
+ return wiimotes;
}
sbt = [[SearchBT alloc] init];
- sbt->maxDevices = max_wiimotes - found_wiimotes;
+ sbt->maxDevices = 32;
bti = [[IOBluetoothDeviceInquiry alloc] init];
[bti setDelegate: sbt];
- [bti setInquiryLength: 5];
+ [bti setInquiryLength: 2];
if ([bti start] == kIOReturnSuccess)
[bti retain];
@@ -136,10 +148,10 @@ int FindWiimotes(Wiimote **wm, int max_wiimotes)
CFRunLoopRun();
[bti stop];
- found_devices = [[bti foundDevices] count];
+ int found_devices = [[bti foundDevices] count];
- NOTICE_LOG(WIIMOTE, "Found %i bluetooth device%c", found_devices,
- found_devices == 1 ? '\0' : 's');
+ if (found_devices)
+ NOTICE_LOG(WIIMOTE, "Found %i bluetooth devices", found_devices);
en = [[bti foundDevices] objectEnumerator];
for (int i = 0; i < found_devices; i++)
@@ -147,42 +159,44 @@ int FindWiimotes(Wiimote **wm, int max_wiimotes)
IOBluetoothDevice *dev = [en nextObject];
if (!IsValidBluetoothName([[dev name] UTF8String]))
continue;
- // Find an unused slot
- for (int k = 0; k < MAX_WIIMOTES; k++) {
- if (wm[k] != NULL ||
- !(g_wiimote_sources[k] & WIIMOTE_SRC_REAL))
- continue;
-
- wm[k] = new Wiimote(k);
- wm[k]->btd = dev;
- found_wiimotes++;
- break;
- }
+
+ Wiimote *wm = new Wiimote();
+ wm->btd = dev;
+ wiimotes.push_back(wm);
}
[bth release];
[bti release];
[sbt release];
- return found_wiimotes;
+ return wiimotes;
+}
+
+bool WiimoteScanner::IsReady() const
+{
+ // TODO: only return true when a BT device is present
+ return true;
}
// Connect to a wiimote with a known address.
bool Wiimote::Connect()
{
- ConnectBT *cbt = [[ConnectBT alloc] init];
-
if (IsConnected())
return false;
+ ConnectBT *cbt = [[ConnectBT alloc] init];
+
[btd openL2CAPChannelSync: &cchan
withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt];
[btd openL2CAPChannelSync: &ichan
withPSM: kBluetoothL2CAPPSMHIDInterrupt delegate: cbt];
- if (ichan == NULL || cchan == NULL) {
+ if (ichan == NULL || cchan == NULL)
+ {
ERROR_LOG(WIIMOTE, "Unable to open L2CAP channels "
"for wiimote %i", index + 1);
- RealDisconnect();
+ Disconnect();
+
+ [cbt release];
return false;
}
@@ -196,40 +210,37 @@ bool Wiimote::Connect()
m_connected = true;
- Handshake();
- SetLEDs(WIIMOTE_LED_1 << index);
-
- m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this);
-
[cbt release];
-
return true;
}
// Disconnect a wiimote.
-void Wiimote::RealDisconnect()
+void Wiimote::Disconnect()
{
- if (!IsConnected())
- return;
-
- NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i", index + 1);
+ if (btd != NULL)
+ [btd closeConnection];
- m_connected = false;
+ if (ichan != NULL)
+ [ichan release];
- if (m_wiimote_thread.joinable())
- m_wiimote_thread.join();
+ if (cchan != NULL)
+ [cchan release];
- [btd closeConnection];
- [ichan release];
- [cchan release];
btd = NULL;
cchan = NULL;
ichan = NULL;
+
+ if (!IsConnected())
+ return;
+
+ NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i", index + 1);
+
+ m_connected = false;
}
-bool Wiimote::IsOpen() const
+bool Wiimote::IsConnected() const
{
- return IsConnected();
+ return m_connected;
}
int Wiimote::IORead(unsigned char *buf)
@@ -246,14 +257,14 @@ int Wiimote::IORead(unsigned char *buf)
return bytes;
}
-int Wiimote::IOWrite(unsigned char *buf, int len)
+int Wiimote::IOWrite(const unsigned char *buf, int len)
{
IOReturn ret;
if (!IsConnected())
return 0;
- ret = [ichan writeAsync: buf length: len refcon: nil];
+ ret = [ichan writeAsync: const_cast<void*>((void *)buf) length: len refcon: nil];
if (ret == kIOReturnSuccess)
return len;
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
index c726a836d9..131befc3ae 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
@@ -23,6 +23,8 @@
#include "IniFile.h"
#include "StringUtil.h"
#include "Timer.h"
+#include "Host.h"
+#include "ConfigManager.h"
#include "WiimoteReal.h"
@@ -33,36 +35,43 @@ unsigned int g_wiimote_sources[MAX_WIIMOTES];
namespace WiimoteReal
{
+void HandleFoundWiimotes(const std::vector<Wiimote*>&);
+void TryToConnectWiimote(Wiimote*);
+void HandleWiimoteDisconnect(int index);
+void DoneWithWiimote(int index);
+
bool g_real_wiimotes_initialized = false;
-unsigned int g_wiimotes_found = 0;
-std::mutex g_refresh_lock;
+std::recursive_mutex g_refresh_lock;
+
+Wiimote* g_wiimotes[MAX_WIIMOTES];
-Wiimote *g_wiimotes[MAX_WIIMOTES];
+WiimoteScanner g_wiimote_scanner;
-Wiimote::Wiimote(const unsigned int _index)
- : index(_index)
+Wiimote::Wiimote()
+ : index()
#ifdef __APPLE__
- , inputlen(0)
+ , btd(), ichan(), cchan(), inputlen(), m_connected()
#elif defined(__linux__) && HAVE_BLUEZ
, cmd_sock(-1), int_sock(-1)
#elif defined(_WIN32)
, dev_handle(0), stack(MSBT_STACK_UNKNOWN)
#endif
- , leds(0), m_last_data_report(Report((u8 *)NULL, 0))
- , m_channel(0), m_connected(false)
+ , m_last_data_report(Report((u8 *)NULL, 0))
+ , m_channel(0), m_run_thread(false)
{
#if defined(__linux__) && HAVE_BLUEZ
bdaddr = (bdaddr_t){{0, 0, 0, 0, 0, 0}};
#endif
-
- DisableDataReporting();
}
Wiimote::~Wiimote()
{
- RealDisconnect();
+ StopThread();
+ if (IsConnected())
+ Disconnect();
+
ClearReadQueue();
// clear write queue
@@ -71,26 +80,28 @@ Wiimote::~Wiimote()
delete[] rpt.first;
}
-// Silly, copying data n stuff, o well, don't use this too often
-void Wiimote::SendPacket(const u8 rpt_id, const void* const data, const unsigned int size)
+// to be called from CPU thread
+void Wiimote::QueueReport(u8 rpt_id, const void* _data, unsigned int size)
{
+ auto const data = static_cast<const u8*>(_data);
+
Report rpt;
rpt.second = size + 2;
rpt.first = new u8[rpt.second];
- rpt.first[0] = 0xA1;
+ rpt.first[0] = WM_SET_REPORT | WM_BT_OUTPUT;
rpt.first[1] = rpt_id;
- memcpy(rpt.first + 2, data, size);
+ std::copy(data, data + size, rpt.first + 2);
m_write_reports.Push(rpt);
}
void Wiimote::DisableDataReporting()
{
- wm_report_mode rpt;
+ wm_report_mode rpt = {};
rpt.mode = WM_REPORT_CORE;
rpt.all_the_time = 0;
rpt.continuous = 0;
rpt.rumble = 0;
- SendPacket(WM_REPORT_MODE, &rpt, sizeof(rpt));
+ QueueReport(WM_REPORT_MODE, &rpt, sizeof(rpt));
}
void Wiimote::ClearReadQueue()
@@ -111,7 +122,7 @@ void Wiimote::ControlChannel(const u16 channel, const void* const data, const u3
{
// Check for custom communication
if (99 == channel)
- Disconnect();
+ EmuStop();
else
{
InterruptChannel(channel, data, size);
@@ -124,24 +135,24 @@ void Wiimote::ControlChannel(const u16 channel, const void* const data, const u3
}
}
-void Wiimote::InterruptChannel(const u16 channel, const void* const data, const u32 size)
+void Wiimote::InterruptChannel(const u16 channel, const void* const _data, const u32 size)
{
- if (0 == m_channel) // first interrupt/control channel sent
+ // first interrupt/control channel sent
+ if (channel != m_channel)
{
+ m_channel = channel;
+
ClearReadQueue();
- // request status
- wm_request_status rpt;
- rpt.rumble = 0;
- SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt));
+ EmuStart();
}
-
- m_channel = channel; // this right?
+
+ auto const data = static_cast<const u8*>(_data);
Report rpt;
rpt.first = new u8[size];
rpt.second = (u8)size;
- memcpy(rpt.first, (u8*)data, size);
+ std::copy(data, data + size, rpt.first);
// Convert output DATA packets to SET_REPORT packets.
// Nintendo Wiimotes work without this translation, but 3rd
@@ -150,13 +161,27 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const
{
rpt.first[0] = WM_SET_REPORT | WM_BT_OUTPUT;
}
-
- if (rpt.first[0] == (WM_SET_REPORT | WM_BT_OUTPUT) &&
- rpt.first[1] == 0x18 && rpt.second == 23)
+
+ // Disallow games from turning off all of the LEDs.
+ // It makes wiimote connection status confusing.
+ if (rpt.first[1] == WM_LEDS)
{
- m_audio_reports.Push(rpt);
- return;
- }
+ auto& leds_rpt = *reinterpret_cast<wm_leds*>(&rpt.first[2]);
+ if (0 == leds_rpt.leds)
+ {
+ // Turn on ALL of the LEDs.
+ leds_rpt.leds = 0xf;
+ }
+ }
+ else if (rpt.first[1] == WM_WRITE_SPEAKER_DATA
+ && !SConfig::GetInstance().m_WiimoteEnableSpeaker)
+ {
+ // Translate speaker data reports into rumble reports.
+ rpt.first[1] = WM_CMD_RUMBLE;
+ // Keep only the rumble bit.
+ rpt.first[2] &= 0x1;
+ rpt.second = 3;
+ }
m_write_reports.Push(rpt);
}
@@ -168,7 +193,14 @@ bool Wiimote::Read()
rpt.first = new unsigned char[MAX_PAYLOAD];
rpt.second = IORead(rpt.first);
- if (rpt.second > 0 && m_channel > 0) {
+ if (0 == rpt.second)
+ {
+ WARN_LOG(WIIMOTE, "Wiimote::IORead failed. Disconnecting wiimote %d.", index + 1);
+ Disconnect();
+ }
+
+ if (rpt.second > 0 && m_channel > 0)
+ {
// Add it to queue
m_read_reports.Push(rpt);
return true;
@@ -180,23 +212,25 @@ bool Wiimote::Read()
bool Wiimote::Write()
{
- Report rpt;
-
- if (last_audio_report.GetTimeDifference() > 5 && m_audio_reports.Pop(rpt))
+ if (!m_write_reports.Empty())
{
- IOWrite(rpt.first, rpt.second);
- last_audio_report.Update();
+ Report const& rpt = m_write_reports.Front();
- delete[] rpt.first;
- return true;
- }
- else if (m_write_reports.Pop(rpt))
- {
- IOWrite(rpt.first, rpt.second);
- delete[] rpt.first;
- return true;
+ bool const is_speaker_data = rpt.first[1] == WM_WRITE_SPEAKER_DATA;
+
+ if (!is_speaker_data || m_last_audio_report.GetTimeDifference() > 5)
+ {
+ IOWrite(rpt.first, rpt.second);
+
+ if (is_speaker_data)
+ m_last_audio_report.Update();
+
+ delete[] rpt.first;
+ m_write_reports.Pop();
+ return true;
+ }
}
-
+
return false;
}
@@ -221,6 +255,12 @@ Report Wiimote::ProcessReadQueue()
void Wiimote::Update()
{
+ if (!IsConnected())
+ {
+ HandleWiimoteDisconnect(index);
+ return;
+ }
+
// Pop through the queued reports
Report const rpt = ProcessReadQueue();
@@ -234,123 +274,151 @@ void Wiimote::Update()
delete[] rpt.first;
}
-void Wiimote::Disconnect()
+bool Wiimote::Prepare(int _index)
{
- m_channel = 0;
+ index = _index;
- DisableDataReporting();
+ // core buttons, no continuous reporting
+ u8 const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_REPORT_TYPE, 0, 0x30};
+
+ // Set the active LEDs and turn on rumble.
+ u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_LED, u8(WIIMOTE_LED_1 << index | 0x1)};
+
+ // Turn off rumble
+ u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_RUMBLE, 0};
+
+ // Request status report
+ u8 const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0};
+ // TODO: check for sane response?
+
+ return (IOWrite(mode_report, sizeof(mode_report))
+ && IOWrite(led_report, sizeof(led_report))
+ && (SLEEP(200), IOWrite(rumble_report, sizeof(rumble_report)))
+ && IOWrite(req_status_report, sizeof(req_status_report)));
}
-bool Wiimote::IsConnected() const
+void Wiimote::EmuStart()
{
- return m_connected;
+ DisableDataReporting();
}
-// Rumble briefly
-void Wiimote::Rumble()
+void Wiimote::EmuStop()
{
- if (!IsConnected())
- return;
+ m_channel = 0;
+
+ DisableDataReporting();
- unsigned char buffer = 0x01;
- DEBUG_LOG(WIIMOTE, "Starting rumble...");
- SendRequest(WM_CMD_RUMBLE, &buffer, 1);
+ NOTICE_LOG(WIIMOTE, "Stopping wiimote data reporting");
+}
- SLEEP(200);
+unsigned int CalculateWantedWiimotes()
+{
+ // Figure out how many real wiimotes are required
+ unsigned int wanted_wiimotes = 0;
+ for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
+ if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] && !g_wiimotes[i])
+ ++wanted_wiimotes;
- DEBUG_LOG(WIIMOTE, "Stopping rumble...");
- buffer = 0x00;
- SendRequest(WM_CMD_RUMBLE, &buffer, 1);
+ return wanted_wiimotes;
}
-// Set the active LEDs.
-// leds is a bitwise or of WIIMOTE_LED_1 through WIIMOTE_LED_4.
-void Wiimote::SetLEDs(int new_leds)
+void WiimoteScanner::WantWiimotes(bool do_want)
{
- unsigned char buffer;
+ m_want_wiimotes = do_want;
+}
- if (!IsConnected())
- return;
+void WiimoteScanner::StartScanning()
+{
+ if (!m_run_thread && IsReady())
+ {
+ m_run_thread = true;
+ m_scan_thread = std::thread(std::mem_fun(&WiimoteScanner::ThreadFunc), this);
+ }
+}
+
+void WiimoteScanner::StopScanning()
+{
+ m_run_thread = false;
+ if (m_scan_thread.joinable())
+ {
+ m_scan_thread.join();
+ }
+}
- // Remove the lower 4 bits because they control rumble
- buffer = leds = (new_leds & 0xF0);
+void CheckForDisconnectedWiimotes()
+{
+ std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
- SendRequest(WM_CMD_LED, &buffer, 1);
+ for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
+ if (g_wiimotes[i] && !g_wiimotes[i]->IsConnected())
+ HandleWiimoteDisconnect(i);
}
-// Send a handshake
-bool Wiimote::Handshake()
+void WiimoteScanner::ThreadFunc()
{
- // Set buffer[0] to 0x04 for continuous reporting
- unsigned char buffer[2] = {0x04, 0x30};
+ Common::SetCurrentThreadName("Wiimote Scanning Thread");
- if (!IsConnected())
- return 0;
+ NOTICE_LOG(WIIMOTE, "Wiimote scanning has started");
+
+ while (m_run_thread)
+ {
+ std::vector<Wiimote*> found_wiimotes;
+
+ //NOTICE_LOG(WIIMOTE, "in loop");
+
+ if (m_want_wiimotes)
+ found_wiimotes = FindWiimotes();
+ else
+ {
+ // Does stuff needed to detect disconnects on Windows
+ Update();
+ }
- DEBUG_LOG(WIIMOTE, "Sending handshake to wiimote");
+ //NOTICE_LOG(WIIMOTE, "after update");
- return SendRequest(WM_CMD_REPORT_TYPE, buffer, 2);
+ // TODO: this is a fairly lame place for this
+ CheckForDisconnectedWiimotes();
+
+ HandleFoundWiimotes(found_wiimotes);
+
+ //std::this_thread::yield();
+ Common::SleepCurrentThread(500);
+ }
+
+ NOTICE_LOG(WIIMOTE, "Wiimote scanning has stopped");
}
-// Send a packet to the wiimote.
-// report_type should be one of WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc.
-bool Wiimote::SendRequest(unsigned char report_type, unsigned char* data, int length)
+void Wiimote::StartThread()
{
- unsigned char buffer[32] = {WM_SET_REPORT | WM_BT_OUTPUT, report_type};
-
- memcpy(buffer + 2, data, length);
+ m_run_thread = true;
+ m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this);
+}
- return (IOWrite(buffer, length + 2) != 0);
+void Wiimote::StopThread()
+{
+ m_run_thread = false;
+ if (m_wiimote_thread.joinable())
+ m_wiimote_thread.join();
}
void Wiimote::ThreadFunc()
{
- char thname[] = "Wiimote # Thread";
- thname[8] = (char)('1' + index);
- Common::SetCurrentThreadName(thname);
-
- // rumble briefly
- Rumble();
+ Common::SetCurrentThreadName("Wiimote Device Thread");
// main loop
- while (IsOpen())
+ while (m_run_thread && IsConnected())
{
#ifdef __APPLE__
- while (Write()) {}
- Common::SleepCurrentThread(1);
+ // Reading happens elsewhere on OSX
+ bool const did_something = Write();
#else
bool const did_something = Write() || Read();
+#endif
if (!did_something)
Common::SleepCurrentThread(1);
-#endif
}
}
-#ifndef _WIN32
-// Connect all discovered wiimotes
-// Return the number of wiimotes that successfully connected.
-static int ConnectWiimotes(Wiimote** wm)
-{
- int connected = 0;
-
- for (int i = 0; i < MAX_WIIMOTES; ++i)
- {
- if (!wm[i] || wm[i]->IsConnected())
- continue;
-
- if (wm[i]->Connect())
- ++connected;
- else
- {
- delete wm[i];
- wm[i] = NULL;
- }
- }
-
- return connected;
-}
-#endif
-
void LoadSettings()
{
std::string ini_filename = File::GetUserPath(D_CONFIG_IDX) + WIIMOTE_INI_NAME ".ini";
@@ -368,116 +436,181 @@ void LoadSettings()
}
}
-unsigned int Initialize()
+// config dialog calls this when some settings change
+void Initialize()
{
- // Return if already initialized
- if (g_real_wiimotes_initialized)
- return g_wiimotes_found;
-
- memset(g_wiimotes, 0, sizeof(g_wiimotes));
+ if (SConfig::GetInstance().m_WiimoteContinuousScanning)
+ g_wiimote_scanner.StartScanning();
+ else
+ g_wiimote_scanner.StopScanning();
+
+ std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
- // Only call FindWiimotes with the number of slots configured for real wiimotes
- unsigned int wanted_wiimotes = 0;
- for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
- if (WIIMOTE_SRC_REAL & g_wiimote_sources[i])
- ++wanted_wiimotes;
+ g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
+
+ if (g_real_wiimotes_initialized)
+ return;
- // Don't bother initializing if we don't want any real wiimotes
- if (0 == wanted_wiimotes)
- {
- g_wiimotes_found = 0;
- return 0;
- }
+ NOTICE_LOG(WIIMOTE, "WiimoteReal::Initialize");
- // Initialized
g_real_wiimotes_initialized = true;
+}
- g_wiimotes_found = FindWiimotes(g_wiimotes, wanted_wiimotes);
+void Shutdown(void)
+{
+ g_wiimote_scanner.StopScanning();
- DEBUG_LOG(WIIMOTE, "Found %i Real Wiimotes, %i wanted",
- g_wiimotes_found, wanted_wiimotes);
+ std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
-#ifndef _WIN32
- atexit(WiimoteReal::Shutdown);
- g_wiimotes_found = ConnectWiimotes(g_wiimotes);
-#endif
+ if (!g_real_wiimotes_initialized)
+ return;
+
+ NOTICE_LOG(WIIMOTE, "WiimoteReal::Shutdown");
- DEBUG_LOG(WIIMOTE, "Connected to %i Real Wiimotes", g_wiimotes_found);
+ g_real_wiimotes_initialized = false;
- return g_wiimotes_found;
+ for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
+ HandleWiimoteDisconnect(i);
}
-void Shutdown(void)
+void ChangeWiimoteSource(unsigned int index, int source)
{
- if (false == g_real_wiimotes_initialized)
- return;
-
- // Uninitialized
- g_real_wiimotes_initialized = false;
+ {
+ std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
+
+ g_wiimote_sources[index] = source;
+ g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
+
+ // kill real connection (or swap to different slot)
+ DoneWithWiimote(index);
+ }
- // Delete wiimotes
- for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
- if (g_wiimotes[i])
- {
- delete g_wiimotes[i];
- g_wiimotes[i] = NULL;
- }
+ // reconnect to emu
+ Host_ConnectWiimote(index, false);
+ if (WIIMOTE_SRC_EMU & source)
+ Host_ConnectWiimote(index, true);
}
-// This is called from the GUI thread
-void Refresh()
+void TryToConnectWiimote(Wiimote* wm)
{
- std::lock_guard<std::mutex> lk(g_refresh_lock);
+ std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);
-#ifdef _WIN32
- Shutdown();
- Initialize();
-#else
- // Make sure real wiimotes have been initialized
- if (!g_real_wiimotes_initialized)
+ for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
{
- Initialize();
- return;
+ if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
+ && !g_wiimotes[i])
+ {
+ if (wm->Connect() && wm->Prepare(i))
+ {
+ NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", i + 1);
+
+ std::swap(g_wiimotes[i], wm);
+ g_wiimotes[i]->StartThread();
+
+ Host_ConnectWiimote(i, true);
+ }
+ break;
+ }
}
- // Find the number of slots configured for real wiimotes
- unsigned int wanted_wiimotes = 0;
- for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
- if (WIIMOTE_SRC_REAL & g_wiimote_sources[i])
- ++wanted_wiimotes;
+ g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
+
+ lk.unlock();
+
+ delete wm;
+}
- // Remove wiimotes that are paired with slots no longer configured for a
- // real wiimote or that are disconnected
- for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
- if (g_wiimotes[i] && (!(WIIMOTE_SRC_REAL & g_wiimote_sources[i]) ||
- !g_wiimotes[i]->IsConnected()))
+void DoneWithWiimote(int index)
+{
+ std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
+
+ if (g_wiimotes[index])
+ {
+ g_wiimotes[index]->StopThread();
+
+ // First see if we can use this real wiimote in another slot.
+ for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
{
- delete g_wiimotes[i];
- g_wiimotes[i] = NULL;
- --g_wiimotes_found;
+ if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
+ && !g_wiimotes[i])
+ {
+ if (g_wiimotes[index]->Prepare(i))
+ {
+ std::swap(g_wiimotes[i], g_wiimotes[index]);
+ g_wiimotes[i]->StartThread();
+
+ Host_ConnectWiimote(i, true);
+ }
+ break;
+ }
}
+ }
+
+ // else, just disconnect the wiimote
+ HandleWiimoteDisconnect(index);
+}
- // Scan for wiimotes if we want more
- if (wanted_wiimotes > g_wiimotes_found)
+void HandleWiimoteDisconnect(int index)
+{
+ Wiimote* wm = NULL;
+
{
- // Scan for wiimotes
- unsigned int num_wiimotes = FindWiimotes(g_wiimotes, wanted_wiimotes);
+ std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
+ std::swap(wm, g_wiimotes[index]);
+ g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
+ }
- DEBUG_LOG(WIIMOTE, "Found %i Real Wiimotes, %i wanted", num_wiimotes, wanted_wiimotes);
+ if (wm)
+ {
+ delete wm;
+ NOTICE_LOG(WIIMOTE, "Disconnected wiimote %i.", index + 1);
+ }
+}
- // Connect newly found wiimotes.
- int num_new_wiimotes = ConnectWiimotes(g_wiimotes);
+void HandleFoundWiimotes(const std::vector<Wiimote*>& wiimotes)
+{
+ std::for_each(wiimotes.begin(), wiimotes.end(), TryToConnectWiimote);
+}
+
+// This is called from the GUI thread
+void Refresh()
+{
+ g_wiimote_scanner.StopScanning();
+
+ {
+ std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);
+ std::vector<Wiimote*> found_wiimotes;
+
+ if (0 != CalculateWantedWiimotes())
+ {
+ // Don't hang dolphin when searching
+ lk.unlock();
+ found_wiimotes = g_wiimote_scanner.FindWiimotes();
+ lk.lock();
+ }
+
+ CheckForDisconnectedWiimotes();
- DEBUG_LOG(WIIMOTE, "Connected to %i additional Real Wiimotes", num_new_wiimotes);
+ // Brief rumble for already connected wiimotes.
+ for (int i = 0; i != MAX_WIIMOTES; ++i)
+ {
+ if (g_wiimotes[i])
+ {
+ g_wiimotes[i]->StopThread();
+ g_wiimotes[i]->Prepare(i);
+ g_wiimotes[i]->StartThread();
+ }
+ }
- g_wiimotes_found = num_wiimotes;
+ HandleFoundWiimotes(found_wiimotes);
}
-#endif
+
+ Initialize();
}
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
{
- std::lock_guard<std::mutex> lk(g_refresh_lock);
+ std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size);
@@ -485,7 +618,7 @@ void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u3
void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
{
- std::lock_guard<std::mutex> lk(g_refresh_lock);
+ std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size);
@@ -495,24 +628,30 @@ void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32
// Read the Wiimote once
void Update(int _WiimoteNumber)
{
- std::lock_guard<std::mutex> lk(g_refresh_lock);
+ std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->Update();
+
+ // Wiimote::Update() may remove the wiimote if it was disconnected.
+ if (!g_wiimotes[_WiimoteNumber])
+ {
+ Host_ConnectWiimote(_WiimoteNumber, false);
+ }
}
void StateChange(EMUSTATE_CHANGE newState)
{
- //std::lock_guard<std::mutex> lk(g_refresh_lock);
+ //std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
// TODO: disable/enable auto reporting, maybe
}
bool IsValidBluetoothName(const std::string& name)
{
- std::string const prefix("Nintendo RVL-");
- return name.size() > prefix.size() &&
- std::equal(prefix.begin(), prefix.end(), name.begin());
+ return
+ "Nintendo RVL-CNT-01" == name ||
+ "Nintendo RVL-CNT-01-TR" == name;
}
}; // end of namespace
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
index edd4b4f71b..cfc66106b4 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
+++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
@@ -20,6 +20,7 @@
#define WIIMOTE_REAL_H
#include <functional>
+#include <vector>
#include "WiimoteRealBase.h"
#include "ChunkFile.h"
@@ -42,7 +43,7 @@ class Wiimote : NonCopyable
{
friend class WiimoteEmu::Wiimote;
public:
- Wiimote(const unsigned int _index);
+ Wiimote();
~Wiimote();
void ControlChannel(const u16 channel, const void* const data, const u32 size);
@@ -53,16 +54,29 @@ public:
bool Read();
bool Write();
+
+ void StartThread();
+ void StopThread();
+
+ // "handshake" / stop packets
+ void EmuStart();
+ void EmuStop();
+
+ // connecting and disconnecting from physical devices
+ // (using address inserted by FindWiimotes)
bool Connect();
- bool IsConnected() const;
- bool IsOpen() const;
void Disconnect();
+
+ // TODO: change to something like IsRelevant
+ bool IsConnected() const;
+
+ bool Prepare(int index);
+
void DisableDataReporting();
- void Rumble();
- void SendPacket(const u8 rpt_id, const void* const data, const unsigned int size);
- void RealDisconnect();
+
+ void QueueReport(u8 rpt_id, const void* data, unsigned int size);
- const unsigned int index;
+ int index;
#if defined(__APPLE__)
IOBluetoothDevice *btd;
@@ -70,21 +84,19 @@ public:
IOBluetoothL2CAPChannel *cchan;
char input[MAX_PAYLOAD];
int inputlen;
+ bool m_connected;
#elif defined(__linux__) && HAVE_BLUEZ
bdaddr_t bdaddr; // Bluetooth address
int cmd_sock; // Command socket
int int_sock; // Interrupt socket
- void Close();
-
#elif defined(_WIN32)
- std::string devicepath; // Unique wiimote reference
+ std::basic_string<TCHAR> devicepath; // Unique wiimote reference
//ULONGLONG btaddr; // Bluetooth address
HANDLE dev_handle; // HID handle
- OVERLAPPED hid_overlap; // Overlap handle
+ OVERLAPPED hid_overlap_read, hid_overlap_write; // Overlap handle
enum win_bt_stack_t stack; // Type of bluetooth stack to use
#endif
- unsigned char leds; // Currently lit leds
protected:
Report m_last_data_report;
@@ -92,23 +104,58 @@ protected:
private:
void ClearReadQueue();
- bool SendRequest(unsigned char report_type, unsigned char* data, int length);
- bool Handshake();
- void SetLEDs(int leds);
- int IORead(unsigned char* buf);
- int IOWrite(unsigned char* buf, int len);
+
+ int IORead(u8* buf);
+ int IOWrite(u8 const* buf, int len);
+
void ThreadFunc();
- bool m_connected;
+ bool m_run_thread;
std::thread m_wiimote_thread;
+
Common::FifoQueue<Report> m_read_reports;
Common::FifoQueue<Report> m_write_reports;
- Common::FifoQueue<Report> m_audio_reports;
- Common::Timer last_audio_report;
+ Common::Timer m_last_audio_report;
+};
+
+class WiimoteScanner
+{
+public:
+ WiimoteScanner();
+ ~WiimoteScanner();
+
+ bool IsReady() const;
+
+ void WantWiimotes(bool do_want);
+
+ void StartScanning();
+ void StopScanning();
+
+ std::vector<Wiimote*> FindWiimotes();
+
+ // function called when not looking for more wiimotes
+ void Update();
+
+private:
+ void ThreadFunc();
+
+ std::thread m_scan_thread;
+
+ volatile bool m_run_thread;
+ volatile bool m_want_wiimotes;
+
+#if defined(_WIN32)
+
+
+#elif defined(__linux__) && HAVE_BLUEZ
+ int device_id;
+ int device_sock;
+#endif
};
-extern std::mutex g_refresh_lock;
+extern std::recursive_mutex g_refresh_lock;
+extern WiimoteScanner g_wiimote_scanner;
extern Wiimote *g_wiimotes[4];
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);
@@ -119,6 +166,7 @@ void DoState(PointerWrap &p);
void StateChange(EMUSTATE_CHANGE newState);
int FindWiimotes(Wiimote** wm, int max_wiimotes);
+void ChangeWiimoteSource(unsigned int index, int source);
bool IsValidBluetoothName(const std::string& name);
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h
index 75a6d3e6a3..1a1f6676cf 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h
+++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h
@@ -41,6 +41,7 @@
#define WM_SET_REPORT 0xA0
#endif
+// TODO: duplicated in WiimoteHid.h
// Commands
#define WM_CMD_RUMBLE 0x10
#define WM_CMD_LED 0x11
@@ -66,8 +67,9 @@
// End Wiimote internal codes
-#define MAX_PAYLOAD 32
-#define WIIMOTE_DEFAULT_TIMEOUT 30
+// It's 23. NOT 32!
+#define MAX_PAYLOAD 23
+#define WIIMOTE_DEFAULT_TIMEOUT 1000
#ifdef _WIN32
// Available bluetooth stacks for Windows.
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp
index cd1da1da71..d0ee46756f 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp
@@ -33,9 +33,6 @@ std::string HLE_IPC_BuildFilename(std::string path_wii, int _size)
{
std::string path_full = File::GetUserPath(D_WIIROOT_IDX);
- if ((path_wii.length() > 0) && (path_wii[1] == '0'))
- path_full += std::string("/title"); // this looks and feel like a hack...
-
// Replaces chars that FAT32 can't support with strings defined in /sys/replace
for (auto i = replacements.begin(); i != replacements.end(); ++i)
{
@@ -48,39 +45,6 @@ std::string HLE_IPC_BuildFilename(std::string path_wii, int _size)
return path_full;
}
-void HLE_IPC_CreateVirtualFATFilesystem()
-{
- const int cdbSize = 0x01400000;
- const std::string cdbPath = Common::GetTitleDataPath(TITLEID_SYSMENU) + "cdb.vff";
- if ((int)File::GetSize(cdbPath) < cdbSize)
- {
- // cdb.vff is a virtual Fat filesystem created on first launch of sysmenu
- // we create it here as it is faster ~3 minutes for me when sysmenu does it ~1 second created here
- const u8 cdbHDR[0x20] = {'V', 'F', 'F', 0x20, 0xfe, 0xff, 1, 0, 1, 0x40, 0, 0, 0, 0x20};
- const u8 cdbFAT[4] = {0xf0, 0xff, 0xff, 0xff};
-
- File::IOFile cdbFile(cdbPath, "wb");
- if (cdbFile)
- {
- cdbFile.WriteBytes(cdbHDR, 0x20);
- cdbFile.WriteBytes(cdbFAT, 0x4);
- cdbFile.Seek(0x14020, SEEK_SET);
- cdbFile.WriteBytes(cdbFAT, 0x4);
- // 20 MiB file
- cdbFile.Seek(cdbSize - 1, SEEK_SET);
- // write the final 0 to 0 file from the second FAT to 20 MiB
- cdbFile.WriteBytes(cdbHDR + 14, 1);
- if (!cdbFile.IsGood())
- {
- cdbFile.Close();
- File::Delete(cdbPath);
- }
- cdbFile.Flush();
- cdbFile.Close();
- }
- }
-}
-
CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std::string& _rDeviceName)
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName, false) // not a real hardware
, m_Mode(0)
@@ -174,6 +138,7 @@ bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
const u64 fileSize = file.GetSize();
INFO_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08llx)", SeekPosition, Mode, m_Name.c_str(), fileSize);
+
switch (Mode)
{
case 0:
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h
index 3698d05c9f..7cdff98a95 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h
@@ -22,7 +22,6 @@
#include "FileUtil.h"
std::string HLE_IPC_BuildFilename(std::string _pFilename, int _size);
-void HLE_IPC_CreateVirtualFATFilesystem();
class CWII_IPC_HLE_Device_FileIO : public IWII_IPC_HLE_Device
{
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp
index 4d10077e6b..9219a64279 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp
@@ -59,6 +59,7 @@
#include "CommonPaths.h"
#include "IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "../Movie.h"
+#include "StringUtil.h"
#include "ec_wii.h"
@@ -966,7 +967,7 @@ u32 CWII_IPC_HLE_Device_es::ES_DIVerify(u8* _pTMD, u32 _sz)
else
{
#ifdef _WIN32
- MoveFile(savePath.c_str(), (savePath + "../backup/").c_str());
+ MoveFile(UTF8ToTStr(savePath).c_str(), UTF8ToTStr(savePath + "../backup/").c_str());
#else
File::CopyDir(savePath.c_str(),(savePath + "../backup/").c_str());
File::DeleteDirRecursively(savePath.c_str());
@@ -980,7 +981,7 @@ u32 CWII_IPC_HLE_Device_es::ES_DIVerify(u8* _pTMD, u32 _sz)
if (File::Exists((savePath + "banner.bin").c_str()))
File::DeleteDirRecursively(savePath);
#ifdef _WIN32
- MoveFile((savePath + "../backup/").c_str(), savePath.c_str());
+ MoveFile(UTF8ToTStr(savePath + "../backup/").c_str(), UTF8ToTStr(savePath).c_str());
#else
File::CopyDir((savePath + "../backup/").c_str(), savePath.c_str());
File::DeleteDirRecursively((savePath + "../backup/").c_str());
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp
index 63f891981c..bcc29f0365 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp
@@ -377,7 +377,7 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
u32 Addr = _BufferOut;
Memory::Write_U32(OwnerID, Addr); Addr += 4;
Memory::Write_U16(GroupID, Addr); Addr += 2;
- memcpy(Memory::GetPointer(Addr), Filename.c_str(), Filename.size()); Addr += 64;
+ memcpy(Memory::GetPointer(Addr), Memory::GetPointer(_BufferIn), 64); Addr += 64;
Memory::Write_U8(OwnerPerm, Addr); Addr += 1;
Memory::Write_U8(GroupPerm, Addr); Addr += 1;
Memory::Write_U8(OtherPerm, Addr); Addr += 1;
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp
index fa4c98dac2..a6025d523e 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp
@@ -681,7 +681,7 @@ char* DecodeError(int ErrorCode)
// (And of course, free the buffer when we were done with it)
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, ErrorCode,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)Message, 1024, NULL);
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)Message, 1024, NULL);
return Message;
#else
return strerror(ErrorCode);
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp
index 6e06f60dd6..b3449ec059 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp
@@ -211,8 +211,7 @@ void CWII_IPC_HLE_WiiMote::EventConnectionAccepted()
void CWII_IPC_HLE_WiiMote::EventDisconnect()
{
// Send disconnect message to plugin
- u8 Message = WIIMOTE_DISCONNECT;
- Wiimote::ControlChannel(m_ConnectionHandle & 0xFF, 99, &Message, 0);
+ Wiimote::ControlChannel(m_ConnectionHandle & 0xFF, 99, NULL, 0);
m_ConnectionState = CONN_INACTIVE;
// Clear channel flags
diff --git a/Source/Core/Core/Src/Movie.cpp b/Source/Core/Core/Src/Movie.cpp
index 6c646f6870..e72163cddb 100644
--- a/Source/Core/Core/Src/Movie.cpp
+++ b/Source/Core/Core/Src/Movie.cpp
@@ -1043,7 +1043,7 @@ bool PlayWiimote(int wiimote, u8 *data, const WiimoteEmu::ReportFeatures& rptf,
if (size != sizeInMovie)
{
- PanicAlertT("Fatal desync. Aborting playback. (Error in PlayWiimote: %u != %u, byte %u.)%s", (u32)sizeInMovie, (u32)size, (u32)g_currentByte, (g_numPads & 0xF)?" Try re-creating the recording with all GameCube controllers disabled (in Configure > Gamecube > Device Settings).":"");
+ PanicAlertT("Fatal desync. Aborting playback. (Error in PlayWiimote: %u != %u, byte %u.)%s", (u32)sizeInMovie, (u32)size, (u32)g_currentByte, (g_numPads & 0xF)?" Try re-creating the recording with all GameCube controllers disabled (in Configure > Gamecube > Device Settings), or restarting Dolphin (Dolphin currently must be restarted every time before playing back a wiimote movie).":"");
EndPlayInput(!g_bReadOnly);
return false;
}
diff --git a/Source/Core/Core/Src/NetPlay.h b/Source/Core/Core/Src/NetPlay.h
index e77f972785..96ff78995a 100644
--- a/Source/Core/Core/Src/NetPlay.h
+++ b/Source/Core/Core/Src/NetPlay.h
@@ -34,7 +34,7 @@ struct Rpt : public std::vector<u8>
typedef std::vector<Rpt> NetWiimote;
-#define NETPLAY_VERSION "Dolphin NetPlay r6423"
+#define NETPLAY_VERSION "Dolphin NetPlay 2013-03-03"
// messages
enum
diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp
index 1d6ea2e70d..ffaea0e868 100644
--- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp
+++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp
@@ -28,8 +28,6 @@
#undef _interlockedbittestandreset
#undef _interlockedbittestandset64
#undef _interlockedbittestandreset64
-#else
-#include <xmmintrin.h>
#endif
#include "../../Core.h"
@@ -514,4 +512,4 @@ void Interpreter::fsqrtx(UGeckoInstruction _inst)
rPS0(_inst.FD) = sqrt(b);
UpdateFPRF(rPS0(_inst.FD));
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-} \ No newline at end of file
+}
diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp
index 5e665eb38e..8e406dbfab 100644
--- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp
+++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp
@@ -24,8 +24,7 @@
#include "Interpreter.h"
#include "../../Core.h"
-#include "../JitCommon/JitBase.h"
-#include "../JitCommon/JitCache.h"
+#include "../JitInterface.h"
#include "Interpreter_FPUtils.h"
@@ -363,34 +362,24 @@ void Interpreter::dcbf(UGeckoInstruction _inst)
{
NPC = PC + 12;
}*/
- // Invalidate the jit block cache on dcbf
- if (jit)
- {
u32 address = Helper_Get_EA_X(_inst);
- jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32);
- }
+ JitInterface::InvalidateICache(address & ~0x1f, 32);
}
void Interpreter::dcbi(UGeckoInstruction _inst)
{
// Removes a block from data cache. Since we don't emulate the data cache, we don't need to do anything to the data cache
// However, we invalidate the jit block cache on dcbi
- if (jit)
- {
u32 address = Helper_Get_EA_X(_inst);
- jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32);
- }
+ JitInterface::InvalidateICache(address & ~0x1f, 32);
}
void Interpreter::dcbst(UGeckoInstruction _inst)
{
// Cache line flush. Since we don't emulate the data cache, we don't need to do anything.
// Invalidate the jit block cache on dcbst in case new code has been loaded via the data cache
- if (jit)
- {
u32 address = Helper_Get_EA_X(_inst);
- jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32);
- }
+ JitInterface::InvalidateICache(address & ~0x1f, 32);
}
void Interpreter::dcbt(UGeckoInstruction _inst)
@@ -409,7 +398,7 @@ void Interpreter::dcbz(UGeckoInstruction _inst)
// HACK but works... we think
if (!Core::g_CoreStartupParameter.bDCBZOFF)
Memory::Memset(Helper_Get_EA_X(_inst) & (~31), 0, 32);
- if (!jit)
+ if (!JitInterface::GetCore())
PowerPC::CheckExceptions();
}
diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
index 5a199b56c8..7847496b6e 100644
--- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
+++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
@@ -26,13 +26,6 @@
#undef _interlockedbittestandreset
#undef _interlockedbittestandset64
#undef _interlockedbittestandreset64
-#else
-static const unsigned short FPU_ROUND_NEAR = 0 << 10;
-static const unsigned short FPU_ROUND_DOWN = 1 << 10;
-static const unsigned short FPU_ROUND_UP = 2 << 10;
-static const unsigned short FPU_ROUND_CHOP = 3 << 10;
-static const unsigned short FPU_ROUND_MASK = 3 << 10;
-#include <xmmintrin.h>
#endif
#include "CPUDetect.h"
@@ -43,6 +36,7 @@ static const unsigned short FPU_ROUND_MASK = 3 << 10;
#include "../../HW/SystemTimers.h"
#include "../../Core.h"
#include "Interpreter.h"
+#include "FPURoundMode.h"
#include "Interpreter_FPUtils.h"
@@ -61,38 +55,11 @@ mffsx: 80036650 (huh?)
// That is, set rounding mode etc when entering jit code or the interpreter loop
// Restore rounding mode when calling anything external
-const u32 MASKS = 0x1F80; // mask away the interrupts.
-const u32 DAZ = 0x40;
-const u32 FTZ = 0x8000;
-
static void FPSCRtoFPUSettings(UReg_FPSCR fp)
{
- // Set FPU rounding mode to mimic the PowerPC's
-#ifdef _M_IX86
- // This shouldn't really be needed anymore since we use SSE
-#ifdef _WIN32
- const int table[4] =
- {
- _RC_NEAR,
- _RC_CHOP,
- _RC_UP,
- _RC_DOWN
- };
- _set_controlfp(_MCW_RC, table[fp.RN]);
-#else
- const unsigned short table[4] =
- {
- FPU_ROUND_NEAR,
- FPU_ROUND_CHOP,
- FPU_ROUND_UP,
- FPU_ROUND_DOWN
- };
- unsigned short mode;
- asm ("fstcw %0" : "=m" (mode) : );
- mode = (mode & ~FPU_ROUND_MASK) | table[fp.RN];
- asm ("fldcw %0" : : "m" (mode));
-#endif
-#endif
+
+ FPURoundMode::SetRoundMode(fp.RN);
+
if (fp.VE || fp.OE || fp.UE || fp.ZE || fp.XE)
{
//PanicAlert("FPSCR - exceptions enabled. Please report. VE=%i OE=%i UE=%i ZE=%i XE=%i",
@@ -101,14 +68,6 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp)
}
// Also corresponding SSE rounding mode setting
- static const u32 ssetable[4] =
- {
- (0 << 13) | MASKS,
- (3 << 13) | MASKS,
- (2 << 13) | MASKS,
- (1 << 13) | MASKS,
- };
- u32 csr = ssetable[FPSCR.RN];
if (FPSCR.NI)
{
// Either one of these two breaks Beyond Good & Evil.
@@ -116,7 +75,7 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp)
// csr |= DAZ;
// csr |= FTZ;
}
- _mm_setcsr(csr);
+ FPURoundMode::SetSIMDMode(FPSCR.RN);
}
void Interpreter::mtfsb0x(UGeckoInstruction _inst)
@@ -234,6 +193,7 @@ void Interpreter::mtmsr(UGeckoInstruction _inst)
{
// Privileged?
MSR = m_GPR[_inst.RS];
+ PowerPC::CheckExceptions();
m_EndBlock = true;
}
diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp
index 8ea35503bf..fee8ed70d8 100644
--- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp
+++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp
@@ -267,7 +267,7 @@ static GekkoOPTemplate table31[] =
{19, Interpreter::mfcr, {"mfcr", OPTYPE_SYSTEM, FL_OUT_D, 0, 0, 0, 0}},
{83, Interpreter::mfmsr, {"mfmsr", OPTYPE_SYSTEM, FL_OUT_D, 0, 0, 0, 0}},
{144, Interpreter::mtcrf, {"mtcrf", OPTYPE_SYSTEM, 0, 0, 0, 0, 0}},
- {146, Interpreter::mtmsr, {"mtmsr", OPTYPE_SYSTEM, FL_ENDBLOCK, 0, 0, 0, 0}},
+ {146, Interpreter::mtmsr, {"mtmsr", OPTYPE_SYSTEM, FL_IN_S | FL_ENDBLOCK, 0, 0, 0, 0}},
{210, Interpreter::mtsr, {"mtsr", OPTYPE_SYSTEM, 0, 0, 0, 0, 0}},
{242, Interpreter::mtsrin, {"mtsrin", OPTYPE_SYSTEM, 0, 0, 0, 0, 0}},
{339, Interpreter::mfspr, {"mfspr", OPTYPE_SPR, FL_OUT_D, 0, 0, 0, 0}},
@@ -297,6 +297,7 @@ static GekkoOPTemplate table31_2[] =
{10, Interpreter::addcx, {"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}},
{522, Interpreter::addcx, {"addcox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}},
{138, Interpreter::addex, {"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}},
+ {650, Interpreter::addex, {"addeox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}},
{234, Interpreter::addmex, {"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}},
{202, Interpreter::addzex, {"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}},
{491, Interpreter::divwx, {"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39, 0, 0, 0}},
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
index 900a8475f7..3995fc9299 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
@@ -24,7 +24,7 @@
#include "Common.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Thunk.h"
#include "../../HLE/HLE.h"
#include "../../Core.h"
@@ -291,7 +291,9 @@ static void ImHere()
void Jit64::Cleanup()
{
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
+ {
ABI_CallFunction((void *)&GPFifo::CheckGatherPipe);
+ }
// SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time.
if (MMCR0.Hex || MMCR1.Hex)
@@ -301,7 +303,8 @@ void Jit64::Cleanup()
void Jit64::WriteExit(u32 destination, int exit_num)
{
Cleanup();
- SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
+
+ SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
//If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock;
@@ -338,7 +341,7 @@ void Jit64::WriteRfiExitDestInEAX()
Cleanup();
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- JMP(asm_routines.outerLoop, true);
+ JMP(asm_routines.dispatcher, true);
}
void Jit64::WriteExceptionExit()
@@ -357,7 +360,7 @@ void Jit64::WriteExternalExceptionExit()
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExternalExceptions));
- SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
+ SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
JMP(asm_routines.dispatcher, true);
}
@@ -561,6 +564,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32)
{
js.fifoBytesThisBlock -= 32;
+ MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
ABI_CallFunction(thunks.ProtectFunction((void *)&GPFifo::CheckGatherPipe, 0));
}
@@ -607,30 +611,6 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
js.firstFPInstructionFound = true;
}
- // Add an external exception check if the instruction writes to the FIFO.
- if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end())
- {
- gpr.Flush(FLUSH_ALL);
- fpr.Flush(FLUSH_ALL);
-
- TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
- FixupBranch clearInt = J_CC(CC_NZ, true);
- TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
- FixupBranch noExtException = J_CC(CC_Z, true);
- TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000));
- FixupBranch noExtIntEnable = J_CC(CC_Z, true);
- TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH));
- FixupBranch noCPInt = J_CC(CC_Z, true);
-
- MOV(32, M(&PC), Imm32(ops[i].address));
- WriteExternalExceptionExit();
-
- SetJumpTarget(noCPInt);
- SetJumpTarget(noExtIntEnable);
- SetJumpTarget(noExtException);
- SetJumpTarget(clearInt);
- }
-
if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING)
{
gpr.Flush(FLUSH_ALL);
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
index 1ebd476134..1d856d6291 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
@@ -62,7 +62,7 @@
if (js.memcheck) \
SetJumpTarget(memException);
-class Jit64 : public JitBase
+class Jit64 : public Jitx86Base
{
private:
GPRRegCache gpr;
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp
index ddb59903d2..cee1f4d048 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp
@@ -310,6 +310,7 @@ static GekkoOPTemplate table31_2[] =
{10, &Jit64::addcx}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{522, &Jit64::addcx}, //"addcox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{138, &Jit64::addex}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
+ {650, &Jit64::addex}, //"addeox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{234, &Jit64::addmex}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{202, &Jit64::addzex}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{491, &Jit64::divwx}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp
index f7082cd1cc..df27a3a641 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp
@@ -15,7 +15,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-#include "ABI.h"
+#include "x64ABI.h"
#include "x64Emitter.h"
#include "../../HW/Memmap.h"
@@ -24,7 +24,7 @@
#include "../../CoreTiming.h"
#include "MemoryUtil.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Jit.h"
#include "../JitCommon/JitCache.h"
@@ -204,7 +204,7 @@ void Jit64AsmRoutineManager::Generate()
MOV(32, M(&NPC), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExternalExceptions));
SetJumpTarget(noExtException);
-
+
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
J_CC(CC_Z, outerLoop, true);
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h
index e8df0877f7..19e1f41ba8 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h
+++ b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h
@@ -18,7 +18,6 @@
#ifndef _JIT64ASM_H
#define _JIT64ASM_H
-#include "x64Emitter.h"
#include "../JitCommon/JitAsmCommon.h"
// In Dolphin, we don't use inline assembly. Instead, we generate all machine-near
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp
index 04e4d09cc9..29d17dc875 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp
@@ -28,7 +28,7 @@
#include "../../HW/Memmap.h"
#include "../PPCTables.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Jit.h"
#include "JitAsm.h"
@@ -302,6 +302,7 @@ void Jit64::stX(UGeckoInstruction inst)
addr += offset;
if ((addr & 0xFFFFF000) == 0xCC008000 && jo.optimizeGatherPipe)
{
+ MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
gpr.FlushLockX(ABI_PARAM1);
MOV(32, R(ABI_PARAM1), gpr.R(s));
if (update)
@@ -329,6 +330,7 @@ void Jit64::stX(UGeckoInstruction inst)
}
else
{
+ MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
switch (accessSize)
{
case 32: ABI_CallFunctionAC(thunks.ProtectFunction(true ? ((void *)&Memory::Write_U32) : ((void *)&Memory::Write_U32_Swap), 2), gpr.R(s), addr); break;
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp
index 9f61e097b8..5766eb3177 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp
@@ -27,7 +27,7 @@
#include "../PPCTables.h"
#include "CPUDetect.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Jit.h"
#include "JitAsm.h"
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp
index 3b14179cd4..a6f57796e4 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp
@@ -28,7 +28,7 @@
#include "../PPCTables.h"
#include "CPUDetect.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Jit.h"
#include "JitAsm.h"
@@ -42,6 +42,7 @@ const u8 GC_ALIGNED16(pbswapShuffle2x4[16]) = {3, 2, 1, 0, 7, 6, 5, 4, 8, 9, 10,
#if 0
static void WriteDual32(u64 value, u32 address)
{
+ MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
Memory::Write_U32((u32)(value >> 32), address);
Memory::Write_U32((u32)value, address + 4);
}
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp
index 14827129f8..7c3766c69a 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp
@@ -23,11 +23,12 @@
#include "../PowerPC.h"
#include "../PPCTables.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Thunk.h"
#include "Jit.h"
#include "JitRegCache.h"
+#include "HW/ProcessorInterface.h"
void Jit64::mtspr(UGeckoInstruction inst)
{
@@ -122,7 +123,29 @@ void Jit64::mtmsr(UGeckoInstruction inst)
gpr.UnlockAll();
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
+
+ // If some exceptions are pending and EE are now enabled, force checking
+ // external exceptions when going out of mtmsr in order to execute delayed
+ // interrupts as soon as possible.
+ TEST(32, M(&MSR), Imm32(0x8000));
+ FixupBranch eeDisabled = J_CC(CC_Z);
+
+ TEST(32, M((void*)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT | EXCEPTION_PERFORMANCE_MONITOR | EXCEPTION_DECREMENTER));
+ FixupBranch noExceptionsPending = J_CC(CC_Z);
+
+ // Check if a CP interrupt is waiting and keep the GPU emulation in sync (issue 4336)
+ TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP));
+ FixupBranch cpInt = J_CC(CC_NZ);
+
+ MOV(32, M(&PC), Imm32(js.compilerPC + 4));
+ WriteExternalExceptionExit();
+
+ SetJumpTarget(cpInt);
+ SetJumpTarget(noExceptionsPending);
+ SetJumpTarget(eeDisabled);
+
WriteExit(js.compilerPC + 4, 0);
+
js.firstFPInstructionFound = false;
}
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp
index 2a830a03cf..fdec5b747d 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp
@@ -1269,7 +1269,7 @@ static const unsigned alwaysUsedList[] = {
Store16, Store32, StoreSingle, StoreDouble, StorePaired, StoreFReg, FDCmpCR,
BlockStart, BlockEnd, IdleBranch, BranchCond, BranchUncond, ShortIdleLoop,
SystemCall, InterpreterBranch, RFIExit, FPExceptionCheck,
- DSIExceptionCheck, ISIException, ExtExceptionCheck, BreakPointCheck,
+ DSIExceptionCheck, ISIException, BreakPointCheck,
Int3, Tramp, Nop
};
static const unsigned extra8RegList[] = {
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h
index 77f7d6977b..5bc7da9d8d 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h
@@ -168,7 +168,7 @@ enum Opcode {
// used for exception checking, at least until someone
// has a better idea of integrating it
FPExceptionCheck, DSIExceptionCheck,
- ISIException, ExtExceptionCheck, BreakPointCheck,
+ ISIException, BreakPointCheck,
// "Opcode" representing a register too far away to
// reference directly; this is a size optimization
Tramp,
@@ -276,8 +276,8 @@ public:
InstLoc EmitLoadMSR() {
return FoldZeroOp(LoadMSR, 0);
}
- InstLoc EmitStoreMSR(InstLoc val) {
- return FoldUOp(StoreMSR, val);
+ InstLoc EmitStoreMSR(InstLoc val, InstLoc pc) {
+ return FoldBiOp(StoreMSR, val, pc);
}
InstLoc EmitStoreFPRF(InstLoc value) {
return FoldUOp(StoreFPRF, value);
@@ -411,9 +411,6 @@ public:
InstLoc EmitISIException(InstLoc dest) {
return EmitUOp(ISIException, dest);
}
- InstLoc EmitExtExceptionCheck(InstLoc pc) {
- return EmitUOp(ExtExceptionCheck, pc);
- }
InstLoc EmitBreakPointCheck(InstLoc pc) {
return EmitUOp(BreakPointCheck, pc);
}
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp
index ce47e2c3ac..88d815e33d 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp
@@ -762,7 +762,6 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
case FPExceptionCheck:
case DSIExceptionCheck:
case ISIException:
- case ExtExceptionCheck:
case BreakPointCheck:
case Int3:
case Tramp:
@@ -994,8 +993,26 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
break;
}
case StoreMSR: {
+ unsigned InstLoc = ibuild->GetImmValue(getOp2(I));
regStoreInstToConstLoc(RI, 32, getOp1(I), &MSR);
regNormalRegClear(RI, I);
+
+ // If some exceptions are pending and EE are now enabled, force checking
+ // external exceptions when going out of mtmsr in order to execute delayed
+ // interrupts as soon as possible.
+ Jit->MOV(32, R(EAX), M(&MSR));
+ Jit->TEST(32, R(EAX), Imm32(0x8000));
+ FixupBranch eeDisabled = Jit->J_CC(CC_Z);
+
+ Jit->MOV(32, R(EAX), M((void*)&PowerPC::ppcState.Exceptions));
+ Jit->TEST(32, R(EAX), R(EAX));
+ FixupBranch noExceptionsPending = Jit->J_CC(CC_Z);
+
+ Jit->MOV(32, M(&PC), Imm32(InstLoc + 4));
+ Jit->WriteExceptionExit(); // TODO: Implement WriteExternalExceptionExit for JitIL
+
+ Jit->SetJumpTarget(eeDisabled);
+ Jit->SetJumpTarget(noExceptionsPending);
break;
}
case StoreGQR: {
@@ -1923,27 +1940,6 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
Jit->WriteExceptionExit();
break;
}
- case ExtExceptionCheck: {
- unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
-
- Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
- FixupBranch clearInt = Jit->J_CC(CC_NZ);
- Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
- FixupBranch noExtException = Jit->J_CC(CC_Z);
- Jit->TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000));
- FixupBranch noExtIntEnable = Jit->J_CC(CC_Z);
- Jit->TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH));
- FixupBranch noCPInt = Jit->J_CC(CC_Z);
-
- Jit->MOV(32, M(&PC), Imm32(InstLoc));
- Jit->WriteExceptionExit();
-
- Jit->SetJumpTarget(noCPInt);
- Jit->SetJumpTarget(noExtIntEnable);
- Jit->SetJumpTarget(noExtException);
- Jit->SetJumpTarget(clearInt);
- break;
- }
case BreakPointCheck: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
@@ -1991,8 +1987,10 @@ void JitIL::WriteCode() {
}
void ProfiledReJit() {
- jit->SetCodePtr(jit->js.rewriteStart);
- DoWriteCode(&((JitIL *)jit)->ibuild, (JitIL *)jit, true, false);
- jit->js.curBlock->codeSize = (int)(jit->GetCodePtr() - jit->js.rewriteStart);
- jit->GetBlockCache()->FinalizeBlock(jit->js.curBlock->blockNum, jit->jo.enableBlocklink, jit->js.curBlock->normalEntry);
+ JitIL *jitil = (JitIL *)jit;
+ jitil->SetCodePtr(jitil->js.rewriteStart);
+ DoWriteCode(&jitil->ibuild, jitil, true, false);
+ jitil->js.curBlock->codeSize = (int)(jitil->GetCodePtr() - jitil->js.rewriteStart);
+ jitil->GetBlockCache()->FinalizeBlock(jitil->js.curBlock->blockNum, jitil->jo.enableBlocklink,
+ jitil->js.curBlock->normalEntry);
}
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp
index d56c9ffee8..f10df33d99 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp
@@ -19,7 +19,7 @@
#include "Common.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Thunk.h"
#include "../../HLE/HLE.h"
#include "../../Core.h"
@@ -389,7 +389,9 @@ static void ImHere()
void JitIL::Cleanup()
{
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
+ {
ABI_CallFunction((void *)&GPFifo::CheckGatherPipe);
+ }
// SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time.
if (MMCR0.Hex || MMCR1.Hex)
@@ -677,11 +679,6 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
ibuild.EmitFPExceptionCheck(ibuild.EmitIntConst(ops[i].address));
}
- if (jit->js.fifoWriteAddresses.find(js.compilerPC) != jit->js.fifoWriteAddresses.end())
- {
- ibuild.EmitExtExceptionCheck(ibuild.EmitIntConst(ops[i].address));
- }
-
if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING)
{
ibuild.EmitBreakPointCheck(ibuild.EmitIntConst(ops[i].address));
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h
index fdda098e44..8c579fa4bd 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h
@@ -57,7 +57,7 @@
#define DISABLE64
#endif
-class JitIL : public JitBase
+class JitIL : public Jitx86Base
{
private:
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp
index 74c290aa9c..aaa155072e 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp
@@ -15,7 +15,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-#include "ABI.h"
+#include "x64ABI.h"
#include "x64Emitter.h"
#include "../../HW/Memmap.h"
@@ -25,7 +25,7 @@
#include "MemoryUtil.h"
#include "CPUDetect.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Thunk.h"
#include "../../HW/GPFifo.h"
@@ -211,14 +211,14 @@ void JitILAsmRoutineManager::Generate()
doTiming = GetCodePtr();
ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
-
+
testExceptions = GetCodePtr();
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
MOV(32, R(EAX), M(&NPC));
MOV(32, M(&PC), R(EAX));
-
+
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
J_CC(CC_Z, outer_loop, true);
//Landing pad for drec space
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp
index 45ceda694a..96902434a6 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp
@@ -27,7 +27,7 @@
#include "../../HW/Memmap.h"
#include "../PPCTables.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "JitIL.h"
#include "JitILAsm.h"
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp
index e06d289cc4..c74abfd8e9 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp
@@ -27,7 +27,7 @@
#include "../PPCTables.h"
#include "CPUDetect.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "JitIL.h"
#include "JitILAsm.h"
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp
index 2f0a0762fd..6e86804bec 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp
@@ -25,7 +25,7 @@
#include "../PPCTables.h"
#include "CPUDetect.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "JitIL.h"
#include "JitILAsm.h"
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp
index f3e25dc2dd..4a1b26a1d6 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp
@@ -23,7 +23,7 @@
#include "../PowerPC.h"
#include "../PPCTables.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Thunk.h"
#include "JitIL.h"
@@ -106,7 +106,7 @@ void JitIL::mfspr(UGeckoInstruction inst)
// --------------
void JitIL::mtmsr(UGeckoInstruction inst)
{
- ibuild.EmitStoreMSR(ibuild.EmitLoadGReg(inst.RS));
+ ibuild.EmitStoreMSR(ibuild.EmitLoadGReg(inst.RS), ibuild.EmitIntConst(js.compilerPC));
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
}
// ==============
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp
index 9418030b9c..fd920c4a48 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp
@@ -311,6 +311,7 @@ static GekkoOPTemplate table31_2[] =
{10, &JitIL::Default}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{522, &JitIL::Default}, //"addcox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{138, &JitIL::addex}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
+ {650, &JitIL::addex}, //"addeox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{234, &JitIL::Default}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{202, &JitIL::addzex}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{491, &JitIL::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp
new file mode 100644
index 0000000000..2c25268c23
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp
@@ -0,0 +1,498 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include <map>
+
+#include "Common.h"
+#include "../../HLE/HLE.h"
+#include "../../Core.h"
+#include "../../PatchEngine.h"
+#include "../../CoreTiming.h"
+#include "../../ConfigManager.h"
+#include "../PowerPC.h"
+#include "../Profiler.h"
+#include "../PPCTables.h"
+#include "../PPCAnalyst.h"
+#include "../../HW/Memmap.h"
+#include "../../HW/GPFifo.h"
+#include "Jit.h"
+#include "JitArm_Tables.h"
+#include "ArmEmitter.h"
+#include "../JitInterface.h"
+
+using namespace ArmGen;
+using namespace PowerPC;
+
+static int CODE_SIZE = 1024*1024*32;
+namespace CPUCompare
+{
+ extern u32 m_BlockStart;
+}
+
+void JitArm::Init()
+{
+ AllocCodeSpace(CODE_SIZE);
+ blocks.Init();
+ asm_routines.Init();
+ // TODO: Investigate why the register cache crashes when only doing Init with
+ // the pointer to this. Seems for some reason it doesn't set the emitter pointer
+ // In the class for some reason?
+ gpr.Init(this);
+ gpr.SetEmitter(this);
+ fpr.Init(this);
+ fpr.SetEmitter(this);
+ jo.enableBlocklink = true;
+ jo.optimizeGatherPipe = false;
+}
+
+void JitArm::ClearCache()
+{
+ ClearCodeSpace();
+ blocks.Clear();
+}
+
+void JitArm::Shutdown()
+{
+ FreeCodeSpace();
+ blocks.Shutdown();
+ asm_routines.Shutdown();
+}
+
+// This is only called by Default() in this file. It will execute an instruction with the interpreter functions.
+void JitArm::WriteCallInterpreter(UGeckoInstruction inst)
+{
+ gpr.Flush();
+ fpr.Flush();
+ Interpreter::_interpreterInstruction instr = GetInterpreterOp(inst);
+ MOVI2R(R0, inst.hex);
+ MOVI2R(R12, (u32)instr);
+ BL(R12);
+}
+void JitArm::unknown_instruction(UGeckoInstruction inst)
+{
+ PanicAlert("unknown_instruction %08x - Fix me ;)", inst.hex);
+}
+
+void JitArm::Default(UGeckoInstruction _inst)
+{
+ WriteCallInterpreter(_inst.hex);
+}
+
+void JitArm::HLEFunction(UGeckoInstruction _inst)
+{
+ gpr.Flush();
+ fpr.Flush();
+ MOVI2R(R0, js.compilerPC);
+ MOVI2R(R1, _inst.hex);
+ QuickCallFunction(R14, (void*)&HLE::Execute);
+ ARMReg rA = gpr.GetReg();
+ LDR(rA, R9, PPCSTATE_OFF(npc));
+ WriteExitDestInR(rA);
+}
+
+void JitArm::DoNothing(UGeckoInstruction _inst)
+{
+ // Yup, just don't do anything.
+}
+
+static const bool ImHereDebug = false;
+static const bool ImHereLog = false;
+static std::map<u32, int> been_here;
+
+static void ImHere()
+{
+ static File::IOFile f;
+ if (ImHereLog)
+ {
+ if (!f)
+ {
+ f.Open("log32.txt", "w");
+ }
+ fprintf(f.GetHandle(), "%08x\n", PC);
+ }
+ if (been_here.find(PC) != been_here.end())
+ {
+ been_here.find(PC)->second++;
+ if ((been_here.find(PC)->second) & 1023)
+ return;
+ }
+ DEBUG_LOG(DYNA_REC, "I'm here - PC = %08x , LR = %08x", PC, LR);
+ been_here[PC] = 1;
+}
+
+void JitArm::Cleanup()
+{
+ if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
+ QuickCallFunction(R14, (void*)&GPFifo::CheckGatherPipe);
+}
+void JitArm::DoDownCount()
+{
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+ MOVI2R(rA, (u32)&CoreTiming::downcount);
+ LDR(rB, rA);
+ if(js.downcountAmount < 255) // We can enlarge this if we used rotations
+ {
+ SUBS(rB, rB, js.downcountAmount);
+ STR(rB, rA);
+ }
+ else
+ {
+ ARMReg rC = gpr.GetReg(false);
+ MOVI2R(rC, js.downcountAmount);
+ SUBS(rB, rB, rC);
+ STR(rB, rA);
+ }
+ gpr.Unlock(rA, rB);
+}
+void JitArm::WriteExitDestInR(ARMReg Reg)
+{
+ STR(Reg, R9, PPCSTATE_OFF(pc));
+ Cleanup();
+ DoDownCount();
+ MOVI2R(Reg, (u32)asm_routines.dispatcher);
+ B(Reg);
+ gpr.Unlock(Reg);
+}
+void JitArm::WriteRfiExitDestInR(ARMReg Reg)
+{
+ STR(Reg, R9, PPCSTATE_OFF(pc));
+ Cleanup();
+ DoDownCount();
+
+ MOVI2R(Reg, (u32)asm_routines.testExceptions);
+ B(Reg);
+ gpr.Unlock(Reg); // This was locked in the instruction beforehand
+}
+void JitArm::WriteExceptionExit()
+{
+ ARMReg A = gpr.GetReg(false);
+ Cleanup();
+ DoDownCount();
+
+ MOVI2R(A, (u32)asm_routines.testExceptions);
+ B(A);
+}
+void JitArm::WriteExit(u32 destination, int exit_num)
+{
+ Cleanup();
+
+ DoDownCount();
+ //If nobody has taken care of this yet (this can be removed when all branches are done)
+ JitBlock *b = js.curBlock;
+ b->exitAddress[exit_num] = destination;
+ b->exitPtrs[exit_num] = GetWritableCodePtr();
+
+ // Link opportunity!
+ int block = blocks.GetBlockNumberFromStartAddress(destination);
+ if (block >= 0 && jo.enableBlocklink)
+ {
+ // It exists! Joy of joy!
+ B(blocks.GetBlock(block)->checkedEntry);
+ b->linkStatus[exit_num] = true;
+ }
+ else
+ {
+ ARMReg A = gpr.GetReg(false);
+ MOVI2R(A, destination);
+ STR(A, R9, PPCSTATE_OFF(pc));
+ MOVI2R(A, (u32)asm_routines.dispatcher);
+ B(A);
+ }
+}
+
+void STACKALIGN JitArm::Run()
+{
+ CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode;
+ pExecAddr();
+}
+
+void JitArm::SingleStep()
+{
+ CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode;
+ pExecAddr();
+}
+
+void JitArm::Trace()
+{
+ char regs[500] = "";
+ char fregs[750] = "";
+
+#ifdef JIT_LOG_GPR
+ for (int i = 0; i < 32; i++)
+ {
+ char reg[50];
+ sprintf(reg, "r%02d: %08x ", i, PowerPC::ppcState.gpr[i]);
+ strncat(regs, reg, 500);
+ }
+#endif
+
+#ifdef JIT_LOG_FPR
+ for (int i = 0; i < 32; i++)
+ {
+ char reg[50];
+ sprintf(reg, "f%02d: %016x ", i, riPS0(i));
+ strncat(fregs, reg, 750);
+ }
+#endif
+
+ DEBUG_LOG(DYNA_REC, "JITARM PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s",
+ PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3],
+ PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr,
+ PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs, fregs);
+}
+
+void JitArm::PrintDebug(UGeckoInstruction inst, u32 level)
+{
+ if (level > 0)
+ printf("Start: %08x OP '%s' Info\n", (u32)GetCodePtr(), PPCTables::GetInstructionName(inst));
+ if (level > 1)
+ {
+ GekkoOPInfo* Info = GetOpInfo(inst.hex);
+ printf("\tOuts\n");
+ if (Info->flags & FL_OUT_A)
+ printf("\t-OUT_A: %x\n", inst.RA);
+ if(Info->flags & FL_OUT_D)
+ printf("\t-OUT_D: %x\n", inst.RD);
+ printf("\tIns\n");
+ // A, AO, B, C, S
+ if(Info->flags & FL_IN_A)
+ printf("\t-IN_A: %x\n", inst.RA);
+ if(Info->flags & FL_IN_A0)
+ printf("\t-IN_A0: %x\n", inst.RA);
+ if(Info->flags & FL_IN_B)
+ printf("\t-IN_B: %x\n", inst.RB);
+ if(Info->flags & FL_IN_C)
+ printf("\t-IN_C: %x\n", inst.RC);
+ if(Info->flags & FL_IN_S)
+ printf("\t-IN_S: %x\n", inst.RS);
+ }
+}
+
+void STACKALIGN JitArm::Jit(u32 em_address)
+{
+ if (GetSpaceLeft() < 0x10000 || blocks.IsFull() || Core::g_CoreStartupParameter.bJITNoBlockCache)
+ {
+ ClearCache();
+ }
+
+ int block_num = blocks.AllocateBlock(em_address);
+ JitBlock *b = blocks.GetBlock(block_num);
+ const u8* BlockPtr = DoJit(em_address, &code_buffer, b);
+ blocks.FinalizeBlock(block_num, jo.enableBlocklink, BlockPtr);
+}
+void JitArm::Break(UGeckoInstruction inst)
+{
+ BKPT(0x4444);
+}
+
+const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b)
+{
+ int blockSize = code_buf->GetSize();
+ // Memory exception on instruction fetch
+ bool memory_exception = false;
+
+ // A broken block is a block that does not end in a branch
+ bool broken_block = false;
+
+ if (Core::g_CoreStartupParameter.bEnableDebugging)
+ {
+ // Comment out the following to disable breakpoints (speed-up)
+ blockSize = 1;
+ broken_block = true;
+ Trace();
+ }
+
+ if (em_address == 0)
+ {
+ Core::SetState(Core::CORE_PAUSE);
+ PanicAlert("ERROR: Compiling at 0. LR=%08x CTR=%08x", LR, CTR);
+ }
+
+ if (Core::g_CoreStartupParameter.bMMU && (em_address & JIT_ICACHE_VMEM_BIT))
+ {
+ if (!Memory::TranslateAddress(em_address, Memory::FLAG_OPCODE))
+ {
+ // Memory exception occurred during instruction fetch
+ memory_exception = true;
+ }
+ }
+
+
+ int size = 0;
+ js.isLastInstruction = false;
+ js.blockStart = em_address;
+ js.fifoBytesThisBlock = 0;
+ js.curBlock = b;
+ js.block_flags = 0;
+ js.cancel = false;
+
+ // Analyze the block, collect all instructions it is made of (including inlining,
+ // if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
+ u32 nextPC = em_address;
+ u32 merged_addresses[32];
+ const int capacity_of_merged_addresses = sizeof(merged_addresses) / sizeof(merged_addresses[0]);
+ int size_of_merged_addresses = 0;
+ if (!memory_exception)
+ {
+ // If there is a memory exception inside a block (broken_block==true), compile up to that instruction.
+ nextPC = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses);
+ }
+ PPCAnalyst::CodeOp *ops = code_buf->codebuffer;
+
+ const u8 *start = GetCodePtr();
+ b->checkedEntry = start;
+ b->runCount = 0;
+
+ // Downcount flag check, Only valid for linked blocks
+ {
+ FixupBranch skip = B_CC(CC_PL);
+ ARMReg rA = gpr.GetReg(false);
+ MOVI2R(rA, js.blockStart);
+ STR(rA, R9, PPCSTATE_OFF(pc));
+ MOVI2R(rA, (u32)asm_routines.doTiming);
+ B(rA);
+ SetJumpTarget(skip);
+ }
+
+ const u8 *normalEntry = GetCodePtr();
+ b->normalEntry = normalEntry;
+
+ if(ImHereDebug)
+ QuickCallFunction(R14, (void *)&ImHere); //Used to get a trace of the last few blocks before a crash, sometimes VERY useful
+
+ if (js.fpa.any)
+ {
+ // This block uses FPU - needs to add FP exception bailout
+ ARMReg A = gpr.GetReg();
+ ARMReg C = gpr.GetReg();
+ Operand2 Shift(2, 10); // 1 << 13
+ MOVI2R(C, js.blockStart); // R3
+ LDR(A, R9, PPCSTATE_OFF(msr));
+ TST(A, Shift);
+ FixupBranch b1 = B_CC(CC_NEQ);
+ STR(C, R9, PPCSTATE_OFF(pc));
+ MOVI2R(A, (u32)asm_routines.fpException);
+ B(A);
+ SetJumpTarget(b1);
+ gpr.Unlock(A, C);
+ }
+ // Conditionally add profiling code.
+ if (Profiler::g_ProfileBlocks) {
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+ MOVI2R(rA, (u32)&b->runCount); // Load in to register
+ LDR(rB, rA); // Load the actual value in to R11.
+ ADD(rB, rB, 1); // Add one to the value
+ STR(rB, rA); // Now store it back in the memory location
+ // get start tic
+ PROFILER_QUERY_PERFORMANCE_COUNTER(&b->ticStart);
+ gpr.Unlock(rA, rB);
+ }
+ gpr.Start(js.gpa);
+ fpr.Start(js.fpa);
+ js.downcountAmount = 0;
+ if (!Core::g_CoreStartupParameter.bEnableDebugging)
+ {
+ for (int i = 0; i < size_of_merged_addresses; ++i)
+ {
+ const u32 address = merged_addresses[i];
+ js.downcountAmount += PatchEngine::GetSpeedhackCycles(address);
+ }
+ }
+
+ js.skipnext = false;
+ js.blockSize = size;
+ js.compilerPC = nextPC;
+ // Translate instructions
+ for (int i = 0; i < (int)size; i++)
+ {
+ js.compilerPC = ops[i].address;
+ js.op = &ops[i];
+ js.instructionNumber = i;
+ const GekkoOPInfo *opinfo = ops[i].opinfo;
+ js.downcountAmount += (opinfo->numCyclesMinusOne + 1);
+
+ if (i == (int)size - 1)
+ {
+ // WARNING - cmp->branch merging will screw this up.
+ js.isLastInstruction = true;
+ js.next_inst = 0;
+ if (Profiler::g_ProfileBlocks) {
+ // CAUTION!!! push on stack regs you use, do your stuff, then pop
+ PROFILER_VPUSH;
+ // get end tic
+ PROFILER_QUERY_PERFORMANCE_COUNTER(&b->ticStop);
+ // tic counter += (end tic - start tic)
+ PROFILER_ADD_DIFF_LARGE_INTEGER(&b->ticCounter, &b->ticStop, &b->ticStart);
+ PROFILER_VPOP;
+ }
+ }
+ else
+ {
+ // help peephole optimizations
+ js.next_inst = ops[i + 1].inst;
+ js.next_compilerPC = ops[i + 1].address;
+ }
+ if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32)
+ {
+ js.fifoBytesThisBlock -= 32;
+ // TODO: This needs thunkmanager for ARM
+ //ARMABI_CallFunction(thunks.ProtectFunction((void *)&GPFifo::CheckGatherPipe, 0));
+ }
+ if (Core::g_CoreStartupParameter.bEnableDebugging)
+ {
+ // Add run count
+ ARMReg RA = gpr.GetReg();
+ ARMReg RB = gpr.GetReg();
+ MOVI2R(RA, (u32)&opinfo->runCount);
+ LDR(RB, RA);
+ ADD(RB, RB, 1);
+ STR(RB, RA);
+ gpr.Unlock(RA, RB);
+ }
+ if (!ops[i].skip)
+ {
+ PrintDebug(ops[i].inst, 0);
+ if (js.memcheck && (opinfo->flags & FL_USE_FPU))
+ {
+ // Don't do this yet
+ BKPT(0x7777);
+ }
+ JitArmTables::CompileInstruction(ops[i]);
+ if (js.memcheck && (opinfo->flags & FL_LOADSTORE))
+ {
+ // Don't do this yet
+ BKPT(0x666);
+ }
+ }
+ }
+ if (memory_exception)
+ BKPT(0x500);
+ if (broken_block)
+ {
+ printf("Broken Block going to 0x%08x\n", nextPC);
+ WriteExit(nextPC, 0);
+ }
+
+ b->flags = js.block_flags;
+ b->codeSize = (u32)(GetCodePtr() - normalEntry);
+ b->originalSize = size;
+ FlushIcache();
+ return start;
+}
+
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h
new file mode 100644
index 0000000000..7067e3a3a4
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h
@@ -0,0 +1,186 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+// ========================
+// See comments in Jit.cpp.
+// ========================
+
+// Mystery: Capcom vs SNK 800aa278
+
+// CR flags approach:
+// * Store that "N+Z flag contains CR0" or "S+Z flag contains CR3".
+// * All flag altering instructions flush this
+// * A flush simply does a conditional write to the appropriate CRx.
+// * If flag available, branch code can become absolutely trivial.
+
+// Settings
+// ----------
+#ifndef _JITARM_H
+#define _JITARM_H
+#include "../CPUCoreBase.h"
+#include "../PPCAnalyst.h"
+#include "JitArmCache.h"
+#include "JitRegCache.h"
+#include "JitFPRCache.h"
+#include "JitAsm.h"
+#include "../JitCommon/JitBase.h"
+
+// Use these to control the instruction selection
+// #define INSTRUCTION_START Default(inst); return;
+// #define INSTRUCTION_START PPCTables::CountInstruction(inst);
+#define INSTRUCTION_START
+#define JITDISABLE(type) \
+ if (Core::g_CoreStartupParameter.bJITOff || \
+ Core::g_CoreStartupParameter.bJIT##type##Off) \
+ {Default(inst); return;}
+#define PPCSTATE_OFF(elem) ((s32)STRUCT_OFF(PowerPC::ppcState, elem) - (s32)STRUCT_OFF(PowerPC::ppcState, spr[0]))
+class JitArm : public JitBase, public ArmGen::ARMXCodeBlock
+{
+private:
+ JitArmBlockCache blocks;
+
+ JitArmAsmRoutineManager asm_routines;
+
+ // TODO: Make arm specific versions of these, shouldn't be too hard to
+ // make it so we allocate some space at the start(?) of code generation
+ // and keep the registers in a cache. Will burn this bridge when we get to
+ // it.
+ ArmRegCache gpr;
+ ArmFPRCache fpr;
+
+ PPCAnalyst::CodeBuffer code_buffer;
+ void DoDownCount();
+
+ void PrintDebug(UGeckoInstruction inst, u32 level);
+
+ void Helper_UpdateCR1(ARMReg value);
+public:
+ JitArm() : code_buffer(32000) {}
+ ~JitArm() {}
+
+ void Init();
+ void Shutdown();
+
+ // Jit!
+
+ void Jit(u32 em_address);
+ const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b);
+
+ JitBaseBlockCache *GetBlockCache() { return &blocks; }
+
+ const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx);
+
+ bool IsInCodeSpace(u8 *ptr) { return IsInSpace(ptr); }
+
+ void Trace();
+
+ void ClearCache();
+
+ const u8 *GetDispatcher() {
+ return asm_routines.dispatcher;
+ }
+ CommonAsmRoutinesBase *GetAsmRoutines() {
+ return &asm_routines;
+ }
+
+ const char *GetName() {
+ return "JITARM";
+ }
+ // Run!
+
+ void Run();
+ void SingleStep();
+
+ // Utilities for use by opcodes
+
+ void WriteExit(u32 destination, int exit_num);
+ void WriteExitDestInR(ARMReg Reg);
+ void WriteRfiExitDestInR(ARMReg Reg);
+ void WriteExceptionExit();
+ void WriteCallInterpreter(UGeckoInstruction _inst);
+ void Cleanup();
+
+ void GenerateRC(int cr = 0);
+ void ComputeRC(int cr = 0);
+
+ // TODO: This shouldn't be here
+ void StoreFromReg(ARMReg dest, ARMReg value, int accessSize, s32 offset);
+ void LoadToReg(ARMReg dest, ARMReg addr, int accessSize, s32 offset);
+
+ // OPCODES
+ void unknown_instruction(UGeckoInstruction _inst);
+ void Default(UGeckoInstruction _inst);
+ void DoNothing(UGeckoInstruction _inst);
+ void HLEFunction(UGeckoInstruction _inst);
+
+ void DynaRunTable4(UGeckoInstruction _inst);
+ void DynaRunTable19(UGeckoInstruction _inst);
+ void DynaRunTable31(UGeckoInstruction _inst);
+ void DynaRunTable59(UGeckoInstruction _inst);
+ void DynaRunTable63(UGeckoInstruction _inst);
+
+ // Breakin shit
+ void Break(UGeckoInstruction _inst);
+ // Branch
+ void bx(UGeckoInstruction _inst);
+ void bcx(UGeckoInstruction _inst);
+ void bclrx(UGeckoInstruction _inst);
+ void sc(UGeckoInstruction _inst);
+ void rfi(UGeckoInstruction _inst);
+ void bcctrx(UGeckoInstruction _inst);
+
+ // Integer
+ void addi(UGeckoInstruction _inst);
+ void addis(UGeckoInstruction _inst);
+ void addx(UGeckoInstruction _inst);
+ void cmp (UGeckoInstruction _inst);
+ void cmpi(UGeckoInstruction _inst);
+ void cmpli(UGeckoInstruction _inst);
+ void negx(UGeckoInstruction _inst);
+ void mulli(UGeckoInstruction _inst);
+ void ori(UGeckoInstruction _inst);
+ void oris(UGeckoInstruction _inst);
+ void orx(UGeckoInstruction _inst);
+ void rlwimix(UGeckoInstruction _inst);
+ void rlwinmx(UGeckoInstruction _inst);
+ void extshx(UGeckoInstruction inst);
+ void extsbx(UGeckoInstruction inst);
+
+ // System Registers
+ void mtmsr(UGeckoInstruction _inst);
+ void mtspr(UGeckoInstruction _inst);
+ void mfspr(UGeckoInstruction _inst);
+
+ // LoadStore
+ void icbi(UGeckoInstruction _inst);
+ void lbz(UGeckoInstruction _inst);
+ void lhz(UGeckoInstruction _inst);
+ void lwz(UGeckoInstruction _inst);
+ void lwzx(UGeckoInstruction _inst);
+ void stw(UGeckoInstruction _inst);
+ void stwu(UGeckoInstruction _inst);
+
+ // Floating point
+ void fabsx(UGeckoInstruction _inst);
+ void faddx(UGeckoInstruction _inst);
+ void fmrx(UGeckoInstruction _inst);
+
+ // Floating point loadStore
+ void lfs(UGeckoInstruction _inst);
+};
+
+#endif // _JIT64_H
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp
new file mode 100644
index 0000000000..1706efafb0
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp
@@ -0,0 +1,46 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+// Enable define below to enable oprofile integration. For this to work,
+// it requires at least oprofile version 0.9.4, and changing the build
+// system to link the Dolphin executable against libopagent. Since the
+// dependency is a little inconvenient and this is possibly a slight
+// performance hit, it's not enabled by default, but it's useful for
+// locating performance issues.
+
+#include "../JitInterface.h"
+#include "Jit.h"
+#include "JitArmCache.h"
+
+
+using namespace ArmGen;
+
+ void JitArmBlockCache::WriteLinkBlock(u8* location, const u8* address)
+ {
+ ARMXEmitter emit(location);
+ emit.B(address);
+ }
+ void JitArmBlockCache::WriteDestroyBlock(const u8* location, u32 address)
+ {
+ ARMXEmitter emit((u8 *)location);
+ emit.MOVI2R(R11, address);
+ emit.MOVI2R(R12, (u32)jit->GetAsmRoutines()->dispatcher);
+ emit.STR(R11, R9, PPCSTATE_OFF(pc));
+ emit.B(R12);
+ }
+
+
diff --git a/Source/Core/DolphinWX/Src/GLInterface/WX.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.h
index 82304942ea..103947d5ad 100644
--- a/Source/Core/DolphinWX/Src/GLInterface/WX.h
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.h
@@ -14,35 +14,20 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-#ifndef _INTERFACEWX_H_
-#define _INTERFACEWX_H_
-
-#if defined HAVE_X11 && HAVE_X11
-#include <GL/glxew.h>
-#include <GL/gl.h>
-#elif defined __APPLE__
-#include <GL/glew.h>
-#import <AppKit/AppKit.h>
-#endif
-#if defined USE_WX && USE_WX
-#include "wx/wx.h"
-#include "wx/glcanvas.h"
-#endif
+#ifndef _JITARMCACHE_H
+#define _JITARMCACHE_H
+
+#include "../JitCommon/JitCache.h"
-#include "InterfaceBase.h"
-class cInterfaceWX : public cInterfaceBase
+typedef void (*CompiledCode)();
+
+class JitArmBlockCache : public JitBaseBlockCache
{
-public:
- void SwapInterval(int Interval);
- void Swap();
- void UpdateFPSDisplay(const char *Text);
- bool Create(void *&window_handle);
- bool MakeCurrent();
- void Shutdown();
-
- void Update();
+private:
+ void WriteLinkBlock(u8* location, const u8* address);
+ void WriteDestroyBlock(const u8* location, u32 address);
};
-#endif
+#endif
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_BackPatch.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_BackPatch.cpp
new file mode 100644
index 0000000000..677dc238a8
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_BackPatch.cpp
@@ -0,0 +1,164 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include <string>
+
+#include "Common.h"
+
+#include "../../HW/Memmap.h"
+#include "Jit.h"
+#include "../JitCommon/JitBackpatch.h"
+#include "StringUtil.h"
+
+#ifdef _M_X64
+static void BackPatchError(const std::string &text, u8 *codePtr, u32 emAddress) {
+ u64 code_addr = (u64)codePtr;
+ disassembler disasm;
+ char disbuf[256];
+ memset(disbuf, 0, 256);
+#ifdef _M_IX86
+ disasm.disasm32(0, code_addr, codePtr, disbuf);
+#else
+ disasm.disasm64(0, code_addr, codePtr, disbuf);
+#endif
+ PanicAlert("%s\n\n"
+ "Error encountered accessing emulated address %08x.\n"
+ "Culprit instruction: \n%s\nat %#llx",
+ text.c_str(), emAddress, disbuf, code_addr);
+ return;
+}
+#endif
+
+// This generates some fairly heavy trampolines, but:
+// 1) It's really necessary. We don't know anything about the context.
+// 2) It doesn't really hurt. Only instructions that access I/O will get these, and there won't be
+// that many of them in a typical program/game.
+bool DisamLoadStore(const u32 inst, ARMReg &rD, u8 &accessSize, bool &Store)
+{
+ u8 op = (inst >> 20) & 0xFF;
+ printf("op: 0x%08x\n", op);
+ switch (op)
+ {
+ case 0x58: // STR
+ {
+ rD = (ARMReg)((inst >> 16) & 0xF);
+ Store = true;
+ accessSize = 32;
+ }
+ break;
+ case 0x59: // LDR
+ {
+ rD = (ARMReg)((inst >> 16) & 0xF);
+ Store = false;
+ accessSize = 32;
+ }
+ break;
+ case 0x05: // LDRH
+ {
+ rD = (ARMReg)((inst >> 16) & 0xF);
+ Store = false;
+ accessSize = 16;
+ }
+ break;
+ case 0x45 + 0x18: // LDRB
+ {
+ rD = (ARMReg)((inst >> 16) & 0xF);
+ Store = false;
+ accessSize = 8;
+ }
+ break;
+ case 0x44 + 0x18: // STRB
+ default:
+ return false;
+ }
+ return true;
+}
+const u8 *JitArm::BackPatch(u8 *codePtr, int accessType, u32 emAddress, void *ctx_void)
+{
+ // TODO: This ctx needs to be filled with our information
+ CONTEXT *ctx = (CONTEXT *)ctx_void;
+
+ // We need to get the destination register before we start
+ u32 Value = *(u32*)codePtr;
+ ARMReg rD;
+ u8 accessSize;
+ bool Store;
+
+ if (!DisamLoadStore(Value, rD, accessSize, Store))
+ {
+ printf("Invalid backpatch at location 0x%08x(0x%08x)\n", ctx->reg_pc, Value);
+ exit(0);
+ }
+
+ if (Store)
+ {
+ const u32 ARMREGOFFSET = 4 * 7;
+ ARMXEmitter emitter(codePtr - ARMREGOFFSET);
+ switch (accessSize)
+ {
+ case 8: // 8bit
+ //emitter.MOVI2R(R14, (u32)&Memory::Write_U8, false); // 1-2
+ return 0;
+ break;
+ case 16: // 16bit
+ //emitter.MOVI2R(R14, (u32)&Memory::Write_U16, false); // 1-2
+ return 0;
+ break;
+ case 32: // 32bit
+ emitter.MOVI2R(R14, (u32)&Memory::Write_U32, false); // 1-2
+ break;
+ }
+ emitter.PUSH(4, R0, R1, R2, R3); // 3
+ emitter.MOV(R0, rD); // Value - 4
+ emitter.MOV(R1, R10); // Addr- 5
+ emitter.BL(R14); // 6
+ emitter.POP(4, R0, R1, R2, R3); // 7
+ emitter.NOP(1); // 8
+ u32 newPC = ctx->reg_pc - (ARMREGOFFSET + 4 * 4);
+ ctx->reg_pc = newPC;
+ emitter.FlushIcache();
+ return codePtr;
+ }
+ else
+ {
+ const u32 ARMREGOFFSET = 4 * 6;
+ ARMXEmitter emitter(codePtr - ARMREGOFFSET);
+ switch (accessSize)
+ {
+ case 8: // 8bit
+ emitter.MOVI2R(R14, (u32)&Memory::Read_U8, false); // 2
+ break;
+ case 16: // 16bit
+ emitter.MOVI2R(R14, (u32)&Memory::Read_U16, false); // 2
+ break;
+ case 32: // 32bit
+ emitter.MOVI2R(R14, (u32)&Memory::Read_U32, false); // 2
+ break;
+ }
+ emitter.PUSH(4, R0, R1, R2, R3); // 3
+ emitter.MOV(R0, R10); // 4
+ emitter.BL(R14); // 5
+ emitter.MOV(R14, R0); // 6
+ emitter.POP(4, R0, R1, R2, R3); // 7
+ emitter.MOV(rD, R14); // 8
+ ctx->reg_pc -= ARMREGOFFSET + (4 * 4);
+ emitter.FlushIcache();
+ return codePtr;
+ }
+ return 0;
+}
+
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp
new file mode 100644
index 0000000000..5a1a4659a6
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp
@@ -0,0 +1,356 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+#include "Common.h"
+#include "Thunk.h"
+
+#include "../../Core.h"
+#include "../PowerPC.h"
+#include "../../CoreTiming.h"
+#include "../PPCTables.h"
+#include "ArmEmitter.h"
+
+#include "Jit.h"
+#include "JitRegCache.h"
+#include "JitAsm.h"
+
+// The branches are known good, or at least reasonably good.
+// No need for a disable-mechanism.
+
+// If defined, clears CR0 at blr and bl-s. If the assumption that
+// flags never carry over between functions holds, then the task for
+// an optimizer becomes much easier.
+
+// #define ACID_TEST
+
+// Zelda and many more games seem to pass the Acid Test.
+
+
+using namespace ArmGen;
+void JitArm::sc(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Branch)
+
+ gpr.Flush();
+ fpr.Flush();
+
+ ARMReg rA = gpr.GetReg();
+ MOVI2R(rA, js.compilerPC + 4);
+ STR(rA, R9, PPCSTATE_OFF(pc));
+ LDR(rA, R9, PPCSTATE_OFF(Exceptions));
+ ORR(rA, rA, EXCEPTION_SYSCALL);
+ STR(rA, R9, PPCSTATE_OFF(Exceptions));
+ gpr.Unlock(rA);
+
+ WriteExceptionExit();
+}
+
+void JitArm::rfi(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Branch)
+
+ gpr.Flush();
+ fpr.Flush();
+
+ // See Interpreter rfi for details
+ const u32 mask = 0x87C0FFFF;
+ const u32 clearMSR13 = 0xFFFBFFFF; // Mask used to clear the bit MSR[13]
+ // MSR = ((MSR & ~mask) | (SRR1 & mask)) & clearMSR13;
+ // R0 = MSR location
+ // R1 = MSR contents
+ // R2 = Mask
+ // R3 = Mask
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+ ARMReg rC = gpr.GetReg();
+ ARMReg rD = gpr.GetReg();
+ MOVI2R(rB, (~mask) & clearMSR13);
+ MOVI2R(rC, mask & clearMSR13);
+
+ LDR(rD, R9, PPCSTATE_OFF(msr));
+
+ AND(rD, rD, rB); // rD = Masked MSR
+ STR(rD, R9, PPCSTATE_OFF(msr));
+
+ LDR(rB, R9, PPCSTATE_OFF(spr[SPR_SRR1])); // rB contains SRR1 here
+
+ AND(rB, rB, rC); // rB contains masked SRR1 here
+ ORR(rB, rD, rB); // rB = Masked MSR OR masked SRR1
+
+ STR(rB, R9, PPCSTATE_OFF(msr)); // STR rB in to rA
+
+ LDR(rA, R9, PPCSTATE_OFF(spr[SPR_SRR0]));
+
+ gpr.Unlock(rB, rC, rD);
+ WriteRfiExitDestInR(rA); // rA gets unlocked here
+ //AND(32, M(&MSR), Imm32((~mask) & clearMSR13));
+ //MOV(32, R(EAX), M(&SRR1));
+ //AND(32, R(EAX), Imm32(mask & clearMSR13));
+ //OR(32, M(&MSR), R(EAX));
+ // NPC = SRR0;
+ //MOV(32, R(EAX), M(&SRR0));
+ //WriteRfiExitDestInEAX();
+}
+
+void JitArm::bx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Branch)
+ // We must always process the following sentence
+ // even if the blocks are merged by PPCAnalyst::Flatten().
+ if (inst.LK)
+ {
+ ARMReg rA = gpr.GetReg(false);
+ u32 Jumpto = js.compilerPC + 4;
+ MOVI2R(rA, Jumpto);
+ STR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
+ //ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
+ }
+ // If this is not the last instruction of a block,
+ // we will skip the rest process.
+ // Because PPCAnalyst::Flatten() merged the blocks.
+ if (!js.isLastInstruction) {
+ return;
+ }
+
+ gpr.Flush();
+ fpr.Flush();
+
+ u32 destination;
+ if (inst.AA)
+ destination = SignExt26(inst.LI << 2);
+ else
+ destination = js.compilerPC + SignExt26(inst.LI << 2);
+ #ifdef ACID_TEST
+ // TODO: Not implemented yet.
+ //if (inst.LK)
+ //AND(32, M(&PowerPC::ppcState.cr), Imm32(~(0xFF000000)));
+ #endif
+ if (destination == js.compilerPC)
+ {
+ //PanicAlert("Idle loop detected at %08x", destination);
+ // CALL(ProtectFunction(&CoreTiming::Idle, 0));
+ // JMP(Asm::testExceptions, true);
+ // make idle loops go faster
+ js.downcountAmount += 8;
+ }
+ WriteExit(destination, 0);
+}
+
+void JitArm::bcx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Branch)
+ // USES_CR
+ _assert_msg_(DYNA_REC, js.isLastInstruction, "bcx not last instruction of block");
+
+ gpr.Flush();
+ fpr.Flush();
+
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+ FixupBranch pCTRDontBranch;
+ if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR
+ {
+ LDR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));
+ SUBS(rB, rB, 1);
+ STR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));
+
+ //SUB(32, M(&CTR), Imm8(1));
+ if (inst.BO & BO_BRANCH_IF_CTR_0)
+ pCTRDontBranch = B_CC(CC_NEQ);
+ else
+ pCTRDontBranch = B_CC(CC_EQ);
+ }
+
+ FixupBranch pConditionDontBranch;
+ if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit
+ {
+ LDRB(rA, R9, PPCSTATE_OFF(cr_fast) + (inst.BI >> 2));
+ TST(rA, 8 >> (inst.BI & 3));
+
+ //TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3)));
+ if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch
+ pConditionDontBranch = B_CC(CC_EQ); // Zero
+ else
+ pConditionDontBranch = B_CC(CC_NEQ); // Not Zero
+ }
+ if (inst.LK)
+ {
+ u32 Jumpto = js.compilerPC + 4;
+ MOVI2R(rB, Jumpto);
+ STR(rB, R9, PPCSTATE_OFF(spr[SPR_LR]));
+ //ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); // Careful, destroys R14, R12
+ }
+ gpr.Unlock(rA, rB);
+
+ u32 destination;
+ if(inst.AA)
+ destination = SignExt16(inst.BD << 2);
+ else
+ destination = js.compilerPC + SignExt16(inst.BD << 2);
+ WriteExit(destination, 0);
+
+ if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0)
+ SetJumpTarget( pConditionDontBranch );
+ if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
+ SetJumpTarget( pCTRDontBranch );
+
+ WriteExit(js.compilerPC + 4, 1);
+}
+void JitArm::bcctrx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Branch)
+
+ gpr.Flush();
+ fpr.Flush();
+
+ // bcctrx doesn't decrement and/or test CTR
+ _dbg_assert_msg_(POWERPC, inst.BO_2 & BO_DONT_DECREMENT_FLAG, "bcctrx with decrement and test CTR option is invalid!");
+
+ if (inst.BO_2 & BO_DONT_CHECK_CONDITION)
+ {
+ // BO_2 == 1z1zz -> b always
+
+ //NPC = CTR & 0xfffffffc;
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+
+ if(inst.LK_3)
+ {
+ u32 Jumpto = js.compilerPC + 4;
+ MOVI2R(rA, Jumpto);
+ STR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
+ // ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
+ }
+ MVN(rB, 0x3); // 0xFFFFFFFC
+ LDR(rA, R9, PPCSTATE_OFF(spr[SPR_CTR]));
+ AND(rA, rA, rB);
+ gpr.Unlock(rB);
+ WriteExitDestInR(rA);
+ }
+ else
+ {
+ // Rare condition seen in (just some versions of?) Nintendo's NES Emulator
+
+ // BO_2 == 001zy -> b if false
+ // BO_2 == 011zy -> b if true
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+
+ LDRB(rA, R9, PPCSTATE_OFF(cr_fast) + (inst.BI >> 2));
+ TST(rA, 8 >> (inst.BI & 3));
+ CCFlags branch;
+ if (inst.BO_2 & BO_BRANCH_IF_TRUE)
+ branch = CC_EQ;
+ else
+ branch = CC_NEQ;
+ FixupBranch b = B_CC(branch);
+
+ LDR(rA, R9, PPCSTATE_OFF(spr[SPR_CTR]));
+ MVN(rB, 0x3); // 0xFFFFFFFC
+ AND(rA, rA, rB);
+
+ if (inst.LK_3){
+ u32 Jumpto = js.compilerPC + 4;
+ MOVI2R(rB, Jumpto);
+ STR(rB, R9, PPCSTATE_OFF(spr[SPR_LR]));
+ //ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
+ }
+ gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR
+ WriteExitDestInR(rA);
+
+ SetJumpTarget(b);
+ WriteExit(js.compilerPC + 4, 1);
+ }
+}
+void JitArm::bclrx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Branch)
+ if (!js.isLastInstruction &&
+ (inst.BO & (1 << 4)) && (inst.BO & (1 << 2))) {
+ if (inst.LK)
+ {
+ ARMReg rA = gpr.GetReg(false);
+ u32 Jumpto = js.compilerPC + 4;
+ MOVI2R(rA, Jumpto);
+ STR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
+ // ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
+ }
+ return;
+ }
+ gpr.Flush();
+ fpr.Flush();
+
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+ FixupBranch pCTRDontBranch;
+ if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR
+ {
+ LDR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));
+ SUBS(rB, rB, 1);
+ STR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));
+
+ //SUB(32, M(&CTR), Imm8(1));
+ if (inst.BO & BO_BRANCH_IF_CTR_0)
+ pCTRDontBranch = B_CC(CC_NEQ);
+ else
+ pCTRDontBranch = B_CC(CC_EQ);
+ }
+
+ FixupBranch pConditionDontBranch;
+ if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit
+ {
+ LDRB(rA, R9, PPCSTATE_OFF(cr_fast) + (inst.BI >> 2));
+ TST(rA, 8 >> (inst.BI & 3));
+ //TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3)));
+ if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch
+ pConditionDontBranch = B_CC(CC_EQ); // Zero
+ else
+ pConditionDontBranch = B_CC(CC_NEQ); // Not Zero
+ }
+
+ // This below line can be used to prove that blr "eats flags" in practice.
+ // This observation will let us do a lot of fun observations.
+ #ifdef ACID_TEST
+ // TODO: Not yet implemented
+ // AND(32, M(&PowerPC::ppcState.cr), Imm32(~(0xFF000000)));
+ #endif
+
+ //MOV(32, R(EAX), M(&LR));
+ //AND(32, R(EAX), Imm32(0xFFFFFFFC));
+ MVN(rB, 0x3); // 0xFFFFFFFC
+ LDR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
+ AND(rA, rA, rB);
+ if (inst.LK){
+ u32 Jumpto = js.compilerPC + 4;
+ MOVI2R(rB, Jumpto);
+ STR(rB, R9, PPCSTATE_OFF(spr[SPR_LR]));
+ //ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
+ }
+ gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR
+ WriteExitDestInR(rA);
+
+ if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0)
+ SetJumpTarget( pConditionDontBranch );
+ if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
+ SetJumpTarget( pCTRDontBranch );
+ WriteExit(js.compilerPC + 4, 1);
+}
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp
new file mode 100644
index 0000000000..fe4c0e3f22
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp
@@ -0,0 +1,80 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+#include "Thunk.h"
+
+#include "../../Core.h"
+#include "../PowerPC.h"
+#include "../../ConfigManager.h"
+#include "../../CoreTiming.h"
+#include "../PPCTables.h"
+#include "ArmEmitter.h"
+#include "../../HW/Memmap.h"
+
+
+#include "Jit.h"
+#include "JitRegCache.h"
+#include "JitFPRCache.h"
+#include "JitAsm.h"
+
+void JitArm::Helper_UpdateCR1(ARMReg value)
+{
+ // Should just update exception flags, not do any compares.
+ PanicAlert("CR1");
+}
+
+void JitArm::fabsx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(FloatingPoint)
+
+ ARMReg vD = fpr.R0(inst.FD);
+ ARMReg vB = fpr.R0(inst.FB);
+
+ VABS(vD, vB);
+
+ if (inst.Rc) Helper_UpdateCR1(vD);
+}
+
+void JitArm::faddx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(FloatingPoint)
+
+ ARMReg vD = fpr.R0(inst.FD);
+ ARMReg vA = fpr.R0(inst.FA);
+ ARMReg vB = fpr.R0(inst.FB);
+
+ VADD(vD, vA, vB);
+ if (inst.Rc) Helper_UpdateCR1(vD);
+}
+
+void JitArm::fmrx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(FloatingPoint)
+ Default(inst); return;
+
+ ARMReg vD = fpr.R0(inst.FD);
+ ARMReg vB = fpr.R0(inst.FB);
+
+ VMOV(vD, vB);
+
+ if (inst.Rc) Helper_UpdateCR1(vD);
+}
+
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp
new file mode 100644
index 0000000000..444d1a6090
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp
@@ -0,0 +1,308 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+#include "Common.h"
+#include "Thunk.h"
+
+#include "../../Core.h"
+#include "../PowerPC.h"
+#include "../../CoreTiming.h"
+#include "../PPCTables.h"
+#include "ArmEmitter.h"
+
+#include "Jit.h"
+#include "JitRegCache.h"
+#include "JitAsm.h"
+extern u32 Helper_Mask(u8 mb, u8 me);
+// ADDI and RLWINMX broken for now
+
+// Assumes that Sign and Zero flags were set by the last operation. Preserves all flags and registers.
+// Jit64 ComputerRC is signed
+// JIT64 GenerateRC is unsigned
+void JitArm::GenerateRC(int cr) {
+ ARMReg rB = gpr.GetReg();
+
+ MOV(rB, 0x4); // Result > 0
+ SetCC(CC_EQ); MOV(rB, 0x2); // Result == 0
+ SetCC(CC_MI); MOV(rB, 0x8); // Result < 0
+ SetCC();
+
+ STRB(rB, R9, PPCSTATE_OFF(cr_fast) + cr);
+ gpr.Unlock(rB);
+}
+void JitArm::ComputeRC(int cr) {
+ ARMReg rB = gpr.GetReg();
+
+ MOV(rB, 0x2); // Result == 0
+ SetCC(CC_LT); MOV(rB, 0x8); // Result < 0
+ SetCC(CC_GT); MOV(rB, 0x4); // Result > 0
+ SetCC();
+
+ STRB(rB, R9, PPCSTATE_OFF(cr_fast) + cr);
+ gpr.Unlock(rB);
+}
+
+void JitArm::addi(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ ARMReg RD = gpr.R(inst.RD);
+
+ if (inst.RA)
+ {
+ ARMReg rA = gpr.GetReg(false);
+ ARMReg RA = gpr.R(inst.RA);
+ MOVI2R(rA, (u32)inst.SIMM_16);
+ ADD(RD, RA, rA);
+ }
+ else
+ MOVI2R(RD, inst.SIMM_16);
+}
+void JitArm::addis(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ ARMReg RD = gpr.R(inst.RD);
+ if (inst.RA)
+ {
+ ARMReg rA = gpr.GetReg(false);
+ ARMReg RA = gpr.R(inst.RA);
+ MOVI2R(rA, inst.SIMM_16 << 16);
+ ADD(RD, RA, rA);
+ }
+ else
+ MOVI2R(RD, inst.SIMM_16 << 16);
+}
+void JitArm::addx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ ARMReg RA = gpr.R(inst.RA);
+ ARMReg RB = gpr.R(inst.RB);
+ ARMReg RD = gpr.R(inst.RD);
+ ADDS(RD, RA, RB);
+ if (inst.Rc) ComputeRC();
+}
+void JitArm::mulli(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ ARMReg RA = gpr.R(inst.RA);
+ ARMReg RD = gpr.R(inst.RD);
+ ARMReg rA = gpr.GetReg();
+ MOVI2R(rA, inst.SIMM_16);
+ MUL(RD, RA, rA);
+ gpr.Unlock(rA);
+}
+void JitArm::ori(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ ARMReg RA = gpr.R(inst.RA);
+ ARMReg RS = gpr.R(inst.RS);
+ ARMReg rA = gpr.GetReg();
+ MOVI2R(rA, inst.UIMM);
+ ORR(RA, RS, rA);
+ gpr.Unlock(rA);
+}
+void JitArm::oris(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ ARMReg RA = gpr.R(inst.RA);
+ ARMReg RS = gpr.R(inst.RS);
+ ARMReg rA = gpr.GetReg();
+ MOVI2R(rA, inst.UIMM << 16);
+ ORR(RA, RS, rA);
+ gpr.Unlock(rA);
+}
+void JitArm::orx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ ARMReg rA = gpr.R(inst.RA);
+ ARMReg rS = gpr.R(inst.RS);
+ ARMReg rB = gpr.R(inst.RB);
+ ORRS(rA, rS, rB);
+ if (inst.Rc)
+ ComputeRC();
+}
+
+void JitArm::extshx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+ ARMReg RA, RS;
+ RA = gpr.R(inst.RA);
+ RS = gpr.R(inst.RS);
+ SXTH(RA, RS);
+ if (inst.Rc){
+ CMP(RA, 0);
+ ComputeRC();
+ }
+}
+void JitArm::extsbx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+ ARMReg RA, RS;
+ RA = gpr.R(inst.RA);
+ RS = gpr.R(inst.RS);
+ SXTB(RA, RS);
+ if (inst.Rc){
+ CMP(RA, 0);
+ ComputeRC();
+ }
+}
+void JitArm::cmp (UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ ARMReg RA = gpr.R(inst.RA);
+ ARMReg RB = gpr.R(inst.RB);
+ int crf = inst.CRFD;
+ CMP(RA, RB);
+ ComputeRC(crf);
+}
+void JitArm::cmpi(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ ARMReg RA = gpr.R(inst.RA);
+ int crf = inst.CRFD;
+ if (inst.SIMM_16 >= 0 && inst.SIMM_16 < 256)
+ {
+ CMP(RA, inst.SIMM_16);
+ }
+ else
+ {
+ ARMReg rA = gpr.GetReg();
+ MOVI2R(rA, inst.SIMM_16);
+ CMP(RA, rA);
+ gpr.Unlock(rA);
+ }
+ ComputeRC(crf);
+}
+void JitArm::cmpli(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ ARMReg RA = gpr.R(inst.RA);
+ ARMReg rA = gpr.GetReg();
+ int crf = inst.CRFD;
+ u32 uimm = (u32)inst.UIMM;
+ if (uimm < 256)
+ {
+ CMP(RA, uimm);
+ }
+ else
+ {
+ MOVI2R(rA, (u32)inst.UIMM);
+ CMP(RA, rA);
+ }
+ // Unsigned GenerateRC()
+
+ MOV(rA, 0x2); // Result == 0
+ SetCC(CC_LO); MOV(rA, 0x8); // Result < 0
+ SetCC(CC_HI); MOV(rA, 0x4); // Result > 0
+ SetCC();
+
+ STRB(rA, R9, PPCSTATE_OFF(cr_fast) + crf);
+ gpr.Unlock(rA);
+
+}
+// Wrong - 27/10/2012
+void JitArm::negx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ ARMReg RA = gpr.R(inst.RA);
+ ARMReg RD = gpr.R(inst.RD);
+
+ RSBS(RD, RA, 0);
+ if (inst.Rc)
+ {
+ GenerateRC();
+ }
+ if (inst.OE)
+ {
+ BKPT(0x333);
+ //GenerateOverflow();
+ }
+}
+void JitArm::rlwimix(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ u32 mask = Helper_Mask(inst.MB,inst.ME);
+ ARMReg RA = gpr.R(inst.RA);
+ ARMReg RS = gpr.R(inst.RS);
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+ MOVI2R(rA, mask);
+
+ Operand2 Shift(RS, ST_ROR, 32 - inst.SH); // This rotates left, while ARM has only rotate right, so swap it.
+ if (inst.Rc)
+ {
+ BIC (rB, RA, rA); // RA & ~mask
+ AND (rA, rA, Shift);
+ ORRS(RA, rB, rA);
+ GenerateRC();
+ }
+ else
+ {
+ BIC (rB, RA, rA); // RA & ~mask
+ AND (rA, rA, Shift);
+ ORR(RA, rB, rA);
+ }
+ gpr.Unlock(rA, rB);
+}
+void JitArm::rlwinmx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(Integer)
+
+ u32 mask = Helper_Mask(inst.MB,inst.ME);
+ ARMReg RA = gpr.R(inst.RA);
+ ARMReg RS = gpr.R(inst.RS);
+ ARMReg rA = gpr.GetReg();
+ MOVI2R(rA, mask);
+
+ Operand2 Shift(RS, ST_ROR, 32 - inst.SH); // This rotates left, while ARM has only rotate right, so swap it.
+ if (inst.Rc)
+ {
+ ANDS(RA, rA, Shift);
+ GenerateRC();
+ }
+ else
+ AND (RA, rA, Shift);
+ gpr.Unlock(rA);
+
+ //m_GPR[inst.RA] = _rotl(m_GPR[inst.RS],inst.SH) & mask;
+}
+
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp
new file mode 100644
index 0000000000..1617b0fef6
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp
@@ -0,0 +1,414 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+#include "Thunk.h"
+
+#include "../../Core.h"
+#include "../PowerPC.h"
+#include "../../ConfigManager.h"
+#include "../../CoreTiming.h"
+#include "../PPCTables.h"
+#include "ArmEmitter.h"
+#include "../../HW/Memmap.h"
+
+
+#include "Jit.h"
+#include "JitRegCache.h"
+#include "JitAsm.h"
+
+#ifdef ANDROID
+#define FASTMEM 0
+#else
+#define FASTMEM 0
+#endif
+void JitArm::stw(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(LoadStore)
+
+ ARMReg RS = gpr.R(inst.RS);
+#if FASTMEM
+ // R10 contains the dest address
+ ARMReg Value = R11;
+ ARMReg RA;
+ if (inst.RA)
+ RA = gpr.R(inst.RA);
+ MOV(Value, RS);
+ if (inst.RA)
+ {
+ MOVI2R(R10, inst.SIMM_16, false);
+ ADD(R10, R10, RA);
+ }
+ else
+ {
+ MOVI2R(R10, (u32)inst.SIMM_16, false);
+ NOP(1);
+ }
+ StoreFromReg(R10, Value, 32, 0);
+#else
+ ARMReg ValueReg = gpr.GetReg();
+ ARMReg Addr = gpr.GetReg();
+ ARMReg Function = gpr.GetReg();
+
+ MOV(ValueReg, RS);
+ if (inst.RA)
+ {
+ MOVI2R(Addr, inst.SIMM_16);
+ ARMReg RA = gpr.R(inst.RA);
+ ADD(Addr, Addr, RA);
+ }
+ else
+ MOVI2R(Addr, (u32)inst.SIMM_16);
+
+ MOVI2R(Function, (u32)&Memory::Write_U32);
+ PUSH(4, R0, R1, R2, R3);
+ MOV(R0, ValueReg);
+ MOV(R1, Addr);
+ BL(Function);
+ POP(4, R0, R1, R2, R3);
+ gpr.Unlock(ValueReg, Addr, Function);
+#endif
+}
+void JitArm::stwu(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(LoadStore)
+
+ ARMReg RA = gpr.R(inst.RA);
+ ARMReg RS = gpr.R(inst.RS);
+ ARMReg ValueReg = gpr.GetReg();
+ ARMReg Addr = gpr.GetReg();
+ ARMReg Function = gpr.GetReg();
+
+ MOVI2R(Addr, inst.SIMM_16);
+ ADD(Addr, Addr, RA);
+
+ // Check and set the update before writing since calling a function can
+ // mess with the "special registers R11+ which may cause some issues.
+ LDR(Function, R9, PPCSTATE_OFF(Exceptions));
+ CMP(Function, EXCEPTION_DSI);
+ FixupBranch DoNotWrite = B_CC(CC_EQ);
+ MOV(RA, Addr);
+ SetJumpTarget(DoNotWrite);
+
+ MOV(ValueReg, RS);
+
+ MOVI2R(Function, (u32)&Memory::Write_U32);
+ PUSH(4, R0, R1, R2, R3);
+ MOV(R0, ValueReg);
+ MOV(R1, Addr);
+ BL(Function);
+ POP(4, R0, R1, R2, R3);
+
+ gpr.Unlock(ValueReg, Addr, Function);
+}
+void JitArm::StoreFromReg(ARMReg dest, ARMReg value, int accessSize, s32 offset)
+{
+ ARMReg rA = gpr.GetReg();
+
+ // All this gets replaced on backpatch
+ MOVI2R(rA, Memory::MEMVIEW32_MASK, false); // 1-2
+ AND(dest, dest, rA); // 3
+ MOVI2R(rA, (u32)Memory::base, false); // 4-5
+ ADD(dest, dest, rA); // 6
+ switch (accessSize)
+ {
+ case 32:
+ REV(value, value); // 7
+ break;
+ case 16:
+ REV16(value, value);
+ break;
+ case 8:
+ NOP(1);
+ break;
+ }
+ switch (accessSize)
+ {
+ case 32:
+ STR(value, dest); // 8
+ break;
+ case 16:
+ // Not implemented
+ break;
+ case 8:
+ // Not implemented
+ break;
+ }
+ gpr.Unlock(rA);
+}
+void JitArm::LoadToReg(ARMReg dest, ARMReg addr, int accessSize, s32 offset)
+{
+ ARMReg rA = gpr.GetReg();
+ MOVI2R(rA, offset, false); // -3
+ ADD(addr, addr, rA); // - 1
+
+ // All this gets replaced on backpatch
+ MOVI2R(rA, Memory::MEMVIEW32_MASK, false); // 2
+ AND(addr, addr, rA); // 3
+ MOVI2R(rA, (u32)Memory::base, false); // 5
+ ADD(addr, addr, rA); // 6
+ switch (accessSize)
+ {
+ case 32:
+ LDR(dest, addr); // 7
+ break;
+ case 16:
+ LDRH(dest, addr);
+ break;
+ case 8:
+ LDRB(dest, addr);
+ break;
+ }
+ switch (accessSize)
+ {
+ case 32:
+ REV(dest, dest); // 9
+ break;
+ case 16:
+ REV16(dest, dest);
+ break;
+ case 8:
+ NOP(1);
+ break;
+
+ }
+ gpr.Unlock(rA);
+}
+void JitArm::lbz(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(LoadStore)
+
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+ ARMReg RD = gpr.R(inst.RD);
+ LDR(rA, R9, PPCSTATE_OFF(Exceptions));
+ CMP(rA, EXCEPTION_DSI);
+ FixupBranch DoNotLoad = B_CC(CC_EQ);
+#if FASTMEM
+ // Backpatch route
+ // Gets loaded in to RD
+ // Address is in R10
+ gpr.Unlock(rA, rB);
+ if (inst.RA)
+ {
+ ARMReg RA = gpr.R(inst.RA);
+ MOV(R10, RA); // - 4
+ }
+ else
+ MOV(R10, 0); // - 4
+ LoadToReg(RD, R10, 8, inst.SIMM_16);
+#else
+
+ if (inst.RA)
+ {
+ MOVI2R(rB, inst.SIMM_16);
+ ARMReg RA = gpr.R(inst.RA);
+ ADD(rB, rB, RA);
+ }
+ else
+ MOVI2R(rB, (u32)inst.SIMM_16);
+
+ MOVI2R(rA, (u32)&Memory::Read_U8);
+ PUSH(4, R0, R1, R2, R3);
+ MOV(R0, rB);
+ BL(rA);
+ MOV(rA, R0);
+ POP(4, R0, R1, R2, R3);
+ MOV(RD, rA);
+ gpr.Unlock(rA, rB);
+#endif
+ SetJumpTarget(DoNotLoad);
+}
+
+void JitArm::lhz(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(LoadStore)
+
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+ ARMReg RD = gpr.R(inst.RD);
+ LDR(rA, R9, PPCSTATE_OFF(Exceptions));
+ CMP(rA, EXCEPTION_DSI);
+ FixupBranch DoNotLoad = B_CC(CC_EQ);
+#if 0 // FASTMEM
+ // Backpatch route
+ // Gets loaded in to RD
+ // Address is in R10
+ gpr.Unlock(rA, rB);
+ if (inst.RA)
+ {
+ ARMReg RA = gpr.R(inst.RA);
+ printf("lhz jump to here: 0x%08x\n", (u32)GetCodePtr());
+ MOV(R10, RA); // - 4
+ }
+ else
+ {
+ printf("lhz jump to here: 0x%08x\n", (u32)GetCodePtr());
+ MOV(R10, 0); // - 4
+ }
+ LoadToReg(RD, R10, 16, (u32)inst.SIMM_16);
+#else
+
+ if (inst.RA)
+ {
+ MOVI2R(rB, inst.SIMM_16);
+ ARMReg RA = gpr.R(inst.RA);
+ ADD(rB, rB, RA);
+ }
+ else
+ MOVI2R(rB, (u32)inst.SIMM_16);
+
+ MOVI2R(rA, (u32)&Memory::Read_U16);
+ PUSH(4, R0, R1, R2, R3);
+ MOV(R0, rB);
+ BL(rA);
+ MOV(rA, R0);
+ POP(4, R0, R1, R2, R3);
+ MOV(RD, rA);
+ gpr.Unlock(rA, rB);
+#endif
+ SetJumpTarget(DoNotLoad);
+}
+void JitArm::lwz(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(LoadStore)
+
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+ ARMReg RD = gpr.R(inst.RD);
+ LDR(rA, R9, PPCSTATE_OFF(Exceptions));
+ CMP(rA, EXCEPTION_DSI);
+ FixupBranch DoNotLoad = B_CC(CC_EQ);
+
+#if FASTMEM
+ // Backpatch route
+ // Gets loaded in to RD
+ // Address is in R10
+ gpr.Unlock(rA, rB);
+ if (inst.RA)
+ {
+ ARMReg RA = gpr.R(inst.RA);
+ MOV(R10, RA); // - 4
+ }
+ else
+ MOV(R10, 0); // - 4
+ LoadToReg(RD, R10, 32, (u32)inst.SIMM_16);
+#else
+ if (inst.RA)
+ {
+ MOVI2R(rB, inst.SIMM_16);
+ ARMReg RA = gpr.R(inst.RA);
+ ADD(rB, rB, RA);
+ }
+ else
+ MOVI2R(rB, (u32)inst.SIMM_16);
+
+ MOVI2R(rA, (u32)&Memory::Read_U32);
+ PUSH(4, R0, R1, R2, R3);
+ MOV(R0, rB);
+ BL(rA);
+ MOV(rA, R0);
+ POP(4, R0, R1, R2, R3);
+ MOV(RD, rA);
+ gpr.Unlock(rA, rB);
+#endif
+ SetJumpTarget(DoNotLoad);
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
+ (inst.hex & 0xFFFF0000) == 0x800D0000 &&
+ (Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 ||
+ (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) &&
+ Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8)
+ {
+ gpr.Flush();
+ fpr.Flush();
+
+ // if it's still 0, we can wait until the next event
+ TST(RD, RD);
+ FixupBranch noIdle = B_CC(CC_NEQ);
+ rA = gpr.GetReg();
+
+ MOVI2R(rA, (u32)&PowerPC::OnIdle);
+ MOVI2R(R0, PowerPC::ppcState.gpr[inst.RA] + (s32)(s16)inst.SIMM_16);
+ BL(rA);
+
+ gpr.Unlock(rA);
+ WriteExceptionExit();
+
+ SetJumpTarget(noIdle);
+
+ //js.compilerPC += 8;
+ return;
+ }
+}
+void JitArm::lwzx(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(LoadStore)
+
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+
+ ARMReg RB = gpr.R(inst.RB);
+ ARMReg RD = gpr.R(inst.RD);
+ LDR(rA, R9, PPCSTATE_OFF(Exceptions));
+ CMP(rA, EXCEPTION_DSI);
+ FixupBranch DoNotLoad = B_CC(CC_EQ);
+#if FASTMEM
+ // Backpatch route
+ // Gets loaded in to RD
+ // Address is in R10
+ gpr.Unlock(rA, rB);
+ if (inst.RA)
+ {
+ ARMReg RA = gpr.R(inst.RA);
+ ADD(R10, RA, RB); // - 4
+ }
+ else
+ MOV(R10, RB); // -4
+ LoadToReg(RD, R10, 32, 0);
+#else
+ if (inst.RA)
+ {
+ ARMReg RA = gpr.R(inst.RA);
+ ADD(rB, RA, RB);
+ }
+ else
+ MOV(rB, RB);
+
+ MOVI2R(rA, (u32)&Memory::Read_U32);
+ PUSH(4, R0, R1, R2, R3);
+ MOV(R0, rB);
+ BL(rA);
+ MOV(rA, R0);
+ POP(4, R0, R1, R2, R3);
+ MOV(RD, rA);
+ gpr.Unlock(rA, rB);
+#endif
+ SetJumpTarget(DoNotLoad);
+ //// u32 temp = Memory::Read_U32(_inst.RA ? (m_GPR[_inst.RA] + m_GPR[_inst.RB]) : m_GPR[_inst.RB]);
+}
+void JitArm::icbi(UGeckoInstruction inst)
+{
+ Default(inst);
+ WriteExit(js.compilerPC + 4, 0);
+}
+
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp
new file mode 100644
index 0000000000..dd36f145a9
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp
@@ -0,0 +1,72 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+#include "Thunk.h"
+
+#include "../../Core.h"
+#include "../PowerPC.h"
+#include "../../ConfigManager.h"
+#include "../../CoreTiming.h"
+#include "../PPCTables.h"
+#include "ArmEmitter.h"
+#include "../../HW/Memmap.h"
+
+
+#include "Jit.h"
+#include "JitRegCache.h"
+#include "JitFPRCache.h"
+#include "JitAsm.h"
+
+void JitArm::lfs(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(LoadStoreFloating)
+ Default(inst); return;
+
+ ARMReg rA = gpr.GetReg();
+ ARMReg rB = gpr.GetReg();
+ LDR(rA, R9, PPCSTATE_OFF(Exceptions));
+ CMP(rA, EXCEPTION_DSI);
+ FixupBranch DoNotLoad = B_CC(CC_EQ);
+
+ if (inst.RA)
+ {
+ MOVI2R(rB, inst.SIMM_16);
+ ARMReg RA = gpr.R(inst.RA);
+ ADD(rB, rB, RA);
+ }
+ else
+ MOVI2R(rB, (u32)inst.SIMM_16);
+
+ MOVI2R(rA, (u32)&Memory::Read_U32);
+ PUSH(4, R0, R1, R2, R3);
+ MOV(R0, rB);
+ BL(rA);
+ MOV(rA, R0);
+ POP(4, R0, R1, R2, R3);
+
+ ARMReg v0 = fpr.R0(inst.FD, false);
+ ARMReg v1 = fpr.R1(inst.FD, false);
+
+ VMOV(v0, rA, false);
+ VMOV(v1, rA, false);
+
+ gpr.Unlock(rA, rB);
+ SetJumpTarget(DoNotLoad);
+}
+
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp
new file mode 100644
index 0000000000..7eb8963e15
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp
@@ -0,0 +1,104 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+#include "Common.h"
+#include "Thunk.h"
+
+#include "../../Core.h"
+#include "../PowerPC.h"
+#include "../../CoreTiming.h"
+#include "../PPCTables.h"
+#include "ArmEmitter.h"
+
+#include "Jit.h"
+#include "JitRegCache.h"
+#include "JitAsm.h"
+
+void JitArm::mtspr(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(SystemRegisters)
+
+ u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
+ ARMReg RD = gpr.R(inst.RD);
+
+ switch (iIndex)
+ {
+ case SPR_LR:
+ case SPR_CTR:
+ case SPR_XER:
+ // These are safe to do the easy way, see the bottom of this function.
+ break;
+
+ case SPR_GQR0:
+ case SPR_GQR0 + 1:
+ case SPR_GQR0 + 2:
+ case SPR_GQR0 + 3:
+ case SPR_GQR0 + 4:
+ case SPR_GQR0 + 5:
+ case SPR_GQR0 + 6:
+ case SPR_GQR0 + 7:
+ // Prevent recompiler from compiling in old quantizer values.
+ // If the value changed, destroy all blocks using this quantizer
+ // This will create a little bit of block churn, but hopefully not too bad.
+ {
+ /*
+ MOV(32, R(EAX), M(&PowerPC::ppcState.spr[iIndex])); // Load old value
+ CMP(32, R(EAX), gpr.R(inst.RD));
+ FixupBranch skip_destroy = J_CC(CC_E, false);
+ int gqr = iIndex - SPR_GQR0;
+ ABI_CallFunctionC(ProtectFunction(&Jit64::DestroyBlocksWithFlag, 1), (u32)BLOCK_USE_GQR0 << gqr);
+ SetJumpTarget(skip_destroy);*/
+ }
+ // TODO - break block if quantizers are written to.
+ default:
+ Default(inst);
+ return;
+ }
+
+ // OK, this is easy.
+ STR(RD, R9, PPCSTATE_OFF(spr) + iIndex * 4);
+}
+
+void JitArm::mfspr(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ JITDISABLE(SystemRegisters)
+
+ u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
+ ARMReg RD = gpr.R(inst.RD);
+ switch (iIndex)
+ {
+ case SPR_WPAR:
+ case SPR_DEC:
+ case SPR_TL:
+ case SPR_TU:
+ Default(inst);
+ return;
+ default:
+ LDR(RD, R9, PPCSTATE_OFF(spr) + iIndex * 4);
+ break;
+ }
+}
+void JitArm::mtmsr(UGeckoInstruction inst)
+{
+ INSTRUCTION_START
+ // Don't interpret this, if we do we get thrown out
+ //JITDISABLE(SystemRegisters)
+
+ STR(gpr.R(inst.RS), R9, PPCSTATE_OFF(msr));
+ WriteExit(js.compilerPC + 4, 0);
+}
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp
new file mode 100644
index 0000000000..1929705df2
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp
@@ -0,0 +1,502 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Jit.h"
+#include "../JitInterface.h"
+#include "JitArm_Tables.h"
+
+// Should be moved in to the Jit class
+typedef void (JitArm::*_Instruction) (UGeckoInstruction instCode);
+
+static _Instruction dynaOpTable[64];
+static _Instruction dynaOpTable4[1024];
+static _Instruction dynaOpTable19[1024];
+static _Instruction dynaOpTable31[1024];
+static _Instruction dynaOpTable59[32];
+static _Instruction dynaOpTable63[1024];
+
+void JitArm::DynaRunTable4(UGeckoInstruction _inst) {(this->*dynaOpTable4 [_inst.SUBOP10])(_inst);}
+void JitArm::DynaRunTable19(UGeckoInstruction _inst) {(this->*dynaOpTable19[_inst.SUBOP10])(_inst);}
+void JitArm::DynaRunTable31(UGeckoInstruction _inst) {(this->*dynaOpTable31[_inst.SUBOP10])(_inst);}
+void JitArm::DynaRunTable59(UGeckoInstruction _inst) {(this->*dynaOpTable59[_inst.SUBOP5 ])(_inst);}
+void JitArm::DynaRunTable63(UGeckoInstruction _inst) {(this->*dynaOpTable63[_inst.SUBOP10])(_inst);}
+
+struct GekkoOPTemplate
+{
+ int opcode;
+ _Instruction Inst;
+ //GekkoOPInfo opinfo; // Doesn't need opinfo, Interpreter fills it out
+};
+
+static GekkoOPTemplate primarytable[] =
+{
+ {4, &JitArm::DynaRunTable4}, //"RunTable4", OPTYPE_SUBTABLE | (4<<24), 0}},
+ {19, &JitArm::DynaRunTable19}, //"RunTable19", OPTYPE_SUBTABLE | (19<<24), 0}},
+ {31, &JitArm::DynaRunTable31}, //"RunTable31", OPTYPE_SUBTABLE | (31<<24), 0}},
+ {59, &JitArm::DynaRunTable59}, //"RunTable59", OPTYPE_SUBTABLE | (59<<24), 0}},
+ {63, &JitArm::DynaRunTable63}, //"RunTable63", OPTYPE_SUBTABLE | (63<<24), 0}},
+
+ {16, &JitArm::bcx}, //"bcx", OPTYPE_SYSTEM, FL_ENDBLOCK}},
+ {18, &JitArm::bx}, //"bx", OPTYPE_SYSTEM, FL_ENDBLOCK}},
+
+ {1, &JitArm::HLEFunction}, //"HLEFunction", OPTYPE_SYSTEM, FL_ENDBLOCK}},
+ {2, &JitArm::Default}, //"DynaBlock", OPTYPE_SYSTEM, 0}},
+ {3, &JitArm::Break}, //"twi", OPTYPE_SYSTEM, FL_ENDBLOCK}},
+ {17, &JitArm::sc}, //"sc", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}},
+
+ {7, &JitArm::mulli}, //"mulli", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_RC_BIT, 2}},
+ {8, &JitArm::Default}, //"subfic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
+ {10, &JitArm::cmpli}, //"cmpli", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
+ {11, &JitArm::cmpi}, //"cmpi", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
+ {12, &JitArm::Default}, //"addic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
+ {13, &JitArm::Default}, //"addic_rc", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CR0}},
+ {14, &JitArm::addi}, //"addi", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
+ {15, &JitArm::addis}, //"addis", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
+
+ {20, &JitArm::rlwimix}, //"rlwimix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_A | FL_IN_S | FL_RC_BIT}},
+ {21, &JitArm::rlwinmx}, //"rlwinmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
+ {23, &JitArm::Default}, //"rlwnmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_IN_B | FL_RC_BIT}},
+
+ {24, &JitArm::ori}, //"ori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
+ {25, &JitArm::oris}, //"oris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
+ {26, &JitArm::Default}, //"xori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
+ {27, &JitArm::Default}, //"xoris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
+ {28, &JitArm::Default}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
+ {29, &JitArm::Default}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
+
+ {32, &JitArm::lwz}, //"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
+ {33, &JitArm::Default}, //"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
+ {34, &JitArm::lbz}, //"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
+ {35, &JitArm::Default}, //"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
+ {40, &JitArm::lhz}, //"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
+ {41, &JitArm::Default}, //"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
+ {42, &JitArm::Default}, //"lha", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
+ {43, &JitArm::Default}, //"lhau", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
+
+ {44, &JitArm::Default}, //"sth", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
+ {45, &JitArm::Default}, //"sthu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
+ {36, &JitArm::stw}, //"stw", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
+ {37, &JitArm::stwu}, //"stwu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
+ {38, &JitArm::Default}, //"stb", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
+ {39, &JitArm::Default}, //"stbu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
+
+ {46, &JitArm::Default}, //"lmw", OPTYPE_SYSTEM, FL_EVIL, 10}},
+ {47, &JitArm::Default}, //"stmw", OPTYPE_SYSTEM, FL_EVIL, 10}},
+
+ {48, &JitArm::lfs}, //"lfs", OPTYPE_LOADFP, FL_IN_A}},
+ {49, &JitArm::Default}, //"lfsu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}},
+ {50, &JitArm::Default}, //"lfd", OPTYPE_LOADFP, FL_IN_A}},
+ {51, &JitArm::Default}, //"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}},
+
+ {52, &JitArm::Default}, //"stfs", OPTYPE_STOREFP, FL_IN_A}},
+ {53, &JitArm::Default}, //"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
+ {54, &JitArm::Default}, //"stfd", OPTYPE_STOREFP, FL_IN_A}},
+ {55, &JitArm::Default}, //"stfdu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
+
+ {56, &JitArm::Default}, //"psq_l", OPTYPE_PS, FL_IN_A}},
+ {57, &JitArm::Default}, //"psq_lu", OPTYPE_PS, FL_OUT_A | FL_IN_A}},
+ {60, &JitArm::Default}, //"psq_st", OPTYPE_PS, FL_IN_A}},
+ {61, &JitArm::Default}, //"psq_stu", OPTYPE_PS, FL_OUT_A | FL_IN_A}},
+
+ //missing: 0, 5, 6, 9, 22, 30, 62, 58
+ {0, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
+ {5, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
+ {6, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
+ {9, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
+ {22, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
+ {30, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
+ {62, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
+ {58, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
+};
+
+static GekkoOPTemplate table4[] =
+{ //SUBOP10
+ {0, &JitArm::Default}, //"ps_cmpu0", OPTYPE_PS, FL_SET_CRn}},
+ {32, &JitArm::Default}, //"ps_cmpo0", OPTYPE_PS, FL_SET_CRn}},
+ {40, &JitArm::Default}, //"ps_neg", OPTYPE_PS, FL_RC_BIT}},
+ {136, &JitArm::Default}, //"ps_nabs", OPTYPE_PS, FL_RC_BIT}},
+ {264, &JitArm::Default}, //"ps_abs", OPTYPE_PS, FL_RC_BIT}},
+ {64, &JitArm::Default}, //"ps_cmpu1", OPTYPE_PS, FL_RC_BIT}},
+ {72, &JitArm::Default}, //"ps_mr", OPTYPE_PS, FL_RC_BIT}},
+ {96, &JitArm::Default}, //"ps_cmpo1", OPTYPE_PS, FL_RC_BIT}},
+ {528, &JitArm::Default}, //"ps_merge00", OPTYPE_PS, FL_RC_BIT}},
+ {560, &JitArm::Default}, //"ps_merge01", OPTYPE_PS, FL_RC_BIT}},
+ {592, &JitArm::Default}, //"ps_merge10", OPTYPE_PS, FL_RC_BIT}},
+ {624, &JitArm::Default}, //"ps_merge11", OPTYPE_PS, FL_RC_BIT}},
+
+ {1014, &JitArm::Default}, //"dcbz_l", OPTYPE_SYSTEM, 0}},
+};
+
+static GekkoOPTemplate table4_2[] =
+{
+ {10, &JitArm::Default}, //"ps_sum0", OPTYPE_PS, 0}},
+ {11, &JitArm::Default}, //"ps_sum1", OPTYPE_PS, 0}},
+ {12, &JitArm::Default}, //"ps_muls0", OPTYPE_PS, 0}},
+ {13, &JitArm::Default}, //"ps_muls1", OPTYPE_PS, 0}},
+ {14, &JitArm::Default}, //"ps_madds0", OPTYPE_PS, 0}},
+ {15, &JitArm::Default}, //"ps_madds1", OPTYPE_PS, 0}},
+ {18, &JitArm::Default}, //"ps_div", OPTYPE_PS, 0, 16}},
+ {20, &JitArm::Default}, //"ps_sub", OPTYPE_PS, 0}},
+ {21, &JitArm::Default}, //"ps_add", OPTYPE_PS, 0}},
+ {23, &JitArm::Default}, //"ps_sel", OPTYPE_PS, 0}},
+ {24, &JitArm::Default}, //"ps_res", OPTYPE_PS, 0}},
+ {25, &JitArm::Default}, //"ps_mul", OPTYPE_PS, 0}},
+ {26, &JitArm::Default}, //"ps_rsqrte", OPTYPE_PS, 0, 1}},
+ {28, &JitArm::Default}, //"ps_msub", OPTYPE_PS, 0}},
+ {29, &JitArm::Default}, //"ps_madd", OPTYPE_PS, 0}},
+ {30, &JitArm::Default}, //"ps_nmsub", OPTYPE_PS, 0}},
+ {31, &JitArm::Default}, //"ps_nmadd", OPTYPE_PS, 0}},
+};
+
+
+static GekkoOPTemplate table4_3[] =
+{
+ {6, &JitArm::Default}, //"psq_lx", OPTYPE_PS, 0}},
+ {7, &JitArm::Default}, //"psq_stx", OPTYPE_PS, 0}},
+ {38, &JitArm::Default}, //"psq_lux", OPTYPE_PS, 0}},
+ {39, &JitArm::Default}, //"psq_stux", OPTYPE_PS, 0}},
+};
+
+static GekkoOPTemplate table19[] =
+{
+ {528, &JitArm::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
+ {16, &JitArm::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
+ {257, &JitArm::Default}, //"crand", OPTYPE_CR, FL_EVIL}},
+ {129, &JitArm::Default}, //"crandc", OPTYPE_CR, FL_EVIL}},
+ {289, &JitArm::Default}, //"creqv", OPTYPE_CR, FL_EVIL}},
+ {225, &JitArm::Default}, //"crnand", OPTYPE_CR, FL_EVIL}},
+ {33, &JitArm::Default}, //"crnor", OPTYPE_CR, FL_EVIL}},
+ {449, &JitArm::Default}, //"cror", OPTYPE_CR, FL_EVIL}},
+ {417, &JitArm::Default}, //"crorc", OPTYPE_CR, FL_EVIL}},
+ {193, &JitArm::Default}, //"crxor", OPTYPE_CR, FL_EVIL}},
+
+ {150, &JitArm::DoNothing}, //"isync", OPTYPE_ICACHE, FL_EVIL}},
+ {0, &JitArm::Default}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}},
+
+ {50, &JitArm::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}},
+ {18, &JitArm::Break}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}}
+};
+
+
+static GekkoOPTemplate table31[] =
+{
+ {28, &JitArm::Default}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {60, &JitArm::Default}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {444, &JitArm::orx}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {124, &JitArm::Default}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {316, &JitArm::Default}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {412, &JitArm::Default}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {476, &JitArm::Default}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {284, &JitArm::Default}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {0, &JitArm::cmp}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
+ {32, &JitArm::Default}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
+ {26, &JitArm::Default}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
+ {922, &JitArm::extshx}, //"extshx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
+ {954, &JitArm::extsbx}, //"extsbx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
+ {536, &JitArm::Default}, //"srwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
+ {792, &JitArm::Default}, //"srawx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
+ {824, &JitArm::Default}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
+ {24, &JitArm::Default}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
+
+ {54, &JitArm::Default}, //"dcbst", OPTYPE_DCACHE, 0, 4}},
+ {86, &JitArm::Default}, //"dcbf", OPTYPE_DCACHE, 0, 4}},
+ {246, &JitArm::Default}, //"dcbtst", OPTYPE_DCACHE, 0, 1}},
+ {278, &JitArm::Default}, //"dcbt", OPTYPE_DCACHE, 0, 1}},
+ {470, &JitArm::Default}, //"dcbi", OPTYPE_DCACHE, 0, 4}},
+ {758, &JitArm::Default}, //"dcba", OPTYPE_DCACHE, 0, 4}},
+ {1014, &JitArm::Default}, //"dcbz", OPTYPE_DCACHE, 0, 4}},
+
+ //load word
+ {23, &JitArm::lwzx}, //"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
+ {55, &JitArm::Default}, //"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
+
+ //load halfword
+ {279, &JitArm::Default}, //"lhzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
+ {311, &JitArm::Default}, //"lhzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
+
+ //load halfword signextend
+ {343, &JitArm::Default}, //"lhax", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
+ {375, &JitArm::Default}, //"lhaux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
+
+ //load byte
+ {87, &JitArm::Default}, //"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
+ {119, &JitArm::Default}, //"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
+
+ //load byte reverse
+ {534, &JitArm::Default}, //"lwbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
+ {790, &JitArm::Default}, //"lhbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
+
+ // Conditional load/store (Wii SMP)
+ {150, &JitArm::Default}, //"stwcxd", OPTYPE_STORE, FL_EVIL | FL_SET_CR0}},
+ {20, &JitArm::Default}, //"lwarx", OPTYPE_LOAD, FL_EVIL | FL_OUT_D | FL_IN_A0B | FL_SET_CR0}},
+
+ //load string (interpret these)
+ {533, &JitArm::Default}, //"lswx", OPTYPE_LOAD, FL_EVIL | FL_IN_A | FL_OUT_D}},
+ {597, &JitArm::Default}, //"lswi", OPTYPE_LOAD, FL_EVIL | FL_IN_AB | FL_OUT_D}},
+
+ //store word
+ {151, &JitArm::Default}, //"stwx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
+ {183, &JitArm::Default}, //"stwux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
+
+ //store halfword
+ {407, &JitArm::Default}, //"sthx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
+ {439, &JitArm::Default}, //"sthux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
+
+ //store byte
+ {215, &JitArm::Default}, //"stbx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
+ {247, &JitArm::Default}, //"stbux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
+
+ //store bytereverse
+ {662, &JitArm::Default}, //"stwbrx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
+ {918, &JitArm::Default}, //"sthbrx", OPTYPE_STORE, FL_IN_A | FL_IN_B}},
+
+ {661, &JitArm::Default}, //"stswx", OPTYPE_STORE, FL_EVIL}},
+ {725, &JitArm::Default}, //"stswi", OPTYPE_STORE, FL_EVIL}},
+
+ // fp load/store
+ {535, &JitArm::Default}, //"lfsx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}},
+ {567, &JitArm::Default}, //"lfsux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}},
+ {599, &JitArm::Default}, //"lfdx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}},
+ {631, &JitArm::Default}, //"lfdux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}},
+
+ {663, &JitArm::Default}, //"stfsx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
+ {695, &JitArm::Default}, //"stfsux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}},
+ {727, &JitArm::Default}, //"stfdx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
+ {759, &JitArm::Default}, //"stfdux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}},
+ {983, &JitArm::Default}, //"stfiwx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
+
+ {19, &JitArm::Default}, //"mfcr", OPTYPE_SYSTEM, FL_OUT_D}},
+ {83, &JitArm::Default}, //"mfmsr", OPTYPE_SYSTEM, FL_OUT_D}},
+ {144, &JitArm::Default}, //"mtcrf", OPTYPE_SYSTEM, 0}},
+ {146, &JitArm::mtmsr}, //"mtmsr", OPTYPE_SYSTEM, FL_ENDBLOCK}},
+ {210, &JitArm::Default}, //"mtsr", OPTYPE_SYSTEM, 0}},
+ {242, &JitArm::Default}, //"mtsrin", OPTYPE_SYSTEM, 0}},
+ {339, &JitArm::mfspr}, //"mfspr", OPTYPE_SPR, FL_OUT_D}},
+ {467, &JitArm::mtspr}, //"mtspr", OPTYPE_SPR, 0, 2}},
+ {371, &JitArm::Default}, //"mftb", OPTYPE_SYSTEM, FL_OUT_D | FL_TIMER}},
+ {512, &JitArm::Default}, //"mcrxr", OPTYPE_SYSTEM, 0}},
+ {595, &JitArm::Default}, //"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 2}},
+ {659, &JitArm::Default}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}},
+
+ {4, &JitArm::Break}, //"tw", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}},
+ {598, &JitArm::Default}, //"sync", OPTYPE_SYSTEM, 0, 2}},
+ {982, &JitArm::icbi}, //"icbi", OPTYPE_SYSTEM, FL_ENDBLOCK, 3}},
+
+ // Unused instructions on GC
+ {310, &JitArm::Default}, //"eciwx", OPTYPE_INTEGER, FL_RC_BIT}},
+ {438, &JitArm::Default}, //"ecowx", OPTYPE_INTEGER, FL_RC_BIT}},
+ {854, &JitArm::Default}, //"eieio", OPTYPE_INTEGER, FL_RC_BIT}},
+ {306, &JitArm::Default}, //"tlbie", OPTYPE_SYSTEM, 0}},
+ {370, &JitArm::Default}, //"tlbia", OPTYPE_SYSTEM, 0}},
+ {566, &JitArm::Default}, //"tlbsync", OPTYPE_SYSTEM, 0}},
+};
+
+static GekkoOPTemplate table31_2[] =
+{
+ {266, &JitArm::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
+ {778, &JitArm::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
+ {10, &JitArm::Default}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
+ {138, &JitArm::Default}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
+ {234, &JitArm::Default}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
+ {202, &JitArm::Default}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
+ {491, &JitArm::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
+ {1003, &JitArm::Default}, //"divwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
+ {459, &JitArm::Default}, //"divwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
+ {971, &JitArm::Default}, //"divwuox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
+ {75, &JitArm::Default}, //"mulhwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
+ {11, &JitArm::Default}, //"mulhwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
+ {235, &JitArm::Default}, //"mullwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
+ {747, &JitArm::Default}, //"mullwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
+ {104, &JitArm::negx}, //"negx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
+ {40, &JitArm::Default}, //"subfx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
+ {552, &JitArm::Default}, //"subox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
+ {8, &JitArm::Default}, //"subfcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
+ {136, &JitArm::Default}, //"subfex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
+ {232, &JitArm::Default}, //"subfmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
+ {200, &JitArm::Default}, //"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
+};
+
+static GekkoOPTemplate table59[] =
+{
+ {18, &JitArm::Default}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}},
+ {20, &JitArm::Default}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {21, &JitArm::Default}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}},
+// {22, &JitArm::Default}, //"fsqrtsx", OPTYPE_FPU, FL_RC_BIT_F}}, // Not implemented on gekko
+ {24, &JitArm::Default}, //"fresx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {25, &JitArm::Default}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {28, &JitArm::Default}, //"fmsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {29, &JitArm::Default}, //"fmaddsx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {30, &JitArm::Default}, //"fnmsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {31, &JitArm::Default}, //"fnmaddsx", OPTYPE_FPU, FL_RC_BIT_F}},
+};
+
+static GekkoOPTemplate table63[] =
+{
+ {264, &JitArm::fabsx}, //"fabsx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {32, &JitArm::Default}, //"fcmpo", OPTYPE_FPU, FL_RC_BIT_F}},
+ {0, &JitArm::Default}, //"fcmpu", OPTYPE_FPU, FL_RC_BIT_F}},
+ {14, &JitArm::Default}, //"fctiwx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {15, &JitArm::Default}, //"fctiwzx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {72, &JitArm::fmrx}, //"fmrx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {136, &JitArm::Default}, //"fnabsx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {40, &JitArm::Default}, //"fnegx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {12, &JitArm::Default}, //"frspx", OPTYPE_FPU, FL_RC_BIT_F}},
+
+ {64, &JitArm::Default}, //"mcrfs", OPTYPE_SYSTEMFP, 0}},
+ {583, &JitArm::Default}, //"mffsx", OPTYPE_SYSTEMFP, 0}},
+ {70, &JitArm::Default}, //"mtfsb0x", OPTYPE_SYSTEMFP, 0, 2}},
+ {38, &JitArm::Default}, //"mtfsb1x", OPTYPE_SYSTEMFP, 0, 2}},
+ {134, &JitArm::Default}, //"mtfsfix", OPTYPE_SYSTEMFP, 0, 2}},
+ {711, &JitArm::Default}, //"mtfsfx", OPTYPE_SYSTEMFP, 0, 2}},
+};
+
+static GekkoOPTemplate table63_2[] =
+{
+ {18, &JitArm::Default}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}},
+ {20, &JitArm::Default}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {21, &JitArm::faddx}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {22, &JitArm::Default}, //"fsqrtx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {23, &JitArm::Default}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {25, &JitArm::Default}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {26, &JitArm::Default}, //"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}},
+ {28, &JitArm::Default}, //"fmsubx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {29, &JitArm::Default}, //"fmaddx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {30, &JitArm::Default}, //"fnmsubx", OPTYPE_FPU, FL_RC_BIT_F}},
+ {31, &JitArm::Default}, //"fnmaddx", OPTYPE_FPU, FL_RC_BIT_F}},
+};
+
+
+namespace JitArmTables
+{
+
+void CompileInstruction(PPCAnalyst::CodeOp & op)
+{
+ JitArm *jitarm = (JitArm *)jit;
+ (jitarm->*dynaOpTable[op.inst.OPCD])(op.inst);
+ GekkoOPInfo *info = op.opinfo;
+ if (info) {
+#ifdef OPLOG
+ if (!strcmp(info->opname, OP_TO_LOG)){ ///"mcrfs"
+ rsplocations.push_back(jit.js.compilerPC);
+ }
+#endif
+ info->compileCount++;
+ info->lastUse = jit->js.compilerPC;
+ }
+}
+
+void InitTables()
+{
+ // once initialized, tables are read-only
+ static bool initialized = false;
+ if (initialized)
+ return;
+
+ //clear
+ for (int i = 0; i < 32; i++)
+ {
+ dynaOpTable59[i] = &JitArm::unknown_instruction;
+ }
+
+ for (int i = 0; i < 1024; i++)
+ {
+ dynaOpTable4 [i] = &JitArm::unknown_instruction;
+ dynaOpTable19[i] = &JitArm::unknown_instruction;
+ dynaOpTable31[i] = &JitArm::unknown_instruction;
+ dynaOpTable63[i] = &JitArm::unknown_instruction;
+ }
+
+ for (int i = 0; i < (int)(sizeof(primarytable) / sizeof(GekkoOPTemplate)); i++)
+ {
+ dynaOpTable[primarytable[i].opcode] = primarytable[i].Inst;
+ }
+
+ for (int i = 0; i < 32; i++)
+ {
+ int fill = i << 5;
+ for (int j = 0; j < (int)(sizeof(table4_2) / sizeof(GekkoOPTemplate)); j++)
+ {
+ int op = fill+table4_2[j].opcode;
+ dynaOpTable4[op] = table4_2[j].Inst;
+ }
+ }
+
+ for (int i = 0; i < 16; i++)
+ {
+ int fill = i << 6;
+ for (int j = 0; j < (int)(sizeof(table4_3) / sizeof(GekkoOPTemplate)); j++)
+ {
+ int op = fill+table4_3[j].opcode;
+ dynaOpTable4[op] = table4_3[j].Inst;
+ }
+ }
+
+ for (int i = 0; i < (int)(sizeof(table4) / sizeof(GekkoOPTemplate)); i++)
+ {
+ int op = table4[i].opcode;
+ dynaOpTable4[op] = table4[i].Inst;
+ }
+
+ for (int i = 0; i < (int)(sizeof(table31) / sizeof(GekkoOPTemplate)); i++)
+ {
+ int op = table31[i].opcode;
+ dynaOpTable31[op] = table31[i].Inst;
+ }
+
+ for (int i = 0; i < 1; i++)
+ {
+ int fill = i << 9;
+ for (int j = 0; j < (int)(sizeof(table31_2) / sizeof(GekkoOPTemplate)); j++)
+ {
+ int op = fill + table31_2[j].opcode;
+ dynaOpTable31[op] = table31_2[j].Inst;
+ }
+ }
+
+ for (int i = 0; i < (int)(sizeof(table19) / sizeof(GekkoOPTemplate)); i++)
+ {
+ int op = table19[i].opcode;
+ dynaOpTable19[op] = table19[i].Inst;
+ }
+
+ for (int i = 0; i < (int)(sizeof(table59) / sizeof(GekkoOPTemplate)); i++)
+ {
+ int op = table59[i].opcode;
+ dynaOpTable59[op] = table59[i].Inst;
+ }
+
+ for (int i = 0; i < (int)(sizeof(table63) / sizeof(GekkoOPTemplate)); i++)
+ {
+ int op = table63[i].opcode;
+ dynaOpTable63[op] = table63[i].Inst;
+ }
+
+ for (int i = 0; i < 32; i++)
+ {
+ int fill = i << 5;
+ for (int j = 0; j < (int)(sizeof(table63_2) / sizeof(GekkoOPTemplate)); j++)
+ {
+ int op = fill + table63_2[j].opcode;
+ dynaOpTable63[op] = table63_2[j].Inst;
+ }
+ }
+
+ initialized = true;
+
+}
+
+} // namespace
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.h
new file mode 100644
index 0000000000..4904ce3984
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.h
@@ -0,0 +1,29 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef JITARM_TABLES_H
+#define JITARM_TABLES_H
+
+#include "../Gekko.h"
+#include "../PPCTables.h"
+
+namespace JitArmTables
+{
+ void CompileInstruction(PPCAnalyst::CodeOp & op);
+ void InitTables();
+}
+#endif
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp
new file mode 100644
index 0000000000..aa999c9a39
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp
@@ -0,0 +1,174 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+
+#include "../../HW/Memmap.h"
+
+#include "../PowerPC.h"
+#include "../../CoreTiming.h"
+#include "MemoryUtil.h"
+
+#include "Jit.h"
+#include "../JitCommon/JitCache.h"
+
+#include "../../HW/GPFifo.h"
+#include "../../Core.h"
+#include "JitAsm.h"
+#include "ArmEmitter.h"
+
+using namespace ArmGen;
+
+//TODO - make an option
+//#if _DEBUG
+// bool enableDebug = false;
+//#else
+// bool enableDebug = false;
+//#endif
+
+JitArmAsmRoutineManager asm_routines;
+
+void JitArmAsmRoutineManager::Generate()
+{
+ enterCode = GetCodePtr();
+ PUSH(2, R11, _LR); // R11 is frame pointer in Debug.
+
+ MOVI2R(R0, (u32)&CoreTiming::downcount);
+ MOVI2R(R9, (u32)&PowerPC::ppcState.spr[0]);
+
+ FixupBranch skipToRealDispatcher = B();
+ dispatcher = GetCodePtr();
+ printf("Dispatcher is %p\n", dispatcher);
+
+ // Downcount Check
+ // The result of slice decrementation should be in flags if somebody jumped here
+ // IMPORTANT - We jump on negative, not carry!!!
+ FixupBranch bail = B_CC(CC_MI);
+
+ SetJumpTarget(skipToRealDispatcher);
+ dispatcherNoCheck = GetCodePtr();
+
+ // This block of code gets the address of the compiled block of code
+ // It runs though to the compiling portion if it isn't found
+ LDR(R12, R9, PPCSTATE_OFF(pc));// Load the current PC into R12
+
+ MOVI2R(R14, JIT_ICACHE_MASK); // Potential for optimization
+ AND(R12, R12, R14); // R12 contains PC & JIT_ICACHE_MASK here.
+ // Confirmed good to this point 08-03-12
+
+ MOVI2R(R14, (u32)jit->GetBlockCache()->GetICache());
+ // Confirmed That this loads the base iCache Location correctly 08-04-12
+
+ LDR(R12, R14, R12); // R12 contains iCache[PC & JIT_ICACHE_MASK] here
+ // R12 Confirmed this is the correct iCache Location loaded.
+ TST(R12, 0xFC); // Test to see if it is a JIT block.
+
+ SetCC(CC_EQ); // Only run next part if R12 is zero
+ // Success, it is our Jitblock.
+ MOVI2R(R14, (u32)jit->GetBlockCache()->GetCodePointers());
+ // LDR R14 right here to get CodePointers()[0] pointer.
+ REV(R12, R12); // Reversing this gives us our JITblock.
+ LSL(R12, R12, 2); // Multiply by four because address locations are u32 in size
+ LDR(R14, R14, R12); // Load the block address in to R14
+
+ B(R14);
+
+ FixupBranch NextBlock = B(); // Jump to end so we can start a new block
+ SetCC(); // Return to always executing codes
+
+ // If we get to this point, that means that we don't have the block cached to execute
+ // So call ArmJit to compile the block and then execute it.
+ MOVI2R(R14, (u32)&Jit);
+ LDR(R0, R9, PPCSTATE_OFF(pc));
+ BL(R14);
+
+ B(dispatcherNoCheck);
+
+ // fpException()
+ // Floating Point Exception Check, Jumped to if false
+ fpException = GetCodePtr();
+ LDR(R0, R9, PPCSTATE_OFF(Exceptions));
+ ORR(R0, R0, EXCEPTION_FPU_UNAVAILABLE);
+ STR(R0, R9, PPCSTATE_OFF(Exceptions));
+ QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
+ LDR(R0, R9, PPCSTATE_OFF(npc));
+ STR(R0, R9, PPCSTATE_OFF(pc));
+ B(dispatcher);
+
+ SetJumpTarget(bail);
+ doTiming = GetCodePtr();
+ // XXX: In JIT64, Advance() gets called /after/ the exception checking
+ // once it jumps back to the start of outerLoop
+ QuickCallFunction(R14, (void*)&CoreTiming::Advance);
+
+ // Does exception checking
+ testExceptions = GetCodePtr();
+ LDR(R0, R9, PPCSTATE_OFF(pc));
+ STR(R0, R9, PPCSTATE_OFF(npc));
+ QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
+ LDR(R0, R9, PPCSTATE_OFF(npc));
+ STR(R0, R9, PPCSTATE_OFF(pc));
+ // Check the state pointer to see if we are exiting
+ // Gets checked on every exception check
+ MOVI2R(R0, (u32)PowerPC::GetStatePtr());
+ MVN(R1, 0);
+ LDR(R0, R0);
+ TST(R0, R1);
+ FixupBranch Exit = B_CC(CC_NEQ);
+
+ SetJumpTarget(NextBlock);
+ B(dispatcher);
+
+ SetJumpTarget(Exit);
+
+ POP(2, R11, _PC);
+ FlushIcache();
+}
+
+void JitArmAsmRoutineManager::GenerateCommon()
+{
+/* fifoDirectWrite8 = AlignCode4();
+ GenFifoWrite(8);
+ fifoDirectWrite16 = AlignCode4();
+ GenFifoWrite(16);
+ fifoDirectWrite32 = AlignCode4();
+ GenFifoWrite(32);
+ fifoDirectWriteFloat = AlignCode4();
+ GenFifoFloatWrite();
+ fifoDirectWriteXmm64 = AlignCode4();
+ GenFifoXmm64Write();
+
+ GenQuantizedLoads();
+ GenQuantizedStores();
+ GenQuantizedSingleStores();
+*/
+ //CMPSD(R(XMM0), M(&zero),
+ // TODO
+
+ // Fast write routines - special case the most common hardware write
+ // TODO: use this.
+ // Even in x86, the param values will be in the right registers.
+ /*
+ const u8 *fastMemWrite8 = AlignCode16();
+ CMP(32, R(ABI_PARAM2), Imm32(0xCC008000));
+ FixupBranch skip_fast_write = J_CC(CC_NE, false);
+ MOV(32, EAX, M(&m_gatherPipeCount));
+ MOV(8, MDisp(EAX, (u32)&m_gatherPipe), ABI_PARAM1);
+ ADD(32, 1, M(&m_gatherPipeCount));
+ RET();
+ SetJumpTarget(skip_fast_write);
+ CALL((void *)&Memory::Write_U8);*/
+}
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.h
new file mode 100644
index 0000000000..9a61e9e653
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.h
@@ -0,0 +1,43 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef _JITARMASM_H
+#define _JITARMASM_H
+#include "ArmEmitter.h"
+#include "../JitCommon/JitAsmCommon.h"
+using namespace ArmGen;
+class JitArmAsmRoutineManager : public CommonAsmRoutinesBase, public ARMXCodeBlock
+{
+private:
+ void Generate();
+ void GenerateCommon();
+
+public:
+ void Init() {
+ AllocCodeSpace(8192);
+ Generate();
+ WriteProtect();
+ }
+
+ void Shutdown() {
+ FreeCodeSpace();
+ }
+};
+
+extern JitArmAsmRoutineManager asm_routines;
+
+#endif // _JIT64ASM_H
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.cpp
new file mode 100644
index 0000000000..535f8446c7
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.cpp
@@ -0,0 +1,169 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Jit.h"
+#include "JitFPRCache.h"
+
+ArmFPRCache::ArmFPRCache()
+{
+ emit = 0;
+}
+
+void ArmFPRCache::Init(ARMXEmitter *emitter)
+{
+ emit = emitter;
+ ARMReg *PPCRegs = GetPPCAllocationOrder(NUMPPCREG);
+ ARMReg *Regs = GetAllocationOrder(NUMARMREG);
+
+ for(u8 a = 0; a < NUMPPCREG; ++a)
+ {
+ ArmCRegs[a].PPCReg = 33;
+ ArmCRegs[a].Reg = PPCRegs[a];
+ ArmCRegs[a].LastLoad = 0;
+ ArmCRegs[a].PS1 = false;
+ }
+ for(u8 a = 0; a < NUMARMREG; ++a)
+ {
+ ArmRegs[a].Reg = Regs[a];
+ ArmRegs[a].free = true;
+ }
+}
+void ArmFPRCache::Start(PPCAnalyst::BlockRegStats &stats)
+{
+ for(u8 a = 0; a < NUMPPCREG; ++a)
+ {
+ ArmCRegs[a].PPCReg = 33;
+ ArmCRegs[a].LastLoad = 0;
+ }
+}
+ARMReg *ArmFPRCache::GetPPCAllocationOrder(int &count)
+{
+ // This will return us the allocation order of the registers we can use on
+ // the ppc side.
+ static ARMReg allocationOrder[] =
+ {
+ D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10,
+ D11, D12, D13, D14, D15, D16, D17, D18, D19,
+ D20, D21, D22, D23, D24, D25, D26, D27
+ };
+ count = sizeof(allocationOrder) / sizeof(const int);
+ return allocationOrder;
+}
+ARMReg *ArmFPRCache::GetAllocationOrder(int &count)
+{
+ // This will return us the allocation order of the registers we can use on
+ // the host side.
+ static ARMReg allocationOrder[] =
+ {
+ D31, D30, D29, D28
+ };
+ count = sizeof(allocationOrder) / sizeof(const int);
+ return allocationOrder;
+}
+
+ARMReg ArmFPRCache::GetReg(bool AutoLock)
+{
+ for(u8 a = 0; a < NUMARMREG; ++a)
+ if(ArmRegs[a].free)
+ {
+ // Alright, this one is free
+ if (AutoLock)
+ ArmRegs[a].free = false;
+ return ArmRegs[a].Reg;
+ }
+ // Uh Oh, we have all them locked....
+ _assert_msg_(_DYNA_REC_, false, "All available registers are locked dumb dumb");
+ return D31;
+}
+void ArmFPRCache::Unlock(ARMReg V0)
+{
+ for(u8 RegNum = 0; RegNum < NUMARMREG; ++RegNum)
+ {
+ if(ArmRegs[RegNum].Reg == V0)
+ {
+ _assert_msg_(_DYNA_REC, !ArmRegs[RegNum].free, "This register is already unlocked");
+ ArmRegs[RegNum].free = true;
+ }
+ }
+}
+ARMReg ArmFPRCache::GetPPCReg(u32 preg, bool PS1, bool preLoad)
+{
+ u32 HighestUsed = 0;
+ u8 Num = 0;
+ for(u8 a = 0; a < NUMPPCREG; ++a){
+ ++ArmCRegs[a].LastLoad;
+ if (ArmCRegs[a].LastLoad > HighestUsed)
+ {
+ HighestUsed = ArmCRegs[a].LastLoad;
+ Num = a;
+ }
+ }
+ // Check if already Loaded
+ for(u8 a = 0; a < NUMPPCREG; ++a)
+ if (ArmCRegs[a].PPCReg == preg && ArmCRegs[a].PS1 == PS1)
+ {
+ ArmCRegs[a].LastLoad = 0;
+ return ArmCRegs[a].Reg;
+ }
+ // Check if we have a free register
+ for (u8 a = 0; a < NUMPPCREG; ++a)
+ if (ArmCRegs[a].PPCReg == 33)
+ {
+ u16 offset = PPCSTATE_OFF(ps) + (preg * 16) + (PS1 ? 8 : 0);
+ if (preLoad)
+ emit->VLDR(ArmCRegs[a].Reg, R9, offset);
+ ArmCRegs[a].PPCReg = preg;
+ ArmCRegs[a].LastLoad = 0;
+ ArmCRegs[a].PS1 = PS1;
+ return ArmCRegs[a].Reg;
+ }
+ // Alright, we couldn't get a free space, dump that least used register
+ u16 offsetOld = PPCSTATE_OFF(ps) + (ArmCRegs[Num].PPCReg * 16) + (ArmCRegs[Num].PS1 ? 8 : 0);
+ emit->VSTR(ArmCRegs[Num].Reg, R9, offsetOld);
+
+ u16 offsetNew = PPCSTATE_OFF(ps) + (preg * 16) + (PS1 ? 8 : 0);
+ if (preLoad)
+ emit->VLDR(ArmCRegs[Num].Reg, R9, offsetNew);
+ ArmCRegs[Num].PPCReg = preg;
+ ArmCRegs[Num].LastLoad = 0;
+ ArmCRegs[Num].PS1 = PS1;
+ return ArmCRegs[Num].Reg;
+
+}
+
+ARMReg ArmFPRCache::R0(u32 preg, bool preLoad)
+{
+ return GetPPCReg(preg, false, preLoad);
+}
+
+ARMReg ArmFPRCache::R1(u32 preg, bool preLoad)
+{
+ return GetPPCReg(preg, true, preLoad);
+}
+
+void ArmFPRCache::Flush()
+{
+ for(u8 a = 0; a < NUMPPCREG; ++a)
+ if (ArmCRegs[a].PPCReg != 33)
+ {
+ u16 offset = PPCSTATE_OFF(ps) + (ArmCRegs[a].PPCReg * 16) + (ArmCRegs[a].PS1 ? 8 : 0);
+ emit->VSTR(ArmCRegs[a].Reg, R9, offset);
+ ArmCRegs[a].PPCReg = 33;
+ ArmCRegs[a].LastLoad = 0;
+ }
+}
+
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.h
new file mode 100644
index 0000000000..6b4f056409
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.h
@@ -0,0 +1,62 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef _JITARMFPRCACHE_H
+#define _JITARMFPRCACHE_H
+
+#include "ArmEmitter.h"
+#include "../Gekko.h"
+#include "../PPCAnalyst.h"
+#include "JitRegCache.h"
+
+#define ARMFPUREGS 32
+using namespace ArmGen;
+
+class ArmFPRCache
+{
+private:
+ PPCCachedReg regs[32];
+ JRCPPC ArmCRegs[ARMFPUREGS];
+ JRCReg ArmRegs[ARMFPUREGS];
+
+ int NUMPPCREG;
+ int NUMARMREG;
+
+ ARMReg *GetAllocationOrder(int &count);
+ ARMReg *GetPPCAllocationOrder(int &count);
+
+ ARMReg GetPPCReg(u32 preg, bool PS1, bool preLoad);
+
+protected:
+ ARMXEmitter *emit;
+
+public:
+ ArmFPRCache();
+ ~ArmFPRCache() {}
+
+ void Init(ARMXEmitter *emitter);
+ void Start(PPCAnalyst::BlockRegStats &stats);
+
+ void SetEmitter(ARMXEmitter *emitter) {emit = emitter;}
+
+ ARMReg GetReg(bool AutoLock = true); // Return a ARM register we can use.
+ void Unlock(ARMReg V0);
+ void Flush();
+ ARMReg R0(u32 preg, bool preLoad = true); // Returns a cached register
+ ARMReg R1(u32 preg, bool preLoad = true);
+};
+#endif
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.cpp
new file mode 100644
index 0000000000..2a9aa2154f
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.cpp
@@ -0,0 +1,168 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Jit.h"
+#include "JitRegCache.h"
+
+ArmRegCache::ArmRegCache()
+{
+ emit = 0;
+}
+
+void ArmRegCache::Init(ARMXEmitter *emitter)
+{
+ emit = emitter;
+ ARMReg *PPCRegs = GetPPCAllocationOrder(NUMPPCREG);
+ ARMReg *Regs = GetAllocationOrder(NUMARMREG);
+ for(u8 a = 0; a < 32; ++a)
+ {
+ // This gives us the memory locations of the gpr registers so we can
+ // load them.
+ regs[a].location = (u8*)&PowerPC::ppcState.gpr[a];
+ regs[a].UsesLeft = 0;
+ }
+ for(u8 a = 0; a < NUMPPCREG; ++a)
+ {
+ ArmCRegs[a].PPCReg = 33;
+ ArmCRegs[a].Reg = PPCRegs[a];
+ ArmCRegs[a].LastLoad = 0;
+ }
+ for(u8 a = 0; a < NUMARMREG; ++a)
+ {
+ ArmRegs[a].Reg = Regs[a];
+ ArmRegs[a].free = true;
+ }
+}
+void ArmRegCache::Start(PPCAnalyst::BlockRegStats &stats)
+{
+ for(u8 a = 0; a < NUMPPCREG; ++a)
+ {
+ ArmCRegs[a].PPCReg = 33;
+ ArmCRegs[a].LastLoad = 0;
+ }
+ for(u8 a = 0; a < 32; ++a)
+ regs[a].UsesLeft = stats.GetTotalNumAccesses(a);
+}
+ARMReg *ArmRegCache::GetPPCAllocationOrder(int &count)
+{
+ // This will return us the allocation order of the registers we can use on
+ // the ppc side.
+ static ARMReg allocationOrder[] =
+ {
+ R0, R1, R2, R3, R4, R5, R6, R7, R8
+ };
+ count = sizeof(allocationOrder) / sizeof(const int);
+ return allocationOrder;
+}
+ARMReg *ArmRegCache::GetAllocationOrder(int &count)
+{
+ // This will return us the allocation order of the registers we can use on
+ // the host side.
+ static ARMReg allocationOrder[] =
+ {
+ R14, R12, R11, R10
+ };
+ count = sizeof(allocationOrder) / sizeof(const int);
+ return allocationOrder;
+}
+
+ARMReg ArmRegCache::GetReg(bool AutoLock)
+{
+ for(u8 a = 0; a < NUMARMREG; ++a)
+ if(ArmRegs[a].free)
+ {
+ // Alright, this one is free
+ if (AutoLock)
+ ArmRegs[a].free = false;
+ return ArmRegs[a].Reg;
+ }
+ // Uh Oh, we have all them locked....
+ _assert_msg_(_DYNA_REC_, false, "All available registers are locked dumb dumb");
+ return R0;
+}
+void ArmRegCache::Lock(ARMReg Reg)
+{
+ for(u8 RegNum = 0; RegNum < NUMARMREG; ++RegNum)
+ if(ArmRegs[RegNum].Reg == Reg)
+ {
+ _assert_msg_(_DYNA_REC, ArmRegs[RegNum].free, "This register is already locked");
+ ArmRegs[RegNum].free = false;
+ }
+ _assert_msg_(_DYNA_REC, false, "Register %d can't be used with lock", Reg);
+}
+void ArmRegCache::Unlock(ARMReg R0, ARMReg R1, ARMReg R2, ARMReg R3)
+{
+ for(u8 RegNum = 0; RegNum < NUMARMREG; ++RegNum)
+ {
+ if(ArmRegs[RegNum].Reg == R0)
+ {
+ _assert_msg_(_DYNA_REC, !ArmRegs[RegNum].free, "This register is already unlocked");
+ ArmRegs[RegNum].free = true;
+ }
+ if( R1 != INVALID_REG && ArmRegs[RegNum].Reg == R1) ArmRegs[RegNum].free = true;
+ if( R2 != INVALID_REG && ArmRegs[RegNum].Reg == R2) ArmRegs[RegNum].free = true;
+ if( R3 != INVALID_REG && ArmRegs[RegNum].Reg == R3) ArmRegs[RegNum].free = true;
+ }
+}
+
+ARMReg ArmRegCache::R(u32 preg)
+{
+ u32 HighestUsed = 0;
+ u8 Num = 0;
+ for(u8 a = 0; a < NUMPPCREG; ++a){
+ ++ArmCRegs[a].LastLoad;
+ if (ArmCRegs[a].LastLoad > HighestUsed)
+ {
+ HighestUsed = ArmCRegs[a].LastLoad;
+ Num = a;
+ }
+ }
+ // Check if already Loaded
+ for(u8 a = 0; a < NUMPPCREG; ++a)
+ if (ArmCRegs[a].PPCReg == preg)
+ {
+ ArmCRegs[a].LastLoad = 0;
+ return ArmCRegs[a].Reg;
+ }
+ // Check if we have a free register
+ for (u8 a = 0; a < NUMPPCREG; ++a)
+ if (ArmCRegs[a].PPCReg == 33)
+ {
+ emit->LDR(ArmCRegs[a].Reg, R9, PPCSTATE_OFF(gpr) + preg * 4);
+ ArmCRegs[a].PPCReg = preg;
+ ArmCRegs[a].LastLoad = 0;
+ return ArmCRegs[a].Reg;
+ }
+ // Alright, we couldn't get a free space, dump that least used register
+ emit->STR(ArmCRegs[Num].Reg, R9, PPCSTATE_OFF(gpr) + ArmCRegs[Num].PPCReg * 4);
+ emit->LDR(ArmCRegs[Num].Reg, R9, PPCSTATE_OFF(gpr) + preg * 4);
+ ArmCRegs[Num].PPCReg = preg;
+ ArmCRegs[Num].LastLoad = 0;
+ return ArmCRegs[Num].Reg;
+}
+
+void ArmRegCache::Flush()
+{
+ for(u8 a = 0; a < NUMPPCREG; ++a)
+ if (ArmCRegs[a].PPCReg != 33)
+ {
+ emit->STR(ArmCRegs[a].Reg, R9, PPCSTATE_OFF(gpr) + ArmCRegs[a].PPCReg * 4);
+ ArmCRegs[a].PPCReg = 33;
+ ArmCRegs[a].LastLoad = 0;
+ }
+}
+
diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.h
new file mode 100644
index 0000000000..7292ce1581
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.h
@@ -0,0 +1,92 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef _JITARMREGCACHE_H
+#define _JITARMREGCACHE_H
+
+#include "ArmEmitter.h"
+#include "../Gekko.h"
+#include "../PPCAnalyst.h"
+
+using namespace ArmGen;
+// This ARM Register cache actually pre loads the most used registers before
+// the block to increase speed since every memory load requires two
+// instructions to load it. We are going to use R0-RMAX as registers for the
+// use of PPC Registers.
+// Allocation order as follows
+#define ARMREGS 16
+// Allocate R0 to R9 for PPC first.
+// For General registers on the host side, start with R14 and go down as we go
+// R13 is reserved for our stack pointer, don't ever use that. Unless you save
+// it
+// So we have R14, R12, R11, R10 to work with instructions
+
+struct PPCCachedReg
+{
+ const u8 *location;
+ u32 UsesLeft;
+};
+struct JRCPPC
+{
+ u32 PPCReg; // Tied to which PPC Register
+ bool PS1;
+ ARMReg Reg; // Tied to which ARM Register
+ u32 LastLoad;
+};
+struct JRCReg
+{
+ ARMReg Reg; // Which reg this is.
+ bool free;
+};
+class ArmRegCache
+{
+private:
+ PPCCachedReg regs[32];
+ JRCPPC ArmCRegs[ARMREGS];
+ JRCReg ArmRegs[ARMREGS]; // Four registers remaining
+
+ int NUMPPCREG;
+ int NUMARMREG;
+
+ ARMReg *GetAllocationOrder(int &count);
+ ARMReg *GetPPCAllocationOrder(int &count);
+
+protected:
+ ARMXEmitter *emit;
+
+public:
+ ArmRegCache();
+ ~ArmRegCache() {}
+
+ void Init(ARMXEmitter *emitter);
+ void Start(PPCAnalyst::BlockRegStats &stats);
+
+ void SetEmitter(ARMXEmitter *emitter) {emit = emitter;}
+
+ ARMReg GetReg(bool AutoLock = true); // Return a ARM register we can use.
+ void Lock(ARMReg reg);
+ void Unlock(ARMReg R0, ARMReg R1 = INVALID_REG, ARMReg R2 = INVALID_REG, ARMReg R3 =
+ INVALID_REG);
+ void Flush();
+ ARMReg R(u32 preg); // Returns a cached register
+
+};
+
+
+
+
+#endif
diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp
index 34b9a681e9..8514450cb8 100644
--- a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp
+++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp
@@ -15,7 +15,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-#include "ABI.h"
+#include "x64ABI.h"
#include "Thunk.h"
#include "CPUDetect.h"
#include "x64Emitter.h"
@@ -26,12 +26,13 @@
#include "../../CoreTiming.h"
#include "MemoryUtil.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "../JitCommon/JitCache.h"
#include "../../HW/GPFifo.h"
#include "../../Core.h"
#include "JitAsmCommon.h"
+#include "JitBase.h"
using namespace Gen;
diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h
index cbec27d2aa..a610a03326 100644
--- a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h
+++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h
@@ -21,16 +21,8 @@
#include "../JitCommon/Jit_Util.h"
#include "Thunk.h"
-class CommonAsmRoutines : public EmuCodeBlock {
-protected:
- void GenQuantizedLoads();
- void GenQuantizedStores();
- void GenQuantizedSingleStores();
-
+class CommonAsmRoutinesBase {
public:
- void GenFifoWrite(int size);
- void GenFifoXmm64Write();
- void GenFifoFloatWrite();
const u8 *fifoDirectWrite8;
const u8 *fifoDirectWrite16;
@@ -72,8 +64,23 @@ public:
// In: XMM0: Bottom 32-bit slot holds the float to be written.
const u8 **singleStoreQuantized;
+};
+
+class CommonAsmRoutines : public CommonAsmRoutinesBase, public EmuCodeBlock
+{
+protected:
+ void GenQuantizedLoads();
+ void GenQuantizedStores();
+ void GenQuantizedSingleStores();
+
+public:
+ void GenFifoWrite(int size);
+ void GenFifoXmm64Write();
+ void GenFifoFloatWrite();
+
private:
ThunkManager thunks;
+
};
#endif
diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp
index 3042cfedba..76e791a94c 100644
--- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp
+++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp
@@ -25,7 +25,7 @@
#include "../../HW/Memmap.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Thunk.h"
#include "x64Analyzer.h"
@@ -160,7 +160,7 @@ const u8 *TrampolineCache::GetWriteTrampoline(const InstructionInfo &info)
// 1) It's really necessary. We don't know anything about the context.
// 2) It doesn't really hurt. Only instructions that access I/O will get these, and there won't be
// that many of them in a typical program/game.
-const u8 *JitBase::BackPatch(u8 *codePtr, int accessType, u32 emAddress, void *ctx_void)
+const u8 *Jitx86Base::BackPatch(u8 *codePtr, int accessType, u32 emAddress, void *ctx_void)
{
#ifdef _M_X64
CONTEXT *ctx = (CONTEXT *)ctx_void;
diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h
index 4b880eb86d..871a112c6c 100644
--- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h
+++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h
@@ -34,6 +34,9 @@
// from the real context.
struct CONTEXT
{
+ #ifdef _M_ARM
+ u32 reg_pc;
+ #else
#ifdef _M_X64
u64 Rip;
u64 Rax;
@@ -41,6 +44,7 @@
u32 Eip;
u32 Eax;
#endif
+ #endif
};
#endif
diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h
index 5352c06d04..9b8c67474c 100644
--- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h
+++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h
@@ -32,12 +32,9 @@
#define JIT_OPCODE 0
-class JitBase : public CPUCoreBase, public EmuCodeBlock
+class JitBase : public CPUCoreBase
{
protected:
- JitBlockCache blocks;
- TrampolineCache trampolines;
-
struct JitOptions
{
bool optimizeStack;
@@ -77,22 +74,35 @@ protected:
u8* rewriteStart;
JitBlock *curBlock;
-
- std::set<u32> fifoWriteAddresses;
};
public:
// This should probably be removed from public:
JitOptions jo;
JitState js;
-
- JitBlockCache *GetBlockCache() { return &blocks; }
+
+ virtual JitBaseBlockCache *GetBlockCache() = 0;
virtual void Jit(u32 em_address) = 0;
+ virtual const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx) = 0;
+
+ virtual const CommonAsmRoutinesBase *GetAsmRoutines() = 0;
+
+ virtual bool IsInCodeSpace(u8 *ptr) = 0;
+};
+
+class Jitx86Base : public JitBase, public EmuCodeBlock
+{
+protected:
+ JitBlockCache blocks;
+ TrampolineCache trampolines;
+public:
+ JitBlockCache *GetBlockCache() { return &blocks; }
+
const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx);
- virtual const CommonAsmRoutines *GetAsmRoutines() = 0;
+ bool IsInCodeSpace(u8 *ptr) { return IsInSpace(ptr); }
};
extern JitBase *jit;
diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp
index d409518bf9..415b37ca61 100644
--- a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp
+++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp
@@ -32,15 +32,13 @@
#include "MemoryUtil.h"
#include "../../HW/Memmap.h"
+#include "../JitInterface.h"
#include "../../CoreTiming.h"
#include "../PowerPC.h"
#include "../PPCTables.h"
#include "../PPCAnalyst.h"
-#include "x64Emitter.h"
-#include "x64Analyzer.h"
-
#include "JitCache.h"
#include "JitBase.h"
@@ -68,12 +66,12 @@ bool JitBlock::ContainsAddress(u32 em_address)
return (em_address >= originalAddress && em_address < originalAddress + 4 * originalSize);
}
- bool JitBlockCache::IsFull() const
+ bool JitBaseBlockCache::IsFull() const
{
return GetNumBlocks() >= MAX_NUM_BLOCKS - 1;
}
- void JitBlockCache::Init()
+ void JitBaseBlockCache::Init()
{
MAX_NUM_BLOCKS = 65536*2;
@@ -91,11 +89,11 @@ bool JitBlock::ContainsAddress(u32 em_address)
}
else
{
- PanicAlert("JitBlockCache::Init() - iCache is already initialized");
+ PanicAlert("JitBaseBlockCache::Init() - iCache is already initialized");
}
if (iCache == 0 || iCacheEx == 0 || iCacheVMEM == 0)
{
- PanicAlert("JitBlockCache::Init() - unable to allocate iCache");
+ PanicAlert("JitBaseBlockCache::Init() - unable to allocate iCache");
}
memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
memset(iCacheEx, JIT_ICACHE_INVALID_BYTE, JIT_ICACHEEX_SIZE);
@@ -104,7 +102,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
Clear();
}
- void JitBlockCache::Shutdown()
+ void JitBaseBlockCache::Shutdown()
{
delete[] blocks;
delete[] blockCodePointers;
@@ -133,7 +131,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
// This clears the JIT cache. It's called from JitCache.cpp when the JIT cache
// is full and when saving and loading states.
- void JitBlockCache::Clear()
+ void JitBaseBlockCache::Clear()
{
if (IsFull())
Core::DisplayMessage("Clearing block cache.", 3000);
@@ -151,7 +149,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS);
}
- void JitBlockCache::ClearSafe()
+ void JitBaseBlockCache::ClearSafe()
{
#ifdef JIT_UNLIMITED_ICACHE
memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
@@ -160,7 +158,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
#endif
}
- /*void JitBlockCache::DestroyBlocksWithFlag(BlockFlag death_flag)
+ /*void JitBaseBlockCache::DestroyBlocksWithFlag(BlockFlag death_flag)
{
for (int i = 0; i < num_blocks; i++)
{
@@ -171,23 +169,23 @@ bool JitBlock::ContainsAddress(u32 em_address)
}
}*/
- void JitBlockCache::Reset()
+ void JitBaseBlockCache::Reset()
{
Shutdown();
Init();
}
- JitBlock *JitBlockCache::GetBlock(int no)
+ JitBlock *JitBaseBlockCache::GetBlock(int no)
{
return &blocks[no];
}
- int JitBlockCache::GetNumBlocks() const
+ int JitBaseBlockCache::GetNumBlocks() const
{
return num_blocks;
}
- bool JitBlockCache::RangeIntersect(int s1, int e1, int s2, int e2) const
+ bool JitBaseBlockCache::RangeIntersect(int s1, int e1, int s2, int e2) const
{
// check if any endpoint is inside the other range
if ((s1 >= s2 && s1 <= e2) ||
@@ -199,7 +197,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
return false;
}
- int JitBlockCache::AllocateBlock(u32 em_address)
+ int JitBaseBlockCache::AllocateBlock(u32 em_address)
{
JitBlock &b = blocks[num_blocks];
b.invalid = false;
@@ -215,12 +213,12 @@ bool JitBlock::ContainsAddress(u32 em_address)
return num_blocks - 1;
}
- void JitBlockCache::FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr)
+ void JitBaseBlockCache::FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr)
{
blockCodePointers[block_num] = code_ptr;
JitBlock &b = blocks[block_num];
- b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress);
- Memory::Write_Opcode_JIT(b.originalAddress, (JIT_OPCODE << 26) | block_num);
+ b.originalFirstOpcode = JitInterface::Read_Opcode_JIT(b.originalAddress);
+ JitInterface::Write_Opcode_JIT(b.originalAddress, (JIT_OPCODE << 26) | block_num);
// Convert the logical address to a physical address for the block map
u32 pAddr = b.originalAddress & 0x1FFFFFFF;
@@ -264,29 +262,29 @@ bool JitBlock::ContainsAddress(u32 em_address)
#endif
}
- const u8 **JitBlockCache::GetCodePointers()
+ const u8 **JitBaseBlockCache::GetCodePointers()
{
return blockCodePointers;
}
#ifdef JIT_UNLIMITED_ICACHE
- u8* JitBlockCache::GetICache()
+ u8* JitBaseBlockCache::GetICache()
{
return iCache;
}
- u8* JitBlockCache::GetICacheEx()
+ u8* JitBaseBlockCache::GetICacheEx()
{
return iCacheEx;
}
- u8* JitBlockCache::GetICacheVMEM()
+ u8* JitBaseBlockCache::GetICacheVMEM()
{
return iCacheVMEM;
}
#endif
- int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
+ int JitBaseBlockCache::GetBlockNumberFromStartAddress(u32 addr)
{
if (!blocks)
return -1;
@@ -317,24 +315,24 @@ bool JitBlock::ContainsAddress(u32 em_address)
return inst;
}
- void JitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector<int> *block_numbers)
+ void JitBaseBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector<int> *block_numbers)
{
for (int i = 0; i < num_blocks; i++)
if (blocks[i].ContainsAddress(em_address))
block_numbers->push_back(i);
}
- u32 JitBlockCache::GetOriginalFirstOp(int block_num)
+ u32 JitBaseBlockCache::GetOriginalFirstOp(int block_num)
{
if (block_num >= num_blocks)
{
- //PanicAlert("JitBlockCache::GetOriginalFirstOp - block_num = %u is out of range", block_num);
+ //PanicAlert("JitBaseBlockCache::GetOriginalFirstOp - block_num = %u is out of range", block_num);
return block_num;
}
return blocks[block_num].originalFirstOpcode;
}
- CompiledCode JitBlockCache::GetCompiledCodeFromBlock(int block_num)
+ CompiledCode JitBaseBlockCache::GetCompiledCodeFromBlock(int block_num)
{
return (CompiledCode)blockCodePointers[block_num];
}
@@ -345,7 +343,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
//Can be faster by doing a queue for blocks to link up, and only process those
//Should probably be done
- void JitBlockCache::LinkBlockExits(int i)
+ void JitBaseBlockCache::LinkBlockExits(int i)
{
JitBlock &b = blocks[i];
if (b.invalid)
@@ -360,8 +358,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]);
if (destinationBlock != -1)
{
- XEmitter emit(b.exitPtrs[e]);
- emit.JMP(blocks[destinationBlock].checkedEntry, true);
+ WriteLinkBlock(b.exitPtrs[e], blocks[destinationBlock].checkedEntry);
b.linkStatus[e] = true;
}
}
@@ -370,7 +367,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
using namespace std;
- void JitBlockCache::LinkBlock(int i)
+ void JitBaseBlockCache::LinkBlock(int i)
{
LinkBlockExits(i);
JitBlock &b = blocks[i];
@@ -386,7 +383,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
}
}
- void JitBlockCache::UnlinkBlock(int i)
+ void JitBaseBlockCache::UnlinkBlock(int i)
{
JitBlock &b = blocks[i];
pair<multimap<u32, int>::iterator, multimap<u32, int>::iterator> ppp;
@@ -403,7 +400,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
}
}
- void JitBlockCache::DestroyBlock(int block_num, bool invalidate)
+ void JitBaseBlockCache::DestroyBlock(int block_num, bool invalidate)
{
if (block_num < 0 || block_num >= num_blocks)
{
@@ -419,7 +416,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
}
b.invalid = true;
#ifdef JIT_UNLIMITED_ICACHE
- Memory::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode?b.originalFirstOpcode:JIT_ICACHE_INVALID_WORD);
+ JitInterface::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode?b.originalFirstOpcode:JIT_ICACHE_INVALID_WORD);
#else
if (Memory::ReadFast32(b.originalAddress) == block_num)
Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress);
@@ -430,18 +427,10 @@ bool JitBlock::ContainsAddress(u32 em_address)
// Send anyone who tries to run this block back to the dispatcher.
// Not entirely ideal, but .. pretty good.
// Spurious entrances from previously linked blocks can only come through checkedEntry
- XEmitter emit((u8 *)b.checkedEntry);
- emit.MOV(32, M(&PC), Imm32(b.originalAddress));
- emit.JMP(jit->GetAsmRoutines()->dispatcher, true);
- // this is not needed really
- /*
- emit.SetCodePtr((u8 *)blockCodePointers[blocknum]);
- emit.MOV(32, M(&PC), Imm32(b.originalAddress));
- emit.JMP(asm_routines.dispatcher, true);
- */
+ WriteDestroyBlock(b.checkedEntry, b.originalAddress);
}
- void JitBlockCache::InvalidateICache(u32 address, const u32 length)
+ void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length)
{
// Convert the logical address to a physical address for the block map
u32 pAddr = address & 0x1FFFFFFF;
@@ -449,7 +438,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
// Optimize the common case of length == 32 which is used by Interpreter::dcb*
bool destroy_block = true;
if (length == 32)
- {
+ {
if (!valid_block[pAddr / 32])
destroy_block = false;
else
@@ -462,7 +451,7 @@ bool JitBlock::ContainsAddress(u32 em_address)
{
std::map<pair<u32,u32>, u32>::iterator it1 = block_map.lower_bound(std::make_pair(pAddr, 0)), it2 = it1;
while (it2 != block_map.end() && it2->first.second < pAddr + length)
- {
+ {
#ifdef JIT_UNLIMITED_ICACHE
JitBlock &b = blocks[it2->second];
if (b.originalAddress & JIT_ICACHE_VMEM_BIT)
@@ -516,3 +505,14 @@ bool JitBlock::ContainsAddress(u32 em_address)
}
#endif
}
+ void JitBlockCache::WriteLinkBlock(u8* location, const u8* address)
+ {
+ XEmitter emit(location);
+ emit.JMP(address, true);
+ }
+ void JitBlockCache::WriteDestroyBlock(const u8* location, u32 address)
+ {
+ XEmitter emit((u8 *)location);
+ emit.MOV(32, M(&PC), Imm32(address));
+ emit.JMP(jit->GetAsmRoutines()->dispatcher, true);
+ }
diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h
index 4214f33875..b148cb8090 100644
--- a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h
+++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h
@@ -78,7 +78,8 @@ struct JitBlock
typedef void (*CompiledCode)();
-class JitBlockCache
+
+class JitBaseBlockCache
{
const u8 **blockCodePointers;
JitBlock *blocks;
@@ -97,9 +98,13 @@ class JitBlockCache
void LinkBlockExits(int i);
void LinkBlock(int i);
void UnlinkBlock(int i);
+
+ // Virtual for overloaded
+ virtual void WriteLinkBlock(u8* location, const u8* address) = 0;
+ virtual void WriteDestroyBlock(const u8* location, u32 address) = 0;
public:
- JitBlockCache() :
+ JitBaseBlockCache() :
blockCodePointers(0), blocks(0), num_blocks(0),
#ifdef JIT_UNLIMITED_ICACHE
iCache(0), iCacheEx(0), iCacheVMEM(0),
@@ -146,4 +151,11 @@ public:
//void DestroyBlocksWithFlag(BlockFlag death_flag);
};
+// x86 BlockCache
+class JitBlockCache : public JitBaseBlockCache
+{
+private:
+ void WriteLinkBlock(u8* location, const u8* address);
+ void WriteDestroyBlock(const u8* location, u32 address);
+};
#endif
diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp
index cc1327c695..f5c4cb022b 100644
--- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp
+++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp
@@ -25,7 +25,7 @@
#include "../../HW/Memmap.h"
#include "../PPCTables.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "JitBase.h"
#include "Jit_Util.h"
diff --git a/Source/Core/Core/Src/PowerPC/JitInterface.cpp b/Source/Core/Core/Src/PowerPC/JitInterface.cpp
new file mode 100644
index 0000000000..2f56f013be
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitInterface.cpp
@@ -0,0 +1,351 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include <algorithm>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "JitInterface.h"
+#include "JitCommon/JitBase.h"
+
+#ifndef _M_GENERIC
+#include "Jit64IL/JitIL.h"
+#include "Jit64/Jit.h"
+#include "Jit64/Jit64_Tables.h"
+#include "Jit64IL/JitIL_Tables.h"
+#endif
+
+#ifdef _M_ARM
+#include "JitArm32/Jit.h"
+#include "JitArm32/JitArm_Tables.h"
+#endif
+
+#include "Profiler.h"
+#include "PPCSymbolDB.h"
+#include "HW/Memmap.h"
+#include "ConfigManager.h"
+
+bool bFakeVMEM = false;
+bool bMMU = false;
+
+namespace JitInterface
+{
+ void DoState(PointerWrap &p)
+ {
+ if (jit && p.GetMode() == PointerWrap::MODE_READ)
+ jit->GetBlockCache()->ClearSafe();
+ }
+ CPUCoreBase *InitJitCore(int core)
+ {
+ bFakeVMEM = SConfig::GetInstance().m_LocalCoreStartupParameter.iTLBHack == 1;
+ bMMU = SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU;
+
+ CPUCoreBase *ptr = NULL;
+ switch(core)
+ {
+ #ifndef _M_GENERIC
+ case 1:
+ {
+ ptr = new Jit64();
+ break;
+ }
+ case 2:
+ {
+ ptr = new JitIL();
+ break;
+ }
+ #endif
+ #ifdef _M_ARM
+ case 3:
+ {
+ ptr = new JitArm();
+ break;
+ }
+ #endif
+ default:
+ {
+ PanicAlert("Unrecognizable cpu_core: %d", core);
+ jit = NULL;
+ return NULL;
+ break;
+ }
+ }
+ jit = static_cast<JitBase*>(ptr);
+ jit->Init();
+ return ptr;
+ }
+ void InitTables(int core)
+ {
+ switch(core)
+ {
+ #ifndef _M_GENERIC
+ case 1:
+ {
+ Jit64Tables::InitTables();
+ break;
+ }
+ case 2:
+ {
+ JitILTables::InitTables();
+ break;
+ }
+ #endif
+ #ifdef _M_ARM
+ case 3:
+ {
+ JitArmTables::InitTables();
+ break;
+ }
+ #endif
+ default:
+ {
+ PanicAlert("Unrecognizable cpu_core: %d", core);
+ break;
+ }
+ }
+ }
+ CPUCoreBase *GetCore()
+ {
+ return jit;
+ }
+
+ void WriteProfileResults(const char *filename)
+ {
+ // Can't really do this with no jit core available
+ #ifndef _M_GENERIC
+
+ std::vector<BlockStat> stats;
+ stats.reserve(jit->GetBlockCache()->GetNumBlocks());
+ u64 cost_sum = 0;
+ #ifdef _WIN32
+ u64 timecost_sum = 0;
+ u64 countsPerSec;
+ QueryPerformanceFrequency((LARGE_INTEGER *)&countsPerSec);
+ #endif
+ for (int i = 0; i < jit->GetBlockCache()->GetNumBlocks(); i++)
+ {
+ const JitBlock *block = jit->GetBlockCache()->GetBlock(i);
+ // Rough heuristic. Mem instructions should cost more.
+ u64 cost = block->originalSize * (block->runCount / 4);
+ #ifdef _WIN32
+ u64 timecost = block->ticCounter;
+ #endif
+ // Todo: tweak.
+ if (block->runCount >= 1)
+ stats.push_back(BlockStat(i, cost));
+ cost_sum += cost;
+ #ifdef _WIN32
+ timecost_sum += timecost;
+ #endif
+ }
+
+ sort(stats.begin(), stats.end());
+ File::IOFile f(filename, "w");
+ if (!f)
+ {
+ PanicAlert("failed to open %s", filename);
+ return;
+ }
+ fprintf(f.GetHandle(), "origAddr\tblkName\tcost\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n");
+ for (unsigned int i = 0; i < stats.size(); i++)
+ {
+ const JitBlock *block = jit->GetBlockCache()->GetBlock(stats[i].blockNum);
+ if (block)
+ {
+ std::string name = g_symbolDB.GetDescription(block->originalAddress);
+ double percent = 100.0 * (double)stats[i].cost / (double)cost_sum;
+ #ifdef _WIN32
+ double timePercent = 100.0 * (double)block->ticCounter / (double)timecost_sum;
+ fprintf(f.GetHandle(), "%08x\t%s\t%llu\t%llu\t%.2lf\t%llf\t%lf\t%i\n",
+ block->originalAddress, name.c_str(), stats[i].cost,
+ block->ticCounter, percent, timePercent,
+ (double)block->ticCounter*1000.0/(double)countsPerSec, block->codeSize);
+ #else
+ fprintf(f.GetHandle(), "%08x\t%s\t%llu\t???\t%.2lf\t???\t???\t%i\n",
+ block->originalAddress, name.c_str(), stats[i].cost, percent, block->codeSize);
+ #endif
+ }
+ }
+ #endif
+ }
+ bool IsInCodeSpace(u8 *ptr)
+ {
+ return jit->IsInCodeSpace(ptr);
+ }
+ const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx)
+ {
+ return jit->BackPatch(codePtr, accessType, em_address, ctx);
+ }
+
+ void ClearCache()
+ {
+ if (jit)
+ jit->ClearCache();
+ }
+ void ClearSafe()
+ {
+ if (jit)
+ jit->GetBlockCache()->ClearSafe();
+ }
+
+ void InvalidateICache(u32 address, u32 size)
+ {
+ if (jit)
+ jit->GetBlockCache()->InvalidateICache(address, size);
+ }
+
+
+ // Memory functions
+ u32 Read_Opcode_JIT_Uncached(const u32 _Address)
+ {
+ u8* iCache;
+ u32 addr;
+ if (_Address & JIT_ICACHE_VMEM_BIT)
+ {
+ iCache = jit->GetBlockCache()->GetICacheVMEM();
+ addr = _Address & JIT_ICACHE_MASK;
+ }
+ else if (_Address & JIT_ICACHE_EXRAM_BIT)
+ {
+ iCache = jit->GetBlockCache()->GetICacheEx();
+ addr = _Address & JIT_ICACHEEX_MASK;
+ }
+ else
+ {
+ iCache = jit->GetBlockCache()->GetICache();
+ addr = _Address & JIT_ICACHE_MASK;
+ }
+ u32 inst = *(u32*)(iCache + addr);
+ if (inst == JIT_ICACHE_INVALID_WORD)
+ {
+ u32 cache_block_start = addr & ~0x1f;
+ u32 mem_block_start = _Address & ~0x1f;
+ u8 *pMem = Memory::GetPointer(mem_block_start);
+ memcpy(iCache + cache_block_start, pMem, 32);
+ inst = *(u32*)(iCache + addr);
+ }
+ inst = Common::swap32(inst);
+
+ if ((inst & 0xfc000000) == 0)
+ {
+ inst = jit->GetBlockCache()->GetOriginalFirstOp(inst);
+ }
+
+ return inst;
+ }
+
+ u32 Read_Opcode_JIT(u32 _Address)
+ {
+ #ifdef FAST_ICACHE
+ if (bMMU && !bFakeVMEM && (_Address & Memory::ADDR_MASK_MEM1))
+ {
+ _Address = Memory::TranslateAddress(_Address, Memory::FLAG_OPCODE);
+ if (_Address == 0)
+ {
+ return 0;
+ }
+ }
+ u32 inst = 0;
+
+ // Bypass the icache for the external interrupt exception handler
+ if ( (_Address & 0x0FFFFF00) == 0x00000500 )
+ inst = Read_Opcode_JIT_Uncached(_Address);
+ else
+ inst = PowerPC::ppcState.iCache.ReadInstruction(_Address);
+ #else
+ u32 inst = Memory::ReadUnchecked_U32(_Address);
+ #endif
+ return inst;
+ }
+
+ // The following function is deprecated in favour of FAST_ICACHE
+ u32 Read_Opcode_JIT_LC(const u32 _Address)
+ {
+ #ifdef JIT_UNLIMITED_ICACHE
+ if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 &&
+ (_Address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area
+ (_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000)
+ {
+ PanicAlertT("iCacheJIT: Reading Opcode from %x. Please report.", _Address);
+ ERROR_LOG(MEMMAP, "iCacheJIT: Reading Opcode from %x. Please report.", _Address);
+ return 0;
+ }
+ u8* iCache;
+ u32 addr;
+ if (_Address & JIT_ICACHE_VMEM_BIT)
+ {
+ iCache = jit->GetBlockCache()->GetICacheVMEM();
+ addr = _Address & JIT_ICACHE_MASK;
+ }
+ else if (_Address & JIT_ICACHE_EXRAM_BIT)
+ {
+ iCache = jit->GetBlockCache()->GetICacheEx();
+ addr = _Address & JIT_ICACHEEX_MASK;
+ }
+ else
+ {
+ iCache = jit->GetBlockCache()->GetICache();
+ addr = _Address & JIT_ICACHE_MASK;
+ }
+ u32 inst = *(u32*)(iCache + addr);
+ if (inst == JIT_ICACHE_INVALID_WORD)
+ inst = Memory::ReadUnchecked_U32(_Address);
+ else
+ inst = Common::swap32(inst);
+ #else
+ u32 inst = Memory::ReadUnchecked_U32(_Address);
+ #endif
+ if ((inst & 0xfc000000) == 0)
+ {
+ inst = jit->GetBlockCache()->GetOriginalFirstOp(inst);
+ }
+ return inst;
+ }
+
+ // WARNING! No checks!
+ // We assume that _Address is cached
+ void Write_Opcode_JIT(const u32 _Address, const u32 _Value)
+ {
+ #ifdef JIT_UNLIMITED_ICACHE
+ if (_Address & JIT_ICACHE_VMEM_BIT)
+ {
+ *(u32*)(jit->GetBlockCache()->GetICacheVMEM() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value);
+ }
+ else if (_Address & JIT_ICACHE_EXRAM_BIT)
+ {
+ *(u32*)(jit->GetBlockCache()->GetICacheEx() + (_Address & JIT_ICACHEEX_MASK)) = Common::swap32(_Value);
+ }
+ else
+ *(u32*)(jit->GetBlockCache()->GetICache() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value);
+ #else
+ Memory::WriteUnchecked_U32(_Value, _Address);
+ #endif
+ }
+
+
+ void Shutdown()
+ {
+ if (jit)
+ {
+ jit->Shutdown();
+ delete jit;
+ jit = NULL;
+ }
+ }
+}
diff --git a/Source/Core/Core/Src/PowerPC/JitInterface.h b/Source/Core/Core/Src/PowerPC/JitInterface.h
new file mode 100644
index 0000000000..9213072ab9
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/JitInterface.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "ChunkFile.h"
+#include "CPUCoreBase.h"
+
+namespace JitInterface
+{
+ void DoState(PointerWrap &p);
+
+ CPUCoreBase *InitJitCore(int core);
+ void InitTables(int core);
+ CPUCoreBase *GetCore();
+
+ // Debugging
+ void WriteProfileResults(const char *filename);
+
+ // Memory Utilities
+ bool IsInCodeSpace(u8 *ptr);
+ const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx);
+
+ // used by JIT to read instructions
+ u32 Read_Opcode_JIT(const u32 _Address);
+ // used by JIT. uses iCacheJIT. Reads in the "Locked cache" mode
+ u32 Read_Opcode_JIT_LC(const u32 _Address);
+ void Write_Opcode_JIT(const u32 _Address, const u32 _Value);
+
+ // Clearing CodeCache
+ void ClearCache();
+
+ void ClearSafe();
+
+ void InvalidateICache(u32 address, u32 size);
+
+ void Shutdown();
+}
+extern bool bFakeVMEM;
+extern bool bMMU;
+
diff --git a/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp
index fa9f278c29..15a85568de 100644
--- a/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp
+++ b/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp
@@ -21,6 +21,7 @@
#include "StringUtil.h"
#include "Interpreter/Interpreter.h"
#include "../HW/Memmap.h"
+#include "JitInterface.h"
#include "PPCTables.h"
#include "PPCSymbolDB.h"
#include "SignatureDB.h"
@@ -368,7 +369,7 @@ u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa,
}
else
{
- inst = Memory::Read_Opcode_JIT(address);
+ inst = JitInterface::Read_Opcode_JIT(address);
}
}
diff --git a/Source/Core/Core/Src/PowerPC/PPCCache.cpp b/Source/Core/Core/Src/PowerPC/PPCCache.cpp
index 6956e9db1c..a0e4c666a4 100644
--- a/Source/Core/Core/Src/PowerPC/PPCCache.cpp
+++ b/Source/Core/Core/Src/PowerPC/PPCCache.cpp
@@ -20,6 +20,7 @@
#include "PowerPC.h"
#include "JitCommon/JitBase.h"
#include "JitCommon/JitCache.h"
+#include "JitInterface.h"
namespace PowerPC
{
@@ -76,8 +77,7 @@ namespace PowerPC
memset(lookup_table_ex, 0xff, sizeof(lookup_table_ex));
memset(lookup_table_vmem, 0xff, sizeof(lookup_table_vmem));
#endif
- if (jit)
- jit->GetBlockCache()->ClearSafe();
+ JitInterface::ClearSafe();
}
void InstructionCache::Init()
@@ -109,8 +109,7 @@ namespace PowerPC
}
#endif
valid[set] = 0;
- if (jit)
- jit->GetBlockCache()->InvalidateICache(addr & ~0x1f, 32);
+ JitInterface::InvalidateICache(addr & ~0x1f, 32);
}
u32 InstructionCache::ReadInstruction(u32 addr)
diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.cpp b/Source/Core/Core/Src/PowerPC/PPCTables.cpp
index d96089cebb..a6975f5860 100644
--- a/Source/Core/Core/Src/PowerPC/PPCTables.cpp
+++ b/Source/Core/Core/Src/PowerPC/PPCTables.cpp
@@ -24,11 +24,7 @@
#include "FileUtil.h"
#include "Interpreter/Interpreter.h"
#include "Interpreter/Interpreter_Tables.h"
-#include "Jit64IL/JitIL_Tables.h"
-#include "Jit64/Jit64_Tables.h"
-
-#include "Jit64IL/JitIL.h"
-#include "Jit64/Jit.h"
+#include "JitInterface.h"
struct op_inf
{
@@ -165,19 +161,9 @@ void InitTables(int cpu_core)
// Interpreter
break;
}
- case 1:
- {
- Jit64Tables::InitTables();
- break;
- }
- case 2:
- {
- JitILTables::InitTables();
- break;
- }
default:
{
- PanicAlert("Unrecognizable cpu_core: %d", cpu_core);
+ JitInterface::InitTables(cpu_core);
break;
}
}
diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.cpp b/Source/Core/Core/Src/PowerPC/PowerPC.cpp
index 8a7b817212..e65b310f5a 100644
--- a/Source/Core/Core/Src/PowerPC/PowerPC.cpp
+++ b/Source/Core/Core/Src/PowerPC/PowerPC.cpp
@@ -29,12 +29,10 @@
#include "../HW/SystemTimers.h"
#include "Interpreter/Interpreter.h"
-#include "JitCommon/JitBase.h"
-#include "Jit64IL/JitIL.h"
-#include "Jit64/Jit.h"
#include "PowerPC.h"
#include "PPCTables.h"
#include "CPUCoreBase.h"
+#include "JitInterface.h"
#include "../Host.h"
#include "HW/EXI.h"
@@ -87,8 +85,7 @@ void DoState(PointerWrap &p)
// SystemTimers::DecrementerSet();
// SystemTimers::TimeBaseSet();
- if (jit && p.GetMode() == PointerWrap::MODE_READ)
- jit->GetBlockCache()->ClearSafe();
+ JitInterface::DoState(p);
}
void ResetRegisters()
@@ -131,28 +128,18 @@ void ResetRegisters()
void Init(int cpu_core)
{
- enum {
- FPU_PREC_24 = 0 << 8,
- FPU_PREC_53 = 2 << 8,
- FPU_PREC_64 = 3 << 8,
- FPU_PREC_MASK = 3 << 8,
- };
-#ifdef _M_IX86
- // sets the floating-point lib to 53-bit
- // PowerPC has a 53bit floating pipeline only
- // eg: sscanf is very sensitive
-#ifdef _WIN32
- _control87(_PC_53, MCW_PC);
-#else
- unsigned short _mode;
- asm ("fstcw %0" : : "m" (_mode));
- _mode = (_mode & ~FPU_PREC_MASK) | FPU_PREC_53;
- asm ("fldcw %0" : : "m" (_mode));
-#endif
-#else
- //x64 doesn't need this - fpu is done with SSE
- //but still - set any useful sse options here
-#endif
+ FPURoundMode::SetPrecisionMode(FPURoundMode::PREC_53);
+
+ memset(ppcState.mojs, 0, sizeof(ppcState.mojs));
+ memset(ppcState.sr, 0, sizeof(ppcState.sr));
+ ppcState.DebugCount = 0;
+ ppcState.dtlb_last = 0;
+ ppcState.dtlb_last = 0;
+ memset(ppcState.dtlb_va, 0, sizeof(ppcState.dtlb_va));
+ memset(ppcState.dtlb_pa, 0, sizeof(ppcState.dtlb_pa));
+ ppcState.itlb_last = 0;
+ memset(ppcState.itlb_va, 0, sizeof(ppcState.itlb_va));
+ memset(ppcState.itlb_pa, 0, sizeof(ppcState.itlb_pa));
memset(ppcState.mojs, 0, sizeof(ppcState.mojs));
memset(ppcState.sr, 0, sizeof(ppcState.sr));
@@ -174,32 +161,23 @@ void Init(int cpu_core)
switch (cpu_core)
{
- case 0:
+ case 0:
{
cpu_core_base = interpreter;
break;
}
- case 1:
- {
- cpu_core_base = new Jit64();
- break;
- }
- case 2:
- {
- cpu_core_base = new JitIL();
- break;
- }
- default:
- {
- PanicAlert("Unrecognizable cpu_core: %d", cpu_core);
- break;
- }
+ default:
+ cpu_core_base = JitInterface::InitJitCore(cpu_core);
+ if (!cpu_core_base) // Handle Situations where JIT core isn't available
+ {
+ WARN_LOG(POWERPC, "Jit core %d not available. Defaulting to interpreter.", cpu_core);
+ cpu_core_base = interpreter;
+ }
+ break;
}
if (cpu_core_base != interpreter)
{
- jit = static_cast<JitBase*>(cpu_core_base);
- jit->Init();
mode = MODE_JIT;
}
else
@@ -213,12 +191,7 @@ void Init(int cpu_core)
void Shutdown()
{
- if (jit)
- {
- jit->Shutdown();
- delete jit;
- jit = NULL;
- }
+ JitInterface::Shutdown();
interpreter->Shutdown();
cpu_core_base = NULL;
state = CPU_POWERDOWN;
@@ -244,7 +217,9 @@ void SetMode(CoreMode new_mode)
case MODE_JIT: // Switching from interpreter to JIT.
// Don't really need to do much. It'll work, the cache will refill itself.
- cpu_core_base = jit;
+ cpu_core_base = JitInterface::GetCore();
+ if (!cpu_core_base) // Has a chance to not get a working JIT core if one isn't active on host
+ cpu_core_base = interpreter;
break;
}
}
diff --git a/Source/Core/Core/Src/PowerPC/Profiler.cpp b/Source/Core/Core/Src/PowerPC/Profiler.cpp
index 3636b00717..fc8942f09b 100644
--- a/Source/Core/Core/Src/PowerPC/Profiler.cpp
+++ b/Source/Core/Core/Src/PowerPC/Profiler.cpp
@@ -15,17 +15,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-#include "JitCommon/JitBase.h"
-
-#include <vector>
-#include <algorithm>
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#include "PPCSymbolDB.h"
-#include "FileUtil.h"
+#include "JitInterface.h"
namespace Profiler
{
@@ -33,73 +23,9 @@ namespace Profiler
bool g_ProfileBlocks;
bool g_ProfileInstructions;
-struct BlockStat
-{
- BlockStat(int bn, u64 c) : blockNum(bn), cost(c) {}
- int blockNum;
- u64 cost;
-
- bool operator <(const BlockStat &other) const
- { return cost > other.cost; }
-};
-
void WriteProfileResults(const char *filename)
{
- std::vector<BlockStat> stats;
- stats.reserve(jit->GetBlockCache()->GetNumBlocks());
- u64 cost_sum = 0;
-#ifdef _WIN32
- u64 timecost_sum = 0;
- u64 countsPerSec;
- QueryPerformanceFrequency((LARGE_INTEGER *)&countsPerSec);
-#endif
- for (int i = 0; i < jit->GetBlockCache()->GetNumBlocks(); i++)
- {
- const JitBlock *block = jit->GetBlockCache()->GetBlock(i);
- if (block && !block->invalid)
- {
- // Rough heuristic. Mem instructions should cost more.
- u64 cost = block->originalSize * (block->runCount / 4);
-#ifdef _WIN32
- u64 timecost = block->ticCounter;
-#endif
- // Todo: tweak.
- if (block->runCount >= 1)
- stats.push_back(BlockStat(i, cost));
- cost_sum += cost;
-#ifdef _WIN32
- timecost_sum += timecost;
-#endif
- }
- }
-
- sort(stats.begin(), stats.end());
- File::IOFile f(filename, "w");
- if (!f)
- {
- PanicAlert("failed to open %s", filename);
- return;
- }
- fprintf(f.GetHandle(), "origAddr\tblkName\tcost\trunCount\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n");
- for (unsigned int i = 0; i < stats.size(); i++)
- {
- const JitBlock *block = jit->GetBlockCache()->GetBlock(stats[i].blockNum);
- if (block && !block->invalid)
- {
- std::string name = g_symbolDB.GetDescription(block->originalAddress);
- double percent = 100.0 * (double)stats[i].cost / (double)cost_sum;
-#ifdef _WIN32
- double timePercent = 100.0 * (double)block->ticCounter / (double)timecost_sum;
- fprintf(f.GetHandle(), "%08x\t%s\t%llu\t%llu\t%llu\t%.2lf\t%llf\t%lf\t%i\n",
- block->originalAddress, name.c_str(), stats[i].cost, block->runCount,
- block->ticCounter, percent, timePercent,
- (double)block->ticCounter*1000.0/(double)countsPerSec, block->codeSize);
-#else
- fprintf(f.GetHandle(), "%08x\t%s\t%llu\t???\t%.2lf\t???\t???\t%i\n",
- block->originalAddress, name.c_str(), stats[i].cost, percent, block->codeSize);
-#endif
- }
- }
+ JitInterface::WriteProfileResults(filename);
}
} // namespace
diff --git a/Source/Core/Core/Src/PowerPC/Profiler.h b/Source/Core/Core/Src/PowerPC/Profiler.h
index ada130e90f..b8beeaae72 100644
--- a/Source/Core/Core/Src/PowerPC/Profiler.h
+++ b/Source/Core/Core/Src/PowerPC/Profiler.h
@@ -57,6 +57,15 @@
#define PROFILER_VPOP
#endif
+struct BlockStat
+{
+ BlockStat(int bn, u64 c) : blockNum(bn), cost(c) {}
+ int blockNum;
+ u64 cost;
+
+ bool operator <(const BlockStat &other) const
+ { return cost > other.cost; }
+};
namespace Profiler
{
diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp
index 084a94e5f6..e0a9ab7858 100644
--- a/Source/Core/Core/Src/State.cpp
+++ b/Source/Core/Core/Src/State.cpp
@@ -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 = 13;
+static const u32 STATE_VERSION = 16;
struct StateHeader
{
diff --git a/Source/Core/Core/Src/MemTools.cpp b/Source/Core/Core/Src/x64MemTools.cpp
index bb6fef6439..fff26b3cb3 100644
--- a/Source/Core/Core/Src/MemTools.cpp
+++ b/Source/Core/Core/Src/x64MemTools.cpp
@@ -52,8 +52,10 @@
#include "MemTools.h"
#include "HW/Memmap.h"
#include "PowerPC/PowerPC.h"
+#include "PowerPC/JitInterface.h"
+#ifndef _M_GENERIC
#include "PowerPC/JitCommon/JitBase.h"
-#include "PowerPC/JitCommon/JitBackpatch.h"
+#endif
#include "x64Analyzer.h"
namespace EMM
@@ -77,7 +79,7 @@ LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs)
PVOID codeAddr = pPtrs->ExceptionRecord->ExceptionAddress;
unsigned char *codePtr = (unsigned char*)codeAddr;
- if (!jit->IsInCodeSpace(codePtr)) {
+ if (!JitInterface::IsInCodeSpace(codePtr)) {
// Let's not prevent debugging.
return (DWORD)EXCEPTION_CONTINUE_SEARCH;
}
@@ -107,7 +109,7 @@ LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs)
//We could emulate the memory accesses here, but then they would still be around to take up
//execution resources. Instead, we backpatch into a generic memory call and retry.
- const u8 *new_rip = jit->BackPatch(codePtr, accessType, emAddress, ctx);
+ const u8 *new_rip = JitInterface::BackPatch(codePtr, accessType, emAddress, ctx);
// Rip/Eip needs to be updated.
if (new_rip)
@@ -182,6 +184,7 @@ void print_trace(const char * msg)
void sigsegv_handler(int signal, siginfo_t *info, void *raw_context)
{
+#ifndef _M_GENERIC
if (signal != SIGSEGV)
{
// We are not interested in other signals - handle it as usual.
@@ -203,7 +206,7 @@ void sigsegv_handler(int signal, siginfo_t *info, void *raw_context)
#else
u8 *fault_instruction_ptr = (u8 *)CREG_EIP(ctx);
#endif
- if (!jit->IsInCodeSpace(fault_instruction_ptr)) {
+ if (!JitInterface::IsInCodeSpace(fault_instruction_ptr)) {
// Let's not prevent debugging.
return;
}
@@ -240,6 +243,7 @@ void sigsegv_handler(int signal, siginfo_t *info, void *raw_context)
CREG_EIP(ctx) = fake_ctx.Eip;
#endif
}
+#endif
}
void InstallExceptionHandler()
diff --git a/Source/Core/DiscIO/DiscIO.vcxproj b/Source/Core/DiscIO/DiscIO.vcxproj
index 6dd24ddd44..722aae2040 100644
--- a/Source/Core/DiscIO/DiscIO.vcxproj
+++ b/Source/Core/DiscIO/DiscIO.vcxproj
@@ -44,7 +44,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -54,7 +54,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
diff --git a/Source/Core/DiscIO/Src/BannerLoader.cpp b/Source/Core/DiscIO/Src/BannerLoader.cpp
index 6451c73670..d38c7e9ea4 100644
--- a/Source/Core/DiscIO/Src/BannerLoader.cpp
+++ b/Source/Core/DiscIO/Src/BannerLoader.cpp
@@ -22,180 +22,8 @@
#include "VolumeCreator.h"
#include "FileUtil.h"
-// HyperIris: dunno if this suitable, may be need move.
-#ifdef _WIN32
-#include <Windows.h>
-#else
-#include <sys/param.h>
-#include <iconv.h>
-#include <errno.h>
-#endif
-
-#ifndef ICONV_CONST
-#if defined __FreeBSD__ || __NetBSD__
-#define ICONV_CONST const
-#else
-#define ICONV_CONST
-#endif
-#endif
-
namespace DiscIO
{
-void IBannerLoader::CopyToStringAndCheck(std::string& _rDestination, const char* _src)
-{
- static bool bValidChars[256];
- static bool bInitialized = false;
-
- if (!bInitialized)
- {
- for (int i = 0; i < 0x20; i++)
- {
- bValidChars[i] = false;
- }
-
- // generate valid chars
- for (int i = 0x20; i < 256; i++)
- {
- bValidChars[i] = true;
- }
-
- bValidChars[0x0a] = true;
- //bValidChars[0xa9] = true;
- //bValidChars[0xe9] = true;
-
- bInitialized = true;
- }
-
- char destBuffer[2048] = {0};
- char* dest = destBuffer;
- const char* src = _src;
-
- // copy the string and check for "unknown" characters
- while (*src != 0x00)
- {
- u8 c = *src;
-
- if (c == 0x0a){c = 0x20;}
-
- if (bValidChars[c] == false)
- {
- src++;
- continue;
- }
-
- *dest = c;
- dest++;
- src++;
- }
-
- // finalize the string
- *dest = 0x00;
-
- _rDestination = destBuffer;
-}
-
-bool IBannerLoader::CopyBeUnicodeToString( std::string& _rDestination, const u16* _src, int length )
-{
- bool returnCode = false;
-#ifdef WIN32
- if (_src)
- {
- u16* buffer = new u16[length];
- if (buffer)
- {
- memcpy(buffer, _src, sizeof(u16)*length);
- for (int i = 0; i < length; i++)
- {
- buffer[i] = swap16(buffer[i]);
- }
-
- u32 ansiNameSize = WideCharToMultiByte(932, 0,
- (LPCWSTR)buffer, (int)wcslen((LPCWSTR)buffer),
- NULL, NULL, NULL, NULL);
- if (ansiNameSize > 0)
- {
- char* pAnsiStrBuffer = new char[ansiNameSize + 1];
- if (pAnsiStrBuffer)
- {
- memset(pAnsiStrBuffer, 0, (ansiNameSize + 1) * sizeof(char));
- if (WideCharToMultiByte(932, 0,
- (LPCWSTR)buffer, (int)wcslen((LPCWSTR)buffer),
- pAnsiStrBuffer, ansiNameSize, NULL, NULL))
- {
- _rDestination = pAnsiStrBuffer;
- returnCode = true;
- }
- delete[] pAnsiStrBuffer;
- }
- }
- delete[] buffer;
- }
- }
-#else
- if (_src)
- {
- iconv_t conv_desc = iconv_open("UTF-8", "CP932");
- if (conv_desc == (iconv_t) -1)
- {
- // Initialization failure.
- if (errno == EINVAL)
- {
- ERROR_LOG(DISCIO, "Conversion from CP932 to UTF-8 is not supported.");
- }
- else
- {
- ERROR_LOG(DISCIO, "Iconv initialization failure: %s\n", strerror (errno));
- }
- return false;
- }
-
- char* src_buffer = new char[length];
- for (int i = 0; i < length; i++)
- src_buffer[i] = swap16(_src[i]);
-
- size_t inbytes = sizeof(char) * length;
- size_t outbytes = 2 * inbytes;
- char* utf8_buffer = new char[outbytes + 1];
- memset(utf8_buffer, 0, (outbytes + 1) * sizeof(char));
-
- // Save the buffer locations because iconv increments them
- char* utf8_buffer_start = utf8_buffer;
- char* src_buffer_start = src_buffer;
-
- size_t iconv_size = iconv(conv_desc,
- (ICONV_CONST char**)&src_buffer, &inbytes,
- &utf8_buffer, &outbytes);
-
- // Handle failures
- if (iconv_size == (size_t) -1)
- {
- ERROR_LOG(DISCIO, "iconv failed.");
- switch (errno) {
- case EILSEQ:
- ERROR_LOG(DISCIO, "Invalid multibyte sequence.");
- break;
- case EINVAL:
- ERROR_LOG(DISCIO, "Incomplete multibyte sequence.");
- break;
- case E2BIG:
- ERROR_LOG(DISCIO, "Insufficient space allocated for output buffer.");
- break;
- default:
- ERROR_LOG(DISCIO, "Error: %s.", strerror(errno));
- }
- }
- else
- {
- _rDestination = utf8_buffer_start;
- returnCode = true;
- }
- delete[] utf8_buffer_start;
- delete[] src_buffer_start;
- iconv_close(conv_desc);
- }
-#endif
- return returnCode;
-}
IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume)
{
@@ -203,9 +31,9 @@ IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVo
{
return new CBannerLoaderWii(pVolume);
}
- if (_rFileSystem.IsValid())
+ if (_rFileSystem.IsValid())
{
- return new CBannerLoaderGC(_rFileSystem);
+ return new CBannerLoaderGC(_rFileSystem, pVolume);
}
return NULL;
diff --git a/Source/Core/DiscIO/Src/BannerLoader.h b/Source/Core/DiscIO/Src/BannerLoader.h
index 1fe48dd364..b30ee17a46 100644
--- a/Source/Core/DiscIO/Src/BannerLoader.h
+++ b/Source/Core/DiscIO/Src/BannerLoader.h
@@ -18,6 +18,9 @@
#ifndef _BANNER_LOADER_H_
#define _BANNER_LOADER_H_
+#include <vector>
+#include <string>
+
#include "Filesystem.h"
namespace DiscIO
@@ -38,24 +41,9 @@ class IBannerLoader
virtual bool GetBanner(u32* _pBannerImage) = 0;
- virtual bool GetName(std::string* _rName) = 0;
- virtual bool GetName(std::vector<std::wstring>& _rNames) {return false;};
- virtual bool GetCompany(std::string& _rCompany) = 0;
-
- virtual bool GetDescription(std::string* _rDescription) = 0;
- virtual bool GetDescription(std::wstring& _rDescription) {return false;};
-
-
- protected:
-
- void CopyToStringAndCheck(std::string& _rDestination, const char* _src);
-
- bool CopyBeUnicodeToString(std::string& _rDestination, const u16* _src, int length);
- private:
- u16 swap16(u16 data)
- {
- return ((data & 0xff00) >> 8) | ((data & 0xff) << 8);
- }
+ virtual std::vector<std::string> GetNames() = 0;
+ virtual std::string GetCompany() = 0;
+ virtual std::vector<std::string> GetDescriptions() = 0;
};
IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume);
diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp
index bf9f634ff8..d8ae259b16 100644
--- a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp
+++ b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp
@@ -23,13 +23,14 @@
namespace DiscIO
{
-CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem)
- : m_pBannerFile(NULL),
- m_IsValid(false)
+CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume)
+ : m_pBannerFile(NULL)
+ , m_IsValid(false)
+ , m_country(volume->GetCountry())
{
// load the opening.bnr
size_t FileSize = (size_t) _rFileSystem.GetFileSize("opening.bnr");
- if (FileSize == sizeof(DVDBanner) || FileSize == sizeof(DVDBanner2))
+ if (FileSize == BNR1_SIZE || FileSize == BNR2_SIZE)
{
m_pBannerFile = new u8[FileSize];
if (m_pBannerFile)
@@ -62,7 +63,6 @@ bool CBannerLoaderGC::IsValid()
return m_IsValid;
}
-
bool CBannerLoaderGC::GetBanner(u32* _pBannerImage)
{
if (!IsValid())
@@ -70,132 +70,111 @@ bool CBannerLoaderGC::GetBanner(u32* _pBannerImage)
return false;
}
- DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile;
+ auto const pBanner = (DVDBanner*)m_pBannerFile;
decode5A3image(_pBannerImage, pBanner->image, DVD_BANNER_WIDTH, DVD_BANNER_HEIGHT);
return true;
}
-bool CBannerLoaderGC::GetName(std::string _rName[])
+std::vector<std::string> CBannerLoaderGC::GetNames()
{
- bool returnCode = false;
+ std::vector<std::string> names;
if (!IsValid())
{
- return false;
+ return names;
}
+ u32 name_count = 0;
+
// find Banner type
switch (m_BNRType)
{
case CBannerLoaderGC::BANNER_BNR1:
- {
- DVDBanner* pBanner = (DVDBanner*)m_pBannerFile;
- char tempBuffer[65] = {0};
- if (pBanner->comment.longTitle[0])
- {
- memcpy(tempBuffer, pBanner->comment.longTitle, 64);
- }
- else
- {
- memcpy(tempBuffer, pBanner->comment.shortTitle, 32);
- }
- for (int i = 0; i < 6; i++)
- {
- CopyToStringAndCheck(_rName[i], tempBuffer);
- }
- returnCode = true;
- }
+ name_count = 1;
break;
+
case CBannerLoaderGC::BANNER_BNR2:
- {
- DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile;
+ name_count = 6;
+ break;
- for (int i = 0; i < 6; i++)
- {
- char tempBuffer[65] = {0};
- if (pBanner->comment[i].longTitle[0])
- {
- memcpy(tempBuffer, pBanner->comment[i].longTitle, 64);
- }
- else
- {
- memcpy(tempBuffer, pBanner->comment[i].shortTitle, 32);
- }
- CopyToStringAndCheck(_rName[i], tempBuffer);
- }
+ default:
+ break;
+ }
- returnCode = true;
+ auto const banner = reinterpret_cast<const DVDBanner*>(m_pBannerFile);
+
+ for (u32 i = 0; i != name_count; ++i)
+ {
+ auto& comment = banner->comment[i];
+ if (comment.longTitle[0])
+ {
+ auto& data = comment.longTitle;
+ names.push_back(GetDecodedString(data));
+ }
+ else
+ {
+ auto& data = comment.shortTitle;
+ names.push_back(GetDecodedString(data));
}
- break;
- default:
- break;
}
- return returnCode;
+ return names;
}
-bool CBannerLoaderGC::GetCompany(std::string& _rCompany)
+std::string CBannerLoaderGC::GetCompany()
{
- _rCompany = "N/A";
+ std::string company;
- if (!IsValid())
+ if (IsValid())
{
- return(false);
+ auto const pBanner = (DVDBanner*)m_pBannerFile;
+ auto& data = pBanner->comment[0].shortMaker;
+ company = GetDecodedString(data);
}
- DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile;
-
- CopyToStringAndCheck(_rCompany, pBanner->comment[0].shortMaker);
-
- return true;
+ return company;
}
-bool CBannerLoaderGC::GetDescription(std::string* _rDescription)
+std::vector<std::string> CBannerLoaderGC::GetDescriptions()
{
- bool returnCode = false;
+ std::vector<std::string> descriptions;
if (!IsValid())
{
- return false;
+ return descriptions;
}
+ u32 desc_count = 0;
+
// find Banner type
switch (m_BNRType)
{
case CBannerLoaderGC::BANNER_BNR1:
- {
- DVDBanner* pBanner = (DVDBanner*)m_pBannerFile;
- char tempBuffer[129] = {0};
- memcpy(tempBuffer, pBanner->comment.comment, 128);
- for (int i = 0; i < 6; i++)
- {
- CopyToStringAndCheck(_rDescription[i], tempBuffer);
- }
- returnCode = true;
- }
+ desc_count = 1;
break;
- case CBannerLoaderGC::BANNER_BNR2:
- {
- DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile;
- for (int i = 0; i< 6; i++)
- {
- char tempBuffer[129] = {0};
- memcpy(tempBuffer, pBanner->comment[i].comment, 128);
- CopyToStringAndCheck(_rDescription[i], tempBuffer);
- }
- returnCode = true;
- }
+ case CBannerLoaderGC::BANNER_BNR2:
+ desc_count = 6;
break;
+
default:
break;
}
- return returnCode;
+
+ auto banner = reinterpret_cast<const DVDBanner*>(m_pBannerFile);
+
+ for (u32 i = 0; i != desc_count; ++i)
+ {
+ auto& data = banner->comment[i].comment;
+ descriptions.push_back(GetDecodedString(data));
+ }
+
+ return descriptions;
}
@@ -223,13 +202,17 @@ CBannerLoaderGC::BANNER_TYPE CBannerLoaderGC::getBannerType()
CBannerLoaderGC::BANNER_TYPE type = CBannerLoaderGC::BANNER_UNKNOWN;
switch (bannerSignature)
{
+ // "BNR1"
case 0x31524e42:
type = CBannerLoaderGC::BANNER_BNR1;
break;
+
+ // "BNR2"
case 0x32524e42:
type = CBannerLoaderGC::BANNER_BNR2;
break;
}
return type;
}
+
} // namespace
diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.h b/Source/Core/DiscIO/Src/BannerLoaderGC.h
index 0527c721c1..8b14a45d43 100644
--- a/Source/Core/DiscIO/Src/BannerLoaderGC.h
+++ b/Source/Core/DiscIO/Src/BannerLoaderGC.h
@@ -19,6 +19,8 @@
#define _BANNER_LOADER_GC_H_
#include "BannerLoader.h"
+#include "VolumeGC.h"
+#include "StringUtil.h"
namespace DiscIO
{
@@ -26,15 +28,16 @@ class CBannerLoaderGC
: public IBannerLoader
{
public:
- CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem);
+ CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume);
virtual ~CBannerLoaderGC();
virtual bool IsValid();
virtual bool GetBanner(u32* _pBannerImage);
- virtual bool GetName(std::string* _rName);
- virtual bool GetCompany(std::string& _rCompany);
- virtual bool GetDescription(std::string* _rDescription);
+
+ virtual std::vector<std::string> GetNames();
+ virtual std::string GetCompany();
+ virtual std::vector<std::string> GetDescriptions();
private:
enum
@@ -60,23 +63,26 @@ class CBannerLoaderGC
char comment[128]; // Game description shown in IPL game start screen in two lines.
};
- // "opening.bnr" file format for JP/US console
+ // "opening.bnr" file format for EU console
struct DVDBanner
{
- u32 id; // 'BNR1'
+ u32 id; // 'BNR2'
u32 padding[7];
u16 image[DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT]; // RGB5A3 96x32 texture image
- DVDBannerComment comment;
+ DVDBannerComment comment[6]; // Comments in six languages (only 1 for BNR1 type)
};
- // "opening.bnr" file format for EU console
- struct DVDBanner2
+ static const u32 BNR1_SIZE = sizeof(DVDBanner) - sizeof(DVDBannerComment) * 5;
+ static const u32 BNR2_SIZE = sizeof(DVDBanner);
+
+ template <u32 N>
+ std::string GetDecodedString(const char (&data)[N])
{
- u32 id; // 'BNR2'
- u32 padding[7];
- u16 image[DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT]; // RGB5A3 96x32 texture image
- DVDBannerComment comment[6]; // Comments in six languages
- };
+ auto const string_decoder = CVolumeGC::GetStringDecoder(m_country);
+
+ // strnlen to trim NULLs
+ return string_decoder(std::string(data, strnlen(data, sizeof(data))));
+ }
u8* m_pBannerFile;
bool m_IsValid;
@@ -84,6 +90,8 @@ class CBannerLoaderGC
void decode5A3image(u32* dst, u16* src, int width, int height);
BANNER_TYPE getBannerType();
+
+ DiscIO::IVolume::ECountry const m_country;
};
} // namespace
diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp
index b23dc4d91a..f606ed8876 100644
--- a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp
+++ b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp
@@ -16,6 +16,7 @@
// http://code.google.com/p/dolphin-emu/
#include <stdio.h>
+#include <algorithm>
#include "Common.h"
#include "ColorUtil.h"
@@ -144,73 +145,48 @@ bool CBannerLoaderWii::GetBanner(u32* _pBannerImage)
return true;
}
-bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& s)
-{
- bool ret = false;
-
- if (IsValid())
- {
- // find Banner type
- SWiiBanner *pBanner = (SWiiBanner*)m_pBannerFile;
-
- // Ensure the string is null-terminating, since the banner format
- // doesn't require it
- u16 *src = new u16[COMMENT_SIZE + 1];
- memcpy(src, &pBanner->m_Comment[index], COMMENT_SIZE * sizeof(u16));
- src[COMMENT_SIZE] = 0;
-
- ret = CopyBeUnicodeToString(s, src, COMMENT_SIZE + 1);
-
- delete [] src;
- }
-
- return ret;
-}
-
-bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::wstring& s)
+bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& result)
{
if (IsValid())
{
- // find Banner type
- SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile;
-
- std::wstring description;
- for (int i = 0; i < COMMENT_SIZE; ++i)
- description.push_back(Common::swap16(pBanner->m_Comment[index][i]));
-
- s = description;
+ auto const banner = reinterpret_cast<const SWiiBanner*>(m_pBannerFile);
+ auto const src_ptr = banner->m_Comment[index];
+
+ // Trim at first NULL
+ auto const length = std::find(src_ptr, src_ptr + COMMENT_SIZE, 0x0) - src_ptr;
+
+ std::wstring src;
+ src.resize(length);
+ std::transform(src_ptr, src_ptr + src.size(), src.begin(), (u16(&)(u16))Common::swap16);
+ result = UTF16ToUTF8(src);
+
return true;
}
+
return false;
}
-bool CBannerLoaderWii::GetName(std::string* _rName)
+std::vector<std::string> CBannerLoaderWii::GetNames()
{
- return GetStringFromComments(NAME_IDX, *_rName);
-}
+ std::vector<std::string> ret(1);
+
+ if (!GetStringFromComments(NAME_IDX, ret[0]))
+ ret.clear();
-bool CBannerLoaderWii::GetName(std::vector<std::wstring>& _rNames)
-{
- std::wstring temp;
- bool ret = GetStringFromComments(NAME_IDX, temp);
- _rNames.push_back(temp);
return ret;
}
-bool CBannerLoaderWii::GetCompany(std::string& _rCompany)
-{
- _rCompany = "N/A";
- return true;
-}
-
-bool CBannerLoaderWii::GetDescription(std::string* _rDescription)
+std::string CBannerLoaderWii::GetCompany()
{
- return GetStringFromComments(DESC_IDX, *_rDescription);
+ return "";
}
-bool CBannerLoaderWii::GetDescription(std::wstring& _rDescription)
+std::vector<std::string> CBannerLoaderWii::GetDescriptions()
{
- return GetStringFromComments(DESC_IDX, _rDescription);
+ std::vector<std::string> result(1);
+ if (!GetStringFromComments(DESC_IDX, result[0]))
+ result.clear();
+ return result;
}
void CBannerLoaderWii::decode5A3image(u32* dst, u16* src, int width, int height)
diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.h b/Source/Core/DiscIO/Src/BannerLoaderWii.h
index 83733cf5ed..036eeeacbd 100644
--- a/Source/Core/DiscIO/Src/BannerLoaderWii.h
+++ b/Source/Core/DiscIO/Src/BannerLoaderWii.h
@@ -35,15 +35,9 @@ class CBannerLoaderWii
virtual bool GetBanner(u32* _pBannerImage);
- virtual bool GetName(std::string* _rName);
-
- bool GetName(std::vector<std::wstring>& _rNames);
-
- virtual bool GetCompany(std::string& _rCompany);
-
- virtual bool GetDescription(std::string* _rDescription);
-
- bool GetDescription(std::wstring& _rDescription);
+ virtual std::vector<std::string> GetNames();
+ virtual std::string GetCompany();
+ virtual std::vector<std::string> GetDescriptions();
private:
@@ -81,7 +75,6 @@ class CBannerLoaderWii
void decode5A3image(u32* dst, u16* src, int width, int height);
bool GetStringFromComments(const CommentIndex index, std::string& s);
- bool GetStringFromComments(const CommentIndex index, std::wstring& s);
};
} // namespace
diff --git a/Source/Core/DiscIO/Src/CISOBlob.cpp b/Source/Core/DiscIO/Src/CISOBlob.cpp
index b3a2e31b2b..8d267c15fb 100644
--- a/Source/Core/DiscIO/Src/CISOBlob.cpp
+++ b/Source/Core/DiscIO/Src/CISOBlob.cpp
@@ -15,24 +15,30 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+#include <algorithm>
+#include <cmath>
+
#include "Blob.h"
#include "CISOBlob.h"
namespace DiscIO
{
+static const char CISO_MAGIC[] = "CISO";
+
CISOFileReader::CISOFileReader(std::FILE* file)
: m_file(file)
{
m_size = m_file.GetSize();
-
- memset(&header, 0, sizeof(header));
+
+ CISOHeader header;
m_file.ReadArray(&header, 1);
+
+ m_block_size = header.block_size;
- CISO_Map_t count = 0;
- int idx;
- for (idx = 0; idx < CISO_MAP_SIZE; idx++)
- ciso_map[idx] = (header.map[idx] == 1) ? count++ : CISO_UNUSED_BLOCK;
+ MapType count = 0;
+ for (u32 idx = 0; idx < CISO_MAP_SIZE; idx++)
+ m_ciso_map[idx] = (1 == header.map[idx]) ? count++ : UNUSED_BLOCK_ID;
}
CISOFileReader* CISOFileReader::Create(const char* filename)
@@ -46,34 +52,45 @@ CISOFileReader* CISOFileReader::Create(const char* filename)
return NULL;
}
+u64 CISOFileReader::GetDataSize() const
+{
+ return GetRawSize();
+}
+
+u64 CISOFileReader::GetRawSize() const
+{
+ return m_size;
+}
+
bool CISOFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
{
- u64 bytesRead = 0;
- while (bytesRead < nbytes)
+ while (nbytes != 0)
{
- u32 block = (u32)(offset / header.block_size);
- u32 data_offset = offset % header.block_size;
- u32 bytes_to_read = (u32)min((u64)(header.block_size - data_offset), nbytes);
- if ((block >= CISO_MAP_SIZE) || (ciso_map[block] == CISO_UNUSED_BLOCK))
+ auto const block = offset / m_block_size;
+ auto const data_offset = offset % m_block_size;
+
+ auto const bytes_to_read = std::min(m_block_size - data_offset, nbytes);
+ if (block < CISO_MAP_SIZE && UNUSED_BLOCK_ID != m_ciso_map[block])
{
- memset(out_ptr, 0, bytes_to_read);
+ // calcualte the base address
+ auto const file_off = CISO_HEADER_SIZE + m_ciso_map[block] * m_block_size + data_offset;
+
+ if (!(m_file.Seek(file_off, SEEK_SET) && m_file.ReadArray(out_ptr, bytes_to_read)))
+ return false;
+
out_ptr += bytes_to_read;
offset += bytes_to_read;
- bytesRead += bytes_to_read;
+ nbytes -= bytes_to_read;
}
else
{
- // calcualte the base address
- u64 file_off = CISO_HEAD_SIZE + ciso_map[block] * (u64)header.block_size + data_offset;
-
- if (!(m_file.Seek(file_off, SEEK_SET) && m_file.ReadBytes(out_ptr, bytes_to_read)))
- return false;
-
+ std::fill_n(out_ptr, bytes_to_read, 0);
out_ptr += bytes_to_read;
offset += bytes_to_read;
- bytesRead += bytes_to_read;
+ nbytes -= bytes_to_read;
}
}
+
return true;
}
@@ -81,8 +98,9 @@ bool IsCISOBlob(const char* filename)
{
File::IOFile f(filename, "rb");
- CISO_Head_t header;
- return (f.ReadArray(&header, 1) && (memcmp(header.magic, CISO_MAGIC, sizeof(header.magic)) == 0));
+ CISOHeader header;
+ return (f.ReadArray(&header, 1) &&
+ std::equal(header.magic, header.magic + sizeof(header.magic), CISO_MAGIC));
}
} // namespace
diff --git a/Source/Core/DiscIO/Src/CISOBlob.h b/Source/Core/DiscIO/Src/CISOBlob.h
index e87e616a21..9b490f0638 100644
--- a/Source/Core/DiscIO/Src/CISOBlob.h
+++ b/Source/Core/DiscIO/Src/CISOBlob.h
@@ -21,43 +21,45 @@
#include "Blob.h"
#include "FileUtil.h"
-#define CISO_MAGIC "CISO"
-#define CISO_HEAD_SIZE (0x8000)
-#define CISO_MAP_SIZE (CISO_HEAD_SIZE - 8)
-
namespace DiscIO
{
bool IsCISOBlob(const char* filename);
-// Blocks that won't compress to less than 97% of the original size are stored as-is.
-struct CISO_Head_t
+static const u32 CISO_HEADER_SIZE = 0x8000;
+static const u32 CISO_MAP_SIZE = CISO_HEADER_SIZE - sizeof(u32) - sizeof(char) * 4;
+
+struct CISOHeader
{
- u8 magic[4]; // "CISO"
- u32 block_size; // stored as litte endian (not network byte order)
- u8 map[CISO_MAP_SIZE]; // 0=unused, 1=used, others=invalid
+ // "CISO"
+ char magic[4];
+
+ // little endian
+ u32 block_size;
+
+ // 0=unused, 1=used, others=invalid
+ u8 map[CISO_MAP_SIZE];
};
-typedef u16 CISO_Map_t;
-
-const CISO_Map_t CISO_UNUSED_BLOCK = (CISO_Map_t)~0;
-
class CISOFileReader : public IBlobReader
{
- File::IOFile m_file;
- CISOFileReader(std::FILE* file);
- s64 m_size;
-
public:
static CISOFileReader* Create(const char* filename);
- u64 GetDataSize() const { return m_size; }
- u64 GetRawSize() const { return m_size; }
+ u64 GetDataSize() const;
+ u64 GetRawSize() const;
bool Read(u64 offset, u64 nbytes, u8* out_ptr);
private:
- CISO_Head_t header;
- CISO_Map_t ciso_map[CISO_MAP_SIZE];
+ CISOFileReader(std::FILE* file);
+
+ typedef u16 MapType;
+ static const MapType UNUSED_BLOCK_ID = -1;
+
+ File::IOFile m_file;
+ u64 m_size;
+ u32 m_block_size;
+ MapType m_ciso_map[CISO_MAP_SIZE];
};
} // namespace
diff --git a/Source/Core/DiscIO/Src/CompressedBlob.cpp b/Source/Core/DiscIO/Src/CompressedBlob.cpp
index c4b1aa1385..2bc4a93ede 100644
--- a/Source/Core/DiscIO/Src/CompressedBlob.cpp
+++ b/Source/Core/DiscIO/Src/CompressedBlob.cpp
@@ -301,7 +301,10 @@ bool DecompressBlobToFile(const char* infile, const char* outfile, CompressCB ca
File::IOFile f(outfile, "wb");
if (!f)
+ {
+ delete reader;
return false;
+ }
const CompressedBlobHeader &header = reader->GetHeader();
u8* buffer = new u8[header.block_size];
diff --git a/Source/Core/DiscIO/Src/DriveBlob.cpp b/Source/Core/DiscIO/Src/DriveBlob.cpp
index e69f8ff34c..2638f3fac4 100644
--- a/Source/Core/DiscIO/Src/DriveBlob.cpp
+++ b/Source/Core/DiscIO/Src/DriveBlob.cpp
@@ -16,6 +16,7 @@
// http://code.google.com/p/dolphin-emu/
#include "DriveBlob.h"
+#include "StringUtil.h"
namespace DiscIO
{
@@ -23,12 +24,9 @@ namespace DiscIO
DriveReader::DriveReader(const char *drive)
{
#ifdef _WIN32
- char path[MAX_PATH];
- strncpy(path, drive, 3);
- path[2] = 0;
- sprintf(path, "\\\\.\\%s", drive);
SectorReader::SetSectorSize(2048);
- hDisc = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ auto const path = UTF8ToTStr(std::string("\\\\.\\") + drive);
+ hDisc = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
if (hDisc != INVALID_HANDLE_VALUE)
{
diff --git a/Source/Core/DiscIO/Src/FileHandlerARC.cpp b/Source/Core/DiscIO/Src/FileHandlerARC.cpp
index a9e4beee5d..63a4876718 100644
--- a/Source/Core/DiscIO/Src/FileHandlerARC.cpp
+++ b/Source/Core/DiscIO/Src/FileHandlerARC.cpp
@@ -27,19 +27,19 @@
namespace DiscIO
{
CARCFile::CARCFile(const std::string& _rFilename)
- : m_pBuffer(NULL)
- , m_Initialized(false)
+ : m_pBuffer(NULL)
+ , m_Initialized(false)
{
- DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rFilename.c_str());
- if (pReader != NULL)
- {
- u64 FileSize = pReader->GetDataSize();
- m_pBuffer = new u8[(u32)FileSize];
- pReader->Read(0, FileSize, m_pBuffer);
- delete pReader;
-
- m_Initialized = ParseBuffer();
- }
+ DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rFilename.c_str());
+ if (pReader != NULL)
+ {
+ u64 FileSize = pReader->GetDataSize();
+ m_pBuffer = new u8[(u32)FileSize];
+ pReader->Read(0, FileSize, m_pBuffer);
+ delete pReader;
+
+ m_Initialized = ParseBuffer();
+ }
}
CARCFile::CARCFile(const std::string& _rFilename, u32 offset)
diff --git a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp
index 47651e2f23..93b569e043 100644
--- a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp
+++ b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp
@@ -20,6 +20,7 @@
#include <string>
#include <vector>
+#include <algorithm>
#include "FileSystemGCWii.h"
#include "StringUtil.h"
@@ -27,10 +28,10 @@
namespace DiscIO
{
CFileSystemGCWii::CFileSystemGCWii(const IVolume *_rVolume)
- : IFileSystem(_rVolume),
- m_Initialized(false),
- m_Valid(false),
- m_OffsetShift(0)
+ : IFileSystem(_rVolume)
+ , m_Initialized(false)
+ , m_Valid(false)
+ , m_OffsetShift(0)
{
m_Valid = DetectFileSystem();
}
@@ -213,9 +214,16 @@ u32 CFileSystemGCWii::Read32(u64 _Offset) const
return Common::swap32(Temp);
}
-void CFileSystemGCWii::GetStringFromOffset(u64 _Offset, char* Filename) const
+std::string CFileSystemGCWii::GetStringFromOffset(u64 _Offset) const
{
- m_rVolume->Read(_Offset, 255, (u8*)Filename);
+ std::string data;
+ data.resize(255);
+ m_rVolume->Read(_Offset, data.size(), (u8*)&data[0]);
+ data.erase(std::find(data.begin(), data.end(), 0x00), data.end());
+
+ // TODO: Should we really always use SHIFT-JIS?
+ // It makes some filenames in Pikmin (NTSC-U) sane, but is it correct?
+ return SHIFTJISToUTF8(data);
}
size_t CFileSystemGCWii::GetFileList(std::vector<const SFileInfo *> &_rFilenames)
@@ -311,18 +319,16 @@ size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _
{
SFileInfo *rFileInfo = &m_FileInfoVector[CurrentIndex];
u64 uOffset = _NameTableOffset + (rFileInfo->m_NameOffset & 0xFFFFFF);
- char filename[512];
- memset(filename, 0, sizeof(filename));
- GetStringFromOffset(uOffset, filename);
+ std::string filename = GetStringFromOffset(uOffset);
// check next index
if (rFileInfo->IsDirectory())
{
// this is a directory, build up the new szDirectory
if (_szDirectory != NULL)
- CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s/", _szDirectory, filename);
+ CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s/", _szDirectory, filename.c_str());
else
- CharArrayFromFormat(rFileInfo->m_FullPath, "%s/", filename);
+ CharArrayFromFormat(rFileInfo->m_FullPath, "%s/", filename.c_str());
CurrentIndex = BuildFilenames(CurrentIndex + 1, (size_t) rFileInfo->m_FileSize, rFileInfo->m_FullPath, _NameTableOffset);
}
@@ -330,9 +336,9 @@ size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _
{
// this is a filename
if (_szDirectory != NULL)
- CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s", _szDirectory, filename);
+ CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s", _szDirectory, filename.c_str());
else
- CharArrayFromFormat(rFileInfo->m_FullPath, "%s", filename);
+ CharArrayFromFormat(rFileInfo->m_FullPath, "%s", filename.c_str());
CurrentIndex++;
}
diff --git a/Source/Core/DiscIO/Src/FileSystemGCWii.h b/Source/Core/DiscIO/Src/FileSystemGCWii.h
index 0e7d836d75..9054ade272 100644
--- a/Source/Core/DiscIO/Src/FileSystemGCWii.h
+++ b/Source/Core/DiscIO/Src/FileSystemGCWii.h
@@ -28,7 +28,7 @@ namespace DiscIO
class CFileSystemGCWii : public IFileSystem
{
public:
- CFileSystemGCWii(const IVolume *_rVolume);
+ CFileSystemGCWii(const IVolume* _rVolume);
virtual ~CFileSystemGCWii();
virtual bool IsValid() const { return m_Valid; }
virtual u64 GetFileSize(const char* _rFullPath);
@@ -44,11 +44,11 @@ public:
private:
bool m_Initialized;
bool m_Valid;
-
u32 m_OffsetShift; // WII offsets are all shifted
+
std::vector <SFileInfo> m_FileInfoVector;
u32 Read32(u64 _Offset) const;
- void GetStringFromOffset(u64 _Offset, char* Filename) const;
+ std::string GetStringFromOffset(u64 _Offset) const;
const SFileInfo* FindFileInfo(const char* _rFullPath);
bool DetectFileSystem();
void InitFileSystem();
diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.cpp b/Source/Core/DiscIO/Src/NANDContentLoader.cpp
index 3c00d66be5..110efd6fa9 100644
--- a/Source/Core/DiscIO/Src/NANDContentLoader.cpp
+++ b/Source/Core/DiscIO/Src/NANDContentLoader.cpp
@@ -273,7 +273,7 @@ bool CNANDContentLoader::Initialize(const std::string& _rName)
continue;
}
- rContent.m_pData = NULL;
+ rContent.m_pData = NULL;
char szFilename[1024];
if (rContent.m_Type & 0x8000) // shared app
diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.h b/Source/Core/DiscIO/Src/NANDContentLoader.h
index 63135df693..f95ae6586c 100644
--- a/Source/Core/DiscIO/Src/NANDContentLoader.h
+++ b/Source/Core/DiscIO/Src/NANDContentLoader.h
@@ -32,14 +32,14 @@ namespace DiscIO
bool Add_Ticket(u64 TitleID, const u8 *p_tik, u32 tikSize);
struct SNANDContent
{
- u32 m_ContentID;
- u16 m_Index;
- u16 m_Type;
- u32 m_Size;
- u8 m_SHA1Hash[20];
- u8 m_Header[36]; //all of the above
-
- u8* m_pData;
+ u32 m_ContentID;
+ u16 m_Index;
+ u16 m_Type;
+ u32 m_Size;
+ u8 m_SHA1Hash[20];
+ u8 m_Header[36]; //all of the above
+
+ u8* m_pData;
};
// pure virtual interface so just the NANDContentManager can create these files only
@@ -47,34 +47,34 @@ class INANDContentLoader
{
public:
- INANDContentLoader() {}
+ INANDContentLoader() {}
- virtual ~INANDContentLoader() {}
+ virtual ~INANDContentLoader() {}
- virtual bool IsValid() const = 0;
+ virtual bool IsValid() const = 0;
virtual void RemoveTitle() const = 0;
- virtual u64 GetTitleID() const = 0;
- virtual u16 GetIosVersion() const = 0;
- virtual u32 GetBootIndex() const = 0;
- virtual size_t GetContentSize() const = 0;
- virtual const SNANDContent* GetContentByIndex(int _Index) const = 0;
+ virtual u64 GetTitleID() const = 0;
+ virtual u16 GetIosVersion() const = 0;
+ virtual u32 GetBootIndex() const = 0;
+ virtual size_t GetContentSize() const = 0;
+ virtual const SNANDContent* GetContentByIndex(int _Index) const = 0;
virtual const u8* GetTMDView() const = 0;
virtual const u8* GetTMDHeader() const = 0;
virtual u32 GetTIKSize() const = 0;
virtual const u8* GetTIK() const = 0;
- virtual const std::vector<SNANDContent>& GetContent() const = 0;
- virtual u16 GetTitleVersion() const = 0;
- virtual u16 GetNumEntries() const = 0;
- virtual DiscIO::IVolume::ECountry GetCountry() const = 0;
+ virtual const std::vector<SNANDContent>& GetContent() const = 0;
+ virtual u16 GetTitleVersion() const = 0;
+ virtual u16 GetNumEntries() const = 0;
+ virtual DiscIO::IVolume::ECountry GetCountry() const = 0;
virtual u8 GetCountryChar() const = 0;
- enum
- {
- TMD_VIEW_SIZE = 0x58,
- TMD_HEADER_SIZE = 0x1e4,
+ enum
+ {
+ TMD_VIEW_SIZE = 0x58,
+ TMD_HEADER_SIZE = 0x1e4,
CONTENT_HEADER_SIZE = 0x24,
TICKET_SIZE = 0x2A4
- };
+ };
};
@@ -83,22 +83,22 @@ class CNANDContentManager
{
public:
- static CNANDContentManager& Access() { return m_Instance; }
+ static CNANDContentManager& Access() { return m_Instance; }
u64 Install_WiiWAD(std::string &fileName);
- const INANDContentLoader& GetNANDLoader(const std::string& _rName, bool forceReload = false);
+ const INANDContentLoader& GetNANDLoader(const std::string& _rName, bool forceReload = false);
const INANDContentLoader& GetNANDLoader(u64 _titleId, bool forceReload = false);
bool RemoveTitle(u64 _titleID);
private:
- CNANDContentManager() {};
+ CNANDContentManager() {};
- ~CNANDContentManager();
+ ~CNANDContentManager();
- static CNANDContentManager m_Instance;
+ static CNANDContentManager m_Instance;
- typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
- CNANDContentMap m_Map;
+ typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
+ CNANDContentMap m_Map;
};
diff --git a/Source/Core/DiscIO/Src/Volume.h b/Source/Core/DiscIO/Src/Volume.h
index 557c71c31f..c19aaf93a8 100644
--- a/Source/Core/DiscIO/Src/Volume.h
+++ b/Source/Core/DiscIO/Src/Volume.h
@@ -22,6 +22,7 @@
#include <vector>
#include "Common.h"
+#include "StringUtil.h"
namespace DiscIO
{
@@ -37,8 +38,9 @@ public:
virtual void GetTMD(u8*, u32 *_sz) const { *_sz=0; }
virtual std::string GetUniqueID() const = 0;
virtual std::string GetMakerID() const = 0;
- virtual std::string GetName() const = 0;
- virtual bool GetWName(std::vector<std::wstring>& _rwNames) const { return false; }
+ // TODO: eliminate?
+ virtual std::string GetName() const;
+ virtual std::vector<std::string> GetNames() const = 0;
virtual u32 GetFSTSize() const = 0;
virtual std::string GetApploaderDate() const = 0;
virtual bool SupportsIntegrityCheck() const { return false; }
diff --git a/Source/Core/DiscIO/Src/VolumeCommon.cpp b/Source/Core/DiscIO/Src/VolumeCommon.cpp
index 415af2725a..4ab433680d 100644
--- a/Source/Core/DiscIO/Src/VolumeCommon.cpp
+++ b/Source/Core/DiscIO/Src/VolumeCommon.cpp
@@ -111,5 +111,13 @@ u8 GetSysMenuRegion(u16 _TitleVersion)
}
}
-};
+std::string IVolume::GetName() const
+{
+ auto names = GetNames();
+ if (names.empty())
+ return "";
+ else
+ return names[0];
+}
+}
diff --git a/Source/Core/DiscIO/Src/VolumeDirectory.cpp b/Source/Core/DiscIO/Src/VolumeDirectory.cpp
index dc76e2e641..be7cdeb565 100644
--- a/Source/Core/DiscIO/Src/VolumeDirectory.cpp
+++ b/Source/Core/DiscIO/Src/VolumeDirectory.cpp
@@ -207,11 +207,10 @@ std::string CVolumeDirectory::GetMakerID() const
return "VOID";
}
-std::string CVolumeDirectory::GetName() const
+std::vector<std::string> CVolumeDirectory::GetNames() const
{
_dbg_assert_(DVDINTERFACE, m_diskHeader);
- std::string name = (char*)(m_diskHeader + 0x20);
- return name;
+ return std::vector<std::string>(1, (char*)(m_diskHeader + 0x20));
}
void CVolumeDirectory::SetName(std::string _Name)
diff --git a/Source/Core/DiscIO/Src/VolumeDirectory.h b/Source/Core/DiscIO/Src/VolumeDirectory.h
index 0547be3b8a..4e28d6460f 100644
--- a/Source/Core/DiscIO/Src/VolumeDirectory.h
+++ b/Source/Core/DiscIO/Src/VolumeDirectory.h
@@ -50,7 +50,7 @@ public:
std::string GetMakerID() const;
- std::string GetName() const;
+ std::vector<std::string> GetNames() const;
void SetName(std::string);
u32 GetFSTSize() const;
@@ -59,7 +59,7 @@ public:
ECountry GetCountry() const;
- u64 GetSize() const;
+ u64 GetSize() const;
void BuildFST();
diff --git a/Source/Core/DiscIO/Src/VolumeGC.cpp b/Source/Core/DiscIO/Src/VolumeGC.cpp
index 09e2c5eaa9..6210172790 100644
--- a/Source/Core/DiscIO/Src/VolumeGC.cpp
+++ b/Source/Core/DiscIO/Src/VolumeGC.cpp
@@ -91,16 +91,17 @@ std::string CVolumeGC::GetMakerID() const
return makerID;
}
-std::string CVolumeGC::GetName() const
+std::vector<std::string> CVolumeGC::GetNames() const
{
- if (m_pReader == NULL)
- return "";
+ std::vector<std::string> names;
+
+ auto const string_decoder = GetStringDecoder(GetCountry());
- char name[128];
- if (!Read(0x20, 0x60, (u8*)&name))
- return "";
+ char name[0x60 + 1] = {};
+ if (m_pReader != NULL && Read(0x20, 0x60, (u8*)name))
+ names.push_back(string_decoder(name));
- return name;
+ return names;
}
u32 CVolumeGC::GetFSTSize() const
@@ -144,4 +145,10 @@ bool CVolumeGC::IsDiscTwo() const
return discTwo;
}
+auto CVolumeGC::GetStringDecoder(ECountry country) -> StringDecoder
+{
+ return (COUNTRY_JAPAN == country || COUNTRY_TAIWAN == country) ?
+ SHIFTJISToUTF8 : CP1252ToUTF8;
+}
+
} // namespace
diff --git a/Source/Core/DiscIO/Src/VolumeGC.h b/Source/Core/DiscIO/Src/VolumeGC.h
index 4221df9493..d7729ee04c 100644
--- a/Source/Core/DiscIO/Src/VolumeGC.h
+++ b/Source/Core/DiscIO/Src/VolumeGC.h
@@ -34,12 +34,16 @@ public:
bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const;
std::string GetUniqueID() const;
std::string GetMakerID() const;
- std::string GetName() const;
+ std::vector<std::string> GetNames() const;
u32 GetFSTSize() const;
std::string GetApploaderDate() const;
ECountry GetCountry() const;
u64 GetSize() const;
bool IsDiscTwo() const;
+
+ typedef std::string(*StringDecoder)(const std::string&);
+
+ static StringDecoder GetStringDecoder(ECountry country);
private:
IBlobReader* m_pReader;
diff --git a/Source/Core/DiscIO/Src/VolumeWad.cpp b/Source/Core/DiscIO/Src/VolumeWad.cpp
index 2f9f0ef961..a10e5bdb42 100644
--- a/Source/Core/DiscIO/Src/VolumeWad.cpp
+++ b/Source/Core/DiscIO/Src/VolumeWad.cpp
@@ -15,6 +15,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+#include <algorithm>
#include <math.h>
#include "VolumeWad.h"
@@ -107,78 +108,42 @@ bool CVolumeWAD::GetTitleID(u8* _pBuffer) const
return true;
}
-bool CVolumeWAD::GetWName(std::vector<std::wstring>& _rwNames) const
+std::vector<std::string> CVolumeWAD::GetNames() const
{
- u32 footer_size;
+ std::vector<std::string> names;
+ u32 footer_size;
if (!Read(0x1C, 4, (u8*)&footer_size))
{
- return false;
+ return names;
}
+
+ footer_size = Common::swap32(footer_size);
+
//Japanese, English, German, French, Spanish, Italian, Dutch, unknown, unknown, Korean
-
- // Offset to the english title
- for (int i = 0; i < 10; i++)
+ for (int i = 0; i != 10; ++i)
{
- u16 temp[42];
- std::wstring out_temp;
+ static const u32 string_length = 42;
+ static const u32 bytes_length = string_length * sizeof(u16);
+
+ u16 temp[string_length];
- if (!Read(0x9C + (i*84) + OpeningBnrOffset, 84, (u8*)&temp) || Common::swap32(footer_size) < 0xF1
- || !temp[0])
+ if (footer_size < 0xF1 || !Read(0x9C + (i * bytes_length) + OpeningBnrOffset, bytes_length, (u8*)&temp))
{
- _rwNames.push_back(L"");
- continue;
+ names.push_back("");
}
- for (int j = 0; j < 42; ++j)
+ else
{
- u16 t = Common::swap16(temp[j]);
- if (t == 0 && j > 0)
- {
- if (out_temp.at(out_temp.size()-1) != ' ')
- out_temp.push_back(' ');
- }
- else
- out_temp.push_back(t);
- }
-
- _rwNames.push_back(out_temp);
- }
- return true;
-}
-
-std::string CVolumeWAD::GetName() const
-{
- u32 footer_size;
-
- if (!Read(0x1C, 4, (u8*)&footer_size))
- return "";
-
-
- //Japanese, English, German, French, Spanish, Italian, Dutch, unknown, unknown, Korean
-
- // Offset to the english title
- char temp[84];
- if (!Read(0xF1 + OpeningBnrOffset, 84, (u8*)&temp) || Common::swap32(footer_size) < 0xF1 ||
- !Common::swap16(temp[0]))
- return "";
-
- // Remove the null bytes due to 16bit char length
- std::string out_temp;
- for (unsigned int i = 0; i < sizeof(temp); i+=2)
- {
- // Replace null chars with a single space per null section
- if (temp[i] == '\0' && i > 0)
- {
- if (out_temp.at(out_temp.size()-1) != ' ')
- out_temp.push_back(' ');
+ std::wstring out_temp;
+ out_temp.resize(string_length);
+ std::transform(temp, temp + out_temp.size(), out_temp.begin(), (u16(&)(u16))Common::swap16);
+ out_temp.erase(std::find(out_temp.begin(), out_temp.end(), 0x00), out_temp.end());
+
+ names.push_back(UTF16ToUTF8(out_temp));
}
- else
- out_temp.push_back(temp[i]);
}
- // Make it a null terminated string
- out_temp.replace(out_temp.end()-1, out_temp.end(), 1, '\0');
- return out_temp;
+ return names;
}
u64 CVolumeWAD::GetSize() const
diff --git a/Source/Core/DiscIO/Src/VolumeWad.h b/Source/Core/DiscIO/Src/VolumeWad.h
index 956844acd1..afc16766a2 100644
--- a/Source/Core/DiscIO/Src/VolumeWad.h
+++ b/Source/Core/DiscIO/Src/VolumeWad.h
@@ -38,8 +38,7 @@ public:
bool GetTitleID(u8* _pBuffer) const;
std::string GetUniqueID() const;
std::string GetMakerID() const;
- std::string GetName() const;
- bool GetWName(std::vector<std::wstring>& _rwNames) const;
+ std::vector<std::string> GetNames() const;
u32 GetFSTSize() const { return 0; }
std::string GetApploaderDate() const { return "0"; }
ECountry GetCountry() const;
diff --git a/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp
index ca010b5ae4..32aa92bd08 100644
--- a/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp
+++ b/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp
@@ -16,6 +16,7 @@
// http://code.google.com/p/dolphin-emu/
#include "VolumeWiiCrypted.h"
+#include "VolumeGC.h"
#include "StringUtil.h"
#include "Crypto/sha1.h"
@@ -168,21 +169,17 @@ std::string CVolumeWiiCrypted::GetMakerID() const
return makerID;
}
-std::string CVolumeWiiCrypted::GetName() const
+std::vector<std::string> CVolumeWiiCrypted::GetNames() const
{
- if (m_pReader == NULL)
- {
- return std::string();
- }
-
- char name[0xFF];
+ std::vector<std::string> names;
+
+ auto const string_decoder = CVolumeGC::GetStringDecoder(GetCountry());
- if (!Read(0x20, 0x60, (u8*)&name))
- {
- return std::string();
- }
+ char name[0xFF] = {};
+ if (m_pReader != NULL && Read(0x20, 0x60, (u8*)&name))
+ names.push_back(string_decoder(name));
- return name;
+ return names;
}
u32 CVolumeWiiCrypted::GetFSTSize() const
diff --git a/Source/Core/DiscIO/Src/VolumeWiiCrypted.h b/Source/Core/DiscIO/Src/VolumeWiiCrypted.h
index 5010e46bbd..56c2a8a363 100644
--- a/Source/Core/DiscIO/Src/VolumeWiiCrypted.h
+++ b/Source/Core/DiscIO/Src/VolumeWiiCrypted.h
@@ -37,7 +37,7 @@ public:
void GetTMD(u8* _pBuffer, u32* _sz) const;
std::string GetUniqueID() const;
std::string GetMakerID() const;
- std::string GetName() const;
+ std::vector<std::string> GetNames() const;
u32 GetFSTSize() const;
std::string GetApploaderDate() const;
ECountry GetCountry() const;
diff --git a/Source/Core/DiscIO/Src/WbfsBlob.cpp b/Source/Core/DiscIO/Src/WbfsBlob.cpp
index 1b7696cc58..0fd89243e3 100644
--- a/Source/Core/DiscIO/Src/WbfsBlob.cpp
+++ b/Source/Core/DiscIO/Src/WbfsBlob.cpp
@@ -75,47 +75,47 @@ bool WbfsFileReader::OpenFiles(const char* filename)
delete new_entry;
return 0 != m_total_files;
}
-
+
new_entry->base_address = m_size;
new_entry->size = new_entry->file.GetSize();
m_size += new_entry->size;
m_total_files ++;
- m_files.push_back(new_entry);
+ m_files.push_back(new_entry);
}
}
bool WbfsFileReader::ReadHeader()
{
m_files[0]->file.Seek(4, SEEK_SET);
-
+
// Read hd size info
m_files[0]->file.ReadBytes(&hd_sector_count, 4);
hd_sector_count = Common::swap32(hd_sector_count);
-
+
m_files[0]->file.ReadBytes(&hd_sector_shift, 1);
hd_sector_size = 1 << hd_sector_shift;
-
+
if(m_size != hd_sector_count * hd_sector_size)
{
//printf("File size doesn't match expected size\n");
return false;
}
-
+
// Read wbfs cluster info
m_files[0]->file.ReadBytes(&wbfs_sector_shift, 1);
wbfs_sector_size = 1 << wbfs_sector_shift;
wbfs_sector_count = m_size / wbfs_sector_size;
-
+
if(wbfs_sector_size < wii_sector_size)
{
//Setting this too low would case a very large memory allocation
return false;
}
-
+
m_blocks_per_disc = (wii_sector_count * wii_sector_size) / wbfs_sector_size;
m_disc_info_size = align(wii_disc_header_size + m_blocks_per_disc * 2, hd_sector_size);
-
+
// Read disc table
m_files[0]->file.Seek(2, SEEK_CUR);
m_files[0]->file.ReadBytes(disc_table, 500);
@@ -125,7 +125,7 @@ bool WbfsFileReader::ReadHeader()
//printf("Game must be in 'slot 0'\n");
return false;
}
-
+
return true;
}
@@ -143,7 +143,7 @@ bool WbfsFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
nbytes -= read_size;
offset += read_size;
}
-
+
return true;
}
@@ -172,16 +172,16 @@ File::IOFile& WbfsFileReader::SeekToCluster(u64 offset, u64* available)
}
}
}
-
+
PanicAlert("Read beyond end of disc");
m_files[0]->file.Seek(0, SEEK_SET);
return m_files[0]->file;
}
WbfsFileReader* WbfsFileReader::Create(const char* filename)
-{
+{
WbfsFileReader* reader = new WbfsFileReader(filename);
-
+
if(reader->IsGood())
{
return reader;
diff --git a/Source/Core/DiscIO/Src/WbfsBlob.h b/Source/Core/DiscIO/Src/WbfsBlob.h
index 300f658ddc..acae008fc2 100644
--- a/Source/Core/DiscIO/Src/WbfsBlob.h
+++ b/Source/Core/DiscIO/Src/WbfsBlob.h
@@ -63,7 +63,7 @@ class WbfsFileReader : public IBlobReader
u16* m_wlba_table;
u64 m_blocks_per_disc;
-
+
bool m_good;
public:
diff --git a/Source/Core/DiscIO/Src/WiiWad.cpp b/Source/Core/DiscIO/Src/WiiWad.cpp
index 24e091f9f4..d718436905 100644
--- a/Source/Core/DiscIO/Src/WiiWad.cpp
+++ b/Source/Core/DiscIO/Src/WiiWad.cpp
@@ -45,10 +45,11 @@ private:
WiiWAD::WiiWAD(const std::string& _rName)
{
- DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
- if (pReader == NULL || File::IsDirectory(_rName))
+ DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
+ if (pReader == NULL || File::IsDirectory(_rName))
{
m_Valid = false;
+ if(pReader) delete pReader;
return;
}
@@ -70,87 +71,87 @@ WiiWAD::~WiiWAD()
u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
{
- if (_Size > 0)
- {
- u8* pTmpBuffer = new u8[_Size];
- _dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
+ if (_Size > 0)
+ {
+ u8* pTmpBuffer = new u8[_Size];
+ _dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
- if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
- {
+ if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
+ {
ERROR_LOG(DISCIO, "WiiWAD: Could not read from file");
- PanicAlertT("WiiWAD: Could not read from file");
- }
- return pTmpBuffer;
- }
+ PanicAlertT("WiiWAD: Could not read from file");
+ }
+ return pTmpBuffer;
+ }
return NULL;
}
bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader)
{
- CBlobBigEndianReader ReaderBig(_rReader);
+ CBlobBigEndianReader ReaderBig(_rReader);
- // get header size
+ // get header size
u32 HeaderSize = ReaderBig.Read32(0);
- if (HeaderSize != 0x20)
- {
- _dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
- return false;
- }
-
- // get header
- u8 Header[0x20];
- _rReader.Read(0, HeaderSize, Header);
+ if (HeaderSize != 0x20)
+ {
+ _dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
+ return false;
+ }
+
+ // get header
+ u8 Header[0x20];
+ _rReader.Read(0, HeaderSize, Header);
u32 HeaderType = ReaderBig.Read32(0x4);
- if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
- return false;
-
- m_CertificateChainSize = ReaderBig.Read32(0x8);
- u32 Reserved = ReaderBig.Read32(0xC);
- m_TicketSize = ReaderBig.Read32(0x10);
- m_TMDSize = ReaderBig.Read32(0x14);
- m_DataAppSize = ReaderBig.Read32(0x18);
- m_FooterSize = ReaderBig.Read32(0x1C);
+ if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
+ return false;
+
+ m_CertificateChainSize = ReaderBig.Read32(0x8);
+ u32 Reserved = ReaderBig.Read32(0xC);
+ m_TicketSize = ReaderBig.Read32(0x10);
+ m_TMDSize = ReaderBig.Read32(0x14);
+ m_DataAppSize = ReaderBig.Read32(0x18);
+ m_FooterSize = ReaderBig.Read32(0x1C);
#if MAX_LOGLEVEL >= DEBUG_LEVEL
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
#else
(void)Reserved;
#endif
- u32 Offset = 0x40;
- m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 0x40);
- m_pTicket = CreateWADEntry(_rReader, m_TicketSize, Offset); Offset += ROUND_UP(m_TicketSize, 0x40);
- m_pTMD = CreateWADEntry(_rReader, m_TMDSize, Offset); Offset += ROUND_UP(m_TMDSize, 0x40);
- m_pDataApp = CreateWADEntry(_rReader, m_DataAppSize, Offset); Offset += ROUND_UP(m_DataAppSize, 0x40);
- m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40);
+ u32 Offset = 0x40;
+ m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 0x40);
+ m_pTicket = CreateWADEntry(_rReader, m_TicketSize, Offset); Offset += ROUND_UP(m_TicketSize, 0x40);
+ m_pTMD = CreateWADEntry(_rReader, m_TMDSize, Offset); Offset += ROUND_UP(m_TMDSize, 0x40);
+ m_pDataApp = CreateWADEntry(_rReader, m_DataAppSize, Offset); Offset += ROUND_UP(m_DataAppSize, 0x40);
+ m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40);
return true;
}
bool WiiWAD::IsWiiWAD(const std::string& _rName)
{
- DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
- if (pReader == NULL)
- return false;
-
- CBlobBigEndianReader Reader(*pReader);
- bool Result = false;
-
- // check for wii wad
- if (Reader.Read32(0x00) == 0x20)
- {
- u32 WADTYpe = Reader.Read32(0x04);
- switch(WADTYpe)
- {
- case 0x49730000:
- case 0x69620000:
- Result = true;
- }
- }
-
- delete pReader;
-
- return Result;
+ DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
+ if (pReader == NULL)
+ return false;
+
+ CBlobBigEndianReader Reader(*pReader);
+ bool Result = false;
+
+ // check for wii wad
+ if (Reader.Read32(0x00) == 0x20)
+ {
+ u32 WADTYpe = Reader.Read32(0x04);
+ switch(WADTYpe)
+ {
+ case 0x49730000:
+ case 0x69620000:
+ Result = true;
+ }
+ }
+
+ delete pReader;
+
+ return Result;
}
diff --git a/Source/Core/DiscIO/Src/WiiWad.h b/Source/Core/DiscIO/Src/WiiWad.h
index 3c219b6627..3b0bad1ed9 100644
--- a/Source/Core/DiscIO/Src/WiiWad.h
+++ b/Source/Core/DiscIO/Src/WiiWad.h
@@ -33,7 +33,7 @@ class WiiWAD
{
public:
- WiiWAD(const std::string& _rName);
+ WiiWAD(const std::string& _rName);
~WiiWAD();
@@ -50,7 +50,7 @@ public:
u8* GetDataApp() const { return m_pDataApp; }
u8* GetFooter() const { return m_pFooter; }
- static bool IsWiiWAD(const std::string& _rName);
+ static bool IsWiiWAD(const std::string& _rName);
private:
diff --git a/Source/Core/DolphinWX/CMakeLists.txt b/Source/Core/DolphinWX/CMakeLists.txt
index 858e05bbfd..1256890eb5 100644
--- a/Source/Core/DolphinWX/CMakeLists.txt
+++ b/Source/Core/DolphinWX/CMakeLists.txt
@@ -10,21 +10,21 @@ set(LIBS core
${GTK2_LIBRARIES}
${XRANDR_LIBRARIES}
${X11_LIBRARIES})
-
-if(SDL2_FOUND)
- # Using shared SDL2
- set(LIBS ${LIBS} ${SDL2_LIBRARY})
-else(SDL2_FOUND)
- if(SDL_FOUND)
- # Using shared SDL
- set(LIBS ${LIBS} ${SDL_LIBRARY})
- else(SDL_FOUND)
- # Using static SDL from Externals
- set(LIBS ${LIBS} SDL)
+if(NOT ANDROID)
+ if(SDL2_FOUND)
+ # Using shared SDL2
+ set(LIBS ${LIBS} ${SDL2_LIBRARY})
+ else(SDL2_FOUND)
+ if(SDL_FOUND)
+ # Using shared SDL
+ set(LIBS ${LIBS} ${SDL_LIBRARY})
+ else(SDL_FOUND)
+ # Using static SDL from Externals
+ set(LIBS ${LIBS} SDL)
+ endif()
endif()
endif()
-
if(LIBAV_FOUND)
set(LIBS ${LIBS} ${LIBAV_LIBRARIES})
endif()
@@ -79,22 +79,23 @@ if(wxWidgets_FOUND)
set(WXLIBS ${wxWidgets_LIBRARIES})
else()
- set(SRCS
- Src/MainNoGUI.cpp)
+ if(ANDROID)
+ set(SRCS Src/MainAndroid.cpp)
+ else()
+ set(SRCS Src/MainNoGUI.cpp)
+ endif()
endif()
if(USE_EGL)
- set(SRCS ${SRCS} Src/GLInterface/EGL.cpp
- Src/GLInterface/X11_Util.cpp)
+ if(NOT ANDROID)
+ set(SRCS ${SRCS} Src/GLInterface/EGL_X11.cpp
+ Src/GLInterface/X11_Util.cpp)
+ endif()
else()
if(WIN32)
set(SRCS ${SRCS} Src/GLInterface/GLW.cpp)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- if(USE_WX)
- set(SRCS ${SRCS} Src/GLInterface/WX.cpp)
- else()
- set(SRCS ${SRCS} Src/GLInterface/AGL.cpp)
- endif()
+ set(SRCS ${SRCS} Src/GLInterface/AGL.cpp)
else()
set(SRCS ${SRCS} Src/GLInterface/GLX.cpp
Src/GLInterface/X11_Util.cpp)
@@ -127,7 +128,9 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set_source_files_properties(${RESOURCES} PROPERTIES
MACOSX_PACKAGE_LOCATION Resources)
else()
- set(SRCS ${SRCS} Src/X11Utils.cpp)
+ if(NOT ANDROID)
+ set(SRCS ${SRCS} Src/X11Utils.cpp)
+ endif()
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" OR
@@ -146,75 +149,77 @@ else()
set(DOLPHIN_EXE ${DOLPHIN_EXE_BASE}-nogui)
endif()
-add_executable(${DOLPHIN_EXE} ${SRCS})
-target_link_libraries(${DOLPHIN_EXE} ${LIBS} ${WXLIBS})
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- include(BundleUtilities)
- set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${DOLPHIN_EXE}.app)
-
- # Ask for an application bundle.
- set_target_properties(${DOLPHIN_EXE} PROPERTIES
- MACOSX_BUNDLE true
- MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in
- )
-
- # Install Cg framework into application bundle.
- copy_resolved_framework_into_bundle(
- # Our framework in "Externals" does not have "Versions/Current/" in
- # its path; work around the missing directory levels using "././".
- "${CMAKE_SOURCE_DIR}/Externals/Cg/Cg.framework/././Cg"
- "${BUNDLE_PATH}/Contents/Frameworks/Cg.framework/././Cg"
- )
-
- # Fix up the bundle after it is finished.
- # There does not seem to be an easy way to run CMake commands post-build,
- # so we invoke CMake again on a generated script.
- file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/postprocess_bundle.cmake "
+if(ANDROID)
+ add_library(${DOLPHIN_EXE} SHARED ${SRCS})
+ target_link_libraries(${DOLPHIN_EXE}
+ log
+ android
+ "-Wl,--whole-archive"
+ ${LIBS}
+ "-Wl,--no-whole-archive"
+ )
+else()
+ add_executable(${DOLPHIN_EXE} ${SRCS})
+ target_link_libraries(${DOLPHIN_EXE} ${LIBS} ${WXLIBS})
+ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
include(BundleUtilities)
- message(\"Fixing up application bundle: ${BUNDLE_PATH}\")
- set(BU_CHMOD_BUNDLE_ITEMS ON)
- fixup_bundle(\"${BUNDLE_PATH}\" \"\" \"\")
- ")
- add_custom_command(TARGET ${DOLPHIN_EXE} POST_BUILD
- COMMAND ${CMAKE_COMMAND} -P postprocess_bundle.cmake
- )
+ set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${DOLPHIN_EXE}.app)
- # Copy data files into application bundle.
- file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/copy_data_into_bundle.cmake "
- file(INSTALL ${CMAKE_SOURCE_DIR}/Data/Sys ${CMAKE_SOURCE_DIR}/Data/User
- DESTINATION ${BUNDLE_PATH}/Contents/Resources
+ # Ask for an application bundle.
+ set_target_properties(${DOLPHIN_EXE} PROPERTIES
+ MACOSX_BUNDLE true
+ MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in
)
- file(GLOB TRANSLATION_FILES RELATIVE ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}/*.gmo
+
+ # Fix up the bundle after it is finished.
+ # There does not seem to be an easy way to run CMake commands post-build,
+ # so we invoke CMake again on a generated script.
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/postprocess_bundle.cmake "
+ include(BundleUtilities)
+ message(\"Fixing up application bundle: ${BUNDLE_PATH}\")
+ set(BU_CHMOD_BUNDLE_ITEMS ON)
+ fixup_bundle(\"${BUNDLE_PATH}\" \"\" \"\")
+ ")
+ add_custom_command(TARGET ${DOLPHIN_EXE} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -P postprocess_bundle.cmake
)
- foreach(TRANSLATION_FILE \${TRANSLATION_FILES})
- string(REPLACE \".gmo\" \".lproj\" TRANSLATION_DIR
- \${TRANSLATION_FILE}
- )
- # It would be better to copy to the new name as a single action,
- # but I can't figure out a way to let CMake do that.
- file(COPY ${CMAKE_BINARY_DIR}/\${TRANSLATION_FILE}
- DESTINATION ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}
- NO_SOURCE_PERMISSIONS
+
+ # Copy data files into application bundle.
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/copy_data_into_bundle.cmake "
+ file(INSTALL ${CMAKE_SOURCE_DIR}/Data/Sys ${CMAKE_SOURCE_DIR}/Data/User
+ DESTINATION ${BUNDLE_PATH}/Contents/Resources
)
- file(RENAME
- ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/\${TRANSLATION_FILE}
- ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/dolphin-emu.mo
+ file(GLOB TRANSLATION_FILES RELATIVE ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/*.gmo
)
- endforeach(TRANSLATION_FILE)
- ")
- add_custom_target(CopyDataIntoBundle ALL
- COMMAND ${CMAKE_COMMAND} -P copy_data_into_bundle.cmake
- VERBATIM
- )
+ foreach(TRANSLATION_FILE \${TRANSLATION_FILES})
+ string(REPLACE \".gmo\" \".lproj\" TRANSLATION_DIR
+ \${TRANSLATION_FILE}
+ )
+ # It would be better to copy to the new name as a single action,
+ # but I can't figure out a way to let CMake do that.
+ file(COPY ${CMAKE_BINARY_DIR}/\${TRANSLATION_FILE}
+ DESTINATION ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}
+ NO_SOURCE_PERMISSIONS
+ )
+ file(RENAME
+ ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/\${TRANSLATION_FILE}
+ ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/dolphin-emu.mo
+ )
+ endforeach(TRANSLATION_FILE)
+ ")
+ add_custom_target(CopyDataIntoBundle ALL
+ COMMAND ${CMAKE_COMMAND} -P copy_data_into_bundle.cmake
+ VERBATIM
+ )
- # Install bundle into systemwide /Applications directory.
- install(DIRECTORY ${BUNDLE_PATH} DESTINATION /Applications
- USE_SOURCE_PERMISSIONS
- )
-else()
- install(TARGETS ${DOLPHIN_EXE} RUNTIME DESTINATION ${bindir})
+ # Install bundle into systemwide /Applications directory.
+ install(DIRECTORY ${BUNDLE_PATH} DESTINATION /Applications
+ USE_SOURCE_PERMISSIONS
+ )
+ else()
+ install(TARGETS ${DOLPHIN_EXE} RUNTIME DESTINATION ${bindir})
+ endif()
endif()
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} ${DOLPHIN_EXE})
diff --git a/Source/Core/DolphinWX/Dolphin.vcxproj b/Source/Core/DolphinWX/Dolphin.vcxproj
index cde306855b..fe0b1dcd2b 100644
--- a/Source/Core/DolphinWX/Dolphin.vcxproj
+++ b/Source/Core/DolphinWX/Dolphin.vcxproj
@@ -136,7 +136,6 @@
<PostBuildEvent>
<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>
@@ -151,7 +150,6 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
<PostBuildEvent>
<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>
@@ -168,7 +166,6 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
<PostBuildEvent>
<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>
@@ -183,7 +180,6 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
<PostBuildEvent>
<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>
@@ -200,7 +196,6 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
<PostBuildEvent>
<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>
@@ -217,7 +212,6 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
<PostBuildEvent>
<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>
diff --git a/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp b/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp
index c3ed12bbea..e08753f40f 100644
--- a/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp
+++ b/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp
@@ -17,6 +17,7 @@
#include "ARCodeAddEdit.h"
#include "ARDecrypt.h"
+#include "WxUtils.h"
extern std::vector<ActionReplay::ARCode> arCodes;
@@ -38,7 +39,7 @@ CARCodeAddEdit::CARCodeAddEdit(int _selection, wxWindow* parent, wxWindowID id,
}
else
{
- currentName = wxString(arCodes.at(selection).name.c_str(), *wxConvCurrent);
+ currentName = StrToWxStr(arCodes.at(selection).name);
tempEntries = arCodes.at(selection);
}
@@ -73,7 +74,7 @@ CARCodeAddEdit::CARCodeAddEdit(int _selection, wxWindow* parent, wxWindowID id,
void CARCodeAddEdit::ChangeEntry(wxSpinEvent& event)
{
ActionReplay::ARCode currentCode = arCodes.at((int)arCodes.size() - event.GetPosition());
- EditCheatName->SetValue(wxString(currentCode.name.c_str(), *wxConvCurrent));
+ EditCheatName->SetValue(StrToWxStr(currentCode.name));
UpdateTextCtrl(currentCode);
}
@@ -84,7 +85,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event))
// Split the entered cheat into lines.
std::vector<std::string> userInputLines;
- SplitString(std::string(EditCheatCode->GetValue().mb_str()), '\n', userInputLines);
+ SplitString(WxStrToStr(EditCheatCode->GetValue()), '\n', userInputLines);
for (size_t i = 0; i < userInputLines.size(); i++)
{
@@ -148,7 +149,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event))
// Add a new AR cheat code.
ActionReplay::ARCode newCheat;
- newCheat.name = std::string(EditCheatName->GetValue().mb_str());
+ newCheat.name = WxStrToStr(EditCheatName->GetValue());
newCheat.ops = decryptedLines;
newCheat.active = true;
@@ -157,7 +158,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event))
else
{
// Update the currently-selected AR cheat code.
- arCodes.at(selection).name = std::string(EditCheatName->GetValue().mb_str());
+ arCodes.at(selection).name = WxStrToStr(EditCheatName->GetValue());
arCodes.at(selection).ops = decryptedLines;
}
diff --git a/Source/Core/DolphinWX/Src/AboutDolphin.cpp b/Source/Core/DolphinWX/Src/AboutDolphin.cpp
index 5e1825b6ae..5126274601 100644
--- a/Source/Core/DolphinWX/Src/AboutDolphin.cpp
+++ b/Source/Core/DolphinWX/Src/AboutDolphin.cpp
@@ -17,6 +17,7 @@
#include "Common.h"
#include "AboutDolphin.h"
+#include "WxUtils.h"
#include "../resources/dolphin_logo.cpp"
#include "scmrev.h"
@@ -62,7 +63,7 @@ AboutDolphin::AboutDolphin(wxWindow *parent, wxWindowID id,
"and should not be used to play games you do\n"
"not legally own.";
wxStaticText* const Message = new wxStaticText(this, wxID_ANY,
- wxString::FromAscii(Text.c_str()));
+ StrToWxStr(Text));
Message->Wrap(GetSize().GetWidth());
wxBoxSizer* const sInfo = new wxBoxSizer(wxVERTICAL);
diff --git a/Source/Core/DolphinWX/Src/CheatsWindow.cpp b/Source/Core/DolphinWX/Src/CheatsWindow.cpp
index 63ddced86b..fb3c3cbb23 100644
--- a/Source/Core/DolphinWX/Src/CheatsWindow.cpp
+++ b/Source/Core/DolphinWX/Src/CheatsWindow.cpp
@@ -24,6 +24,7 @@
#include "ISOProperties.h"
#include "HW/Memmap.h"
#include "Frame.h"
+#include "WxUtils.h"
#define MAX_CHEAT_SEARCH_RESULTS_DISPLAY 256
@@ -273,7 +274,7 @@ void wxCheatsWindow::Load_ARCodes()
{
ARCode code = GetARCode(i);
ARCodeIndex ind;
- u32 index = m_CheckListBox_CheatsList->Append(wxString(code.name.c_str(), *wxConvCurrent));
+ u32 index = m_CheckListBox_CheatsList->Append(StrToWxStr(code.name));
m_CheckListBox_CheatsList->Check(index, code.active);
ind.index = i;
ind.uiIndex = index;
@@ -291,18 +292,18 @@ void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& WXUNUSED (e
if ((int)indexList[i].uiIndex == index)
{
ARCode code = GetARCode(i);
- m_Label_Codename->SetLabel(_("Name: ") + wxString(code.name.c_str(), *wxConvCurrent));
+ m_Label_Codename->SetLabel(_("Name: ") + StrToWxStr(code.name));
char text[CHAR_MAX];
char* numcodes = text;
sprintf(numcodes, "Number of Codes: %lu", (unsigned long)code.ops.size());
- m_Label_NumCodes->SetLabel(wxString::FromAscii(numcodes));
+ m_Label_NumCodes->SetLabel(StrToWxStr(numcodes));
m_ListBox_CodesList->Clear();
for (size_t j = 0; j < code.ops.size(); j++)
{
char text2[CHAR_MAX];
char* ops = text2;
sprintf(ops, "%08x %08x", code.ops[j].cmd_addr, code.ops[j].value);
- m_ListBox_CodesList->Append(wxString::FromAscii(ops));
+ m_ListBox_CodesList->Append(StrToWxStr(ops));
}
}
}
@@ -347,7 +348,7 @@ void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED (eve
const std::vector<std::string> &arLog = ActionReplay::GetSelfLog();
for (u32 i = 0; i < arLog.size(); i++)
{
- m_TextCtrl_Log->AppendText(wxString::FromAscii(arLog[i].c_str()));
+ m_TextCtrl_Log->AppendText(StrToWxStr(arLog[i]));
}
}
@@ -619,7 +620,7 @@ void CreateCodeDialog::PressOK(wxCommandEvent& ev)
// create the new code
ActionReplay::ARCode new_cheat;
new_cheat.active = false;
- new_cheat.name = std::string(code_name.ToAscii());
+ new_cheat.name = WxStrToStr(code_name);
const ActionReplay::AREntry new_entry(code_address, code_value);
new_cheat.ops.push_back(new_entry);
diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp
index dc044afe09..cbd780e6aa 100644
--- a/Source/Core/DolphinWX/Src/ConfigMain.cpp
+++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp
@@ -33,6 +33,7 @@
#include "IPC_HLE/WII_IPC_HLE.h"
#include "NANDContentLoader.h"
+#include "WxUtils.h"
#include "Globals.h" // Local
#include "ConfigMain.h"
#include "ConfigManager.h"
@@ -52,6 +53,21 @@ using std::function;
#define TEXT_BOX(page, text) new wxStaticText(page, wxID_ANY, text, wxDefaultPosition, wxDefaultSize)
+struct CPUCore
+{
+ int CPUid;
+ const char *name;
+};
+const CPUCore CPUCores[] = {
+ {0, "Interpreter (VERY slow)"},
+#ifdef _M_ARM
+ {3, "Arm JIT (experimental)"},
+#else
+ {1, "JIT Recompiler (recommended)"},
+ {2, "JITIL experimental recompiler"},
+#endif
+};
+
extern CFrame* main_frame;
// keep these in sync with CConfigMain::InitializeGUILists
@@ -100,7 +116,6 @@ static const wxLanguage langIds[] =
#define EXIDEV_AM_BB_STR _trans("AM-Baseboard")
#define EXIDEV_GECKO_STR "USBGecko"
-#define CSTR_TRANS(a) wxString(wxGetTranslation(wxT(a))).mb_str()
#define WXSTR_TRANS(a) wxString(wxGetTranslation(wxT(a)))
#ifdef WIN32
//only used with xgettext to be picked up as translatable string.
@@ -188,7 +203,7 @@ CConfigMain::CConfigMain(wxWindow* parent, wxWindowID id, const wxString& title,
// Update selected ISO paths
for(u32 i = 0; i < SConfig::GetInstance().m_ISOFolder.size(); i++)
{
- ISOPaths->Append(wxString(SConfig::GetInstance().m_ISOFolder[i].c_str(), *wxConvCurrent));
+ ISOPaths->Append(StrToWxStr(SConfig::GetInstance().m_ISOFolder[i]));
}
}
@@ -241,7 +256,6 @@ void CConfigMain::UpdateGUI()
PathsPage->Disable();
}
}
-
void CConfigMain::InitializeGUILists()
{
// General page
@@ -253,10 +267,9 @@ void CConfigMain::InitializeGUILists()
arrayStringFor_Framelimit.Add(wxString::Format(wxT("%i"), i));
// Emulator Engine
- arrayStringFor_CPUEngine.Add(_("Interpreter (VERY slow)"));
- arrayStringFor_CPUEngine.Add(_("JIT Recompiler (recommended)"));
- arrayStringFor_CPUEngine.Add(_("JITIL experimental recompiler"));
-
+ for (unsigned int a = 0; a < (sizeof(CPUCores) / sizeof(CPUCore)); ++a)
+ arrayStringFor_CPUEngine.Add(_(CPUCores[a].name));
+
// DSP Engine
arrayStringFor_DSPEngine.Add(_("DSP HLE emulation (fast)"));
arrayStringFor_DSPEngine.Add(_("DSP LLE recompiler"));
@@ -329,7 +342,9 @@ void CConfigMain::InitializeGUIValues()
UseFPSForLimiting->SetValue(SConfig::GetInstance().b_UseFPS);
// General - Advanced
- CPUEngine->SetSelection(startup_params.iCPUCore);
+ for (unsigned int a = 0; a < (sizeof(CPUCores) / sizeof(CPUCore)); ++a)
+ if (CPUCores[a].CPUid == startup_params.iCPUCore)
+ CPUEngine->SetSelection(a);
_NTSCJ->SetValue(startup_params.bForceNTSCJ);
@@ -477,10 +492,10 @@ void CConfigMain::InitializeGUIValues()
// Paths
RecursiveISOPath->SetValue(SConfig::GetInstance().m_RecursiveISOFolder);
- DefaultISO->SetPath(wxString(startup_params.m_strDefaultGCM.c_str(), *wxConvCurrent));
- DVDRoot->SetPath(wxString(startup_params.m_strDVDRoot.c_str(), *wxConvCurrent));
- ApploaderPath->SetPath(wxString(startup_params.m_strApploader.c_str(), *wxConvCurrent));
- NANDRoot->SetPath(wxString(SConfig::GetInstance().m_NANDPath.c_str(), *wxConvCurrent));
+ DefaultISO->SetPath(StrToWxStr(startup_params.m_strDefaultGCM));
+ DVDRoot->SetPath(StrToWxStr(startup_params.m_strDVDRoot));
+ ApploaderPath->SetPath(StrToWxStr(startup_params.m_strApploader));
+ NANDRoot->SetPath(StrToWxStr(SConfig::GetInstance().m_NANDPath));
}
void CConfigMain::InitializeGUITooltips()
@@ -860,7 +875,7 @@ void CConfigMain::OnOk(wxCommandEvent& WXUNUSED (event))
{
Close();
- // Save the config. Dolphin crashes to often to save the settings on closing only
+ // Save the config. Dolphin crashes too often to only save the settings on closing
SConfig::GetInstance().SaveSettings();
}
@@ -888,7 +903,7 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event)
break;
// Core - Advanced
case ID_CPUENGINE:
- SConfig::GetInstance().m_LocalCoreStartupParameter.iCPUCore = CPUEngine->GetSelection();
+ SConfig::GetInstance().m_LocalCoreStartupParameter.iCPUCore = CPUCores[CPUEngine->GetSelection()].CPUid;
if (main_frame->g_pCodeWindow)
main_frame->g_pCodeWindow->GetMenuBar()->Check(IDM_INTERPRETER,
SConfig::GetInstance().m_LocalCoreStartupParameter.iCPUCore?false:true);
@@ -958,10 +973,10 @@ void CConfigMain::AudioSettingsChanged(wxCommandEvent& event)
break;
case ID_BACKEND:
- VolumeSlider->Enable(SupportsVolumeChanges(std::string(BackendSelection->GetStringSelection().mb_str())));
- Latency->Enable(std::string(BackendSelection->GetStringSelection().mb_str()) == BACKEND_OPENAL);
- DPL2Decoder->Enable(std::string(BackendSelection->GetStringSelection().mb_str()) == BACKEND_OPENAL);
- SConfig::GetInstance().sBackend = BackendSelection->GetStringSelection().mb_str();
+ VolumeSlider->Enable(SupportsVolumeChanges(WxStrToStr(BackendSelection->GetStringSelection())));
+ Latency->Enable(WxStrToStr(BackendSelection->GetStringSelection()) == BACKEND_OPENAL);
+ DPL2Decoder->Enable(WxStrToStr(BackendSelection->GetStringSelection()) == BACKEND_OPENAL);
+ SConfig::GetInstance().sBackend = WxStrToStr(BackendSelection->GetStringSelection());
AudioCommon::UpdateSoundStream();
break;
@@ -982,9 +997,9 @@ void CConfigMain::AddAudioBackends()
for (std::vector<std::string>::const_iterator iter = backends.begin();
iter != backends.end(); ++iter)
{
- BackendSelection->Append(wxString::FromAscii((*iter).c_str()));
+ BackendSelection->Append(StrToWxStr(*iter));
int num = BackendSelection->\
- FindString(wxString::FromAscii(SConfig::GetInstance().sBackend.c_str()));
+ FindString(StrToWxStr(SConfig::GetInstance().sBackend));
BackendSelection->SetSelection(num);
}
}
@@ -1046,12 +1061,12 @@ void CConfigMain::GCSettingsChanged(wxCommandEvent& event)
void CConfigMain::ChooseMemcardPath(std::string& strMemcard, bool isSlotA)
{
- std::string filename = std::string(wxFileSelector(
+ std::string filename = WxStrToStr(wxFileSelector(
_("Choose a file to open"),
- wxString::FromUTF8(File::GetUserPath(D_GCUSER_IDX).c_str()),
+ StrToWxStr(File::GetUserPath(D_GCUSER_IDX)),
isSlotA ? wxT(GC_MEMCARDA) : wxT(GC_MEMCARDB),
wxEmptyString,
- _("Gamecube Memory Cards (*.raw,*.gcp)") + wxString(wxT("|*.raw;*.gcp"))).mb_str());
+ _("Gamecube Memory Cards (*.raw,*.gcp)") + wxString(wxT("|*.raw;*.gcp"))));
if (!filename.empty())
{
@@ -1242,7 +1257,7 @@ void CConfigMain::AddRemoveISOPaths(wxCommandEvent& event)
SConfig::GetInstance().m_ISOFolder.clear();
for (unsigned int i = 0; i < ISOPaths->GetCount(); i++)
- SConfig::GetInstance().m_ISOFolder.push_back(std::string(ISOPaths->GetStrings()[i].mb_str()));
+ SConfig::GetInstance().m_ISOFolder.push_back(WxStrToStr(ISOPaths->GetStrings()[i]));
}
void CConfigMain::RecursiveDirectoryChanged(wxCommandEvent& WXUNUSED (event))
@@ -1253,24 +1268,25 @@ void CConfigMain::RecursiveDirectoryChanged(wxCommandEvent& WXUNUSED (event))
void CConfigMain::DefaultISOChanged(wxFileDirPickerEvent& WXUNUSED (event))
{
- SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = DefaultISO->GetPath().mb_str();
+ SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = WxStrToStr(DefaultISO->GetPath());
}
void CConfigMain::DVDRootChanged(wxFileDirPickerEvent& WXUNUSED (event))
{
- SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDVDRoot = DVDRoot->GetPath().mb_str();
+ SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDVDRoot = WxStrToStr(DVDRoot->GetPath());
}
void CConfigMain::ApploaderPathChanged(wxFileDirPickerEvent& WXUNUSED (event))
{
- SConfig::GetInstance().m_LocalCoreStartupParameter.m_strApploader = ApploaderPath->GetPath().mb_str();
+ SConfig::GetInstance().m_LocalCoreStartupParameter.m_strApploader = WxStrToStr(ApploaderPath->GetPath());
}
void CConfigMain::NANDRootChanged(wxFileDirPickerEvent& WXUNUSED (event))
{
std::string NANDPath =
- SConfig::GetInstance().m_NANDPath = File::GetUserPath(D_WIIROOT_IDX, std::string(NANDRoot->GetPath().mb_str()));
- NANDRoot->SetPath(wxString(NANDPath.c_str(), *wxConvCurrent));
+ SConfig::GetInstance().m_NANDPath =
+ File::GetUserPath(D_WIIROOT_IDX, WxStrToStr(NANDRoot->GetPath()));
+ NANDRoot->SetPath(StrToWxStr(NANDPath));
SConfig::GetInstance().m_SYSCONF->UpdateLocation();
DiscIO::cUIDsys::AccessInstance().UpdateLocation();
DiscIO::CSharedContent::AccessInstance().UpdateLocation();
diff --git a/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp b/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp
index 58e73b167e..96dbac8ff8 100644
--- a/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp
@@ -19,6 +19,7 @@
#include "StringUtil.h"
#include "PowerPC/PowerPC.h"
#include "BreakpointWindow.h"
+#include "../WxUtils.h"
BEGIN_EVENT_TABLE(BreakPointDlg, wxDialog)
EVT_BUTTON(wxID_OK, BreakPointDlg::OnOK)
@@ -42,14 +43,14 @@ void BreakPointDlg::OnOK(wxCommandEvent& event)
{
wxString AddressString = m_pEditAddress->GetLineText(0);
u32 Address = 0;
- if (AsciiToHex(AddressString.mb_str(), Address))
+ if (AsciiToHex(WxStrToStr(AddressString).c_str(), Address))
{
PowerPC::breakpoints.Add(Address);
Parent->NotifyUpdate();
Close();
}
else
- PanicAlert("The address %s is invalid.", (const char *)AddressString.ToUTF8());
+ PanicAlert("The address %s is invalid.", WxStrToStr(AddressString).c_str());
event.Skip();
}
diff --git a/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp b/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp
index 496cb8fe5d..a23e9194fd 100644
--- a/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp
@@ -23,6 +23,7 @@
#include "PowerPC/PPCSymbolDB.h"
#include "PowerPC/PowerPC.h"
#include "HW/Memmap.h"
+#include "../WxUtils.h"
CBreakPointView::CBreakPointView(wxWindow* parent, const wxWindowID id)
: wxListCtrl(parent, id, wxDefaultPosition, wxDefaultSize,
@@ -50,20 +51,20 @@ void CBreakPointView::Update()
if (!rBP.bTemporary)
{
wxString temp;
- temp = wxString::FromAscii(rBP.bOn ? "on" : " ");
+ temp = StrToWxStr(rBP.bOn ? "on" : " ");
int Item = InsertItem(0, temp);
- temp = wxString::FromAscii("BP");
+ temp = StrToWxStr("BP");
SetItem(Item, 1, temp);
Symbol *symbol = g_symbolDB.GetSymbolFromAddr(rBP.iAddress);
if (symbol)
{
- temp = wxString::FromAscii(g_symbolDB.GetDescription(rBP.iAddress));
+ temp = StrToWxStr(g_symbolDB.GetDescription(rBP.iAddress));
SetItem(Item, 2, temp);
}
sprintf(szBuffer, "%08x", rBP.iAddress);
- temp = wxString::FromAscii(szBuffer);
+ temp = StrToWxStr(szBuffer);
SetItem(Item, 3, temp);
SetItemData(Item, rBP.iAddress);
@@ -76,27 +77,27 @@ void CBreakPointView::Update()
const TMemCheck& rMemCheck = rMemChecks[i];
wxString temp;
- temp = wxString::FromAscii((rMemCheck.Break || rMemCheck.Log) ? "on" : " ");
+ temp = StrToWxStr((rMemCheck.Break || rMemCheck.Log) ? "on" : " ");
int Item = InsertItem(0, temp);
- temp = wxString::FromAscii("MC");
+ temp = StrToWxStr("MC");
SetItem(Item, 1, temp);
Symbol *symbol = g_symbolDB.GetSymbolFromAddr(rMemCheck.StartAddress);
if (symbol)
{
- temp = wxString::FromAscii(g_symbolDB.GetDescription(rMemCheck.StartAddress));
+ temp = StrToWxStr(g_symbolDB.GetDescription(rMemCheck.StartAddress));
SetItem(Item, 2, temp);
}
sprintf(szBuffer, "%08x to %08x", rMemCheck.StartAddress, rMemCheck.EndAddress);
- temp = wxString::FromAscii(szBuffer);
+ temp = StrToWxStr(szBuffer);
SetItem(Item, 3, temp);
size_t c = 0;
if (rMemCheck.OnRead) szBuffer[c++] = 'r';
if (rMemCheck.OnWrite) szBuffer[c++] = 'w';
szBuffer[c] = 0x00;
- temp = wxString::FromAscii(szBuffer);
+ temp = StrToWxStr(szBuffer);
SetItem(Item, 4, temp);
SetItemData(Item, rMemCheck.StartAddress);
diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp
index f696aaab64..31ad19d6da 100644
--- a/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp
@@ -23,6 +23,7 @@
#include "Host.h"
#include "CodeView.h"
#include "SymbolDB.h"
+#include "../WxUtils.h"
#include <wx/event.h>
#include <wx/clipbrd.h>
@@ -223,7 +224,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
{
char disasm[256];
debugger->disasm(selection, disasm, 256);
- wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(disasm)));
+ wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(disasm)));
}
break;
@@ -231,7 +232,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
{
char temp[24];
sprintf(temp, "%08x", debugger->readInstruction(selection));
- wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(temp)));
+ wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
}
break;
@@ -252,7 +253,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
debugger->disasm(addr, disasm, 256);
text = text + StringFromFormat("%08x: ", addr) + disasm + "\r\n";
}
- wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(text.c_str())));
+ wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text)));
}
}
break;
@@ -297,12 +298,12 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
Symbol *symbol = symbol_db->GetSymbolFromAddr(selection);
if (symbol)
{
- wxTextEntryDialog input_symbol(this, wxString::FromAscii("Rename symbol:"),
+ wxTextEntryDialog input_symbol(this, StrToWxStr("Rename symbol:"),
wxGetTextFromUserPromptStr,
- wxString::FromAscii(symbol->name.c_str()));
+ StrToWxStr(symbol->name));
if (input_symbol.ShowModal() == wxID_OK)
{
- symbol->name = input_symbol.GetValue().mb_str();
+ symbol->name = WxStrToStr(input_symbol.GetValue());
Refresh(); // Redraw to show the renamed symbol
}
Host_NotifyMapLoaded();
@@ -327,23 +328,23 @@ void CCodeView::OnMouseUpR(wxMouseEvent& event)
wxMenu* menu = new wxMenu;
//menu->Append(IDM_GOTOINMEMVIEW, "&Goto in mem view");
menu->Append(IDM_FOLLOWBRANCH,
- wxString::FromAscii("&Follow branch"))->Enable(AddrToBranch(selection) ? true : false);
+ StrToWxStr("&Follow branch"))->Enable(AddrToBranch(selection) ? true : false);
menu->AppendSeparator();
#if wxUSE_CLIPBOARD
- menu->Append(IDM_COPYADDRESS, wxString::FromAscii("Copy &address"));
- menu->Append(IDM_COPYFUNCTION, wxString::FromAscii("Copy &function"))->Enable(isSymbol);
- menu->Append(IDM_COPYCODE, wxString::FromAscii("Copy &code line"));
- menu->Append(IDM_COPYHEX, wxString::FromAscii("Copy &hex"));
+ menu->Append(IDM_COPYADDRESS, StrToWxStr("Copy &address"));
+ menu->Append(IDM_COPYFUNCTION, StrToWxStr("Copy &function"))->Enable(isSymbol);
+ menu->Append(IDM_COPYCODE, StrToWxStr("Copy &code line"));
+ menu->Append(IDM_COPYHEX, StrToWxStr("Copy &hex"));
menu->AppendSeparator();
#endif
- menu->Append(IDM_RENAMESYMBOL, wxString::FromAscii("Rename &symbol"))->Enable(isSymbol);
+ menu->Append(IDM_RENAMESYMBOL, StrToWxStr("Rename &symbol"))->Enable(isSymbol);
menu->AppendSeparator();
menu->Append(IDM_RUNTOHERE, _("&Run To Here"));
menu->Append(IDM_ADDFUNCTION, _("&Add function"));
- menu->Append(IDM_JITRESULTS, wxString::FromAscii("PPC vs X86"));
- menu->Append(IDM_INSERTBLR, wxString::FromAscii("Insert &blr"));
- menu->Append(IDM_INSERTNOP, wxString::FromAscii("Insert &nop"));
- menu->Append(IDM_PATCHALERT, wxString::FromAscii("Patch alert"));
+ menu->Append(IDM_JITRESULTS, StrToWxStr("PPC vs X86"));
+ menu->Append(IDM_INSERTBLR, StrToWxStr("Insert &blr"));
+ menu->Append(IDM_INSERTNOP, StrToWxStr("Insert &nop"));
+ menu->Append(IDM_PATCHALERT, StrToWxStr("Patch alert"));
PopupMenu(menu);
event.Skip(true);
}
@@ -489,7 +490,7 @@ void CCodeView::OnPaint(wxPaintEvent& event)
dc.SetTextForeground(_T("#000000"));
}
- dc.DrawText(wxString::FromAscii(dis2), 17 + 17*charWidth, rowY1);
+ dc.DrawText(StrToWxStr(dis2), 17 + 17*charWidth, rowY1);
// ------------
}
@@ -499,7 +500,7 @@ void CCodeView::OnPaint(wxPaintEvent& event)
else
dc.SetTextForeground(_T("#8000FF")); // purple
- dc.DrawText(wxString::FromAscii(dis), 17 + (plain ? 1*charWidth : 9*charWidth), rowY1);
+ dc.DrawText(StrToWxStr(dis), 17 + (plain ? 1*charWidth : 9*charWidth), rowY1);
if (desc[0] == 0)
{
@@ -513,7 +514,7 @@ void CCodeView::OnPaint(wxPaintEvent& event)
//UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE);
if (strlen(desc))
{
- dc.DrawText(wxString::FromAscii(desc), 17 + 35 * charWidth, rowY1);
+ dc.DrawText(StrToWxStr(desc), 17 + 35 * charWidth, rowY1);
}
}
diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp
index 1c0776862c..9172a3af9a 100644
--- a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp
@@ -30,6 +30,7 @@
#include "CodeWindow.h"
#include "CodeView.h"
+#include "../WxUtils.h"
#include "FileUtil.h"
#include "Core.h"
#include "HW/Memmap.h"
@@ -38,6 +39,7 @@
#include "LogManager.h"
#include "HW/CPU.h"
#include "PowerPC/PowerPC.h"
+#include "PowerPC/JitInterface.h"
#include "Debugger/PPCDebugInterface.h"
#include "Debugger/Debugger_SymbolMap.h"
#include "PowerPC/PPCAnalyst.h"
@@ -45,8 +47,6 @@
#include "PowerPC/PPCSymbolDB.h"
#include "PowerPC/SignatureDB.h"
#include "PowerPC/PPCTables.h"
-#include "PowerPC/JitCommon/JitBase.h"
-#include "PowerPC/JitCommon/JitCache.h" // for ClearCache()
#include "ConfigManager.h"
@@ -211,7 +211,7 @@ void CCodeWindow::OnAddrBoxChange(wxCommandEvent& event)
wxTextCtrl* pAddrCtrl = (wxTextCtrl*)GetToolBar()->FindControl(IDM_ADDRBOX);
wxString txt = pAddrCtrl->GetValue();
- std::string text(txt.mb_str());
+ std::string text(WxStrToStr(txt));
text = StripSpaces(text);
if (text.size() == 8)
{
@@ -260,8 +260,7 @@ void CCodeWindow::SingleStep()
{
if (CCPU::IsStepping())
{
- if (jit)
- jit->GetBlockCache()->InvalidateICache(PC, 4);
+ JitInterface::InvalidateICache(PC, 4);
CCPU::StepOpcode(&sync_event);
wxThread::Sleep(20);
// need a short wait here
@@ -314,7 +313,7 @@ void CCodeWindow::UpdateLists()
Symbol *caller_symbol = g_symbolDB.GetSymbolFromAddr(caller_addr);
if (caller_symbol)
{
- int idx = callers->Append(wxString::FromAscii(StringFromFormat
+ int idx = callers->Append(StrToWxStr(StringFromFormat
("< %s (%08x)", caller_symbol->name.c_str(), caller_addr).c_str()));
callers->SetClientData(idx, (void*)(u64)caller_addr);
}
@@ -327,7 +326,7 @@ void CCodeWindow::UpdateLists()
Symbol *call_symbol = g_symbolDB.GetSymbolFromAddr(call_addr);
if (call_symbol)
{
- int idx = calls->Append(wxString::FromAscii(StringFromFormat
+ int idx = calls->Append(StrToWxStr(StringFromFormat
("> %s (%08x)", call_symbol->name.c_str(), call_addr).c_str()));
calls->SetClientData(idx, (void*)(u64)call_addr);
}
@@ -346,12 +345,12 @@ void CCodeWindow::UpdateCallstack()
for (size_t i = 0; i < stack.size(); i++)
{
- int idx = callstack->Append(wxString::FromAscii(stack[i].Name.c_str()));
+ int idx = callstack->Append(StrToWxStr(stack[i].Name));
callstack->SetClientData(idx, (void*)(u64)stack[i].vAddress);
}
if (!ret)
- callstack->Append(wxString::FromAscii("invalid callstack"));
+ callstack->Append(StrToWxStr("invalid callstack"));
}
// Create CPU Mode menus
@@ -362,7 +361,7 @@ void CCodeWindow::CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParam
wxMenu* pCoreMenu = new wxMenu;
wxMenuItem* interpreter = pCoreMenu->Append(IDM_INTERPRETER, _("&Interpreter core"),
- wxString::FromAscii("This is necessary to get break points"
+ StrToWxStr("This is necessary to get break points"
" and stepping to work as explained in the Developer Documentation. But it can be very"
" slow, perhaps slower than 1 fps."),
wxITEM_CHECK);
@@ -430,7 +429,7 @@ void CCodeWindow::CreateMenuOptions(wxMenu* pMenu)
boottopause->Check(bBootToPause);
wxMenuItem* automaticstart = pMenu->Append(IDM_AUTOMATICSTART, _("&Automatic start"),
- wxString::FromAscii(
+ StrToWxStr(
"Automatically load the Default ISO when Dolphin starts, or the last game you loaded,"
" if you have not given it an elf file with the --elf command line. [This can be"
" convenient if you are bug-testing with a certain game and want to rebuild"
@@ -492,10 +491,8 @@ void CCodeWindow::OnCPUMode(wxCommandEvent& event)
}
// Clear the JIT cache to enable these changes
- if (jit)
- {
- jit->ClearCache();
- }
+ JitInterface::ClearCache();
+
// Update
UpdateButtonStates();
}
@@ -509,7 +506,7 @@ void CCodeWindow::OnJitMenu(wxCommandEvent& event)
break;
case IDM_CLEARCODECACHE:
- jit->ClearCache();
+ JitInterface::ClearCache();
break;
case IDM_SEARCHINSTRUCTION:
@@ -519,10 +516,10 @@ void CCodeWindow::OnJitMenu(wxCommandEvent& event)
for (u32 addr = 0x80000000; addr < 0x80100000; addr += 4)
{
const char *name = PPCTables::GetInstructionName(Memory::ReadUnchecked_U32(addr));
- if (name && !strcmp((const char *)str.mb_str(), name))
+ auto const wx_name = WxStrToStr(str);
+ if (name && (wx_name == name))
{
- std::string mb_str(str.mb_str());
- NOTICE_LOG(POWERPC, "Found %s at %08x", mb_str.c_str(), addr);
+ NOTICE_LOG(POWERPC, "Found %s at %08x", wx_name.c_str(), addr);
}
}
break;
diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp
index 706b398dce..ef4622d14f 100644
--- a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp
@@ -25,6 +25,7 @@
#include "DebuggerUIUtil.h"
+#include "../WxUtils.h"
#include "RegisterWindow.h"
#include "BreakpointWindow.h"
#include "MemoryWindow.h"
@@ -65,7 +66,7 @@ void CCodeWindow::Load()
std::string fontDesc;
ini.Get("General", "DebuggerFont", &fontDesc);
if (!fontDesc.empty())
- DebuggerFont.SetNativeFontInfoUserDesc(wxString::FromAscii(fontDesc.c_str()));
+ DebuggerFont.SetNativeFontInfoUserDesc(StrToWxStr(fontDesc));
// Boot to pause or not
ini.Get("General", "AutomaticStart", &bAutomaticStart, false);
@@ -107,7 +108,7 @@ void CCodeWindow::Save()
ini.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX));
ini.Set("General", "DebuggerFont",
- std::string(DebuggerFont.GetNativeFontInfoUserDesc().mb_str()));
+ WxStrToStr(DebuggerFont.GetNativeFontInfoUserDesc()));
// Boot to pause or not
ini.Set("General", "AutomaticStart", GetMenuBar()->IsChecked(IDM_AUTOMATICSTART));
@@ -154,7 +155,7 @@ void CCodeWindow::CreateMenuSymbols(wxMenuBar *pMenuBar)
pSymbolsMenu->Append(IDM_SAVEMAPFILE, _("&Save symbol map"));
pSymbolsMenu->AppendSeparator();
pSymbolsMenu->Append(IDM_SAVEMAPFILEWITHCODES, _("Save code"),
- wxString::FromAscii("Save the entire disassembled code. This may take a several seconds"
+ StrToWxStr("Save the entire disassembled code. This may take a several seconds"
" and may require between 50 and 100 MB of hard drive space. It will only save code"
" that are in the first 4 MB of memory, if you are debugging a game that load .rel"
" files with code to memory you may want to increase that to perhaps 8 MB, you can do"
@@ -208,7 +209,7 @@ void CCodeWindow::OnProfilerMenu(wxCommandEvent& event)
break;
}
wxString OpenCommand;
- OpenCommand = filetype->GetOpenCommand(wxString::From8BitData(filename.c_str()));
+ OpenCommand = filetype->GetOpenCommand(StrToWxStr(filename));
if(!OpenCommand.IsEmpty())
wxExecute(OpenCommand, wxEXEC_SYNC);
}
@@ -284,7 +285,8 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
if (!path.IsEmpty())
{
- std::ifstream f(path.mb_str());
+ std::ifstream f;
+ OpenFStream(f, WxStrToStr(path), std::ios_base::in);
std::string line;
while (std::getline(f, line))
@@ -312,13 +314,13 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
{
wxTextEntryDialog input_prefix(
this,
- wxString::FromAscii("Only export symbols with prefix:\n(Blank for all symbols)"),
+ StrToWxStr("Only export symbols with prefix:\n(Blank for all symbols)"),
wxGetTextFromUserPromptStr,
wxEmptyString);
if (input_prefix.ShowModal() == wxID_OK)
{
- std::string prefix(input_prefix.GetValue().mb_str());
+ std::string prefix(WxStrToStr(input_prefix.GetValue()));
wxString path = wxFileSelector(
_T("Save signature as"), wxEmptyString, wxEmptyString, wxEmptyString,
@@ -328,8 +330,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
{
SignatureDB db;
db.Initialize(&g_symbolDB, prefix.c_str());
- std::string filename(path.mb_str());
- db.Save(path.mb_str());
+ db.Save(WxStrToStr(path).c_str());
}
}
}
@@ -343,7 +344,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
if (!path.IsEmpty())
{
SignatureDB db;
- db.Load(path.mb_str());
+ db.Load(WxStrToStr(path).c_str());
db.Apply(&g_symbolDB);
}
}
@@ -366,7 +367,7 @@ void CCodeWindow::NotifyMapLoaded()
symbols->Clear();
for (PPCSymbolDB::XFuncMap::iterator iter = g_symbolDB.GetIterator(); iter != g_symbolDB.End(); ++iter)
{
- int idx = symbols->Append(wxString::FromAscii(iter->second.name.c_str()));
+ int idx = symbols->Append(StrToWxStr(iter->second.name));
symbols->SetClientData(idx, (void*)&iter->second);
}
symbols->Thaw();
diff --git a/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp
index a4591d3994..e77b57399e 100644
--- a/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp
@@ -22,6 +22,7 @@
#include <wx/artprov.h>
+#include "../WxUtils.h"
#include "StringUtil.h"
#include "DSPDebugWindow.h"
#include "DSPRegisterView.h"
@@ -220,7 +221,7 @@ void DSPDebuggerLLE::UpdateSymbolMap()
for (SymbolDB::XFuncMap::iterator iter = DSPSymbols::g_dsp_symbol_db.GetIterator();
iter != DSPSymbols::g_dsp_symbol_db.End(); ++iter)
{
- int idx = m_SymbolList->Append(wxString::FromAscii(iter->second.name.c_str()));
+ int idx = m_SymbolList->Append(StrToWxStr(iter->second.name));
m_SymbolList->SetClientData(idx, (void*)&iter->second);
}
m_SymbolList->Thaw();
@@ -250,8 +251,7 @@ void DSPDebuggerLLE::OnAddrBoxChange(wxCommandEvent& event)
wxTextCtrl* pAddrCtrl = (wxTextCtrl*)m_Toolbar->FindControl(ID_ADDRBOX);
wxString txt = pAddrCtrl->GetValue();
- std::string text(txt.mb_str());
- text = StripSpaces(text);
+ auto text = StripSpaces(WxStrToStr(txt));
if (text.size())
{
u32 addr;
diff --git a/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp b/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp
index ca275ba66a..b8634e14dc 100644
--- a/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp
@@ -17,7 +17,7 @@
#include "DSPDebugWindow.h"
#include "DSPRegisterView.h"
-
+#include "../WxUtils.h"
wxString CDSPRegTable::GetValue(int row, int col)
{
@@ -25,7 +25,7 @@ wxString CDSPRegTable::GetValue(int row, int col)
{
switch (col)
{
- case 0: return wxString::FromAscii(pdregname(row));
+ case 0: return StrToWxStr(pdregname(row));
case 1: return wxString::Format(wxT("0x%04x"), DSPCore_ReadRegister(row));
default: return wxEmptyString;
}
diff --git a/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp
index 69cee04db5..7f98af6c57 100644
--- a/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp
@@ -37,6 +37,7 @@
#include "Core.h"
#include "StringUtil.h"
#include "LogManager.h"
+#include "../WxUtils.h"
#include "../Globals.h"
@@ -119,9 +120,9 @@ void CJitWindow::Compare(u32 em_address)
}
// Do not merge this "if" with the above - block_num changes inside it.
if (block_num < 0) {
- ppc_box->SetValue(wxString::FromAscii(StringFromFormat("(non-code address: %08x)",
- em_address).c_str()));
- x86_box->SetValue(wxString::FromAscii(StringFromFormat("(no translation)").c_str()));
+ ppc_box->SetValue(StrToWxStr(StringFromFormat("(non-code address: %08x)",
+ em_address)));
+ x86_box->SetValue(StrToWxStr(StringFromFormat("(no translation)")));
delete[] xDis;
return;
}
@@ -150,7 +151,7 @@ void CJitWindow::Compare(u32 em_address)
*sptr++ = 10;
num_x86_instructions++;
}
- x86_box->SetValue(wxString::FromAscii((char*)xDis));
+ x86_box->SetValue(StrToWxStr((char*)xDis));
// == Fill in ppc box
u32 ppc_addr = block->originalAddress;
@@ -189,11 +190,11 @@ void CJitWindow::Compare(u32 em_address)
sptr += sprintf(sptr, "Num bytes: PPC: %i x86: %i (blowup: %i%%)\n",
size * 4, block->codeSize, 100 * (block->codeSize / (4 * size) - 1));
- ppc_box->SetValue(wxString::FromAscii((char*)xDis));
+ ppc_box->SetValue(StrToWxStr((char*)xDis));
} else {
- ppc_box->SetValue(wxString::FromAscii(StringFromFormat(
- "(non-code address: %08x)", em_address).c_str()));
- x86_box->SetValue(wxString::FromAscii("---"));
+ ppc_box->SetValue(StrToWxStr(StringFromFormat(
+ "(non-code address: %08x)", em_address)));
+ x86_box->SetValue("---");
}
delete[] xDis;
diff --git a/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp b/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp
index f66e781ca3..41e09a7451 100644
--- a/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp
@@ -15,6 +15,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+#include "../WxUtils.h"
#include "MemoryCheckDlg.h"
#include "Common.h"
#include "StringUtil.h"
@@ -79,9 +80,9 @@ void MemoryCheckDlg::OnOK(wxCommandEvent& event)
u32 StartAddress, EndAddress;
bool EndAddressOK = EndAddressString.Len() &&
- AsciiToHex(EndAddressString.mb_str(), EndAddress);
+ AsciiToHex(WxStrToStr(EndAddressString).c_str(), EndAddress);
- if (AsciiToHex(StartAddressString.mb_str(), StartAddress) &&
+ if (AsciiToHex(WxStrToStr(StartAddressString).c_str(), StartAddress) &&
(OnRead || OnWrite) && (Log || Break))
{
TMemCheck MemCheck;
diff --git a/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp b/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp
index c6244fb7de..14d1aed8c0 100644
--- a/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp
@@ -22,6 +22,8 @@
#include "HW/Memmap.h"
#include "MemoryView.h"
+#include "../WxUtils.h"
+
#include <wx/event.h>
#include <wx/clipbrd.h>
@@ -149,7 +151,7 @@ void CMemoryView::OnPopupMenu(wxCommandEvent& event)
{
char temp[24];
sprintf(temp, "%08x", debugger->readExtraMemory(memory, selection));
- wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(temp)));
+ wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
}
break;
#endif
@@ -186,16 +188,16 @@ void CMemoryView::OnMouseDownR(wxMouseEvent& event)
wxMenu* menu = new wxMenu;
//menu.Append(IDM_GOTOINMEMVIEW, "&Goto in mem view");
#if wxUSE_CLIPBOARD
- menu->Append(IDM_COPYADDRESS, wxString::FromAscii("Copy &address"));
- menu->Append(IDM_COPYHEX, wxString::FromAscii("Copy &hex"));
+ menu->Append(IDM_COPYADDRESS, StrToWxStr("Copy &address"));
+ menu->Append(IDM_COPYHEX, StrToWxStr("Copy &hex"));
#endif
- menu->Append(IDM_TOGGLEMEMORY, wxString::FromAscii("Toggle &memory"));
+ menu->Append(IDM_TOGGLEMEMORY, StrToWxStr("Toggle &memory"));
wxMenu* viewAsSubMenu = new wxMenu;
- viewAsSubMenu->Append(IDM_VIEWASFP, wxString::FromAscii("FP value"));
- viewAsSubMenu->Append(IDM_VIEWASASCII, wxString::FromAscii("ASCII"));
- viewAsSubMenu->Append(IDM_VIEWASHEX, wxString::FromAscii("Hex"));
- menu->AppendSubMenu(viewAsSubMenu, wxString::FromAscii("View As:"));
+ viewAsSubMenu->Append(IDM_VIEWASFP, StrToWxStr("FP value"));
+ viewAsSubMenu->Append(IDM_VIEWASASCII, StrToWxStr("ASCII"));
+ viewAsSubMenu->Append(IDM_VIEWASHEX, StrToWxStr("Hex"));
+ menu->AppendSubMenu(viewAsSubMenu, StrToWxStr("View As:"));
PopupMenu(menu);
}
@@ -285,7 +287,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
char mem[256];
debugger->getRawMemoryString(memory, address, mem, 256);
dc.SetTextForeground(_T("#000080"));
- dc.DrawText(wxString::FromAscii(mem), 17+fontSize*(8), rowY1);
+ dc.DrawText(StrToWxStr(mem), 17+fontSize*(8), rowY1);
dc.SetTextForeground(_T("#000000"));
}
@@ -361,9 +363,9 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
char desc[256] = "";
if (viewAsType != VIEWAS_HEX)
- dc.DrawText(wxString::FromAscii(dis), textPlacement + fontSize*(8 + 8), rowY1);
+ dc.DrawText(StrToWxStr(dis), textPlacement + fontSize*(8 + 8), rowY1);
else
- dc.DrawText(wxString::FromAscii(dis), textPlacement, rowY1);
+ dc.DrawText(StrToWxStr(dis), textPlacement, rowY1);
if (desc[0] == 0)
strcpy(desc, debugger->getDescription(address).c_str());
@@ -371,7 +373,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
dc.SetTextForeground(_T("#0000FF"));
if (strlen(desc))
- dc.DrawText(wxString::FromAscii(desc), 17+fontSize*((8+8+8+30)*2), rowY1);
+ dc.DrawText(StrToWxStr(desc), 17+fontSize*((8+8+8+30)*2), rowY1);
// Show blue memory check dot
if (debugger->isMemCheck(address))
diff --git a/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp
index 5673d7b7c1..4b87cfa154 100644
--- a/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp
@@ -20,6 +20,8 @@
#include <wx/listctrl.h>
#include <wx/thread.h>
#include <wx/listctrl.h>
+
+#include "../WxUtils.h"
#include "MemoryWindow.h"
#include "HW/CPU.h"
#include "PowerPC/PowerPC.h"
@@ -152,8 +154,8 @@ void CMemoryWindow::JumpToAddress(u32 _Address)
void CMemoryWindow::SetMemoryValue(wxCommandEvent& event)
{
- std::string str_addr = std::string(addrbox->GetValue().mb_str());
- std::string str_val = std::string(valbox->GetValue().mb_str());
+ std::string str_addr = WxStrToStr(addrbox->GetValue());
+ std::string str_val = WxStrToStr(valbox->GetValue());
u32 addr;
u32 val;
@@ -179,7 +181,7 @@ void CMemoryWindow::OnAddrBoxChange(wxCommandEvent& event)
if (txt.size())
{
u32 addr;
- sscanf(txt.mb_str(), "%08x", &addr);
+ sscanf(WxStrToStr(txt).c_str(), "%08x", &addr);
memview->Center(addr & ~3);
}
@@ -349,10 +351,7 @@ void CMemoryWindow::onSearch(wxCommandEvent& event)
tmpstr = new char[newsize + 1];
memset(tmpstr, 0, newsize + 1);
}
- //sprintf(tmpstr, "%s%s", tmpstr, rawData.c_str());
- //strcpy(&tmpstr[1], rawData.ToAscii());
- //memcpy(&tmpstr[1], &rawData.c_str()[0], rawData.size());
- sprintf(tmpstr, "%s%s", tmpstr, (const char *)rawData.mb_str());
+ sprintf(tmpstr, "%s%s", tmpstr, WxStrToStr(rawData).c_str());
tmp2 = &Dest.front();
count = 0;
for(i = 0; i < strlen(tmpstr); i++)
@@ -376,7 +375,7 @@ void CMemoryWindow::onSearch(wxCommandEvent& event)
tmpstr = new char[size+1];
tmp2 = &Dest.front();
- sprintf(tmpstr, "%s", (const char *)rawData.mb_str());
+ sprintf(tmpstr, "%s", WxStrToStr(rawData).c_str());
for(i = 0; i < size; i++)
tmp2[i] = tmpstr[i];
@@ -393,7 +392,7 @@ void CMemoryWindow::onSearch(wxCommandEvent& event)
u32 addr = 0;
if (txt.size())
{
- sscanf(txt.mb_str(), "%08x", &addr);
+ sscanf(WxStrToStr(txt).c_str(), "%08x", &addr);
}
i = addr+4;
for( ; i < szRAM; i++)
diff --git a/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp b/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp
index c4a30fd522..0c414cb522 100644
--- a/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp
+++ b/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp
@@ -20,6 +20,7 @@
#include "PowerPC/PowerPC.h"
#include "HW/ProcessorInterface.h"
#include "IniFile.h"
+#include "../WxUtils.h"
// F-zero 80005e60 wtf??
@@ -51,9 +52,9 @@ wxString CRegTable::GetValue(int row, int col)
{
if (row < 32) {
switch (col) {
- case 0: return wxString::FromAscii(GetGPRName(row));
+ case 0: return StrToWxStr(GetGPRName(row));
case 1: return wxString::Format(wxT("%08x"), GPR(row));
- case 2: return wxString::FromAscii(GetFPRName(row));
+ case 2: return StrToWxStr(GetFPRName(row));
case 3: return wxString::Format(wxT("%016llx"), riPS0(row));
case 4: return wxString::Format(wxT("%016llx"), riPS1(row));
default: return wxEmptyString;
@@ -61,7 +62,7 @@ wxString CRegTable::GetValue(int row, int col)
} else {
if (row - 32 < NUM_SPECIALS) {
switch (col) {
- case 0: return wxString::FromAscii(special_reg_names[row - 32]);
+ case 0: return StrToWxStr(special_reg_names[row - 32]);
case 1: return wxString::Format(wxT("%08x"), GetSpecialRegValue(row - 32));
default: return wxEmptyString;
}
@@ -91,7 +92,7 @@ static void SetSpecialRegValue(int reg, u32 value) {
void CRegTable::SetValue(int row, int col, const wxString& strNewVal)
{
u32 newVal = 0;
- if (TryParse(std::string(strNewVal.mb_str()), &newVal))
+ if (TryParse(WxStrToStr(strNewVal), &newVal))
{
if (row < 32) {
if (col == 1)
diff --git a/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp b/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp
index 81268e3467..6e18c192eb 100644
--- a/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp
+++ b/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp
@@ -22,6 +22,7 @@
#include "FifoPlayer/FifoPlayer.h"
#include "FifoPlayer/FifoRecorder.h"
#include "OpcodeDecoding.h"
+#include "WxUtils.h"
#include <wx/spinctrl.h>
#include <wx/clipbrd.h>
@@ -395,7 +396,7 @@ void FifoPlayerDlg::OnSaveFile(wxCommandEvent& WXUNUSED(event))
if (!path.empty())
{
wxBeginBusyCursor();
- bool result = file->Save(path.mb_str());
+ bool result = file->Save(WxStrToStr(path).c_str());
wxEndBusyCursor();
if (!result)
@@ -752,10 +753,10 @@ void FifoPlayerDlg::OnObjectCmdListSelectionChanged(wxCommandEvent& event)
char name[64]="\0", desc[512]="\0";
GetBPRegInfo(cmddata+1, name, sizeof(name), desc, sizeof(desc));
newLabel = _("BP register ");
- newLabel += (name[0] != '\0') ? wxString(name, *wxConvCurrent) : wxString::Format(_("UNKNOWN_%02X"), *(cmddata+1));
+ newLabel += (name[0] != '\0') ? StrToWxStr(name) : wxString::Format(_("UNKNOWN_%02X"), *(cmddata+1));
newLabel += wxT(":\n");
if (desc[0] != '\0')
- newLabel += wxString(desc, *wxConvCurrent);
+ newLabel += StrToWxStr(desc);
else
newLabel += _("No description available");
}
diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp
index d390b8afcd..a0a030081e 100644
--- a/Source/Core/DolphinWX/Src/Frame.cpp
+++ b/Source/Core/DolphinWX/Src/Frame.cpp
@@ -100,37 +100,6 @@ CPanel::CPanel(
else
SetCursor(wxNullCursor);
break;
-
- case WIIMOTE_DISCONNECT:
- if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
- {
- const int wiimote_idx = lParam;
- const int wiimote_num = wiimote_idx + 1;
-
- //Auto reconnect if option is turned on.
- //TODO: Make this only auto reconnect wiimotes that have the option activated.
- SConfig::GetInstance().LoadSettingsWii();//Make sure we are using the newest settings.
- if (SConfig::GetInstance().m_WiiAutoReconnect[wiimote_idx])
- {
- GetUsbPointer()->AccessWiiMote(wiimote_idx | 0x100)->Activate(true);
- NOTICE_LOG(WIIMOTE, "Wiimote %i has been auto-reconnected...", wiimote_num);
- }
- else
- {
- // The Wiimote has been disconnected, we offer reconnect here.
- wxMessageDialog *dlg = new wxMessageDialog(
- this,
- wxString::Format(_("Wiimote %i has been disconnected by system.\nMaybe this game doesn't support multi-wiimote,\nor maybe it is due to idle time out or other reason.\nDo you want to reconnect immediately?"), wiimote_num),
- _("Reconnect Wiimote Confirm"),
- wxYES_NO | wxSTAY_ON_TOP | wxICON_INFORMATION, //wxICON_QUESTION,
- wxDefaultPosition);
-
- if (dlg->ShowModal() == wxID_YES)
- GetUsbPointer()->AccessWiiMote(wiimote_idx | 0x100)->Activate(true);
-
- dlg->Destroy();
- }
- }
}
break;
@@ -690,7 +659,7 @@ void CFrame::OnGameListCtrl_ItemActivated(wxListEvent& WXUNUSED (event))
// 1. Boot the selected iso
// 2. Boot the default or last loaded iso.
// 3. Call BrowseForDirectory if the gamelist is empty
- if (!m_GameListCtrl->GetGameNames().size() &&
+ if (!m_GameListCtrl->GetISO(0) &&
!((SConfig::GetInstance().m_ListGC &&
SConfig::GetInstance().m_ListWii &&
SConfig::GetInstance().m_ListWad) &&
@@ -724,7 +693,7 @@ void CFrame::OnGameListCtrl_ItemActivated(wxListEvent& WXUNUSED (event))
m_GameListCtrl->Update();
}
- else if (!m_GameListCtrl->GetGameNames().size())
+ else if (!m_GameListCtrl->GetISO(0))
m_GameListCtrl->BrowseForDirectory();
else
// Game started by double click
@@ -735,7 +704,7 @@ bool IsHotkey(wxKeyEvent &event, int Id)
{
return (event.GetKeyCode() != WXK_NONE &&
event.GetKeyCode() == SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkey[Id] &&
- event.GetModifiers() == SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkeyModifier[Id]);
+ event.GetModifiers() == SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkeyModifier[Id]);
}
int GetCmdForHotkey(unsigned int key)
diff --git a/Source/Core/DolphinWX/Src/FrameAui.cpp b/Source/Core/DolphinWX/Src/FrameAui.cpp
index 0550c5cd39..6f10d46722 100644
--- a/Source/Core/DolphinWX/Src/FrameAui.cpp
+++ b/Source/Core/DolphinWX/Src/FrameAui.cpp
@@ -21,6 +21,7 @@
#include "Globals.h" // Local
#include "Frame.h"
#include "LogWindow.h"
+#include "WxUtils.h"
#include "ConfigManager.h" // Core
@@ -548,7 +549,7 @@ void CFrame::OnDropDownToolbarItem(wxAuiToolBarEvent& event)
for (u32 i = 0; i < Perspectives.size(); i++)
{
wxMenuItem* mItem = new wxMenuItem(menuPopup, IDM_PERSPECTIVES_0 + i,
- wxString::FromAscii(Perspectives[i].Name.c_str()),
+ StrToWxStr(Perspectives[i].Name),
wxT(""), wxITEM_CHECK);
menuPopup->Append(mItem);
if (i == ActivePerspective) mItem->Check(true);
@@ -580,7 +581,7 @@ void CFrame::OnToolBar(wxCommandEvent& event)
return;
}
SaveIniPerspectives();
- GetStatusBar()->SetStatusText(wxString::FromAscii(std::string
+ GetStatusBar()->SetStatusText(StrToWxStr(std::string
("Saved " + Perspectives[ActivePerspective].Name).c_str()), 0);
break;
case IDM_PERSPECTIVES_ADD_PANE:
@@ -633,7 +634,7 @@ void CFrame::OnDropDownToolbarSelect(wxCommandEvent& event)
}
SPerspectives Tmp;
- Tmp.Name = dlg.GetValue().mb_str();
+ Tmp.Name = WxStrToStr(dlg.GetValue());
Tmp.Perspective = m_Mgr->SavePerspective();
ActivePerspective = (u32)Perspectives.size();
@@ -870,7 +871,7 @@ void CFrame::LoadIniPerspectives()
ini.Get(_Section.c_str(), "Width", &_Width, "70,25");
ini.Get(_Section.c_str(), "Height", &_Height, "80,80");
- Tmp.Perspective = wxString::FromAscii(_Perspective.c_str());
+ Tmp.Perspective = StrToWxStr(_Perspective);
SplitString(_Width, ',', _SWidth);
SplitString(_Height, ',', _SHeight);
@@ -940,7 +941,7 @@ void CFrame::SaveIniPerspectives()
for (u32 i = 0; i < Perspectives.size(); i++)
{
std::string _Section = "P - " + Perspectives[i].Name;
- ini.Set(_Section.c_str(), "Perspective", Perspectives[i].Perspective.mb_str());
+ ini.Set(_Section.c_str(), "Perspective", WxStrToStr(Perspectives[i].Perspective));
std::string SWidth = "", SHeight = "";
for (u32 j = 0; j < Perspectives[i].Width.size(); j++)
diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp
index 56dde8e2ce..f9d737d05e 100644
--- a/Source/Core/DolphinWX/Src/FrameTools.cpp
+++ b/Source/Core/DolphinWX/Src/FrameTools.cpp
@@ -35,7 +35,7 @@ Core::GetWindowHandle().
#include "VideoBackendBase.h"
#ifdef __APPLE__
-#include <ApplicationServices/ApplicationServices.h>
+#include <AppKit/AppKit.h>
#endif
#include "Globals.h" // Local
@@ -74,6 +74,20 @@ Core::GetWindowHandle().
#include <wx/datetime.h> // wxWidgets
+#ifdef _WIN32
+#ifndef SM_XVIRTUALSCREEN
+#define SM_XVIRTUALSCREEN 76
+#endif
+#ifndef SM_YVIRTUALSCREEN
+#define SM_YVIRTUALSCREEN 77
+#endif
+#ifndef SM_CXVIRTUALSCREEN
+#define SM_CXVIRTUALSCREEN 78
+#endif
+#ifndef SM_CYVIRTUALSCREEN
+#define SM_CYVIRTUALSCREEN 79
+#endif
+#endif
// Resources
extern "C" {
@@ -101,7 +115,7 @@ void CFrame::CreateMenu()
drives = cdio_get_devices();
// Windows Limitation of 24 character drives
for (unsigned int i = 0; i < drives.size() && i < 24; i++) {
- externalDrive->Append(IDM_DRIVE1 + i, wxString::FromAscii(drives[i].c_str()));
+ externalDrive->Append(IDM_DRIVE1 + i, StrToWxStr(drives[i]));
}
fileMenu->AppendSeparator();
@@ -601,12 +615,10 @@ void CFrame::DoOpen(bool Boot)
// Should we boot a new game or just change the disc?
if (Boot && !path.IsEmpty())
- BootGame(std::string(path.mb_str()));
+ BootGame(WxStrToStr(path));
else
{
- char newDiscpath[2048];
- strncpy(newDiscpath, path.mb_str(), strlen(path.mb_str())+1);
- DVDInterface::ChangeDisc(newDiscpath);
+ DVDInterface::ChangeDisc(WxStrToStr(path).c_str());
}
}
@@ -693,7 +705,7 @@ void CFrame::OnPlayRecording(wxCommandEvent& WXUNUSED (event))
GetMenuBar()->FindItem(IDM_RECORDREADONLY)->Check(true);
}
- if(Movie::PlayInput(path.mb_str()))
+ if (Movie::PlayInput(WxStrToStr(path).c_str()))
BootGame(std::string(""));
}
@@ -793,39 +805,13 @@ void CFrame::ToggleDisplayMode(bool bFullscreen)
#elif defined(HAVE_XRANDR) && HAVE_XRANDR
m_XRRConfig->ToggleDisplayMode(bFullscreen);
#elif defined __APPLE__
- if (!bFullscreen) {
- CGRestorePermanentDisplayConfiguration();
- CGDisplayRelease(CGMainDisplayID());
- return;
- }
-
- CFArrayRef modes = CGDisplayAvailableModes(CGMainDisplayID());
- for (CFIndex i = 0; i < CFArrayGetCount(modes); i++)
- {
- CFDictionaryRef mode;
- CFNumberRef ref;
- int x, y, w, h, d;
-
- sscanf(SConfig::GetInstance().m_LocalCoreStartupParameter.\
- strFullscreenResolution.c_str(), "%dx%d", &x, &y);
-
- mode = (CFDictionaryRef)CFArrayGetValueAtIndex(modes, i);
- ref = (CFNumberRef)CFDictionaryGetValue(mode, kCGDisplayWidth);
- CFNumberGetValue(ref, kCFNumberIntType, &w);
- ref = (CFNumberRef)CFDictionaryGetValue(mode, kCGDisplayHeight);
- CFNumberGetValue(ref, kCFNumberIntType, &h);
- ref = (CFNumberRef)CFDictionaryGetValue(mode,
- kCGDisplayBitsPerPixel);
- CFNumberGetValue(ref, kCFNumberIntType, &d);
-
- if (CFDictionaryContainsKey(mode, kCGDisplayModeIsStretched))
- continue;
- if (w != x || h != y || d != 32)
- continue;;
-
- CGDisplaySwitchToMode(CGMainDisplayID(), mode);
- }
-
+ NSView* view = (NSView *)m_RenderFrame->GetHandle();
+ [[view window] toggleFullScreen:[view window]];
+
+ if(bFullscreen)
+ CGDisplayHideCursor(CGMainDisplayID());
+ else
+ CGDisplayShowCursor(CGMainDisplayID());
#endif
}
@@ -863,14 +849,23 @@ void CFrame::StartGame(const std::string& filename)
position = wxDefaultPosition;
#endif
+ wxSize size(SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowWidth,
+ SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowHeight);
+#ifdef _WIN32
+ // Out of desktop check
+ int leftPos = GetSystemMetrics(SM_XVIRTUALSCREEN);
+ int topPos = GetSystemMetrics(SM_YVIRTUALSCREEN);
+ int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+ if ((leftPos + width) < (position.x + size.GetWidth()) || leftPos > position.x || (topPos + height) < (position.y + size.GetHeight()) || topPos > position.y)
+ position.x = position.y = wxDefaultCoord;
+#endif
m_RenderFrame = new CRenderFrame((wxFrame*)this, wxID_ANY, _("Dolphin"), position);
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bKeepWindowOnTop)
m_RenderFrame->SetWindowStyle(m_RenderFrame->GetWindowStyle() | wxSTAY_ON_TOP);
else
m_RenderFrame->SetWindowStyle(m_RenderFrame->GetWindowStyle() & ~wxSTAY_ON_TOP);
- wxSize size(SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowWidth,
- SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowHeight);
m_RenderFrame->SetClientSize(size.GetWidth(), size.GetHeight());
m_RenderFrame->Bind(wxEVT_CLOSE_WINDOW, &CFrame::OnRenderParentClose, this);
m_RenderFrame->Bind(wxEVT_ACTIVATE, &CFrame::OnActive, this);
@@ -1015,7 +1010,7 @@ void CFrame::DoStop()
X11Utils::InhibitScreensaver(X11Utils::XDisplayFromHandle(GetHandle()),
X11Utils::XWindowFromHandle(GetHandle()), false);
#endif
- m_RenderFrame->SetTitle(wxString::FromAscii(scm_rev_str));
+ m_RenderFrame->SetTitle(StrToWxStr(scm_rev_str));
// Destroy the renderer frame when not rendering to main
m_RenderParent->Unbind(wxEVT_SIZE, &CFrame::OnRenderParentResize, this);
@@ -1081,7 +1076,7 @@ void CFrame::DoRecordingSave()
if(path.IsEmpty())
return;
- Movie::SaveRecording(path.mb_str());
+ Movie::SaveRecording(WxStrToStr(path).c_str());
if (!paused)
DoPause();
@@ -1212,7 +1207,7 @@ void CFrame::StatusBarMessage(const char * Text, ...)
vsnprintf(Str, MAX_BYTES, Text, ArgPtr);
va_end(ArgPtr);
- if (this->GetStatusBar()->IsEnabled()) this->GetStatusBar()->SetStatusText(wxString::FromAscii(Str),0);
+ if (this->GetStatusBar()->IsEnabled()) this->GetStatusBar()->SetStatusText(StrToWxStr(Str),0);
}
@@ -1248,7 +1243,8 @@ void CFrame::OnImportSave(wxCommandEvent& WXUNUSED (event))
if (!path.IsEmpty())
{
- CWiiSaveCrypted* saveFile = new CWiiSaveCrypted(path.mb_str());
+ // TODO: Does this actually need to be dynamically allocated for some reason?
+ CWiiSaveCrypted* saveFile = new CWiiSaveCrypted(WxStrToStr(path).c_str());
delete saveFile;
}
}
@@ -1288,7 +1284,7 @@ void CFrame::OnInstallWAD(wxCommandEvent& event)
_T("Wii WAD file (*.wad)|*.wad"),
wxFD_OPEN | wxFD_PREVIEW | wxFD_FILE_MUST_EXIST,
this);
- fileName = path.mb_str();
+ fileName = WxStrToStr(path);
break;
}
default:
@@ -1354,11 +1350,7 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect)
GetUsbPointer()->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
wxString msg(wxString::Format(wxT("Wiimote %i %s"), wm_idx + 1,
connect ? wxT("Connected") : wxT("Disconnected")));
- Core::DisplayMessage(msg.ToAscii(), 3000);
-
- // Wait for the wiimote to connect
- while (GetUsbPointer()->AccessWiiMote(wm_idx | 0x100)->IsConnected() != connect)
- {}
+ Core::DisplayMessage(WxStrToStr(msg), 3000);
Host_UpdateMainFrame();
}
}
@@ -1398,7 +1390,7 @@ void CFrame::OnLoadStateFromFile(wxCommandEvent& WXUNUSED (event))
this);
if (!path.IsEmpty())
- State::LoadAs((const char*)path.mb_str());
+ State::LoadAs(WxStrToStr(path));
}
void CFrame::OnSaveStateToFile(wxCommandEvent& WXUNUSED (event))
@@ -1412,7 +1404,7 @@ void CFrame::OnSaveStateToFile(wxCommandEvent& WXUNUSED (event))
this);
if (!path.IsEmpty())
- State::SaveAs((const char*)path.mb_str());
+ State::SaveAs(WxStrToStr(path));
}
void CFrame::OnLoadLastState(wxCommandEvent& WXUNUSED (event))
diff --git a/Source/Core/DolphinWX/Src/GLInterface.h b/Source/Core/DolphinWX/Src/GLInterface.h
index a81f17104c..2923ff7bf4 100644
--- a/Source/Core/DolphinWX/Src/GLInterface.h
+++ b/Source/Core/DolphinWX/Src/GLInterface.h
@@ -18,21 +18,24 @@
#define _GLINTERFACE_H_
#include "Thread.h"
-
-#if defined(USE_EGL) && USE_EGL
-#include "GLInterface/EGL.h"
-#elif defined(USE_WX) && USE_WX
-#include "GLInterface/WX.h"
+#ifdef ANDROID
+#include <GLES2/gl2.h>
+#include <GLInterface/InterfaceBase.h>
+#elif defined(USE_EGL) && USE_EGL
+#include "GLInterface/EGL_X11.h"
#elif defined(__APPLE__)
#include "GLInterface/AGL.h"
#elif defined(_WIN32)
#include "GLInterface/WGL.h"
#elif defined(HAVE_X11) && HAVE_X11
#include "GLInterface/GLX.h"
+#else
+#error Platform doesnt have a GLInterface
#endif
typedef struct {
-#if defined(USE_EGL) && USE_EGL // This is currently a X11/EGL implementation for desktop
+#ifdef ANDROID
+#elif defined(USE_EGL) && USE_EGL // This is currently a X11/EGL implementation for desktop
int screen;
Display *dpy;
Display *evdpy;
@@ -46,12 +49,8 @@ typedef struct {
std::thread xEventThread;
int x, y;
unsigned int width, height;
-#elif defined(USE_WX) && USE_WX
- wxGLCanvas *glCanvas;
- wxGLContext *glCtxt;
- wxPanel *panel;
#elif defined(__APPLE__)
- NSWindow *cocoaWin;
+ NSView *cocoaWin;
NSOpenGLContext *cocoaCtx;
#elif defined(HAVE_X11) && HAVE_X11
int screen;
diff --git a/Source/Core/DolphinWX/Src/GLInterface/AGL.cpp b/Source/Core/DolphinWX/Src/GLInterface/AGL.cpp
index cf68c0baa4..2fa042daef 100644
--- a/Source/Core/DolphinWX/Src/GLInterface/AGL.cpp
+++ b/Source/Core/DolphinWX/Src/GLInterface/AGL.cpp
@@ -20,6 +20,8 @@
#include "RenderBase.h"
#include "ConfigManager.h"
+#include <wx/panel.h>
+
#include "VertexShaderManager.h"
#include "../GLInterface.h"
#include "AGL.h"
@@ -29,12 +31,6 @@ void cInterfaceAGL::Swap()
[GLWin.cocoaCtx flushBuffer];
}
-// Show the current FPS
-void cInterfaceAGL::UpdateFPSDisplay(const char *text)
-{
- [GLWin.cocoaWin setTitle: [NSString stringWithUTF8String: text]];
-}
-
// Create rendering window.
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
bool cInterfaceAGL::Create(void *&window_handle)
@@ -46,9 +42,7 @@ bool cInterfaceAGL::Create(void *&window_handle)
s_backbuffer_width = _twidth;
s_backbuffer_height = _theight;
- NSRect size;
- NSUInteger style = NSMiniaturizableWindowMask;
- NSOpenGLPixelFormatAttribute attr[2] = { NSOpenGLPFADoubleBuffer, 0 };
+ NSOpenGLPixelFormatAttribute attr[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, NSOpenGLPFAAccelerated, 0 };
NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc]
initWithAttributes: attr];
if (fmt == nil) {
@@ -64,55 +58,44 @@ bool cInterfaceAGL::Create(void *&window_handle)
return NULL;
}
- if (SConfig::GetInstance().m_LocalCoreStartupParameter.bFullscreen) {
- size = [[NSScreen mainScreen] frame];
- style |= NSBorderlessWindowMask;
- } else {
- size = NSMakeRect(_tx, _ty, _twidth, _theight);
- style |= NSResizableWindowMask | NSTitledWindowMask;
- }
-
- GLWin.cocoaWin = [[NSWindow alloc] initWithContentRect: size
- styleMask: style backing: NSBackingStoreBuffered defer: NO];
+
+ GLWin.cocoaWin = (NSView*)(((wxPanel*)window_handle)->GetHandle());;
if (GLWin.cocoaWin == nil) {
ERROR_LOG(VIDEO, "failed to create window");
return NULL;
}
- if (SConfig::GetInstance().m_LocalCoreStartupParameter.bFullscreen) {
- CGDisplayCapture(CGMainDisplayID());
- [GLWin.cocoaWin setLevel: CGShieldingWindowLevel()];
- }
-
- [GLWin.cocoaCtx setView: [GLWin.cocoaWin contentView]];
- [GLWin.cocoaWin makeKeyAndOrderFront: nil];
+ [[GLWin.cocoaWin window] makeFirstResponder:GLWin.cocoaWin];
+ [GLWin.cocoaCtx setView: GLWin.cocoaWin];
+ [[GLWin.cocoaWin window] makeKeyAndOrderFront: nil];
return true;
}
bool cInterfaceAGL::MakeCurrent()
{
- int width, height;
-
- width = [[GLWin.cocoaWin contentView] frame].size.width;
- height = [[GLWin.cocoaWin contentView] frame].size.height;
- if (width == s_backbuffer_width && height == s_backbuffer_height)
- return;
-
- [GLWin.cocoaCtx setView: [GLWin.cocoaWin contentView]];
- [GLWin.cocoaCtx update];
[GLWin.cocoaCtx makeCurrentContext];
- s_backbuffer_width = width;
- s_backbuffer_height = height;
- return true;
+ return true;
}
// Close backend
void cInterfaceAGL::Shutdown()
{
- [GLWin.cocoaWin close];
[GLWin.cocoaCtx clearDrawable];
[GLWin.cocoaCtx release];
+ GLWin.cocoaCtx = nil;
+}
+
+void cInterfaceAGL::Update()
+{
+ if( s_backbuffer_width == [GLWin.cocoaWin frame].size.width
+ && s_backbuffer_height == [GLWin.cocoaWin frame].size.height)
+ return;
+
+ s_backbuffer_width = [GLWin.cocoaWin frame].size.width;
+ s_backbuffer_height = [GLWin.cocoaWin frame].size.height;
+
+ [GLWin.cocoaCtx update];
}
diff --git a/Source/Core/DolphinWX/Src/GLInterface/AGL.h b/Source/Core/DolphinWX/Src/GLInterface/AGL.h
index e03256ab4e..ea4ed66778 100644
--- a/Source/Core/DolphinWX/Src/GLInterface/AGL.h
+++ b/Source/Core/DolphinWX/Src/GLInterface/AGL.h
@@ -28,10 +28,11 @@ class cInterfaceAGL : public cInterfaceBase
{
public:
void Swap();
- void UpdateFPSDisplay(const char *Text);
bool Create(void *&window_handle);
bool MakeCurrent();
- void Shutdown();
+ void Shutdown();
+ void Update();
+
};
#endif
diff --git a/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp b/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.cpp
index 304eb92059..ccb2fc04b8 100644
--- a/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp
+++ b/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.cpp
@@ -19,7 +19,7 @@
#include "RenderBase.h"
#include "../GLInterface.h"
-#include "EGL.h"
+#include "EGL_X11.h"
// Show the current FPS
void cInterfaceEGL::UpdateFPSDisplay(const char *text)
@@ -141,7 +141,7 @@ bool cInterfaceEGL::Create(void *&window_handle)
return false;
}
- GLWin.egl_surf = eglCreateWindowSurface(GLWin.egl_dpy, config, GLWin.win, NULL);
+ GLWin.egl_surf = eglCreateWindowSurface(GLWin.egl_dpy, config, (NativeWindowType)GLWin.win, NULL);
if (!GLWin.egl_surf) {
ERROR_LOG(VIDEO, "Error: eglCreateWindowSurface failed\n");
return false;
diff --git a/Source/Core/DolphinWX/Src/GLInterface/EGL.h b/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.h
index 513fb2ce4a..e47573e4d8 100644
--- a/Source/Core/DolphinWX/Src/GLInterface/EGL.h
+++ b/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.h
@@ -20,6 +20,7 @@
#include <EGL/egl.h>
#ifdef USE_GLES
#include <GLES2/gl2.h>
+#include <X11/Xutil.h>
#else
#include <GL/glxew.h>
#include <GL/gl.h>
diff --git a/Source/Core/DolphinWX/Src/GLInterface/GLX.cpp b/Source/Core/DolphinWX/Src/GLInterface/GLX.cpp
index 5745823cbf..196830be66 100644
--- a/Source/Core/DolphinWX/Src/GLInterface/GLX.cpp
+++ b/Source/Core/DolphinWX/Src/GLInterface/GLX.cpp
@@ -69,8 +69,6 @@ bool cInterfaceGLX::Create(void *&window_handle)
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_DEPTH_SIZE, 24,
- GLX_SAMPLE_BUFFERS_ARB, g_Config.iMultisampleMode != MULTISAMPLE_OFF?1:0,
- GLX_SAMPLES_ARB, g_Config.iMultisampleMode != MULTISAMPLE_OFF?1:0,
None };
int attrListDefault[] = {
diff --git a/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h b/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h
index c2d1ffc54b..1c00a1fd89 100644
--- a/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h
+++ b/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h
@@ -23,11 +23,11 @@ protected:
u32 s_backbuffer_width;
u32 s_backbuffer_height;
public:
- virtual void Swap() = 0;
- virtual void UpdateFPSDisplay(const char *Text) = 0;
- virtual bool Create(void *&window_handle) = 0;
- virtual bool MakeCurrent() = 0;
- virtual void Shutdown() = 0;
+ virtual void Swap() {}
+ virtual void UpdateFPSDisplay(const char *Text) {}
+ virtual bool Create(void *&window_handle) { return true; }
+ virtual bool MakeCurrent() { return true; }
+ virtual void Shutdown() {}
virtual void SwapInterval(int Interval) { }
virtual u32 GetBackBufferWidth() { return s_backbuffer_width; }
diff --git a/Source/Core/DolphinWX/Src/GLInterface/WX.cpp b/Source/Core/DolphinWX/Src/GLInterface/WX.cpp
deleted file mode 100644
index 16de6369a7..0000000000
--- a/Source/Core/DolphinWX/Src/GLInterface/WX.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (C) 2003 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "VideoConfig.h"
-#include "Host.h"
-#include "RenderBase.h"
-
-#include "VertexShaderManager.h"
-#include "../GLInterface.h"
-#include "WX.h"
-
-void cInterfaceWX::SwapInterval(int Interval)
-{
- // WX interface only used on Apple
-#ifdef __APPLE__
-#if defined USE_WX && USE_WX
- NSOpenGLContext *ctx = GLWin.glCtxt->GetWXGLContext();
-#else
- NSOpenGLContext *ctx = GLWin.cocoaCtx;
-#endif
- [ctx setValues: &Interval forParameter: NSOpenGLCPSwapInterval];
-#endif
-}
-
-void cInterfaceWX::Swap()
-{
- GLWin.glCanvas->SwapBuffers();
-}
-
-void cInterfaceWX::UpdateFPSDisplay(const char *text)
-{
- // Handled by Host_UpdateTitle()
-}
-
-// Create rendering window.
-// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
-bool cInterfaceWX::Create(void *&window_handle)
-{
- int _tx, _ty, _twidth, _theight;
- Host_GetRenderWindowSize(_tx, _ty, _twidth, _theight);
-
- // Control window size and picture scaling
- s_backbuffer_width = _twidth;
- s_backbuffer_height = _theight;
-
- GLWin.panel = (wxPanel *)window_handle;
- GLWin.glCanvas = new wxGLCanvas(GLWin.panel, wxID_ANY, NULL,
- wxPoint(0, 0), wxSize(_twidth, _theight));
- GLWin.glCanvas->Show(true);
- if (GLWin.glCtxt == NULL) // XXX dirty hack
- GLWin.glCtxt = new wxGLContext(GLWin.glCanvas);
- return true;
-}
-
-bool cInterfaceWX::MakeCurrent()
-{
- return GLWin.glCanvas->SetCurrent(*GLWin.glCtxt);
-}
-
-// Update window width, size and etc. Called from Render.cpp
-void cInterfaceWX::Update()
-{
- int width, height;
-
- GLWin.panel->GetSize(&width, &height);
- if (width == s_backbuffer_width && height == s_backbuffer_height)
- return;
-
- GLWin.glCanvas->SetFocus();
- GLWin.glCanvas->SetSize(0, 0, width, height);
- GLWin.glCtxt->SetCurrent(*GLWin.glCanvas);
- s_backbuffer_width = width;
- s_backbuffer_height = height;
-}
-
-// Close backend
-void cInterfaceWX::Shutdown()
-{
- GLWin.glCanvas->Hide();
-}
-
-
diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp
index 6fd298ad81..bf09161555 100644
--- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp
+++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp
@@ -35,6 +35,7 @@
#include "CDUtils.h"
#include "WxUtils.h"
#include "Main.h"
+#include "MathUtil.h"
#include "../resources/Flag_Europe.xpm"
#include "../resources/Flag_Germany.xpm"
@@ -257,7 +258,7 @@ void CGameListCtrl::BrowseForDirectory()
if (dialog.ShowModal() == wxID_OK)
{
- std::string sPath(dialog.GetPath().mb_str());
+ std::string sPath(WxStrToStr(dialog.GetPath()));
std::vector<std::string>::iterator itResult = std::find(
SConfig::GetInstance().m_ISOFolder.begin(),
SConfig::GetInstance().m_ISOFolder.end(), sPath);
@@ -285,10 +286,6 @@ void CGameListCtrl::Update()
m_imageListSmall = NULL;
}
- // NetPlay : Set/Reset the GameList string
- m_gameList.clear();
- m_gamePath.clear();
-
Hide();
ScanForISOs();
@@ -384,35 +381,18 @@ void CGameListCtrl::Update()
SetFocus();
}
-wxString NiceSizeFormat(s64 _size)
+wxString NiceSizeFormat(u64 _size)
{
- const char* sizes[] = {"b", "KB", "MB", "GB", "TB", "PB", "EB"};
- int s = 0;
- int frac = 0;
-
- while (_size > (s64)1024)
- {
- s++;
- frac = (int)_size & 1023;
- _size /= (s64)1024;
- }
-
- float f = (float)_size + ((float)frac / 1024.0f);
-
- wxString NiceString;
- char tempstr[32];
- sprintf(tempstr,"%3.1f %s", f, sizes[s]);
- NiceString = wxString::FromAscii(tempstr);
- return(NiceString);
-}
+ const char* const unit_symbols[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"};
+
+ auto const unit = Log2(std::max<u64>(_size, 1)) / 10;
+ auto const unit_size = (1 << (unit * 10));
+
+ // ugly rounding integer math
+ auto const value = (_size + unit_size / 2) / unit_size;
+ auto const frac = (_size % unit_size * 10 + unit_size / 2) / unit_size % 10;
-std::string CGameListCtrl::GetGamePaths() const
-{
- return m_gamePath;
-}
-std::string CGameListCtrl::GetGameNames() const
-{
- return m_gameList;
+ return StrToWxStr(StringFromFormat("%llu.%llu %s", value, frac, unit_symbols[unit]));
}
void CGameListCtrl::InsertItemInReportView(long _Index)
@@ -423,25 +403,7 @@ void CGameListCtrl::InsertItemInReportView(long _Index)
// company: 0x007030
int ImageIndex = -1;
-#ifdef _WIN32
- wxCSConv SJISConv(*(wxCSConv*)wxConvCurrent);
- static bool validCP932 = ::IsValidCodePage(932) != 0;
- if (validCP932)
- {
- SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS));
- }
- else
- {
- WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932");
- }
-#else
- // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)
- // it returns CP-932, in order to use iconv we need to use CP932
- wxCSConv SJISConv(wxT("CP932"));
-#endif
-
GameListItem& rISOFile = *m_ISOFiles[_Index];
- m_gamePath.append(rISOFile.GetFileName() + '\n');
// Insert a first row with nothing in it, that will be used as the Index
long ItemIndex = InsertItem(_Index, wxEmptyString);
@@ -454,55 +416,33 @@ void CGameListCtrl::InsertItemInReportView(long _Index)
// Set the game's banner in the second column
SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex);
-
- std::wstring wstring_name;
- const std::wstring& wstring_description = rISOFile.GetDescription();
- std::string company;
- wxString name;
- wxString description;
-
- // We show the company string on Gamecube only
- // On Wii we show the description instead as the company string is empty
- if (rISOFile.GetPlatform() == GameListItem::GAMECUBE_DISC)
- company = rISOFile.GetCompany().c_str();
int SelectedLanguage = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage;
+
+ // Is this sane?
switch (rISOFile.GetCountry())
{
case DiscIO::IVolume::COUNTRY_TAIWAN:
case DiscIO::IVolume::COUNTRY_JAPAN:
- {
- rISOFile.GetName(wstring_name, -1);
- name = wxString(rISOFile.GetName(0).c_str(), SJISConv);
- m_gameList.append(StringFromFormat("%s (J)\n", (const char *)name.c_str()));
- description = wxString(company.size() ? company.c_str() :
- rISOFile.GetDescription(0).c_str(), SJISConv);
- }
+ SelectedLanguage = -1;
break;
+
case DiscIO::IVolume::COUNTRY_USA:
SelectedLanguage = 0;
+ break;
+
default:
- {
- wxCSConv WindowsCP1252(wxFontMapper::GetEncodingName(wxFONTENCODING_CP1252));
- rISOFile.GetName(wstring_name, SelectedLanguage);
-
- name = wxString(rISOFile.GetName(SelectedLanguage).c_str(), WindowsCP1252);
- m_gameList.append(StringFromFormat("%s (%c)\n",
- rISOFile.GetName(SelectedLanguage).c_str(),
- (rISOFile.GetCountry() == DiscIO::IVolume::COUNTRY_USA) ? 'U' : 'E'));
- description = wxString(company.size() ? company.c_str() :
- rISOFile.GetDescription(SelectedLanguage).c_str(), WindowsCP1252);
- }
break;
}
+
+ std::string const name = rISOFile.GetName(SelectedLanguage);
+ SetItem(_Index, COLUMN_TITLE, StrToWxStr(name), -1);
- if (wstring_name.length())
- name = wstring_name.c_str();
- if (wstring_description.length())
- description = wstring_description.c_str();
-
- SetItem(_Index, COLUMN_TITLE, name, -1);
- SetItem(_Index, COLUMN_NOTES, description, -1);
+ // We show the company string on Gamecube only
+ // On Wii we show the description instead as the company string is empty
+ std::string const notes = (rISOFile.GetPlatform() == GameListItem::GAMECUBE_DISC) ?
+ rISOFile.GetCompany() : rISOFile.GetDescription(SelectedLanguage);
+ SetItem(_Index, COLUMN_NOTES, StrToWxStr(notes), -1);
// Emulation state
SetItemColumnImage(_Index, COLUMN_EMULATION_STATE, m_EmuStateImageIndex[rISOFile.GetEmuState()]);
@@ -614,7 +554,7 @@ void CGameListCtrl::ScanForISOs()
// Update with the progress (i) and the message
dialog.Update(i, wxString::Format(_("Scanning %s"),
- wxString(FileName.c_str(), *wxConvCurrent).c_str()));
+ StrToWxStr(FileName)));
if (dialog.WasCancelled())
break;
@@ -858,7 +798,7 @@ void CGameListCtrl::OnMouseMotion(wxMouseEvent& event)
char temp[2048];
sprintf(temp, "^ %s%s%s", emuState[emu_state - 1],
issues.size() > 0 ? " :\n" : "", issues.c_str());
- toolTip = new wxEmuStateTip(this, wxString(temp, *wxConvCurrent), &toolTip);
+ toolTip = new wxEmuStateTip(this, StrToWxStr(temp), &toolTip);
}
else
toolTip = new wxEmuStateTip(this, _("Not Set"), &toolTip);
@@ -999,8 +939,7 @@ void CGameListCtrl::OnOpenContainingFolder(wxCommandEvent& WXUNUSED (event))
if (!iso)
return;
- wxString strPath(iso->GetFileName().c_str(), wxConvUTF8);
- wxFileName path = wxFileName::FileName(strPath);
+ wxFileName path = wxFileName::FileName(StrToWxStr(iso->GetFileName()));
path.MakeAbsolute();
WxUtils::Explore(path.GetPath().char_str());
}
@@ -1115,9 +1054,9 @@ void CGameListCtrl::OnWiki(wxCommandEvent& WXUNUSED (event))
void CGameListCtrl::MultiCompressCB(const char* text, float percent, void* arg)
{
percent = (((float)m_currentItem) + percent) / (float)m_numberItem;
- wxString textString(StringFromFormat("%s (%i/%i) - %s",
+ wxString textString(StrToWxStr(StringFromFormat("%s (%i/%i) - %s",
m_currentFilename.c_str(), (int)m_currentItem+1,
- (int)m_numberItem, text).c_str(), *wxConvCurrent);
+ (int)m_numberItem, text)));
((wxProgressDialog*)arg)->Update((int)(percent*1000), textString);
}
@@ -1170,13 +1109,13 @@ void CGameListCtrl::CompressSelection(bool _compress)
std::string OutputFileName;
BuildCompleteFilename(OutputFileName,
- (const char *)browseDialog.GetPath().mb_str(wxConvUTF8),
+ WxStrToStr(browseDialog.GetPath()),
FileName);
- if (wxFileExists(wxString::FromAscii(OutputFileName.c_str())) &&
+ if (wxFileExists(StrToWxStr(OutputFileName)) &&
wxMessageBox(
wxString::Format(_("The file %s already exists.\nDo you wish to replace it?"),
- wxString(OutputFileName.c_str(), *wxConvCurrent).c_str()),
+ StrToWxStr(OutputFileName)),
_("Confirm File Overwrite"),
wxYES_NO) == wxNO)
continue;
@@ -1198,13 +1137,13 @@ void CGameListCtrl::CompressSelection(bool _compress)
std::string OutputFileName;
BuildCompleteFilename(OutputFileName,
- (const char *)browseDialog.GetPath().mb_str(wxConvUTF8),
+ WxStrToStr(browseDialog.GetPath()),
FileName);
- if (wxFileExists(wxString::FromAscii(OutputFileName.c_str())) &&
+ if (wxFileExists(StrToWxStr(OutputFileName)) &&
wxMessageBox(
wxString::Format(_("The file %s already exists.\nDo you wish to replace it?"),
- wxString(OutputFileName.c_str(), *wxConvCurrent).c_str()),
+ StrToWxStr(OutputFileName)),
_("Confirm File Overwrite"),
wxYES_NO) == wxNO)
continue;
@@ -1225,7 +1164,7 @@ void CGameListCtrl::CompressSelection(bool _compress)
void CGameListCtrl::CompressCB(const char* text, float percent, void* arg)
{
((wxProgressDialog*)arg)->
- Update((int)(percent*1000), wxString(text, *wxConvCurrent));
+ Update((int)(percent*1000), StrToWxStr(text));
}
void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event))
@@ -1251,8 +1190,8 @@ void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event))
path = wxFileSelector(
_("Save decompressed GCM/ISO"),
- wxString(FilePath.c_str(), *wxConvCurrent),
- wxString(FileName.c_str(), *wxConvCurrent) + FileType.After('*'),
+ StrToWxStr(FilePath),
+ StrToWxStr(FileName) + FileType.After('*'),
wxEmptyString,
FileType + wxT("|") + wxGetTranslation(wxALL_FILES),
wxFD_SAVE,
@@ -1262,8 +1201,8 @@ void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event))
{
path = wxFileSelector(
_("Save compressed GCM/ISO"),
- wxString(FilePath.c_str(), *wxConvCurrent),
- wxString(FileName.c_str(), *wxConvCurrent) + _T(".gcz"),
+ StrToWxStr(FilePath),
+ StrToWxStr(FileName) + _T(".gcz"),
wxEmptyString,
_("All compressed GC/Wii ISO files (gcz)") +
wxString::Format(wxT("|*.gcz|%s"), wxGetTranslation(wxALL_FILES)),
diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.h b/Source/Core/DolphinWX/Src/GameListCtrl.h
index 5d97c12724..f1923e97c5 100644
--- a/Source/Core/DolphinWX/Src/GameListCtrl.h
+++ b/Source/Core/DolphinWX/Src/GameListCtrl.h
@@ -47,10 +47,6 @@ public:
void Update();
- // Net Play method
- std::string GetGamePaths() const;
- std::string GetGameNames() const;
-
void BrowseForDirectory();
const GameListItem *GetSelectedISO();
const GameListItem *GetISO(size_t index) const;
@@ -84,10 +80,6 @@ private:
}
}
- // NetPlay string for the gamelist
- std::string m_gameList;
- std::string m_gamePath;
-
int last_column;
int last_sort;
wxSize lastpos;
diff --git a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp
index e015c55ae8..76d4833c0b 100644
--- a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp
+++ b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp
@@ -13,6 +13,7 @@
// If not, see http://www.gnu.org/licenses/
#include "GeckoCodeDiag.h"
+#include "WxUtils.h"
#include <SFML/Network/Http.hpp>
@@ -76,7 +77,7 @@ void CodeConfigPanel::UpdateCodeList()
gcodes_end = m_gcodes.end();
for (; gcodes_iter!=gcodes_end; ++gcodes_iter)
{
- m_listbox_gcodes->Append(wxString(gcodes_iter->name.c_str(), *wxConvCurrent));
+ m_listbox_gcodes->Append(StrToWxStr(gcodes_iter->name));
if (gcodes_iter->enabled)
m_listbox_gcodes->Check(m_listbox_gcodes->GetCount()-1, true);
}
@@ -109,7 +110,7 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&)
if (sel > -1)
{
- m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name) + wxString(m_gcodes[sel].name.c_str(), *wxConvCurrent));
+ m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name) + StrToWxStr(m_gcodes[sel].name));
// notes textctrl
m_infobox.textctrl_notes->Clear();
@@ -117,10 +118,10 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&)
notes_iter = m_gcodes[sel].notes.begin(),
notes_end = m_gcodes[sel].notes.end();
for (; notes_iter!=notes_end; ++notes_iter)
- m_infobox.textctrl_notes->AppendText(wxString(notes_iter->c_str(), *wxConvCurrent));
+ m_infobox.textctrl_notes->AppendText(StrToWxStr(*notes_iter));
m_infobox.textctrl_notes->ScrollLines(-99); // silly
- m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator) + wxString(m_gcodes[sel].creator.c_str(), *wxConvCurrent));
+ m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator) + StrToWxStr(m_gcodes[sel].creator));
// add codes to info listbox
std::vector<GeckoCode::Code>::const_iterator
diff --git a/Source/Core/DolphinWX/Src/ISOFile.cpp b/Source/Core/DolphinWX/Src/ISOFile.cpp
index 833268ad63..797780c32e 100644
--- a/Source/Core/DolphinWX/Src/ISOFile.cpp
+++ b/Source/Core/DolphinWX/Src/ISOFile.cpp
@@ -28,6 +28,7 @@
#include "StringUtil.h"
#include "Hash.h"
#include "IniFile.h"
+#include "WxUtils.h"
#include "Filesystem.h"
#include "BannerLoader.h"
@@ -36,7 +37,7 @@
#include "ChunkFile.h"
#include "ConfigManager.h"
-#define CACHE_REVISION 0x10F
+#define CACHE_REVISION 0x112
#define DVD_BANNER_WIDTH 96
#define DVD_BANNER_HEIGHT 32
@@ -65,26 +66,10 @@ GameListItem::GameListItem(const std::string& _rFileName)
else
{
m_Platform = WII_WAD;
- pVolume->GetWName(m_wNames);
}
- m_Company = "N/A";
+ m_volume_names = pVolume->GetNames();
-
- m_Name[0] = pVolume->GetName();
-
- if(m_Name[0] == "") // Couldn't find the name in the WAD...
- {
- std::string FileName;
- SplitPath(m_FileName, NULL, &FileName, NULL);
- m_Name[0] = FileName; // Then just display the filename... Better than something like "No Name"
- }
-
- for (int i = 0; i < 6; i++)
- {
- m_Name[i] = m_Name[0];
- m_Description[i] = "No Description";
- }
m_Country = pVolume->GetCountry();
m_FileSize = File::GetSize(_rFileName);
m_VolumeSize = pVolume->GetSize();
@@ -104,12 +89,9 @@ GameListItem::GameListItem(const std::string& _rFileName)
{
if (pBannerLoader->IsValid())
{
- m_wNames.clear();
- pBannerLoader->GetName(m_wNames);
- pBannerLoader->GetName(m_Name);
- pBannerLoader->GetCompany(m_Company);
- pBannerLoader->GetDescription(m_wDescription);
- pBannerLoader->GetDescription(m_Description);
+ m_names = pBannerLoader->GetNames();
+ m_company = pBannerLoader->GetCompany();
+ m_descriptions = pBannerLoader->GetDescriptions();
if (pBannerLoader->GetBanner(g_ImageTemp))
{
@@ -129,25 +111,6 @@ GameListItem::GameListItem(const std::string& _rFileName)
delete pFileSystem;
}
- std::vector<std::wstring>::iterator i, end = m_wNames.end();
- std::wstring wFileName;
- for (i = m_wNames.begin(); i != end; ++i)
- {
- if (*i == L"")
- {
- if (!wFileName.length())
- {
- std::string FileName;
- SplitPath(m_FileName, NULL, &FileName, NULL);
- int length = FileName.length();
- wFileName.reserve(length+1);
- for (int j = 0; j < length; ++j)
- wFileName.push_back(FileName[j]);
- wFileName.push_back(0);
- }
- *i = wFileName;
- }
- }
delete pVolume;
@@ -208,33 +171,10 @@ void GameListItem::SaveToCache()
void GameListItem::DoState(PointerWrap &p)
{
- p.Do(m_Name[0]); p.Do(m_Name[1]); p.Do(m_Name[2]);
- p.Do(m_Name[3]); p.Do(m_Name[4]); p.Do(m_Name[5]);
-
- int wNamesSize = m_wNames.size();
- p.Do(wNamesSize);
-
- if (p.mode == p.MODE_READ)
- {
- for (int i = 0; i < wNamesSize; ++i)
- {
- std::wstring temp;
- p.Do(temp);
- m_wNames.push_back(temp);
- }
- }
- else
- {
- for (int i = 0; i < wNamesSize; ++i)
- {
- p.Do(m_wNames[i]);
- }
- }
-
- p.Do(m_Company);
- p.Do(m_Description[0]); p.Do(m_Description[1]); p.Do(m_Description[2]);
- p.Do(m_Description[3]); p.Do(m_Description[4]); p.Do(m_Description[5]);
- p.Do(m_wDescription);
+ p.Do(m_volume_names);
+ p.Do(m_company);
+ p.Do(m_names);
+ p.Do(m_descriptions);
p.Do(m_UniqueID);
p.Do(m_FileSize);
p.Do(m_VolumeSize);
@@ -263,49 +203,73 @@ std::string GameListItem::CreateCacheFilename()
return fullname;
}
-const std::string& GameListItem::GetDescription(int index) const
+std::string GameListItem::GetCompany() const
{
- if ((index >=0) && (index < 6))
- {
- return m_Description[index];
- }
- return m_Description[0];
+ if (m_company.empty())
+ return "N/A";
+ else
+ return m_company;
}
-const std::wstring& GameListItem::GetDescription() const
+// (-1 = Japanese, 0 = English, etc)
+std::string GameListItem::GetDescription(int _index) const
{
- return m_wDescription;
+ const u32 index = _index + 1;
+
+ if (index < m_descriptions.size())
+ return m_descriptions[index];
+
+ if (!m_descriptions.empty())
+ return m_descriptions[0];
+
+ return "";
}
-const std::string& GameListItem::GetName(int index) const
+// (-1 = Japanese, 0 = English, etc)
+std::string GameListItem::GetVolumeName(int _index) const
{
- if ((index >=0) && (index < 6))
- {
- return m_Name[index];
- }
- return m_Name[0];
+ u32 const index = _index + 1;
+
+ if (index < m_volume_names.size() && !m_volume_names[index].empty())
+ return m_volume_names[index];
+
+ if (!m_volume_names.empty())
+ return m_volume_names[0];
+
+ return "";
}
-bool GameListItem::GetName(std::wstring& wName, int index) const
+// (-1 = Japanese, 0 = English, etc)
+std::string GameListItem::GetBannerName(int _index) const
{
- // This function will only succeed for wii discs with banners or WADs
- // utilize the same array as for gc discs (-1= Japanese, 0 = English etc
- index++;
- if ((index >= 0) && (index < 10))
- {
- if (m_wNames.size() > (size_t)index)
- {
- wName = m_wNames[index];
- return true;
- }
- }
- if (m_wNames.size() > 0)
+ u32 const index = _index + 1;
+
+ if (index < m_names.size() && !m_names[index].empty())
+ return m_names[index];
+
+ if (!m_names.empty())
+ return m_names[0];
+
+ return "";
+}
+
+// (-1 = Japanese, 0 = English, etc)
+std::string GameListItem::GetName(int _index) const
+{
+ // Prefer name from banner, fallback to name from volume, fallback to filename
+
+ std::string name = GetBannerName(_index);
+
+ if (name.empty())
+ name = GetVolumeName(_index);
+
+ if (name.empty())
{
- wName = m_wNames[0];
- return true;
+ // No usable name, return filename (better than nothing)
+ SplitPath(GetFileName(), NULL, &name, NULL);
}
- return false;
+ return name;
}
const std::string GameListItem::GetWiiFSPath() const
@@ -331,7 +295,7 @@ const std::string GameListItem::GetWiiFSPath() const
File::CreateFullPath(Path);
if (Path[0] == '.')
- ret = std::string(wxGetCwd().mb_str()) + std::string(Path).substr(strlen(ROOT_DIR));
+ ret = WxStrToStr(wxGetCwd()) + std::string(Path).substr(strlen(ROOT_DIR));
else
ret = std::string(Path);
}
diff --git a/Source/Core/DolphinWX/Src/ISOFile.h b/Source/Core/DolphinWX/Src/ISOFile.h
index e58dcf7713..354a2f7fad 100644
--- a/Source/Core/DolphinWX/Src/ISOFile.h
+++ b/Source/Core/DolphinWX/Src/ISOFile.h
@@ -18,6 +18,9 @@
#ifndef __ISOFILE_H_
#define __ISOFILE_H_
+#include <vector>
+#include <string>
+
#include "Volume.h"
#include "VolumeCreator.h"
@@ -34,11 +37,11 @@ public:
bool IsValid() const {return m_Valid;}
const std::string& GetFileName() const {return m_FileName;}
- const std::string& GetName(int index) const;
- bool GetName(std::wstring& wName, int index=0) const;
- const std::string& GetCompany() const {return m_Company;}
- const std::string& GetDescription(int index) const;
- const std::wstring& GetDescription() const;
+ std::string GetBannerName(int index) const;
+ std::string GetVolumeName(int index) const;
+ std::string GetName(int index) const;
+ std::string GetCompany() const;
+ std::string GetDescription(int index = 0) const;
const std::string& GetUniqueID() const {return m_UniqueID;}
const std::string GetWiiFSPath() const;
DiscIO::IVolume::ECountry GetCountry() const {return m_Country;}
@@ -65,11 +68,15 @@ public:
private:
std::string m_FileName;
- std::string m_Name[6];
- std::vector<std::wstring> m_wNames;
- std::string m_Company;
- std::string m_Description[6];
- std::wstring m_wDescription;
+
+ // TODO: eliminate this and overwrite with names from banner when available?
+ std::vector<std::string> m_volume_names;
+
+ // Stuff from banner
+ std::string m_company;
+ std::vector<std::string> m_names;
+ std::vector<std::string> m_descriptions;
+
std::string m_UniqueID;
std::string m_issues;
diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp
index c44aad5d5b..f765a7a8e0 100644
--- a/Source/Core/DolphinWX/Src/ISOProperties.cpp
+++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp
@@ -23,6 +23,7 @@
#include "CommonPaths.h"
#include "Globals.h"
+#include "WxUtils.h"
#include "VolumeCreator.h"
#include "Filesystem.h"
#include "ISOProperties.h"
@@ -136,7 +137,8 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW
else
{
// Will fail out if GameConfig folder doesn't exist
- std::ofstream f(GameIniFile.c_str());
+ std::ofstream f;
+ OpenFStream(f, GameIniFile, std::ios_base::out);
if (f)
{
f << "# " << OpenISO->GetUniqueID() << " - " << OpenISO->GetName() << '\n'
@@ -150,21 +152,14 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW
LoadGameConfig();
else
wxMessageBox(wxString::Format(_("Could not create %s"),
- wxString::From8BitData(GameIniFile.c_str()).c_str()),
+ StrToWxStr(GameIniFile).c_str()),
_("Error"), wxOK|wxICON_ERROR, this);
}
// Disk header and apploader
- std::wstring wname;
- wxString name;
- if (OpenGameListItem->GetName(wname))
- name = wname.c_str();
- else
- name = wxString(OpenISO->GetName().c_str(), wxConvUTF8);
- m_Name->SetValue(name);
-
- m_GameID->SetValue(wxString(OpenISO->GetUniqueID().c_str(), wxConvUTF8));
+ m_Name->SetValue(StrToWxStr(OpenISO->GetName()));
+ m_GameID->SetValue(StrToWxStr(OpenISO->GetUniqueID()));
switch (OpenISO->GetCountry())
{
case DiscIO::IVolume::COUNTRY_EUROPE:
@@ -204,9 +199,9 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW
m_Country->SetValue(_("UNKNOWN"));
break;
}
- wxString temp = _T("0x") + wxString::From8BitData(OpenISO->GetMakerID().c_str());
+ wxString temp = _T("0x") + StrToWxStr(OpenISO->GetMakerID());
m_MakerID->SetValue(temp);
- m_Date->SetValue(wxString::From8BitData(OpenISO->GetApploaderDate().c_str()));
+ m_Date->SetValue(StrToWxStr(OpenISO->GetApploaderDate()));
m_FST->SetValue(wxString::Format(wxT("%u"), OpenISO->GetFSTSize()));
// Here we set all the info to be shown (be it SJIS or Ascii) + we set the window title
@@ -271,12 +266,12 @@ size_t CISOProperties::CreateDirectoryTree(wxTreeItemId& parent,
// check next index
if (rFileInfo->IsDirectory())
{
- wxTreeItemId item = m_Treectrl->AppendItem(parent, wxString::From8BitData(itemName), 1, 1);
+ wxTreeItemId item = m_Treectrl->AppendItem(parent, StrToWxStr(itemName), 1, 1);
CurrentIndex = CreateDirectoryTree(item, fileInfos, CurrentIndex + 1, (size_t)rFileInfo->m_FileSize);
}
else
{
- m_Treectrl->AppendItem(parent, wxString::From8BitData(itemName), 2, 2);
+ m_Treectrl->AppendItem(parent, StrToWxStr(itemName), 2, 2);
CurrentIndex++;
}
}
@@ -321,6 +316,8 @@ void CISOProperties::CreateGUIControls(bool IsWad)
DCBZOFF->SetToolTip(_("Bypass the clearing of the data cache by the DCBZ instruction. Usually leave this option disabled."));
VBeam = new wxCheckBox(m_GameConfig, ID_VBEAM, _("Accurate VBeam emulation"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
VBeam->SetToolTip(_("If the FPS is erratic, this option may help. (ON = Compatible, OFF = Fast)"));
+ SyncGPU = new wxCheckBox(m_GameConfig, ID_SYNCGPU, _("Synchronise GPU thread"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
+ SyncGPU->SetToolTip(_("Synchonises the GPU and CPU threads to help prevent random freezes in Dual Core mode. (ON = Compatible, OFF = Fast)"));
FastDiscSpeed = new wxCheckBox(m_GameConfig, ID_DISCSPEED, _("Speed up Disc Transfer Rate"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
FastDiscSpeed->SetToolTip(_("Enable fast disc access. Needed for a few games. (ON = Fast, OFF = Compatible)"));
BlockMerging = new wxCheckBox(m_GameConfig, ID_MERGEBLOCKS, _("Enable Block Merging"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
@@ -362,9 +359,10 @@ void CISOProperties::CreateGUIControls(bool IsWad)
sbCoreOverrides->Add(CPUThread, 0, wxLEFT, 5);
sbCoreOverrides->Add(SkipIdle, 0, wxLEFT, 5);
sbCoreOverrides->Add(MMU, 0, wxLEFT, 5);
- sbCoreOverrides->Add(DCBZOFF, 0, wxLEFT, 5);
sbCoreOverrides->Add(TLBHack, 0, wxLEFT, 5);
+ sbCoreOverrides->Add(DCBZOFF, 0, wxLEFT, 5);
sbCoreOverrides->Add(VBeam, 0, wxLEFT, 5);
+ sbCoreOverrides->Add(SyncGPU, 0, wxLEFT, 5);
sbCoreOverrides->Add(FastDiscSpeed, 0, wxLEFT, 5);
sbCoreOverrides->Add(BlockMerging, 0, wxLEFT, 5);
sbCoreOverrides->Add(DSPHLE, 0, wxLEFT, 5);
@@ -661,12 +659,12 @@ void CISOProperties::OnExtractFile(wxCommandEvent& WXUNUSED (event))
if (DiscIO::IsVolumeWiiDisc(OpenISO))
{
- int partitionNum = wxAtoi(File.SubString(10, 11));
- File.Remove(0, 12); // Remove "Partition x/"
- WiiDisc.at(partitionNum).FileSystem->ExportFile(File.mb_str(), Path.mb_str());
+ int partitionNum = wxAtoi(File.Mid(File.find_first_of("/"), 1));
+ File.Remove(0, File.find_first_of("/") +1); // Remove "Partition x/"
+ WiiDisc.at(partitionNum).FileSystem->ExportFile(WxStrToStr(File).c_str(), WxStrToStr(Path).c_str());
}
else
- pFileSystem->ExportFile(File.mb_str(), Path.mb_str());
+ pFileSystem->ExportFile(WxStrToStr(File).c_str(), WxStrToStr(Path).c_str());
}
void CISOProperties::ExportDir(const char* _rFullPath, const char* _rExportFolder, const int partitionNum)
@@ -727,7 +725,7 @@ void CISOProperties::ExportDir(const char* _rFullPath, const char* _rExportFolde
(u32)(((float)(i - index[0]) / (float)(index[1] - index[0])) * 100)));
dialog.Update(i, wxString::Format(_("Extracting %s"),
- wxString(fst[i]->m_FullPath, *wxConvCurrent).c_str()));
+ StrToWxStr(fst[i]->m_FullPath)));
if (dialog.WasCancelled())
break;
@@ -778,9 +776,9 @@ void CISOProperties::OnExtractDir(wxCommandEvent& event)
{
if (DiscIO::IsVolumeWiiDisc(OpenISO))
for (u32 i = 0; i < WiiDisc.size(); i++)
- ExportDir(NULL, Path.mb_str(), i);
+ ExportDir(NULL, WxStrToStr(Path).c_str(), i);
else
- ExportDir(NULL, Path.mb_str());
+ ExportDir(NULL, WxStrToStr(Path).c_str());
return;
}
@@ -796,12 +794,12 @@ void CISOProperties::OnExtractDir(wxCommandEvent& event)
if (DiscIO::IsVolumeWiiDisc(OpenISO))
{
- int partitionNum = wxAtoi(Directory.SubString(10, 11));
- Directory.Remove(0, 12); // Remove "Partition x/"
- ExportDir(Directory.mb_str(), Path.mb_str(), partitionNum);
+ int partitionNum = wxAtoi(Directory.Mid(Directory.find_first_of("/"), 1));
+ Directory.Remove(0, Directory.find_first_of("/") +1); // Remove "Partition x/"
+ ExportDir(WxStrToStr(Directory).c_str(), WxStrToStr(Path).c_str(), partitionNum);
}
else
- ExportDir(Directory.mb_str(), Path.mb_str());
+ ExportDir(WxStrToStr(Directory).c_str(), WxStrToStr(Path).c_str());
}
void CISOProperties::OnExtractDataFromHeader(wxCommandEvent& event)
@@ -821,15 +819,15 @@ void CISOProperties::OnExtractDataFromHeader(wxCommandEvent& event)
bool ret = false;
if (event.GetId() == IDM_EXTRACTAPPLOADER)
{
- ret = FS->ExportApploader(Path.mb_str());
+ ret = FS->ExportApploader(WxStrToStr(Path).c_str());
}
else if (event.GetId() == IDM_EXTRACTDOL)
{
- ret = FS->ExportDOL(Path.mb_str());
+ ret = FS->ExportDOL(WxStrToStr(Path).c_str());
}
if (!ret)
- PanicAlertT("Failed to extract to %s!", (const char *)Path.mb_str());
+ PanicAlertT("Failed to extract to %s!", WxStrToStr(Path).c_str());
}
class IntegrityCheckThread : public wxThread
@@ -862,7 +860,7 @@ void CISOProperties::CheckPartitionIntegrity(wxCommandEvent& event)
return;
// Get the partition number from the item text ("Partition N")
- int PartitionNum = wxAtoi(PartitionName.SubString(10, 11));
+ int PartitionNum = wxAtoi(PartitionName.Mid(PartitionName.find_first_of("0123456789"), 1));
const WiiPartition& Partition = WiiDisc[PartitionNum];
wxProgressDialog* dialog = new wxProgressDialog(
@@ -941,6 +939,11 @@ void CISOProperties::LoadGameConfig()
else
VBeam->Set3StateValue(wxCHK_UNDETERMINED);
+ if (GameIni.Get("Core", "SyncGPU", &bTemp))
+ SyncGPU->Set3StateValue((wxCheckBoxState)bTemp);
+ else
+ SyncGPU->Set3StateValue(wxCHK_UNDETERMINED);
+
if (GameIni.Get("Core", "FastDiscSpeed", &bTemp))
FastDiscSpeed->Set3StateValue((wxCheckBoxState)bTemp);
else
@@ -989,7 +992,7 @@ void CISOProperties::LoadGameConfig()
GameIni.Get("EmuState", "EmulationIssues", &sTemp);
if (!sTemp.empty())
{
- EmuIssues->SetValue(wxString(sTemp.c_str(), *wxConvCurrent));
+ EmuIssues->SetValue(StrToWxStr(sTemp));
}
EmuIssues->Enable(EmuState->GetSelection() != 0);
@@ -1030,6 +1033,11 @@ bool CISOProperties::SaveGameConfig()
else
GameIni.Set("Core", "VBeam", VBeam->Get3StateValue());
+ if (SyncGPU->Get3StateValue() == wxCHK_UNDETERMINED)
+ GameIni.DeleteKey("Core", "SyncGPU");
+ else
+ GameIni.Set("Core", "SyncGPU", SyncGPU->Get3StateValue());
+
if (FastDiscSpeed->Get3StateValue() == wxCHK_UNDETERMINED)
GameIni.DeleteKey("Core", "FastDiscSpeed");
else
@@ -1075,7 +1083,7 @@ bool CISOProperties::SaveGameConfig()
GameIni.Get("EmuState","EmulationIssues", &sTemp);
if (EmuIssues->GetValue() != sTemp)
bRefreshList = true;
- GameIni.Set("EmuState", "EmulationIssues", (const char*)EmuIssues->GetValue().mb_str(*wxConvCurrent));
+ GameIni.Set("EmuState", "EmulationIssues", WxStrToStr(EmuIssues->GetValue()));
PatchList_Save();
ActionReplayList_Save();
@@ -1086,7 +1094,7 @@ bool CISOProperties::SaveGameConfig()
void CISOProperties::OnEditConfig(wxCommandEvent& WXUNUSED (event))
{
- if (wxFileExists(wxString::From8BitData(GameIniFile.c_str())))
+ if (File::Exists(GameIniFile))
{
SaveGameConfig();
@@ -1107,7 +1115,7 @@ void CISOProperties::OnEditConfig(wxCommandEvent& WXUNUSED (event))
}
}
wxString OpenCommand;
- OpenCommand = filetype->GetOpenCommand(wxString::From8BitData(GameIniFile.c_str()));
+ OpenCommand = filetype->GetOpenCommand(StrToWxStr(GameIniFile));
if(OpenCommand.IsEmpty())
PanicAlertT("Couldn't find open command for extension 'ini'!");
else
@@ -1156,7 +1164,7 @@ void CISOProperties::PatchList_Load()
for (std::vector<PatchEngine::Patch>::const_iterator it = onFrame.begin(); it != onFrame.end(); ++it)
{
PatchEngine::Patch p = *it;
- Patches->Append(wxString(p.name.c_str(), *wxConvCurrent));
+ Patches->Append(StrToWxStr(p.name));
Patches->Check(index, p.active);
++index;
}
@@ -1209,7 +1217,7 @@ void CISOProperties::PatchButtonClicked(wxCommandEvent& event)
CPatchAddEdit dlg(-1, this, 1, _("Add Patch"));
if (dlg.ShowModal() == wxID_OK)
{
- Patches->Append(wxString(onFrame.back().name.c_str(), *wxConvCurrent));
+ Patches->Append(StrToWxStr(onFrame.back().name));
Patches->Check((unsigned int)(onFrame.size() - 1), onFrame.back().active);
}
}
@@ -1238,7 +1246,7 @@ void CISOProperties::ActionReplayList_Load()
for (std::vector<ActionReplay::ARCode>::const_iterator it = arCodes.begin(); it != arCodes.end(); ++it)
{
ActionReplay::ARCode arCode = *it;
- Cheats->Append(wxString(arCode.name.c_str(), *wxConvCurrent));
+ Cheats->Append(StrToWxStr(arCode.name));
Cheats->Check(index, arCode.active);
++index;
}
@@ -1256,7 +1264,7 @@ void CISOProperties::ActionReplayList_Save()
for (std::vector<ActionReplay::AREntry>::const_iterator iter2 = code.ops.begin(); iter2 != code.ops.end(); ++iter2)
{
- lines.push_back(std::string(wxString::Format(wxT("%08X %08X"), iter2->cmd_addr, iter2->value).mb_str()));
+ lines.push_back(WxStrToStr(wxString::Format(wxT("%08X %08X"), iter2->cmd_addr, iter2->value)));
}
++index;
}
@@ -1280,7 +1288,7 @@ void CISOProperties::ActionReplayButtonClicked(wxCommandEvent& event)
CARCodeAddEdit dlg(-1, this, 1, _("Add ActionReplay Code"));
if (dlg.ShowModal() == wxID_OK)
{
- Cheats->Append(wxString::From8BitData(arCodes.back().name.c_str()));
+ Cheats->Append(StrToWxStr(arCodes.back().name));
Cheats->Check((unsigned int)(arCodes.size() - 1), arCodes.back().active);
}
}
@@ -1306,56 +1314,26 @@ void CISOProperties::OnChangeBannerLang(wxCommandEvent& event)
void CISOProperties::ChangeBannerDetails(int lang)
{
- std::wstring wname;
- wxString shortName,
- comment,
- maker;
-
-#ifdef _WIN32
- wxCSConv SJISConv(*(wxCSConv*)wxConvCurrent);
- static bool validCP932 = ::IsValidCodePage(932) != 0;
- if (validCP932)
- {
- SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS));
- }
- else
- {
- WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932");
- }
-#else
- // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)
- // it returns CP-932, in order to use iconv we need to use CP932
- wxCSConv SJISConv(wxT("CP932"));
-#endif
+ // why?
switch (OpenGameListItem->GetCountry())
{
case DiscIO::IVolume::COUNTRY_TAIWAN:
case DiscIO::IVolume::COUNTRY_JAPAN:
-
- if (OpenGameListItem->GetName(wname, -1))
- shortName = wname.c_str();
- else
- shortName = wxString(OpenGameListItem->GetName(0).c_str(), SJISConv);
-
- if ((comment = OpenGameListItem->GetDescription().c_str()).size() == 0)
- comment = wxString(OpenGameListItem->GetDescription(0).c_str(), SJISConv);
- maker = wxString(OpenGameListItem->GetCompany().c_str(), SJISConv);
+ lang = -1;
break;
+
case DiscIO::IVolume::COUNTRY_USA:
lang = 0;
+ break;
+
default:
- {
- wxCSConv WindowsCP1252(wxFontMapper::GetEncodingName(wxFONTENCODING_CP1252));
- if (OpenGameListItem->GetName(wname, lang))
- shortName = wname.c_str();
- else
- shortName = wxString(OpenGameListItem->GetName(lang).c_str(), WindowsCP1252);
- if ((comment = OpenGameListItem->GetDescription().c_str()).size() == 0)
- comment = wxString(OpenGameListItem->GetDescription(lang).c_str(), WindowsCP1252);
- maker = wxString(OpenGameListItem->GetCompany().c_str(), WindowsCP1252);
- }
break;
}
+
+ wxString const shortName = StrToWxStr(OpenGameListItem->GetBannerName(lang));
+ wxString const comment = StrToWxStr(OpenGameListItem->GetDescription(lang));
+ wxString const maker = StrToWxStr(OpenGameListItem->GetCompany());
+
// Updates the informations shown in the window
m_ShortName->SetValue(shortName);
m_Comment->SetValue(comment);
@@ -1364,5 +1342,6 @@ void CISOProperties::ChangeBannerDetails(int lang)
std::string filename, extension;
SplitPath(OpenGameListItem->GetFileName(), 0, &filename, &extension);
// Also sets the window's title
- SetTitle(wxString(StringFromFormat("%s%s: %s - ", filename.c_str(), extension.c_str(), OpenGameListItem->GetUniqueID().c_str()).c_str(), *wxConvCurrent)+shortName);
+ SetTitle(StrToWxStr(StringFromFormat("%s%s: %s - ", filename.c_str(),
+ extension.c_str(), OpenGameListItem->GetUniqueID().c_str())) + shortName);
}
diff --git a/Source/Core/DolphinWX/Src/ISOProperties.h b/Source/Core/DolphinWX/Src/ISOProperties.h
index 499b242516..41e7d250a0 100644
--- a/Source/Core/DolphinWX/Src/ISOProperties.h
+++ b/Source/Core/DolphinWX/Src/ISOProperties.h
@@ -70,7 +70,7 @@ private:
// Core
wxCheckBox *CPUThread, *SkipIdle, *MMU, *DCBZOFF, *TLBHack;
- wxCheckBox *VBeam, *FastDiscSpeed, *BlockMerging, *DSPHLE;
+ wxCheckBox *VBeam, *SyncGPU, *FastDiscSpeed, *BlockMerging, *DSPHLE;
// Wii
wxCheckBox *EnableWideScreen;
// Video
@@ -130,6 +130,7 @@ private:
ID_DCBZOFF,
ID_TLBHACK,
ID_VBEAM,
+ ID_SYNCGPU,
ID_DISCSPEED,
ID_MERGEBLOCKS,
ID_AUDIO_DSP_HLE,
diff --git a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp
index 1efcf98af6..14772d8676 100644
--- a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp
+++ b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp
@@ -17,10 +17,7 @@
#include "InputConfigDiag.h"
#include "UDPConfigDiag.h"
-
-#define WXSTR_FROM_STR(s) (wxString::FromUTF8((s).c_str()))
-#define WXTSTR_FROM_CSTR(s) (wxGetTranslation(wxString::FromUTF8(s)))
-#define STR_FROM_WXSTR(w) (std::string((w).ToUTF8()))
+#include "WxUtils.h"
void GamepadPage::ConfigUDPWii(wxCommandEvent &event)
{
@@ -37,7 +34,7 @@ void GamepadPage::ConfigExtension(wxCommandEvent& event)
if (ex->switch_extension)
{
wxDialog dlg(this, -1,
- WXTSTR_FROM_CSTR(ex->attachments[ex->switch_extension]->GetName().c_str()),
+ StrToWxStr(ex->attachments[ex->switch_extension]->GetName()),
wxDefaultPosition, wxDefaultSize);
wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL);
@@ -67,7 +64,7 @@ PadSettingExtension::PadSettingExtension(wxWindow* const parent, ControllerEmu::
e = extension->attachments.end();
for (; i!=e; ++i)
- ((wxChoice*)wxcontrol)->Append(WXTSTR_FROM_CSTR((*i)->GetName().c_str()));
+ ((wxChoice*)wxcontrol)->Append(StrToWxStr((*i)->GetName()));
UpdateGUI();
}
@@ -83,7 +80,7 @@ void PadSettingExtension::UpdateValue()
}
PadSettingCheckBox::PadSettingCheckBox(wxWindow* const parent, ControlState& _value, const char* const label)
- : PadSetting(new wxCheckBox(parent, -1, WXTSTR_FROM_CSTR(label), wxDefaultPosition))
+ : PadSetting(new wxCheckBox(parent, -1, StrToWxStr(label), wxDefaultPosition))
, value(_value)
{
UpdateGUI();
@@ -119,8 +116,8 @@ ControlDialog::ControlDialog(GamepadPage* const parent, InputPlugin& plugin, Con
m_devq = m_parent->controller->default_device;
// GetStrings() sounds slow :/
- //device_cbox = new wxComboBox(this, -1, WXSTR_FROM_STR(ref->device_qualifier.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER);
- device_cbox = new wxComboBox(this, -1, WXSTR_FROM_STR(m_devq.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER);
+ //device_cbox = new wxComboBox(this, -1, StrToWxStr(ref->device_qualifier.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER);
+ device_cbox = new wxComboBox(this, -1, StrToWxStr(m_devq.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER);
device_cbox->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &ControlDialog::SetDevice, this);
device_cbox->Bind(wxEVT_COMMAND_TEXT_ENTER, &ControlDialog::SetDevice, this);
@@ -145,9 +142,9 @@ ControlButton::ControlButton(wxWindow* const parent, ControllerInterface::Contro
, control_reference(_ref)
{
if (label.empty())
- SetLabel(WXSTR_FROM_STR(_ref->expression));
+ SetLabel(StrToWxStr(_ref->expression));
else
- SetLabel(WXSTR_FROM_STR(label));
+ SetLabel(StrToWxStr(label));
}
void InputConfigDialog::UpdateProfileComboBox()
@@ -169,7 +166,7 @@ void InputConfigDialog::UpdateProfileComboBox()
for (; si!=se; ++si)
{
std::string str(si->begin() + si->find_last_of('/') + 1 , si->end() - 4) ;
- strs.push_back(WXSTR_FROM_STR(str));
+ strs.push_back(StrToWxStr(str));
}
std::vector< GamepadPage* >::iterator i = m_padpages.begin(),
@@ -209,7 +206,7 @@ void ControlDialog::UpdateListContents()
i = dev->Inputs().begin(),
e = dev->Inputs().end();
for (; i!=e; ++i)
- control_lbox->Append(WXSTR_FROM_STR((*i)->GetName()));
+ control_lbox->Append(StrToWxStr((*i)->GetName()));
}
else
{
@@ -218,7 +215,7 @@ void ControlDialog::UpdateListContents()
i = dev->Outputs().begin(),
e = dev->Outputs().end();
for (; i!=e; ++i)
- control_lbox->Append(WXSTR_FROM_STR((*i)->GetName()));
+ control_lbox->Append(StrToWxStr((*i)->GetName()));
}
}
}
@@ -227,7 +224,7 @@ void ControlDialog::SelectControl(const std::string& name)
{
//UpdateGUI();
- const int f = control_lbox->FindString(WXSTR_FROM_STR(name));
+ const int f = control_lbox->FindString(StrToWxStr(name));
if (f >= 0)
control_lbox->Select(f);
}
@@ -235,7 +232,7 @@ void ControlDialog::SelectControl(const std::string& name)
void ControlDialog::UpdateGUI()
{
// update textbox
- textctrl->SetValue(WXSTR_FROM_STR(control_reference->expression));
+ textctrl->SetValue(StrToWxStr(control_reference->expression));
// updates the "bound controls:" label
m_bound_label->SetLabel(wxString::Format(_("Bound Controls: %lu"),
@@ -244,7 +241,7 @@ void ControlDialog::UpdateGUI()
void GamepadPage::UpdateGUI()
{
- device_cbox->SetValue(WXSTR_FROM_STR(controller->default_device.ToString()));
+ device_cbox->SetValue(StrToWxStr(controller->default_device.ToString()));
std::vector< ControlGroupBox* >::const_iterator g = control_groups.begin(),
ge = control_groups.end();
@@ -255,7 +252,7 @@ void GamepadPage::UpdateGUI()
, e = (*g)->control_buttons.end();
for (; i!=e; ++i)
//if (std::string::npos == (*i)->control_reference->expression.find_first_of("`|&!#"))
- (*i)->SetLabel(WXSTR_FROM_STR((*i)->control_reference->expression));
+ (*i)->SetLabel(StrToWxStr((*i)->control_reference->expression));
//else
//(*i)->SetLabel(wxT("..."));
@@ -294,7 +291,7 @@ void GamepadPage::LoadDefaults(wxCommandEvent&)
void ControlDialog::SetControl(wxCommandEvent&)
{
- control_reference->expression = STR_FROM_WXSTR(textctrl->GetValue());
+ control_reference->expression = WxStrToStr(textctrl->GetValue());
std::lock_guard<std::recursive_mutex> lk(m_plugin.controls_lock);
g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device);
@@ -304,10 +301,10 @@ void ControlDialog::SetControl(wxCommandEvent&)
void GamepadPage::SetDevice(wxCommandEvent&)
{
- controller->default_device.FromString(STR_FROM_WXSTR(device_cbox->GetValue()));
+ controller->default_device.FromString(WxStrToStr(device_cbox->GetValue()));
// show user what it was validated as
- device_cbox->SetValue(WXSTR_FROM_STR(controller->default_device.ToString()));
+ device_cbox->SetValue(StrToWxStr(controller->default_device.ToString()));
// this will set all the controls to this default device
controller->UpdateDefaultDevice();
@@ -319,10 +316,10 @@ void GamepadPage::SetDevice(wxCommandEvent&)
void ControlDialog::SetDevice(wxCommandEvent&)
{
- m_devq.FromString(STR_FROM_WXSTR(device_cbox->GetValue()));
+ m_devq.FromString(WxStrToStr(device_cbox->GetValue()));
// show user what it was validated as
- device_cbox->SetValue(WXSTR_FROM_STR(m_devq.ToString()));
+ device_cbox->SetValue(StrToWxStr(m_devq.ToString()));
// update gui
UpdateListContents();
@@ -349,12 +346,12 @@ void ControlDialog::SetSelectedControl(wxCommandEvent&)
// non-default device
if (false == (m_devq == m_parent->controller->default_device))
- expr.append(wxT('`')).append(WXSTR_FROM_STR(m_devq.ToString())).append(wxT('`'));
+ expr.append(wxT('`')).append(StrToWxStr(m_devq.ToString())).append(wxT('`'));
// append the control name
expr += control_lbox->GetString(num);
- control_reference->expression = STR_FROM_WXSTR(expr);
+ control_reference->expression = WxStrToStr(expr);
std::lock_guard<std::recursive_mutex> lk(m_plugin.controls_lock);
g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device);
@@ -380,12 +377,12 @@ void ControlDialog::AppendControl(wxCommandEvent& event)
// non-default device
if (false == (m_devq == m_parent->controller->default_device))
- expr.append(wxT('`')).append(WXSTR_FROM_STR(m_devq.ToString())).append(wxT('`'));
+ expr.append(wxT('`')).append(StrToWxStr(m_devq.ToString())).append(wxT('`'));
// append the control name
expr += control_lbox->GetString(num);
- control_reference->expression = STR_FROM_WXSTR(expr);
+ control_reference->expression = WxStrToStr(expr);
std::lock_guard<std::recursive_mutex> lk(m_plugin.controls_lock);
g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device);
@@ -475,7 +472,7 @@ void GamepadPage::DetectControl(wxCommandEvent& event)
g_controller_interface.UpdateReference(btn->control_reference, controller->default_device);
}
- btn->SetLabel(WXSTR_FROM_STR(btn->control_reference->expression));
+ btn->SetLabel(StrToWxStr(btn->control_reference->expression));
}
}
@@ -565,7 +562,7 @@ void GamepadPage::GetProfilePath(std::string& path)
path += PROFILES_PATH;
path += m_plugin.profile_name;
path += '/';
- path += STR_FROM_WXSTR(profile_cbox->GetValue());
+ path += WxStrToStr(profile_cbox->GetValue());
path += ".ini";
}
}
@@ -615,7 +612,7 @@ void GamepadPage::DeleteProfile(wxCommandEvent&)
if (File::Exists(fnamecstr) &&
AskYesNoT("Are you sure you want to delete \"%s\"?",
- STR_FROM_WXSTR(profile_cbox->GetValue()).c_str()))
+ WxStrToStr(profile_cbox->GetValue()).c_str()))
{
File::Delete(fnamecstr);
@@ -637,9 +634,9 @@ void InputConfigDialog::UpdateDeviceComboBox()
for (; di!=de; ++di)
{
dq.FromDevice(*di);
- (*i)->device_cbox->Append(WXSTR_FROM_STR(dq.ToString()));
+ (*i)->device_cbox->Append(StrToWxStr(dq.ToString()));
}
- (*i)->device_cbox->SetValue(WXSTR_FROM_STR((*i)->controller->default_device.ToString()));
+ (*i)->device_cbox->SetValue(StrToWxStr((*i)->controller->default_device.ToString()));
}
}
@@ -680,7 +677,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
for (; ci != ce; ++ci)
{
- wxStaticText* const label = new wxStaticText(parent, -1, WXTSTR_FROM_CSTR((*ci)->name));
+ wxStaticText* const label = new wxStaticText(parent, -1, StrToWxStr((*ci)->name));
ControlButton* const control_button = new ControlButton(parent, (*ci)->control_ref, 80);
control_button->SetFont(m_SmallFont);
@@ -734,7 +731,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
PadSettingSpin* setting = new PadSettingSpin(parent, *i);
setting->wxcontrol->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &GamepadPage::AdjustSetting, eventsink);
options.push_back(setting);
- szr->Add(new wxStaticText(parent, -1, WXTSTR_FROM_CSTR((*i)->name)));
+ szr->Add(new wxStaticText(parent, -1, StrToWxStr((*i)->name)));
szr->Add(setting->wxcontrol, 0, wxLEFT, 0);
}
@@ -760,7 +757,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
options.push_back(threshold_cbox);
wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL);
- szr->Add(new wxStaticText(parent, -1, WXTSTR_FROM_CSTR(group->settings[0]->name)),
+ szr->Add(new wxStaticText(parent, -1, StrToWxStr(group->settings[0]->name)),
0, wxCENTER|wxRIGHT, 3);
szr->Add(threshold_cbox->wxcontrol, 0, wxRIGHT, 3);
@@ -795,7 +792,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
setting->wxcontrol->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &GamepadPage::AdjustSetting, eventsink);
options.push_back(setting);
wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL);
- szr->Add(new wxStaticText(parent, -1, WXTSTR_FROM_CSTR((*i)->name)), 0, wxCENTER|wxRIGHT, 3);
+ szr->Add(new wxStaticText(parent, -1, StrToWxStr((*i)->name)), 0, wxCENTER|wxRIGHT, 3);
szr->Add(setting->wxcontrol, 0, wxRIGHT, 3);
Add(szr, 0, wxALL|wxCENTER, 3);
}
@@ -859,7 +856,7 @@ ControlGroupsSizer::ControlGroupsSizer(ControllerEmu* const controller, wxWindow
{
ControlGroupBox* control_group_box = new ControlGroupBox(controller->groups[i], parent, eventsink);
wxStaticBoxSizer *control_group =
- new wxStaticBoxSizer(wxVERTICAL, parent, WXTSTR_FROM_CSTR(controller->groups[i]->name));
+ new wxStaticBoxSizer(wxVERTICAL, parent, StrToWxStr(controller->groups[i]->name));
control_group->Add(control_group_box);
const size_t grp_size = controller->groups[i]->controls.size() + controller->groups[i]->settings.size();
@@ -955,7 +952,7 @@ GamepadPage::GamepadPage(wxWindow* parent, InputPlugin& plugin, const unsigned i
InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin, const std::string& name, const int tab_num)
- : wxDialog(parent, wxID_ANY, WXTSTR_FROM_CSTR(name.c_str()), wxPoint(128,-1), wxDefaultSize)
+ : wxDialog(parent, wxID_ANY, StrToWxStr(name), wxPoint(128,-1), wxDefaultSize)
, m_plugin(plugin)
{
m_pad_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT);
@@ -963,7 +960,7 @@ InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin
{
GamepadPage* gp = new GamepadPage(m_pad_notebook, m_plugin, i, this);
m_padpages.push_back(gp);
- m_pad_notebook->AddPage(gp, wxString::Format(wxT("%s %u"), WXTSTR_FROM_CSTR(m_plugin.gui_name), 1+i));
+ m_pad_notebook->AddPage(gp, wxString::Format(wxT("%s %u"), StrToWxStr(m_plugin.gui_name), 1+i));
}
m_pad_notebook->SetSelection(tab_num);
diff --git a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp
index ff5ed3b9cd..efb7db59af 100644
--- a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp
+++ b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp
@@ -16,6 +16,7 @@
// http://code.google.com/p/dolphin-emu/
#include "InputConfigDiag.h"
+#include "WxUtils.h"
void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
{
@@ -48,7 +49,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
// label for sticks and stuff
if (64 == bitmap.GetHeight())
- dc.DrawText(wxString::FromAscii((*g)->control_group->name).Upper(), 4, 2);
+ dc.DrawText(StrToWxStr((*g)->control_group->name).Upper(), 4, 2);
switch ( (*g)->control_group->type )
{
@@ -227,7 +228,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
// text
const char* const name = (*g)->control_group->controls[n]->name;
// bit of hax so ZL, ZR show up as L, R
- dc.DrawText(wxString::FromAscii((name[1] && name[1] < 'a') ? name[1] : name[0]), n*12 + 2, 1);
+ dc.DrawText(StrToWxStr(std::string(1, (name[1] && name[1] < 'a') ? name[1] : name[0])), n*12 + 2, 1);
}
delete[] bitmasks;
@@ -263,7 +264,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
dc.DrawRectangle(0, n*12, trigs[n], 14);
// text
- dc.DrawText(wxString::FromAscii((*g)->control_group->controls[n]->name), 3, n*12 + 1);
+ dc.DrawText(StrToWxStr((*g)->control_group->controls[n]->name), 3, n*12 + 1);
}
delete[] trigs;
@@ -298,8 +299,8 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
dc.DrawRectangle(64, n*12, 32, 14);
// text
- dc.DrawText(wxString::FromAscii((*g)->control_group->controls[n+trigger_count]->name), 3, n*12 + 1);
- dc.DrawText(wxString::FromAscii((*g)->control_group->controls[n]->name[0]), 64 + 3, n*12 + 1);
+ dc.DrawText(StrToWxStr((*g)->control_group->controls[n+trigger_count]->name), 3, n*12 + 1);
+ dc.DrawText(StrToWxStr(std::string(1, (*g)->control_group->controls[n]->name[0])), 64 + 3, n*12 + 1);
}
// threshold box
diff --git a/Source/Core/DolphinWX/Src/LogConfigWindow.cpp b/Source/Core/DolphinWX/Src/LogConfigWindow.cpp
index 162647c64d..a4a5fa647a 100644
--- a/Source/Core/DolphinWX/Src/LogConfigWindow.cpp
+++ b/Source/Core/DolphinWX/Src/LogConfigWindow.cpp
@@ -20,6 +20,7 @@
#include "ConsoleListener.h"
#include "LogWindow.h"
#include "FileUtil.h"
+#include "WxUtils.h"
LogConfigWindow::LogConfigWindow(wxWindow* parent, CLogWindow *log_window, wxWindowID id)
: wxPanel(parent, id, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _("Log Configuration"))
@@ -74,7 +75,7 @@ void LogConfigWindow::CreateGUIControls()
m_checks = new wxCheckListBox(this, wxID_ANY);
m_checks->Bind(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, &LogConfigWindow::OnLogCheck, this);
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++)
- m_checks->Append(wxString::FromAscii(m_LogManager->GetFullName((LogTypes::LOG_TYPE)i)));
+ m_checks->Append(StrToWxStr(m_LogManager->GetFullName((LogTypes::LOG_TYPE)i)));
// Sizers
wxStaticBoxSizer* sbOutputs = new wxStaticBoxSizer(wxVERTICAL, this, _("Logger Outputs"));
diff --git a/Source/Core/DolphinWX/Src/LogWindow.cpp b/Source/Core/DolphinWX/Src/LogWindow.cpp
index 4c9c495713..27e5856410 100644
--- a/Source/Core/DolphinWX/Src/LogWindow.cpp
+++ b/Source/Core/DolphinWX/Src/LogWindow.cpp
@@ -21,6 +21,8 @@
#include "IniFile.h"
#include "FileUtil.h"
#include "Debugger/DebuggerUIUtil.h"
+#include "WxUtils.h"
+
#include <wx/fontmap.h>
// Milliseconds between msgQueue flushes to wxTextCtrl
@@ -41,25 +43,7 @@ CLogWindow::CLogWindow(CFrame *parent, wxWindowID id, const wxPoint& pos,
, x(0), y(0), winpos(0)
, Parent(parent), m_ignoreLogTimer(false), m_LogAccess(true)
, m_Log(NULL), m_cmdline(NULL), m_FontChoice(NULL)
- , m_SJISConv(wxT(""))
{
-#ifdef _WIN32
- static bool validCP932 = ::IsValidCodePage(932) != 0;
- if (validCP932)
- {
- m_SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS));
- }
- else
- {
- WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932");
- m_SJISConv = *(wxCSConv*)wxConvCurrent;
- }
-#else
- // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)
- // it returns CP-932, in order to use iconv we need to use CP932
- m_SJISConv = wxCSConv(wxT("CP932"));
-#endif
-
m_LogManager = LogManager::GetInstance();
CreateGUIControls();
@@ -208,7 +192,7 @@ void CLogWindow::SaveSettings()
void CLogWindow::OnSubmit(wxCommandEvent& WXUNUSED (event))
{
if (!m_cmdline) return;
- Console_Submit(m_cmdline->GetValue().To8BitData());
+ Console_Submit(WxStrToStr(m_cmdline->GetValue()).c_str());
m_cmdline->SetValue(wxEmptyString);
}
@@ -247,7 +231,7 @@ wxTextCtrl* CLogWindow::CreateTextCtrl(wxPanel* parent, wxWindowID id, long Styl
#else
TC->SetBackgroundColour(*wxBLACK);
#endif
- if (m_FontChoice && m_FontChoice->GetSelection() < (int)LogFont.size())
+ if (m_FontChoice && m_FontChoice->GetSelection() < (int)LogFont.size() && m_FontChoice->GetSelection() >= 0)
TC->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, LogFont[m_FontChoice->GetSelection()]));
return TC;
@@ -370,5 +354,6 @@ void CLogWindow::Log(LogTypes::LOG_LEVELS level, const char *text)
if (msgQueue.size() >= 100)
msgQueue.pop();
- msgQueue.push(std::pair<u8, wxString>((u8)level, wxString(text, m_SJISConv)));
+
+ msgQueue.push(std::make_pair(u8(level), StrToWxStr(text)));
}
diff --git a/Source/Core/DolphinWX/Src/LogWindow.h b/Source/Core/DolphinWX/Src/LogWindow.h
index 86fd1d3b4f..54a59c4d91 100644
--- a/Source/Core/DolphinWX/Src/LogWindow.h
+++ b/Source/Core/DolphinWX/Src/LogWindow.h
@@ -75,8 +75,6 @@ private:
std::mutex m_LogSection;
- wxCSConv m_SJISConv;
-
DECLARE_EVENT_TABLE()
wxTextCtrl * CreateTextCtrl(wxPanel* parent, wxWindowID id = wxID_ANY, long Style = NULL);
diff --git a/Source/Core/DolphinWX/Src/Main.cpp b/Source/Core/DolphinWX/Src/Main.cpp
index 338ed59547..dace5a1928 100644
--- a/Source/Core/DolphinWX/Src/Main.cpp
+++ b/Source/Core/DolphinWX/Src/Main.cpp
@@ -32,6 +32,7 @@
#include "Host.h" // Core
#include "HW/Wiimote.h"
+#include "WxUtils.h"
#include "Globals.h" // Local
#include "Main.h"
#include "ConfigManager.h"
@@ -47,6 +48,24 @@
#ifdef _WIN32
#include <shellapi.h>
+
+#ifndef SM_XVIRTUALSCREEN
+#define SM_XVIRTUALSCREEN 76
+#endif
+#ifndef SM_YVIRTUALSCREEN
+#define SM_YVIRTUALSCREEN 77
+#endif
+#ifndef SM_CXVIRTUALSCREEN
+#define SM_CXVIRTUALSCREEN 78
+#endif
+#ifndef SM_CYVIRTUALSCREEN
+#define SM_CYVIRTUALSCREEN 79
+#endif
+
+#endif
+
+#ifdef __APPLE__
+#import <AppKit/AppKit.h>
#endif
// Nvidia drivers >= v302 will check if the application exports a global
@@ -162,6 +181,11 @@ bool DolphinApp::OnInit()
wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL
},
{
+ wxCMD_LINE_OPTION, "m", "movie",
+ "Play a movie file",
+ wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL
+ },
+ {
wxCMD_LINE_NONE, NULL, NULL, NULL, wxCMD_LINE_VAL_NONE, 0
}
};
@@ -181,6 +205,7 @@ bool DolphinApp::OnInit()
&videoBackendName);
selectAudioEmulation = parser.Found(wxT("audio_emulation"),
&audioEmulationName);
+ playMovie = parser.Found(wxT("movie"), &movieFile);
#endif // wxUSE_CMDLINE_PARSER
#if defined _DEBUG && defined _WIN32
@@ -201,6 +226,7 @@ bool DolphinApp::OnInit()
wxHandleFatalExceptions(true);
#endif
+#ifndef _M_ARM
// TODO: if First Boot
if (!cpu_info.bSSE2)
{
@@ -209,9 +235,21 @@ bool DolphinApp::OnInit()
"Sayonara!\n");
return false;
}
+#endif
+#ifdef __APPLE__
+ if (floor(NSAppKitVersionNumber) < NSAppKitVersionNumber10_7)
+ {
+ PanicAlertT("Hi,\n\nDolphin requires OS X 10.7 or greater.\n"
+ "Unfortunately you're running an old version of OS X.\n"
+ "The last Dolphin version to support OS X 10.6 is Dolphin 3.5\n"
+ "Please upgrade to 10.7 or greater to use the newest Dolphin version.\n\n"
+ "Sayonara!\n");
+ return false;
+ }
+#endif
#ifdef _WIN32
- if (!wxSetWorkingDirectory(wxString(File::GetExeDirectory().c_str(), *wxConvCurrent)))
+ if (!wxSetWorkingDirectory(StrToWxStr(File::GetExeDirectory())))
{
INFO_LOG(CONSOLE, "set working directory failed");
}
@@ -246,7 +284,7 @@ bool DolphinApp::OnInit()
if (selectVideoBackend && videoBackendName != wxEmptyString)
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoBackend =
- std::string(videoBackendName.mb_str());
+ WxStrToStr(videoBackendName);
if (selectAudioEmulation)
{
@@ -285,10 +323,11 @@ bool DolphinApp::OnInit()
// do not allow windows to be created off the desktop.
#ifdef _WIN32
// Out of desktop check
- HWND hDesktop = GetDesktopWindow();
- RECT rc;
- GetWindowRect(hDesktop, &rc);
- if (rc.right < x + w || rc.bottom < y + h)
+ int leftPos = GetSystemMetrics(SM_XVIRTUALSCREEN);
+ int topPos = GetSystemMetrics(SM_YVIRTUALSCREEN);
+ int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+ if ((leftPos + width) < (x + w) || leftPos > x || (topPos + height) < (y + h) || topPos > y)
x = y = wxDefaultCoord;
#elif defined __APPLE__
if (y < 1)
@@ -296,7 +335,7 @@ bool DolphinApp::OnInit()
#endif
main_frame = new CFrame((wxFrame*)NULL, wxID_ANY,
- wxString::FromAscii(scm_rev_str),
+ StrToWxStr(scm_rev_str),
wxPoint(x, y), wxSize(w, h),
UseDebugger, BatchMode, UseLogger);
SetTopWindow(main_frame);
@@ -317,7 +356,7 @@ void DolphinApp::MacOpenFile(const wxString &fileName)
LoadFile = true;
if (m_afterinit == NULL)
- main_frame->BootGame(std::string(FileToLoad.mb_str()));
+ main_frame->BootGame(WxStrToStr(FileToLoad));
}
void DolphinApp::AfterInit(wxTimerEvent& WXUNUSED(event))
@@ -328,10 +367,23 @@ void DolphinApp::AfterInit(wxTimerEvent& WXUNUSED(event))
if (!BatchMode)
main_frame->UpdateGameList();
+ if (playMovie && movieFile != wxEmptyString)
+ {
+ if (Movie::PlayInput(movieFile.char_str()))
+ {
+ if (LoadFile && FileToLoad != wxEmptyString)
+ {
+ main_frame->BootGame(WxStrToStr(FileToLoad));
+ }
+ else
+ main_frame->BootGame(std::string(""));
+ }
+ }
+
// First check if we have an exec command line.
- if (LoadFile && FileToLoad != wxEmptyString)
+ else if (LoadFile && FileToLoad != wxEmptyString)
{
- main_frame->BootGame(std::string(FileToLoad.mb_str()));
+ main_frame->BootGame(WxStrToStr(FileToLoad));
}
// If we have selected Automatic Start, start the default ISO,
// or if no default ISO exists, start the last loaded ISO
@@ -339,17 +391,7 @@ void DolphinApp::AfterInit(wxTimerEvent& WXUNUSED(event))
{
if (main_frame->g_pCodeWindow->AutomaticStart())
{
- if(!SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM.empty()
- && File::Exists(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM))
- {
- main_frame->BootGame(SConfig::GetInstance().m_LocalCoreStartupParameter.
- m_strDefaultGCM);
- }
- else if(!SConfig::GetInstance().m_LastFilename.empty()
- && File::Exists(SConfig::GetInstance().m_LastFilename))
- {
- main_frame->BootGame(SConfig::GetInstance().m_LastFilename);
- }
+ main_frame->BootGame("");
}
}
}
@@ -390,10 +432,6 @@ void DolphinApp::InitLanguageSupport()
int DolphinApp::OnExit()
{
WiimoteReal::Shutdown();
-#ifdef _WIN32
- if (SConfig::GetInstance().m_WiiAutoUnpair)
- WiimoteReal::UnPair();
-#endif
VideoBackend::ClearList();
SConfig::Shutdown();
LogManager::Shutdown();
@@ -422,7 +460,7 @@ void Host_SysMessage(const char *fmt, ...)
va_end(list);
if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0;
- //wxMessageBox(wxString::FromAscii(msg));
+ //wxMessageBox(StrToWxStr(msg));
PanicAlert("%s", msg);
}
@@ -431,14 +469,13 @@ bool wxMsgAlert(const char* caption, const char* text, bool yes_no, int /*Style*
#ifdef __WXGTK__
if (wxIsMainThread())
#endif
- return wxYES == wxMessageBox(wxString::FromUTF8(text),
- wxString::FromUTF8(caption),
+ return wxYES == wxMessageBox(StrToWxStr(text), StrToWxStr(caption),
(yes_no) ? wxYES_NO : wxOK, wxGetActiveWindow());
#ifdef __WXGTK__
else
{
wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_PANIC);
- event.SetString(wxString::FromUTF8(caption) + wxT(":") + wxString::FromUTF8(text));
+ event.SetString(StrToWxStr(caption) + wxT(":") + StrToWxStr(text));
event.SetInt(yes_no);
main_frame->GetEventHandler()->AddPendingEvent(event);
main_frame->panic_event.Wait();
@@ -449,7 +486,7 @@ bool wxMsgAlert(const char* caption, const char* text, bool yes_no, int /*Style*
std::string wxStringTranslator(const char *text)
{
- return (const char *)wxString(wxGetTranslation(wxString::From8BitData(text))).ToUTF8();
+ return WxStrToStr(wxGetTranslation(wxString::FromUTF8(text)));
}
// Accessor for the main window class
@@ -540,7 +577,7 @@ void Host_UpdateMainFrame()
void Host_UpdateTitle(const char* title)
{
wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_UPDATETITLE);
- event.SetString(wxString::FromAscii(title));
+ event.SetString(StrToWxStr(title));
main_frame->GetEventHandler()->AddPendingEvent(event);
}
@@ -607,7 +644,7 @@ void Host_UpdateStatusBar(const char* _pText, int Field)
{
wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_UPDATESTATUSBAR);
// Set the event string
- event.SetString(wxString::FromAscii(_pText));
+ event.SetString(StrToWxStr(_pText));
// Update statusbar field
event.SetInt(Field);
// Post message
diff --git a/Source/Core/DolphinWX/Src/Main.h b/Source/Core/DolphinWX/Src/Main.h
index 0fb99fcfd4..d043a6c24e 100644
--- a/Source/Core/DolphinWX/Src/Main.h
+++ b/Source/Core/DolphinWX/Src/Main.h
@@ -40,7 +40,9 @@ private:
wxTimer *m_afterinit;
bool BatchMode;
bool LoadFile;
+ bool playMovie;
wxString FileToLoad;
+ wxString movieFile;
wxLocale *m_locale;
void AfterInit(wxTimerEvent& WXUNUSED(event));
diff --git a/Source/Core/DolphinWX/Src/MainAndroid.cpp b/Source/Core/DolphinWX/Src/MainAndroid.cpp
new file mode 100644
index 0000000000..ca2119921d
--- /dev/null
+++ b/Source/Core/DolphinWX/Src/MainAndroid.cpp
@@ -0,0 +1,149 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "Common.h"
+#include "FileUtil.h"
+
+#include "Core.h"
+#include "Host.h"
+#include "CPUDetect.h"
+#include "Thread.h"
+
+#include "PowerPC/PowerPC.h"
+#include "HW/Wiimote.h"
+
+#include "VideoBackendBase.h"
+#include "ConfigManager.h"
+#include "LogManager.h"
+#include "BootManager.h"
+
+#include <jni.h>
+#include <android/log.h>
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "Dolphinemu", __VA_ARGS__))
+
+bool rendererHasFocus = true;
+bool running = true;
+
+void Host_NotifyMapLoaded() {}
+void Host_RefreshDSPDebuggerWindow() {}
+
+void Host_ShowJitResults(unsigned int address){}
+
+Common::Event updateMainFrameEvent;
+void Host_Message(int Id)
+{
+}
+
+void* Host_GetRenderHandle()
+{
+ return NULL;
+}
+
+void* Host_GetInstance() { return NULL; }
+
+void Host_UpdateTitle(const char* title){};
+
+void Host_UpdateLogDisplay(){}
+
+void Host_UpdateDisasmDialog(){}
+
+void Host_UpdateMainFrame()
+{
+}
+
+void Host_UpdateBreakPointView(){}
+
+bool Host_GetKeyState(int keycode)
+{
+ return false;
+}
+
+void Host_GetRenderWindowSize(int& x, int& y, int& width, int& height)
+{
+ x = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowXPos;
+ y = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowYPos;
+ width = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowWidth;
+ height = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowHeight;
+}
+
+void Host_RequestRenderWindowSize(int width, int height) {}
+void Host_SetStartupDebuggingParameters()
+{
+}
+
+bool Host_RendererHasFocus()
+{
+ return true;
+}
+
+void Host_ConnectWiimote(int wm_idx, bool connect) {}
+
+void Host_SetWaitCursor(bool enable){}
+
+void Host_UpdateStatusBar(const char* _pText, int Filed){}
+
+void Host_SysMessage(const char *fmt, ...)
+{
+ va_list list;
+ char msg[512];
+
+ va_start(list, fmt);
+ vsprintf(msg, fmt, list);
+ va_end(list);
+
+ size_t len = strlen(msg);
+ if (msg[len - 1] != '\n') {
+ msg[len - 1] = '\n';
+ msg[len] = '\0';
+ }
+ LOGI(msg);
+}
+
+void Host_SetWiiMoteConnectionState(int _State) {}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_dolphinemuactivity_main(JNIEnv *env, jobject obj)
+{
+ LogManager::Init();
+ SConfig::Init();
+ VideoBackend::PopulateList();
+ VideoBackend::ActivateBackend(SConfig::GetInstance().
+ m_LocalCoreStartupParameter.m_strVideoBackend);
+ WiimoteReal::LoadSettings();
+
+ // No use running the loop when booting fails
+ if (BootManager::BootCore(""))
+ {
+ while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
+ updateMainFrameEvent.Wait();
+ }
+
+ WiimoteReal::Shutdown();
+ VideoBackend::ClearList();
+ SConfig::Shutdown();
+ LogManager::Shutdown();
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/Source/Core/DolphinWX/Src/MemcardManager.cpp b/Source/Core/DolphinWX/Src/MemcardManager.cpp
index b3a7ab22b8..0bbbbd0a7b 100644
--- a/Source/Core/DolphinWX/Src/MemcardManager.cpp
+++ b/Source/Core/DolphinWX/Src/MemcardManager.cpp
@@ -17,6 +17,8 @@
#include "MemcardManager.h"
#include "Common.h"
+
+#include "WxUtils.h"
#include "wx/mstream.h"
#define ARROWS slot ? _T("") : ARROW[slot], slot ? ARROW[slot] : _T("")
@@ -212,7 +214,7 @@ void CMemcardManager::CreateGUIControls()
sPages->Add(m_NextPage[slot], 0, wxEXPAND|wxALL, 1);
m_MemcardPath[slot] = new wxFilePickerCtrl(this, ID_MEMCARDPATH_A + slot,
- wxString::From8BitData(File::GetUserPath(D_GCUSER_IDX).c_str()), _("Choose a memory card:"),
+ StrToWxStr(File::GetUserPath(D_GCUSER_IDX)), _("Choose a memory card:"),
_("Gamecube Memory Cards (*.raw,*.gcp)") + wxString(wxT("|*.raw;*.gcp")), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL|wxFLP_OPEN);
m_MemcardList[slot] = new CMemcardListCtrl(this, ID_MEMCARDLIST_A + slot, wxDefaultPosition, wxSize(350,400),
@@ -263,7 +265,7 @@ void CMemcardManager::CreateGUIControls()
m_Delete[i]->Disable();
if (DefaultMemcard[i].length())
{
- m_MemcardPath[i]->SetPath(wxString::From8BitData(DefaultMemcard[i].c_str()));
+ m_MemcardPath[i]->SetPath(StrToWxStr(DefaultMemcard[i]));
ChangePath(i);
}
}
@@ -290,7 +292,7 @@ void CMemcardManager::ChangePath(int slot)
}
else
{
- if (m_MemcardPath[slot]->GetPath().length() && ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot))
+ if (m_MemcardPath[slot]->GetPath().length() && ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot))
{
if (memoryCard[slot2])
{
@@ -345,7 +347,7 @@ void CMemcardManager::OnPageChange(wxCommandEvent& event)
m_NextPage[slot]->Disable();
m_MemcardList[slot]->nextPage = false;
}
- ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot);
+ ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot);
break;
case ID_PREVPAGE_A:
slot = SLOT_A;
@@ -361,7 +363,7 @@ void CMemcardManager::OnPageChange(wxCommandEvent& event)
m_PrevPage[slot]->Disable();
m_MemcardList[slot]->prevPage = false;
}
- ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot);
+ ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot);
break;
}
}
@@ -373,7 +375,7 @@ void CMemcardManager::OnMenuChange(wxCommandEvent& event)
{
case ID_MEMCARDPATH_A:
case ID_MEMCARDPATH_B:
- DefaultMemcard[_id - ID_MEMCARDPATH_A] = m_MemcardPath[_id - ID_MEMCARDPATH_A]->GetPath().mb_str();
+ DefaultMemcard[_id - ID_MEMCARDPATH_A] = WxStrToStr(m_MemcardPath[_id - ID_MEMCARDPATH_A]->GetPath());
return;
case ID_USEPAGES:
mcmSettings.usePages = !mcmSettings.usePages;
@@ -400,8 +402,8 @@ void CMemcardManager::OnMenuChange(wxCommandEvent& event)
break;
}
- if (memoryCard[SLOT_A]) ReloadMemcard(m_MemcardPath[SLOT_A]->GetPath().mb_str(), SLOT_A);
- if (memoryCard[SLOT_B]) ReloadMemcard(m_MemcardPath[SLOT_B]->GetPath().mb_str(), SLOT_B);
+ if (memoryCard[SLOT_A]) ReloadMemcard(WxStrToStr(m_MemcardPath[SLOT_A]->GetPath()).c_str(), SLOT_A);
+ if (memoryCard[SLOT_B]) ReloadMemcard(WxStrToStr(m_MemcardPath[SLOT_B]->GetPath()).c_str(), SLOT_B);
}
bool CMemcardManager::CopyDeleteSwitch(u32 error, int slot)
{
@@ -416,7 +418,7 @@ bool CMemcardManager::CopyDeleteSwitch(u32 error, int slot)
memoryCard[slot]->FixChecksums();
if (!memoryCard[slot]->Save()) PanicAlert(E_SAVEFAILED);
page[slot] = FIRSTPAGE;
- ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot);
+ ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot);
}
break;
case NOMEMCARD:
@@ -517,8 +519,8 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
wxString fileName = wxFileSelector(
_("Select a save file to import"),
(strcmp(DefaultIOPath.c_str(), "/Users/GC") == 0)
- ? wxString::FromAscii("")
- : wxString::From8BitData(DefaultIOPath.c_str()),
+ ? StrToWxStr("")
+ : StrToWxStr(DefaultIOPath),
wxEmptyString, wxEmptyString,
_("GameCube Savegame files(*.gci;*.gcs;*.sav)") + wxString(wxT("|*.gci;*.gcs;*.sav|")) +
_("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) +
@@ -532,11 +534,11 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
_("GCI File(*.gci)") + wxString(_T("|*.gci")),
wxFD_OVERWRITE_PROMPT|wxFD_SAVE, this);
if (temp2.empty()) break;
- fileName2 = temp2.mb_str();
+ fileName2 = WxStrToStr(temp2);
}
if (fileName.length() > 0)
{
- CopyDeleteSwitch(memoryCard[slot]->ImportGci(fileName.mb_str(), fileName2), slot);
+ CopyDeleteSwitch(memoryCard[slot]->ImportGci(WxStrToStr(fileName).c_str(), fileName2), slot);
}
}
break;
@@ -555,8 +557,8 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
}
wxString fileName = wxFileSelector(
_("Export save as..."),
- wxString::From8BitData(DefaultIOPath.c_str()),
- wxString::From8BitData(gciFilename.c_str()), wxT(".gci"),
+ StrToWxStr(DefaultIOPath),
+ StrToWxStr(gciFilename), wxT(".gci"),
_("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) +
_("MadCatz Gameshark files(*.gcs)") + wxString(wxT("|*.gcs|")) +
_("Datel MaxDrive/Pro files(*.sav)") + wxString(wxT("|*.sav")),
@@ -564,9 +566,9 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
if (fileName.length() > 0)
{
- if (!CopyDeleteSwitch(memoryCard[slot]->ExportGci(index, fileName.mb_str(), ""), -1))
+ if (!CopyDeleteSwitch(memoryCard[slot]->ExportGci(index, WxStrToStr(fileName).c_str(), ""), -1))
{
- File::Delete(std::string(fileName.mb_str()));
+ File::Delete(WxStrToStr(fileName));
}
}
}
@@ -576,7 +578,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
case ID_EXPORTALL_B:
{
std::string path1, path2, mpath;
- mpath = m_MemcardPath[slot]->GetPath().mb_str();
+ mpath = WxStrToStr(m_MemcardPath[slot]->GetPath());
SplitPath(mpath, &path1, &path2, NULL);
path1 += path2;
File::CreateDir(path1);
@@ -702,26 +704,11 @@ bool CMemcardManager::ReloadMemcard(const char *fileName, int card)
std::string title = memoryCard[card]->GetSaveComment1(fileIndex);
std::string comment = memoryCard[card]->GetSaveComment2(fileIndex);
- bool ascii = memoryCard[card]->IsAsciiEncoding();
-
-#ifdef _WIN32
- wxCSConv SJISConv(*(wxCSConv*)wxConvCurrent);
- static bool validCP932 = ::IsValidCodePage(932) != 0;
- if (validCP932)
- {
- SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS));
- }
- else
- {
- WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932");
- }
-#else
- // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)
- // it returns CP-932, in order to use iconv we need to use CP932
- wxCSConv SJISConv(wxT("CP932"));
-#endif
- wxTitle = wxString(title.c_str(), ascii ? *wxConvCurrent : SJISConv);
- wxComment = wxString(comment.c_str(), ascii ? *wxConvCurrent : SJISConv);
+ auto const string_decoder = memoryCard[card]->IsAsciiEncoding() ?
+ CP1252ToUTF8 : SHIFTJISToUTF8;
+
+ wxTitle = StrToWxStr(string_decoder(title));
+ wxComment = StrToWxStr(string_decoder(comment));
m_MemcardList[card]->SetItem(index, COLUMN_TITLE, wxTitle);
m_MemcardList[card]->SetItem(index, COLUMN_COMMENT, wxComment);
diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp
index 142a7ea00c..76bb76881b 100644
--- a/Source/Core/DolphinWX/Src/NetWindow.cpp
+++ b/Source/Core/DolphinWX/Src/NetWindow.cpp
@@ -18,11 +18,13 @@
#include <FileUtil.h>
#include <IniFile.h>
+#include "WxUtils.h"
#include "NetPlay.h"
#include "NetWindow.h"
#include "Frame.h"
#include <sstream>
+#include <string>
#define NETPLAY_TITLEBAR "Dolphin NetPlay"
@@ -34,6 +36,24 @@ static NetPlay* netplay_ptr = NULL;
extern CFrame* main_frame;
NetPlayDiag *NetPlayDiag::npd = NULL;
+std::string BuildGameName(const GameListItem& game)
+{
+ // Lang needs to be consistent
+ auto const lang = 0;
+
+ std::string name(game.GetBannerName(lang));
+ if (name.empty())
+ name = game.GetVolumeName(lang);
+
+ return name + " (" + game.GetUniqueID() + ")";
+}
+
+void FillWithGameNames(wxListBox* game_lbox, const CGameListCtrl& game_list)
+{
+ for (u32 i = 0 ; auto game = game_list.GetISO(i); ++i)
+ game_lbox->Append(StrToWxStr(BuildGameName(*game)));
+}
+
NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* const game_list)
: wxFrame(parent, wxID_ANY, wxT(NETPLAY_TITLEBAR), wxDefaultPosition, wxDefaultSize)
, m_game_list(game_list)
@@ -50,7 +70,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl*
std::string nickname;
netplay_section.Get("Nickname", &nickname, "Player");
- m_nickname_text = new wxTextCtrl(panel, wxID_ANY, wxString::From8BitData(nickname.c_str()));
+ m_nickname_text = new wxTextCtrl(panel, wxID_ANY, StrToWxStr(nickname));
wxBoxSizer* const nick_szr = new wxBoxSizer(wxHORIZONTAL);
nick_szr->Add(nick_lbl, 0, wxCENTER);
@@ -72,7 +92,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl*
std::string address;
netplay_section.Get("Address", &address, "localhost");
- m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, wxString::FromAscii(address.c_str()));
+ m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(address));
wxStaticText* const port_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Port :"),
wxDefaultPosition, wxDefaultSize);
@@ -80,7 +100,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl*
// string? w/e
std::string port;
netplay_section.Get("ConnectPort", &port, "2626");
- m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY, wxString::FromAscii(port.c_str()));
+ m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(port));
wxButton* const connect_btn = new wxButton(connect_tab, wxID_ANY, _("Connect"));
connect_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &NetPlaySetupDiag::OnJoin, this);
@@ -113,18 +133,15 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl*
// string? w/e
std::string port;
netplay_section.Get("HostPort", &port, "2626");
- m_host_port_text = new wxTextCtrl(host_tab, wxID_ANY, wxString::FromAscii(port.c_str()));
+ m_host_port_text = new wxTextCtrl(host_tab, wxID_ANY, StrToWxStr(port));
wxButton* const host_btn = new wxButton(host_tab, wxID_ANY, _("Host"));
host_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &NetPlaySetupDiag::OnHost, this);
m_game_lbox = new wxListBox(host_tab, wxID_ANY);
m_game_lbox->Bind(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, &NetPlaySetupDiag::OnHost, this);
-
- std::istringstream ss(game_list->GetGameNames());
- std::string game;
- while (std::getline(ss,game))
- m_game_lbox->Append(wxString(game.c_str(), *wxConvCurrent));
+
+ FillWithGameNames(m_game_lbox, *game_list);
wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL);
top_szr->Add(port_lbl, 0, wxCENTER | wxRIGHT, 5);
@@ -167,10 +184,10 @@ NetPlaySetupDiag::~NetPlaySetupDiag()
inifile.Load(dolphin_ini);
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
- netplay_section.Set("Nickname", m_nickname_text->GetValue().mb_str());
- netplay_section.Set("Address", m_connect_ip_text->GetValue().mb_str());
- netplay_section.Set("ConnectPort", m_connect_port_text->GetValue().mb_str());
- netplay_section.Set("HostPort", m_host_port_text->GetValue().mb_str());
+ netplay_section.Set("Nickname", WxStrToStr(m_nickname_text->GetValue()));
+ netplay_section.Set("Address", WxStrToStr(m_connect_ip_text->GetValue()));
+ netplay_section.Set("ConnectPort", WxStrToStr(m_connect_port_text->GetValue()));
+ netplay_section.Set("HostPort", WxStrToStr(m_host_port_text->GetValue()));
inifile.Save(dolphin_ini);
main_frame->g_NetPlaySetupDiag = NULL;
@@ -191,13 +208,13 @@ void NetPlaySetupDiag::OnHost(wxCommandEvent&)
return;
}
- std::string game(m_game_lbox->GetStringSelection().mb_str());
+ std::string game(WxStrToStr(m_game_lbox->GetStringSelection()));
npd = new NetPlayDiag(m_parent, m_game_list, game, true);
unsigned long port = 0;
m_host_port_text->GetValue().ToULong(&port);
netplay_ptr = new NetPlayServer(u16(port)
- , std::string(m_nickname_text->GetValue().mb_str()), npd, game);
+ , WxStrToStr(m_nickname_text->GetValue()), npd, game);
if (netplay_ptr->is_connected)
{
npd->Show();
@@ -222,8 +239,8 @@ void NetPlaySetupDiag::OnJoin(wxCommandEvent&)
npd = new NetPlayDiag(m_parent, m_game_list, "");
unsigned long port = 0;
m_connect_port_text->GetValue().ToULong(&port);
- netplay_ptr = new NetPlayClient(std::string(m_connect_ip_text->GetValue().mb_str())
- , (u16)port, npd, std::string(m_nickname_text->GetValue().mb_str()));
+ netplay_ptr = new NetPlayClient(WxStrToStr(m_connect_ip_text->GetValue())
+ , (u16)port, npd, WxStrToStr(m_nickname_text->GetValue()));
if (netplay_ptr->is_connected)
{
npd->Show();
@@ -250,7 +267,7 @@ NetPlayDiag::NetPlayDiag(wxWindow* const parent, const CGameListCtrl* const game
// top crap
m_game_btn = new wxButton(panel, wxID_ANY,
- wxString(m_selected_game.c_str(), *wxConvCurrent).Prepend(_(" Game : ")),
+ StrToWxStr(m_selected_game).Prepend(_(" Game : ")),
wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
if (is_hosting)
@@ -351,7 +368,7 @@ void NetPlayDiag::OnChat(wxCommandEvent&)
if (s.Length())
{
- netplay_ptr->SendChatMessage(std::string(s.mb_str()));
+ netplay_ptr->SendChatMessage(WxStrToStr(s));
m_chat_text->AppendText(s.Prepend(wxT(" >> ")).Append(wxT('\n')));
m_chat_msg_text->Clear();
}
@@ -359,24 +376,17 @@ void NetPlayDiag::OnChat(wxCommandEvent&)
void NetPlayDiag::OnStart(wxCommandEvent&)
{
- // find path for selected game
- std::string ntmp, ptmp, path;
- std::istringstream nss(m_game_list->GetGameNames()), pss(m_game_list->GetGamePaths());
-
- while(std::getline(nss,ntmp))
+ // find path for selected game, sloppy..
+ for (u32 i = 0 ; auto game = m_game_list->GetISO(i); ++i)
{
- std::getline(pss,ptmp);
- if (m_selected_game == ntmp)
+ if (m_selected_game == BuildGameName(*game))
{
- path = ptmp;
- break;
+ netplay_ptr->StartGame(game->GetFileName());
+ return;
}
}
-
- if (path.length())
- netplay_ptr->StartGame(path);
- else
- PanicAlertT("Game not found!!");
+
+ PanicAlertT("Game not found!");
}
void NetPlayDiag::OnStop(wxCommandEvent&)
@@ -412,7 +422,7 @@ void NetPlayDiag::OnMsgChangeGame(const std::string& filename)
{
wxCommandEvent evt(wxEVT_THREAD, NP_GUI_EVT_CHANGE_GAME);
// TODO: using a wxString in AddPendingEvent from another thread is unsafe i guess?
- evt.SetString(wxString(filename.c_str(), *wxConvCurrent));
+ evt.SetString(StrToWxStr(filename));
GetEventHandler()->AddPendingEvent(evt);
}
@@ -436,7 +446,7 @@ void NetPlayDiag::OnPadBuffHelp(wxCommandEvent&)
<< time * (60.0f/1000) << "(60fps) / "
<< time * (50.0f/1000) << "(50fps) >\n";
- m_chat_text->AppendText(wxString(ss.str().c_str(), *wxConvCurrent));
+ m_chat_text->AppendText(StrToWxStr(ss.str()));
}
void NetPlayDiag::OnAdjustBuffer(wxCommandEvent& event)
@@ -447,7 +457,7 @@ void NetPlayDiag::OnAdjustBuffer(wxCommandEvent& event)
std::ostringstream ss;
ss << "< Pad Buffer: " << val << " >";
netplay_ptr->SendChatMessage(ss.str());
- m_chat_text->AppendText(wxString(ss.str().c_str(), *wxConvCurrent).Append(wxT('\n')));
+ m_chat_text->AppendText(StrToWxStr(ss.str()).Append(wxT('\n')));
}
void NetPlayDiag::OnQuit(wxCommandEvent&)
@@ -468,7 +478,7 @@ void NetPlayDiag::OnThread(wxCommandEvent& event)
m_player_lbox->Clear();
std::istringstream ss(tmps);
while (std::getline(ss, tmps))
- m_player_lbox->Append(wxString(tmps.c_str(), *wxConvCurrent));
+ m_player_lbox->Append(StrToWxStr(tmps));
m_player_lbox->SetSelection(selection);
@@ -477,7 +487,7 @@ void NetPlayDiag::OnThread(wxCommandEvent& event)
case NP_GUI_EVT_CHANGE_GAME :
// update selected game :/
{
- m_selected_game.assign(event.GetString().mb_str());
+ m_selected_game.assign(WxStrToStr(event.GetString()));
m_game_btn->SetLabel(event.GetString().Prepend(_(" Game : ")));
}
break;
@@ -503,7 +513,7 @@ void NetPlayDiag::OnThread(wxCommandEvent& event)
std::string s;
chat_msgs.Pop(s);
//PanicAlert("message: %s", s.c_str());
- m_chat_text->AppendText(wxString(s.c_str(), *wxConvCurrent).Append(wxT('\n')));
+ m_chat_text->AppendText(StrToWxStr(s).Append(wxT('\n')));
}
}
@@ -515,7 +525,7 @@ void NetPlayDiag::OnChangeGame(wxCommandEvent&)
if (game_name.length())
{
- m_selected_game = std::string(game_name.mb_str());
+ m_selected_game = WxStrToStr(game_name);
netplay_ptr->ChangeGame(m_selected_game);
m_game_btn->SetLabel(game_name.Prepend(_(" Game : ")));
}
@@ -549,11 +559,7 @@ ChangeGameDiag::ChangeGameDiag(wxWindow* const parent, const CGameListCtrl* cons
m_game_lbox = new wxListBox(this, wxID_ANY);
m_game_lbox->Bind(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, &ChangeGameDiag::OnPick, this);
- // fill list with games
- std::istringstream ss(game_list->GetGameNames());
- std::string game;
- while (std::getline(ss,game))
- m_game_lbox->Append(wxString(game.c_str(), *wxConvCurrent));
+ FillWithGameNames(m_game_lbox, *game_list);
wxButton* const ok_btn = new wxButton(this, wxID_OK, _("Change"));
ok_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &ChangeGameDiag::OnPick, this);
diff --git a/Source/Core/DolphinWX/Src/PHackSettings.cpp b/Source/Core/DolphinWX/Src/PHackSettings.cpp
index 83f08d9cb7..dcfa1a8501 100644
--- a/Source/Core/DolphinWX/Src/PHackSettings.cpp
+++ b/Source/Core/DolphinWX/Src/PHackSettings.cpp
@@ -17,6 +17,7 @@
#include "PHackSettings.h"
#include "ConfigManager.h"
+#include "WxUtils.h"
extern PHackData PHack_Data;
@@ -97,8 +98,8 @@ void CPHackSettings::LoadPHackData()
if (sTemp.empty())
sTemp = wxString(_("(UNKNOWN)")).char_str();
if (i == 0)
- PHackChoice->Append(wxString("-------------", *wxConvCurrent));
- PHackChoice->Append(wxString(sTemp.c_str(), *wxConvCurrent));
+ PHackChoice->Append(StrToWxStr("-------------"));
+ PHackChoice->Append(StrToWxStr(sTemp));
}
PHackChoice->Select(0);
@@ -106,8 +107,8 @@ void CPHackSettings::LoadPHackData()
PHackSZFar->Set3StateValue((wxCheckBoxState)PHack_Data.PHackSZFar);
PHackExP->Set3StateValue((wxCheckBoxState)PHack_Data.PHackExP);
- PHackZNear->SetValue(wxString(PHack_Data.PHZNear.c_str(), *wxConvCurrent));
- PHackZFar->SetValue(wxString(PHack_Data.PHZFar.c_str(), *wxConvCurrent));
+ PHackZNear->SetValue(StrToWxStr(PHack_Data.PHZNear));
+ PHackZFar->SetValue(StrToWxStr(PHack_Data.PHZFar));
}
void CPHackSettings::SetRefresh(wxCommandEvent& event)
@@ -128,9 +129,9 @@ void CPHackSettings::SetRefresh(wxCommandEvent& event)
PHPresetsIni.Get(sIndex, "PH_ExtraParam", &bTemp);
PHackExP->Set3StateValue((wxCheckBoxState)bTemp);
PHPresetsIni.Get(sIndex, "PH_ZNear", &sTemp);
- PHackZNear->SetValue(wxString(sTemp.c_str(), *wxConvCurrent));
+ PHackZNear->SetValue(StrToWxStr(sTemp));
PHPresetsIni.Get(sIndex, "PH_ZFar", &sTemp);
- PHackZFar->SetValue(wxString(sTemp.c_str(), *wxConvCurrent));
+ PHackZFar->SetValue(StrToWxStr(sTemp));
}
}
diff --git a/Source/Core/DolphinWX/Src/PatchAddEdit.cpp b/Source/Core/DolphinWX/Src/PatchAddEdit.cpp
index 7d521006d3..ead7918d34 100644
--- a/Source/Core/DolphinWX/Src/PatchAddEdit.cpp
+++ b/Source/Core/DolphinWX/Src/PatchAddEdit.cpp
@@ -16,6 +16,7 @@
// http://code.google.com/p/dolphin-emu/
#include "PatchAddEdit.h"
+#include "WxUtils.h"
extern std::vector<PatchEngine::Patch> onFrame;
@@ -48,7 +49,7 @@ void CPatchAddEdit::CreateGUIControls(int _selection)
}
else
{
- currentName = wxString(onFrame.at(_selection).name.c_str(), *wxConvCurrent);
+ currentName = StrToWxStr(onFrame.at(_selection).name);
tempEntries = onFrame.at(_selection).entries;
}
@@ -66,7 +67,7 @@ void CPatchAddEdit::CreateGUIControls(int _selection)
EntrySelection->SetValue((int)tempEntries.size()-1);
wxArrayString wxArrayStringFor_EditPatchType;
for (int i = 0; i < 3; ++i)
- wxArrayStringFor_EditPatchType.Add(wxString::FromAscii(PatchEngine::PatchTypeStrings[i]));
+ wxArrayStringFor_EditPatchType.Add(StrToWxStr(PatchEngine::PatchTypeStrings[i]));
EditPatchType = new wxRadioBox(this, ID_EDITPATCH_TYPE, _("Type"), wxDefaultPosition, wxDefaultSize, wxArrayStringFor_EditPatchType, 3, wxRA_SPECIFY_COLS);
EditPatchType->SetSelection((int)tempEntries.at(0).type);
wxStaticText* EditPatchValueText = new wxStaticText(this, ID_EDITPATCH_VALUE_TEXT, _("Value:"));
@@ -121,7 +122,7 @@ void CPatchAddEdit::SavePatchData(wxCommandEvent& event)
if (selection == -1)
{
PatchEngine::Patch newPatch;
- newPatch.name = std::string(EditPatchName->GetValue().mb_str());
+ newPatch.name = WxStrToStr(EditPatchName->GetValue());
newPatch.entries = tempEntries;
newPatch.active = true;
@@ -129,7 +130,7 @@ void CPatchAddEdit::SavePatchData(wxCommandEvent& event)
}
else
{
- onFrame.at(selection).name = std::string(EditPatchName->GetValue().mb_str());
+ onFrame.at(selection).name = WxStrToStr(EditPatchName->GetValue());
onFrame.at(selection).entries = tempEntries;
}
diff --git a/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp b/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp
index 2f31311495..9619f38dee 100644
--- a/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp
+++ b/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp
@@ -4,6 +4,8 @@
#include "Common.h"
#include "ControllerEmu.h"
#include "IniFile.h"
+#include "WxUtils.h"
+
#include <string>
UDPConfigDiag::UDPConfigDiag(wxWindow * const parent, UDPWrapper * _wrp) :
@@ -26,7 +28,7 @@ UDPConfigDiag::UDPConfigDiag(wxWindow * const parent, UDPWrapper * _wrp) :
wxBoxSizer *const port_sizer = new wxBoxSizer(wxHORIZONTAL);
port_sizer->Add(new wxStaticText(this, wxID_ANY, _("UDP Port:")), 0, wxALIGN_CENTER);
- port_tbox = new wxTextCtrl(this, wxID_ANY, wxString::FromUTF8(wrp->port.c_str()));
+ port_tbox = new wxTextCtrl(this, wxID_ANY, StrToWxStr(wrp->port));
port_sizer->Add(port_tbox, 1, wxLEFT | wxEXPAND, 5);
enable->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &UDPConfigDiag::ChangeState, this);
@@ -71,7 +73,7 @@ void UDPConfigDiag::ChangeUpdateFlags(wxCommandEvent & WXUNUSED(event))
void UDPConfigDiag::ChangeState(wxCommandEvent & WXUNUSED(event))
{
- wrp->udpEn=enable->GetValue();
- wrp->port=port_tbox->GetValue().mb_str(wxConvUTF8);
+ wrp->udpEn = enable->GetValue();
+ wrp->port = WxStrToStr(port_tbox->GetValue());
wrp->Refresh();
}
diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp
index 0ca4715c3d..29f6ed109a 100644
--- a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp
+++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp
@@ -82,6 +82,7 @@ wxString af_desc = wxTRANSLATE("Enable anisotropic filtering.\nEnhances visual q
wxString aa_desc = wxTRANSLATE("Reduces the amount of aliasing caused by rasterizing 3D graphics.\nThis makes the rendered picture look less blocky.\nHeavily decreases emulation speed and sometimes causes issues.\n\nIf unsure, select None.");
wxString scaled_efb_copy_desc = wxTRANSLATE("Greatly increases quality of textures generated using render to texture effects.\nRaising the internal resolution will improve the effect of this setting.\nSlightly decreases performance and possibly causes issues (although unlikely).\n\nIf unsure, leave this checked.");
wxString pixel_lighting_desc = wxTRANSLATE("Calculate lighting of 3D graphics per-pixel rather than per vertex.\nDecreases emulation speed by some percent (depending on your GPU).\nThis usually is a safe enhancement, but might cause issues sometimes.\n\nIf unsure, leave this unchecked.");
+wxString hacked_buffer_upload_desc = wxTRANSLATE("Use a hacked upload strategy to stream vertices.\nThis usually speed up, but is forbidden by OpenGL specification and may causes heavy glitches.\n\nIf unsure, leave this unchecked.");
wxString force_filtering_desc = wxTRANSLATE("Force texture filtering even if the emulated game explicitly disabled it.\nImproves texture quality slightly but causes glitches in some games.\n\nIf unsure, leave this unchecked.");
wxString _3d_vision_desc = wxTRANSLATE("Enable 3D effects via stereoscopy using Nvidia 3D Vision technology if it's supported by your GPU.\nPossibly causes issues.\nRequires fullscreen to work.\n\nIf unsure, leave this unchecked.");
wxString internal_res_desc = wxTRANSLATE("Specifies the resolution used to render at. A high resolution will improve visual quality a lot but is also quite heavy on performance and might cause glitches in certain games.\n\"Multiple of 640x528\" is a bit slower than \"Window Size\" but yields less issues. Generally speaking, the lower the internal resolution is, the better your performance will be.\n\nIf unsure, select 640x528.");
@@ -92,7 +93,7 @@ wxString efb_copy_texture_desc = wxTRANSLATE("Store EFB copies in GPU texture ob
wxString efb_copy_ram_desc = wxTRANSLATE("Accurately emulate EFB copies.\nSome games depend on this for certain graphical effects or gameplay functionality.\n\nIf unsure, check EFB to Texture instead.");
wxString stc_desc = wxTRANSLATE("The safer you adjust this, the less likely the emulator will be missing any texture updates from RAM.\n\nIf unsure, use the rightmost value.");
wxString wireframe_desc = wxTRANSLATE("Render the scene as a wireframe.\n\nIf unsure, leave this unchecked.");
-wxString disable_fog_desc = wxTRANSLATE("Improves performance but causes glitches in most games which rely on proper fog emulation.\n\nIf unsure, leave this unchecked.");
+wxString disable_fog_desc = wxTRANSLATE("Makes distant objects more visible by removing fog, thus increasing the overall detail.\nDisabling fog will break some games which rely on proper fog emulation.\n\nIf unsure, leave this unchecked.");
wxString disable_alphapass_desc = wxTRANSLATE("Skip the destination alpha pass used in many games for various graphical effects.\n\nIf unsure, leave this unchecked.");
wxString show_fps_desc = wxTRANSLATE("Show the number of frames rendered per second as a measure of emulation speed.\n\nIf unsure, leave this unchecked.");
wxString log_fps_to_file_desc = wxTRANSLATE("Log the number of frames rendered per second to User/Logs/fps.txt. Use this feature when you want to measure the performance of Dolphin.\n\nIf unsure, leave this unchecked.");
@@ -141,7 +142,7 @@ wxArrayString GetListOfResolutions()
if (std::find(resos.begin(), resos.end(), strRes) == resos.end())
{
resos.push_back(strRes);
- retlist.Add(wxString::FromAscii(res));
+ retlist.Add(StrToWxStr(res));
}
ZeroMemory(&dmi, sizeof(dmi));
}
@@ -180,8 +181,7 @@ wxArrayString GetListOfResolutions()
VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, const std::string& _ininame)
: wxDialog(parent, -1,
- wxString::Format(_("Dolphin %s Graphics Configuration"),
- wxGetTranslation(wxString::From8BitData(title.c_str()))),
+ wxString::Format(_("Dolphin %s Graphics Configuration"), wxGetTranslation(StrToWxStr(title))),
wxDefaultPosition, wxDefaultSize)
, vconfig(g_Config)
, ininame(_ininame)
@@ -212,9 +212,9 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
it = g_available_video_backends.begin(),
itend = g_available_video_backends.end();
for (; it != itend; ++it)
- choice_backend->AppendString(wxGetTranslation(wxString::FromAscii((*it)->GetName().c_str())));
+ choice_backend->AppendString(wxGetTranslation(StrToWxStr((*it)->GetDisplayName())));
- choice_backend->SetStringSelection(wxGetTranslation(wxString::FromAscii(g_video_backend->GetName().c_str())));
+ choice_backend->SetStringSelection(wxGetTranslation(StrToWxStr(g_video_backend->GetDisplayName())));
choice_backend->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_Backend, this);
szr_basic->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5);
@@ -236,7 +236,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
it = vconfig.backend_info.Adapters.begin(),
itend = vconfig.backend_info.Adapters.end();
for (; it != itend; ++it)
- choice_adapter->AppendString(wxString::FromAscii(it->c_str()));
+ choice_adapter->AppendString(StrToWxStr(*it));
choice_adapter->Select(vconfig.iAdapter);
@@ -259,7 +259,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
RegisterControl(choice_display_resolution, wxGetTranslation(display_res_desc));
choice_display_resolution->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_DisplayResolution, this);
- choice_display_resolution->SetStringSelection(wxString::FromAscii(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution.c_str()));
+ choice_display_resolution->SetStringSelection(StrToWxStr(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution));
szr_display->Add(label_display_resolution, 1, wxALIGN_CENTER_VERTICAL, 0);
szr_display->Add(choice_display_resolution);
@@ -355,7 +355,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
it = vconfig.backend_info.AAModes.begin(),
itend = vconfig.backend_info.AAModes.end();
for (; it != itend; ++it)
- choice_aamode->AppendString(wxGetTranslation(wxString::FromAscii(it->c_str())));
+ choice_aamode->AppendString(wxGetTranslation(StrToWxStr(*it)));
choice_aamode->Select(vconfig.iMultisampleMode);
szr_enh->Add(text_aamode, 1, wxALIGN_CENTER_VERTICAL, 0);
@@ -380,12 +380,12 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
it = vconfig.backend_info.PPShaders.begin(),
itend = vconfig.backend_info.PPShaders.end();
for (; it != itend; ++it)
- choice_ppshader->AppendString(wxString::FromAscii(it->c_str()));
+ choice_ppshader->AppendString(StrToWxStr(*it));
if (vconfig.sPostProcessingShader.empty())
choice_ppshader->Select(0);
else
- choice_ppshader->SetStringSelection(wxString::FromAscii(vconfig.sPostProcessingShader.c_str()));
+ choice_ppshader->SetStringSelection(StrToWxStr(vconfig.sPostProcessingShader));
choice_ppshader->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_PPShader, this);
@@ -398,11 +398,13 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
szr_enh->Add(pixel_lighting = CreateCheckBox(page_enh, _("Per-Pixel Lighting"), wxGetTranslation(pixel_lighting_desc), vconfig.bEnablePixelLighting));
szr_enh->Add(CreateCheckBox(page_enh, _("Force Texture Filtering"), wxGetTranslation(force_filtering_desc), vconfig.bForceFiltering));
+ szr_enh->Add(CreateCheckBox(page_enh, _("Widescreen Hack"), wxGetTranslation(ws_hack_desc), vconfig.bWidescreenHack));
+ szr_enh->Add(CreateCheckBox(page_enh, _("Disable Fog"), wxGetTranslation(disable_fog_desc), vconfig.bDisableFog));
+
// 3D Vision
_3d_vision = CreateCheckBox(page_enh, _("3D Vision"), wxGetTranslation(_3d_vision_desc), vconfig.b3DVision);
_3d_vision->Show(vconfig.backend_info.bSupports3DVision);
szr_enh->Add(_3d_vision);
- szr_enh->Add(CreateCheckBox(page_enh, _("Widescreen Hack"), wxGetTranslation(ws_hack_desc), vconfig.bWidescreenHack));
// TODO: Add anaglyph 3d here
wxStaticBoxSizer* const group_enh = new wxStaticBoxSizer(wxVERTICAL, page_enh, _("Enhancements"));
@@ -487,13 +489,16 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
// - other hacks
{
wxGridSizer* const szr_other = new wxGridSizer(2, 5, 5);
-
+ SettingCheckBox* hacked_buffer_upload_cb;
szr_other->Add(CreateCheckBox(page_hacks, _("Cache Display Lists"), wxGetTranslation(dlc_desc), vconfig.bDlistCachingEnable));
- szr_other->Add(CreateCheckBox(page_hacks, _("Disable Fog"), wxGetTranslation(disable_fog_desc), vconfig.bDisableFog));
szr_other->Add(CreateCheckBox(page_hacks, _("Skip Dest. Alpha Pass"), wxGetTranslation(disable_alphapass_desc), vconfig.bDstAlphaPass));
szr_other->Add(CreateCheckBox(page_hacks, _("OpenCL Texture Decoder"), wxGetTranslation(opencl_desc), vconfig.bEnableOpenCL));
szr_other->Add(CreateCheckBox(page_hacks, _("OpenMP Texture Decoder"), wxGetTranslation(omp_desc), vconfig.bOMPDecoder));
+ szr_other->Add(hacked_buffer_upload_cb = CreateCheckBox(page_hacks, _("Hacked Buffer Upload"), wxGetTranslation(hacked_buffer_upload_desc), vconfig.bHackedBufferUpload));
+ if (Core::GetState() != Core::CORE_UNINITIALIZED)
+ hacked_buffer_upload_cb->Disable();
+
wxStaticBoxSizer* const group_other = new wxStaticBoxSizer(wxVERTICAL, page_hacks, _("Other"));
group_other->Add(szr_other, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
szr_hacks->Add(group_other, 0, wxEXPAND | wxALL, 5);
@@ -565,7 +570,6 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
szr_misc->Add(cb_prog_scan);
}
-
wxStaticBoxSizer* const group_misc = new wxStaticBoxSizer(wxVERTICAL, page_advanced, _("Misc"));
szr_advanced->Add(group_misc, 0, wxEXPAND | wxALL, 5);
group_misc->Add(szr_misc, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
@@ -595,7 +599,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
void VideoConfigDiag::Event_DisplayResolution(wxCommandEvent &ev)
{
SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution =
- choice_display_resolution->GetStringSelection().mb_str();
+ WxStrToStr(choice_display_resolution->GetStringSelection());
#if defined(HAVE_XRANDR) && HAVE_XRANDR
main_frame->m_XRRConfig->Update();
#endif
diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.h b/Source/Core/DolphinWX/Src/VideoConfigDiag.h
index c7a19c6cb8..90a42c34a1 100644
--- a/Source/Core/DolphinWX/Src/VideoConfigDiag.h
+++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.h
@@ -20,6 +20,7 @@
#include <wx/spinctrl.h>
#include "MsgHandler.h"
+#include "WxUtils.h"
template <typename W>
class BoolSetting : public W
@@ -99,7 +100,7 @@ protected:
else
{
// Select current backend again
- choice_backend->SetStringSelection(wxString::FromAscii(g_video_backend->GetName().c_str()));
+ choice_backend->SetStringSelection(StrToWxStr(g_video_backend->GetName()));
}
}
@@ -129,7 +130,7 @@ protected:
{
const int sel = ev.GetInt();
if (sel)
- vconfig.sPostProcessingShader = ev.GetString().mb_str();
+ vconfig.sPostProcessingShader = WxStrToStr(ev.GetString());
else
vconfig.sPostProcessingShader.clear();
diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp
index ea23e532e7..475718ed2e 100644
--- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp
+++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp
@@ -4,13 +4,6 @@
#include "HW/WiimoteReal/WiimoteReal.h"
#include "Frame.h"
-const wxString& ConnectedWiimotesString()
-{
- static wxString str;
- str.Printf(_("%i connected"), WiimoteReal::Initialize());
- return str;
-}
-
WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin)
: wxDialog(parent, -1, _("Dolphin Wiimote Configuration"), wxDefaultPosition, wxDefaultSize)
, m_plugin(plugin)
@@ -64,27 +57,31 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
// "Real wiimotes" controls
- connected_wiimotes_txt = new wxStaticText(this, -1, ConnectedWiimotesString());
-
wxButton* const refresh_btn = new wxButton(this, -1, _("Refresh"), wxDefaultPosition);
refresh_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::RefreshRealWiimotes, this);
-#ifdef _WIN32
- wxButton* const pairup_btn = new wxButton(this, -1, _("Pair Up"), wxDefaultPosition);
- pairup_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::PairUpRealWiimotes, this);
-#endif
-
-
- // "Real wiimotes" layout
- wxStaticBoxSizer* const real_wiimotes_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Real Wiimotes"));
- wxFlexGridSizer* const real_wiimotes_sizer = new wxFlexGridSizer(3, 5, 5);
- real_wiimotes_sizer->Add(connected_wiimotes_txt, 0, wxALIGN_CENTER_VERTICAL);
-#ifdef _WIN32
- real_wiimotes_sizer->Add(pairup_btn);
-#endif
- real_wiimotes_sizer->Add(refresh_btn);
- real_wiimotes_group->Add(real_wiimotes_sizer, 1, wxALL, 5);
-
+ wxStaticBoxSizer* const real_wiimotes_group = new wxStaticBoxSizer(wxVERTICAL, this, _("Real Wiimotes"));
+
+ wxBoxSizer* const real_wiimotes_sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ if (!WiimoteReal::g_wiimote_scanner.IsReady())
+ real_wiimotes_group->Add(new wxStaticText(this, -1, _("A supported bluetooth device could not be found.\n"
+ "You must manually connect your wiimotes.")), 0, wxALIGN_CENTER | wxALL, 5);
+
+ wxCheckBox* const continuous_scanning = new wxCheckBox(this, wxID_ANY, _("Continuous Scanning"));
+ continuous_scanning->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnContinuousScanning, this);
+ continuous_scanning->SetValue(SConfig::GetInstance().m_WiimoteContinuousScanning);
+
+ auto wiimote_speaker = new wxCheckBox(this, wxID_ANY, _("Enable Speaker Data"));
+ wiimote_speaker->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnEnableSpeaker, this);
+ wiimote_speaker->SetValue(SConfig::GetInstance().m_WiimoteEnableSpeaker);
+
+ real_wiimotes_sizer->Add(continuous_scanning, 0, wxALIGN_CENTER_VERTICAL);
+ real_wiimotes_sizer->AddStretchSpacer(1);
+ real_wiimotes_sizer->Add(refresh_btn, 0, wxALL | wxALIGN_CENTER, 5);
+
+ real_wiimotes_group->Add(wiimote_speaker, 0);
+ real_wiimotes_group->Add(real_wiimotes_sizer, 0, wxEXPAND);
// "General Settings" controls
const wxString str[] = { _("Bottom"), _("Top") };
@@ -188,33 +185,9 @@ void WiimoteConfigDiag::ConfigEmulatedWiimote(wxCommandEvent& ev)
m_emu_config_diag->Destroy();
}
-void WiimoteConfigDiag::UpdateGUI()
-{
- connected_wiimotes_txt->SetLabel(ConnectedWiimotesString());
-}
-
-#ifdef _WIN32
-void WiimoteConfigDiag::PairUpRealWiimotes(wxCommandEvent&)
-{
- const int paired = WiimoteReal::PairUp();
-
- if (paired > 0)
- {
- // TODO: Maybe add a label of newly paired up wiimotes?
- WiimoteReal::Refresh();
- UpdateGUI();
- }
- else if (paired < 0)
- PanicAlertT("A supported bluetooth device could not be found!\n"
- "If you are not using Microsoft's bluetooth stack "
- "you must manually pair your wiimotes and use only the \"Refresh\" button.");
-}
-#endif
-
void WiimoteConfigDiag::RefreshRealWiimotes(wxCommandEvent&)
{
WiimoteReal::Refresh();
- UpdateGUI();
}
void WiimoteConfigDiag::SelectSource(wxCommandEvent& event)
@@ -222,30 +195,15 @@ void WiimoteConfigDiag::SelectSource(wxCommandEvent& event)
// This needs to be changed now in order for refresh to work right.
// Revert if the dialog is canceled.
int index = m_wiimote_index_from_ctrl_id[event.GetId()];
- g_wiimote_sources[index] = event.GetInt();
+
+ WiimoteReal::ChangeWiimoteSource(index, event.GetInt());
+
if (g_wiimote_sources[index] != WIIMOTE_SRC_EMU && g_wiimote_sources[index] != WIIMOTE_SRC_HYBRID)
wiimote_configure_bt[index]->Disable();
else
wiimote_configure_bt[index]->Enable();
}
-void WiimoteConfigDiag::UpdateWiimoteStatus()
-{
- for (int index = 0; index < 4; ++index)
- {
- if (m_orig_wiimote_sources[index] != g_wiimote_sources[index])
- {
- // Disconnect first, otherwise the new source doesn't seem to work
- CFrame::ConnectWiimote(index, false);
- // Connect wiimotes
- if (WIIMOTE_SRC_EMU & g_wiimote_sources[index])
- CFrame::ConnectWiimote(index, true);
- else if (WIIMOTE_SRC_REAL & g_wiimote_sources[index] && WiimoteReal::g_wiimotes[index])
- CFrame::ConnectWiimote(index, WiimoteReal::g_wiimotes[index]->IsConnected());
- }
- }
-}
-
void WiimoteConfigDiag::RevertSource()
{
for (int i = 0; i < 4; ++i)
@@ -267,7 +225,6 @@ void WiimoteConfigDiag::Save(wxCommandEvent& event)
sec.Set("Source", (int)g_wiimote_sources[i]);
}
- UpdateWiimoteStatus();
inifile.Save(ini_filename);
diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h
index 2b2e60de4a..4c33661ca2 100644
--- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h
+++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h
@@ -24,20 +24,13 @@ class WiimoteConfigDiag : public wxDialog
public:
WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin);
-#ifdef _WIN32
- void PairUpRealWiimotes(wxCommandEvent& event);
-#endif
void RefreshRealWiimotes(wxCommandEvent& event);
-
void SelectSource(wxCommandEvent& event);
- void UpdateWiimoteStatus();
void RevertSource();
-
void ConfigEmulatedWiimote(wxCommandEvent& event);
void Save(wxCommandEvent& event);
- void UpdateGUI();
void OnSensorBarPos(wxCommandEvent& event)
{
@@ -64,6 +57,17 @@ public:
SConfig::GetInstance().m_WiimoteReconnectOnLoad = event.IsChecked();
event.Skip();
}
+ void OnContinuousScanning(wxCommandEvent& event)
+ {
+ SConfig::GetInstance().m_WiimoteContinuousScanning = event.IsChecked();
+ WiimoteReal::Initialize();
+ event.Skip();
+ }
+ void OnEnableSpeaker(wxCommandEvent& event)
+ {
+ SConfig::GetInstance().m_WiimoteEnableSpeaker = event.IsChecked();
+ event.Skip();
+ }
private:
void Cancel(wxCommandEvent& event);
@@ -76,8 +80,6 @@ private:
wxButton* wiimote_configure_bt[4];
std::map<wxWindowID, unsigned int> m_wiimote_index_from_conf_bt_id;
-
- wxStaticText* connected_wiimotes_txt;
};
diff --git a/Source/Core/DolphinWX/Src/WxUtils.cpp b/Source/Core/DolphinWX/Src/WxUtils.cpp
index 22fa10b84d..6856c96481 100644
--- a/Source/Core/DolphinWX/Src/WxUtils.cpp
+++ b/Source/Core/DolphinWX/Src/WxUtils.cpp
@@ -20,12 +20,14 @@
#include <wx/wx.h>
#include <wx/string.h>
+#include "WxUtils.h"
+
namespace WxUtils {
// Launch a file according to its mime type
void Launch(const char *filename)
{
- if (! ::wxLaunchDefaultBrowser(wxString(filename, *wxConvCurrent)))
+ if (! ::wxLaunchDefaultBrowser(StrToWxStr(filename)))
{
// WARN_LOG
}
@@ -34,7 +36,7 @@ void Launch(const char *filename)
// Launch an file explorer window on a certain path
void Explore(const char *path)
{
- wxString wxPath = wxString(path, *wxConvCurrent);
+ wxString wxPath = StrToWxStr(path);
// Default to file
if (! wxPath.Contains(wxT("://")))
{
@@ -52,3 +54,14 @@ void Explore(const char *path)
}
} // namespace
+
+std::string WxStrToStr(const wxString& str)
+{
+ return str.ToUTF8().data();
+}
+
+wxString StrToWxStr(const std::string& str)
+{
+ //return wxString::FromUTF8Unchecked(str.c_str());
+ return wxString::FromUTF8(str.c_str());
+}
diff --git a/Source/Core/DolphinWX/Src/WxUtils.h b/Source/Core/DolphinWX/Src/WxUtils.h
index 8e837e9e96..61a16b298e 100644
--- a/Source/Core/DolphinWX/Src/WxUtils.h
+++ b/Source/Core/DolphinWX/Src/WxUtils.h
@@ -18,7 +18,11 @@
#ifndef WXUTILS_H
#define WXUTILS_H
-namespace WxUtils {
+#include <string>
+#include <wx/string.h>
+
+namespace WxUtils
+{
// Launch a file according to its mime type
void Launch(const char *filename);
@@ -28,4 +32,7 @@ void Explore(const char *path);
} // namespace
+std::string WxStrToStr(const wxString& str);
+wxString StrToWxStr(const std::string& str);
+
#endif // WXUTILS
diff --git a/Source/Core/DolphinWX/Src/X11Utils.cpp b/Source/Core/DolphinWX/Src/X11Utils.cpp
index f032f81e96..6c4282cceb 100644
--- a/Source/Core/DolphinWX/Src/X11Utils.cpp
+++ b/Source/Core/DolphinWX/Src/X11Utils.cpp
@@ -26,6 +26,7 @@ extern char **environ;
#if defined(HAVE_WX) && HAVE_WX
#include <string>
#include <algorithm>
+#include "WxUtils.h"
#endif
namespace X11Utils
@@ -350,7 +351,7 @@ void XRRConfiguration::AddResolutions(wxArrayString& arrayStringFor_FullscreenRe
if (std::find(resos.begin(), resos.end(), strRes) == resos.end())
{
resos.push_back(strRes);
- arrayStringFor_FullscreenResolution.Add(wxString::FromUTF8(strRes.c_str()));
+ arrayStringFor_FullscreenResolution.Add(StrToWxStr(strRes));
}
}
}
diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp
index c23e9df17e..01baf9cf1a 100644
--- a/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp
+++ b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp
@@ -4,7 +4,7 @@
#include "DInput.h"
-#include <StringUtil.h>
+#include "StringUtil.h"
#ifdef CIFACE_USE_DINPUT_JOYSTICK
#include "DInputJoystick.h"
@@ -41,24 +41,18 @@ BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
std::string GetDeviceName(const LPDIRECTINPUTDEVICE8 device)
{
- std::string out;
-
- DIPROPSTRING str;
- ZeroMemory(&str, sizeof(str));
+ DIPROPSTRING str = {};
str.diph.dwSize = sizeof(str);
str.diph.dwHeaderSize = sizeof(str.diph);
str.diph.dwHow = DIPH_DEVICE;
+ std::string result;
if (SUCCEEDED(device->GetProperty(DIPROP_PRODUCTNAME, &str.diph)))
{
- const int size = WideCharToMultiByte(CP_UTF8, 0, str.wsz, -1, NULL, 0, NULL, NULL);
- char* const data = new char[size];
- if (size == WideCharToMultiByte(CP_UTF8, 0, str.wsz, -1, data, size, NULL, NULL))
- out.assign(data);
- delete[] data;
+ result = StripSpaces(UTF16ToUTF8(str.wsz));
}
- return StripSpaces(out);
+ return result;
}
void Init(std::vector<ControllerInterface::Device*>& devices, HWND hwnd)
diff --git a/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm
index 56e360019a..c22e267044 100644
--- a/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm
+++ b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm
@@ -69,6 +69,7 @@ bool Keyboard::UpdateInput()
CGRectMakeWithDictionaryRepresentation(boundsDictionary, &bounds);
}
+ CFRelease(windowDescriptions);
CFRelease(windowArray);
CGEventRef event = CGEventCreate(nil);
diff --git a/Source/Core/InputCommon/Src/X11InputBase.cpp b/Source/Core/InputCommon/Src/X11InputBase.cpp
index 7f33a7ee7b..d23d2d77c5 100644
--- a/Source/Core/InputCommon/Src/X11InputBase.cpp
+++ b/Source/Core/InputCommon/Src/X11InputBase.cpp
@@ -25,92 +25,92 @@ namespace InputCommon
// Taken from wxw source code
KeySym wxCharCodeWXToX(int id)
{
- KeySym keySym;
+ KeySym keySym;
- switch (id)
- {
- case WXK_CANCEL: keySym = XK_Cancel; break;
- case WXK_BACK: keySym = XK_BackSpace; break;
- case WXK_TAB: keySym = XK_Tab; break;
- case WXK_CLEAR: keySym = XK_Clear; break;
- case WXK_RETURN: keySym = XK_Return; break;
- case WXK_SHIFT: keySym = XK_Shift_L; break;
- case WXK_CONTROL: keySym = XK_Control_L; break;
- case WXK_ALT: keySym = XK_Meta_L; break;
- case WXK_CAPITAL: keySym = XK_Caps_Lock; break;
- case WXK_MENU : keySym = XK_Menu; break;
- case WXK_PAUSE: keySym = XK_Pause; break;
- case WXK_ESCAPE: keySym = XK_Escape; break;
- case WXK_SPACE: keySym = ' '; break;
- case WXK_PAGEUP: keySym = XK_Prior; break;
- case WXK_PAGEDOWN: keySym = XK_Next; break;
- case WXK_END: keySym = XK_End; break;
- case WXK_HOME : keySym = XK_Home; break;
- case WXK_LEFT : keySym = XK_Left; break;
- case WXK_UP: keySym = XK_Up; break;
- case WXK_RIGHT: keySym = XK_Right; break;
- case WXK_DOWN : keySym = XK_Down; break;
- case WXK_SELECT: keySym = XK_Select; break;
- case WXK_PRINT: keySym = XK_Print; break;
- case WXK_EXECUTE: keySym = XK_Execute; break;
- case WXK_INSERT: keySym = XK_Insert; break;
- case WXK_DELETE: keySym = XK_Delete; break;
- case WXK_HELP : keySym = XK_Help; break;
- case WXK_NUMPAD0: keySym = XK_KP_0; break; case WXK_NUMPAD_INSERT: keySym = XK_KP_Insert; break;
- case WXK_NUMPAD1: keySym = XK_KP_1; break; case WXK_NUMPAD_END: keySym = XK_KP_End; break;
- case WXK_NUMPAD2: keySym = XK_KP_2; break; case WXK_NUMPAD_DOWN: keySym = XK_KP_Down; break;
- case WXK_NUMPAD3: keySym = XK_KP_3; break; case WXK_NUMPAD_PAGEDOWN: keySym = XK_KP_Page_Down; break;
- case WXK_NUMPAD4: keySym = XK_KP_4; break; case WXK_NUMPAD_LEFT: keySym = XK_KP_Left; break;
- case WXK_NUMPAD5: keySym = XK_KP_5; break;
- case WXK_NUMPAD6: keySym = XK_KP_6; break; case WXK_NUMPAD_RIGHT: keySym = XK_KP_Right; break;
- case WXK_NUMPAD7: keySym = XK_KP_7; break; case WXK_NUMPAD_HOME: keySym = XK_KP_Home; break;
- case WXK_NUMPAD8: keySym = XK_KP_8; break; case WXK_NUMPAD_UP: keySym = XK_KP_Up; break;
- case WXK_NUMPAD9: keySym = XK_KP_9; break; case WXK_NUMPAD_PAGEUP: keySym = XK_KP_Page_Up; break;
- case WXK_NUMPAD_DECIMAL: keySym = XK_KP_Decimal; break; case WXK_NUMPAD_DELETE: keySym = XK_KP_Delete; break;
- case WXK_NUMPAD_MULTIPLY: keySym = XK_KP_Multiply; break;
- case WXK_NUMPAD_ADD: keySym = XK_KP_Add; break;
- case WXK_NUMPAD_SUBTRACT: keySym = XK_KP_Subtract; break;
- case WXK_NUMPAD_DIVIDE: keySym = XK_KP_Divide; break;
- case WXK_NUMPAD_ENTER: keySym = XK_KP_Enter; break;
- case WXK_NUMPAD_SEPARATOR: keySym = XK_KP_Separator; break;
- case WXK_F1: keySym = XK_F1; break;
- case WXK_F2: keySym = XK_F2; break;
- case WXK_F3: keySym = XK_F3; break;
- case WXK_F4: keySym = XK_F4; break;
- case WXK_F5: keySym = XK_F5; break;
- case WXK_F6: keySym = XK_F6; break;
- case WXK_F7: keySym = XK_F7; break;
- case WXK_F8: keySym = XK_F8; break;
- case WXK_F9: keySym = XK_F9; break;
- case WXK_F10: keySym = XK_F10; break;
- case WXK_F11: keySym = XK_F11; break;
- case WXK_F12: keySym = XK_F12; break;
- case WXK_F13: keySym = XK_F13; break;
- case WXK_F14: keySym = XK_F14; break;
- case WXK_F15: keySym = XK_F15; break;
- case WXK_F16: keySym = XK_F16; break;
- case WXK_F17: keySym = XK_F17; break;
- case WXK_F18: keySym = XK_F18; break;
- case WXK_F19: keySym = XK_F19; break;
- case WXK_F20: keySym = XK_F20; break;
- case WXK_F21: keySym = XK_F21; break;
- case WXK_F22: keySym = XK_F22; break;
- case WXK_F23: keySym = XK_F23; break;
- case WXK_F24: keySym = XK_F24; break;
- case WXK_NUMLOCK: keySym = XK_Num_Lock; break;
- case WXK_SCROLL: keySym = XK_Scroll_Lock; break;
+ switch (id)
+ {
+ case WXK_CANCEL: keySym = XK_Cancel; break;
+ case WXK_BACK: keySym = XK_BackSpace; break;
+ case WXK_TAB: keySym = XK_Tab; break;
+ case WXK_CLEAR: keySym = XK_Clear; break;
+ case WXK_RETURN: keySym = XK_Return; break;
+ case WXK_SHIFT: keySym = XK_Shift_L; break;
+ case WXK_CONTROL: keySym = XK_Control_L; break;
+ case WXK_ALT: keySym = XK_Meta_L; break;
+ case WXK_CAPITAL: keySym = XK_Caps_Lock; break;
+ case WXK_MENU : keySym = XK_Menu; break;
+ case WXK_PAUSE: keySym = XK_Pause; break;
+ case WXK_ESCAPE: keySym = XK_Escape; break;
+ case WXK_SPACE: keySym = ' '; break;
+ case WXK_PAGEUP: keySym = XK_Prior; break;
+ case WXK_PAGEDOWN: keySym = XK_Next; break;
+ case WXK_END: keySym = XK_End; break;
+ case WXK_HOME : keySym = XK_Home; break;
+ case WXK_LEFT : keySym = XK_Left; break;
+ case WXK_UP: keySym = XK_Up; break;
+ case WXK_RIGHT: keySym = XK_Right; break;
+ case WXK_DOWN : keySym = XK_Down; break;
+ case WXK_SELECT: keySym = XK_Select; break;
+ case WXK_PRINT: keySym = XK_Print; break;
+ case WXK_EXECUTE: keySym = XK_Execute; break;
+ case WXK_INSERT: keySym = XK_Insert; break;
+ case WXK_DELETE: keySym = XK_Delete; break;
+ case WXK_HELP : keySym = XK_Help; break;
+ case WXK_NUMPAD0: keySym = XK_KP_0; break; case WXK_NUMPAD_INSERT: keySym = XK_KP_Insert; break;
+ case WXK_NUMPAD1: keySym = XK_KP_1; break; case WXK_NUMPAD_END: keySym = XK_KP_End; break;
+ case WXK_NUMPAD2: keySym = XK_KP_2; break; case WXK_NUMPAD_DOWN: keySym = XK_KP_Down; break;
+ case WXK_NUMPAD3: keySym = XK_KP_3; break; case WXK_NUMPAD_PAGEDOWN: keySym = XK_KP_Page_Down; break;
+ case WXK_NUMPAD4: keySym = XK_KP_4; break; case WXK_NUMPAD_LEFT: keySym = XK_KP_Left; break;
+ case WXK_NUMPAD5: keySym = XK_KP_5; break;
+ case WXK_NUMPAD6: keySym = XK_KP_6; break; case WXK_NUMPAD_RIGHT: keySym = XK_KP_Right; break;
+ case WXK_NUMPAD7: keySym = XK_KP_7; break; case WXK_NUMPAD_HOME: keySym = XK_KP_Home; break;
+ case WXK_NUMPAD8: keySym = XK_KP_8; break; case WXK_NUMPAD_UP: keySym = XK_KP_Up; break;
+ case WXK_NUMPAD9: keySym = XK_KP_9; break; case WXK_NUMPAD_PAGEUP: keySym = XK_KP_Page_Up; break;
+ case WXK_NUMPAD_DECIMAL: keySym = XK_KP_Decimal; break; case WXK_NUMPAD_DELETE: keySym = XK_KP_Delete; break;
+ case WXK_NUMPAD_MULTIPLY: keySym = XK_KP_Multiply; break;
+ case WXK_NUMPAD_ADD: keySym = XK_KP_Add; break;
+ case WXK_NUMPAD_SUBTRACT: keySym = XK_KP_Subtract; break;
+ case WXK_NUMPAD_DIVIDE: keySym = XK_KP_Divide; break;
+ case WXK_NUMPAD_ENTER: keySym = XK_KP_Enter; break;
+ case WXK_NUMPAD_SEPARATOR: keySym = XK_KP_Separator; break;
+ case WXK_F1: keySym = XK_F1; break;
+ case WXK_F2: keySym = XK_F2; break;
+ case WXK_F3: keySym = XK_F3; break;
+ case WXK_F4: keySym = XK_F4; break;
+ case WXK_F5: keySym = XK_F5; break;
+ case WXK_F6: keySym = XK_F6; break;
+ case WXK_F7: keySym = XK_F7; break;
+ case WXK_F8: keySym = XK_F8; break;
+ case WXK_F9: keySym = XK_F9; break;
+ case WXK_F10: keySym = XK_F10; break;
+ case WXK_F11: keySym = XK_F11; break;
+ case WXK_F12: keySym = XK_F12; break;
+ case WXK_F13: keySym = XK_F13; break;
+ case WXK_F14: keySym = XK_F14; break;
+ case WXK_F15: keySym = XK_F15; break;
+ case WXK_F16: keySym = XK_F16; break;
+ case WXK_F17: keySym = XK_F17; break;
+ case WXK_F18: keySym = XK_F18; break;
+ case WXK_F19: keySym = XK_F19; break;
+ case WXK_F20: keySym = XK_F20; break;
+ case WXK_F21: keySym = XK_F21; break;
+ case WXK_F22: keySym = XK_F22; break;
+ case WXK_F23: keySym = XK_F23; break;
+ case WXK_F24: keySym = XK_F24; break;
+ case WXK_NUMLOCK: keySym = XK_Num_Lock; break;
+ case WXK_SCROLL: keySym = XK_Scroll_Lock; break;
// Input fix: Config dialogs read all alphabetic characters as UPPERCASE and
// saves the UPPERCASE keycodes. X11 reads these as lowercase by default.
default:
- if (id >= 65 && id <= 90)
- // Standard uppercase letter: return lowercase keycode
- keySym = (KeySym)id + 32;
- else
- // All other keyboard characters
- keySym = id <= 255 ? (KeySym)id : 0;
- }
+ if (id >= 65 && id <= 90)
+ // Standard uppercase letter: return lowercase keycode
+ keySym = (KeySym)id + 32;
+ else
+ // All other keyboard characters
+ keySym = id <= 255 ? (KeySym)id : 0;
+ }
- return keySym;
+ return keySym;
}
int wxKeyModWXToX(int modstate)
{
@@ -125,178 +125,178 @@ int wxKeyModWXToX(int modstate)
}
#endif
void XKeyToString(unsigned int keycode, char *keyStr) {
- switch (keycode) {
-
- case XK_Insert:
- sprintf(keyStr, "INSERT");
- break;
- case XK_Delete:
- sprintf(keyStr, "DELETE");
- break;
- case XK_Home:
- sprintf(keyStr, "HOME");
- break;
- case XK_End:
- sprintf(keyStr, "END");
- break;
- case XK_Prior:
- sprintf(keyStr, "PAGEUP");
- break;
- case XK_Next:
- sprintf(keyStr, "PAGEDOWN");
- break;
- case XK_Left:
- sprintf(keyStr, "LEFT");
- break;
- case XK_Up:
- sprintf(keyStr, "UP");
- break;
- case XK_Right:
- sprintf(keyStr, "RIGHT");
- break;
- case XK_Down:
- sprintf(keyStr, "DOWN");
- break;
- case XK_Return:
- sprintf(keyStr, "RETURN");
- break;
- case XK_Escape:
- sprintf(keyStr, "ESCAPE");
- break;
- case XK_Caps_Lock:
- sprintf(keyStr, "CAPSLOCK");
- break;
- case XK_BackSpace:
- sprintf(keyStr, "BACKSPACE");
- break;
- case XK_Tab:
- sprintf(keyStr, "TAB");
- break;
- case XK_KP_Enter:
- sprintf(keyStr, "KP ENTER");
- break;
- case XK_KP_Left:
- sprintf(keyStr, "KP LEFT");
- break;
- case XK_KP_Up:
- sprintf(keyStr, "KP UP");
- break;
- case XK_KP_Right:
- sprintf(keyStr, "KP RIGHT");
- break;
- case XK_KP_Down:
- sprintf(keyStr, "KP DOWN");
- break;
- case XK_KP_Insert:
- sprintf(keyStr, "KP Insert");
- break;
- case XK_KP_Delete:
- sprintf(keyStr, "KP Delete");
- break;
- case XK_KP_Page_Down:
- sprintf(keyStr, "KP Page Down");
- break;
- case XK_KP_Page_Up:
- sprintf(keyStr, "KP Page Up");
- break;
- case XK_KP_Separator:
- sprintf(keyStr, "KP Separator");
- break;
- case XK_KP_Home:
- sprintf(keyStr, "KP Home");
- break;
- case XK_KP_End:
- sprintf(keyStr, "KP End");
- break;
- case XK_KP_Subtract:
- sprintf(keyStr, "KP -");
- break;
- case XK_KP_Add:
- sprintf(keyStr, "KP +");
- break;
- case XK_KP_Multiply:
- sprintf(keyStr, "KP *");
- break;
- case XK_KP_Divide:
- sprintf(keyStr, "KP /");
- break;
- case XK_KP_Decimal:
- sprintf(keyStr, "KP .");
- break;
- case XK_KP_0:
- sprintf(keyStr, "KP 0");
- break;
- case XK_KP_1:
- sprintf(keyStr, "KP 1");
- break;
- case XK_KP_2:
- sprintf(keyStr, "KP 2");
- break;
- case XK_KP_3:
- sprintf(keyStr, "KP 3");
- break;
- case XK_KP_4:
- sprintf(keyStr, "KP 4");
- break;
- case XK_KP_5:
- sprintf(keyStr, "KP 5");
- break;
- case XK_KP_6:
- sprintf(keyStr, "KP 6");
- break;
- case XK_KP_7:
- sprintf(keyStr, "KP 7");
- break;
- case XK_KP_8:
- sprintf(keyStr, "KP 8");
- break;
- case XK_KP_9:
- sprintf(keyStr, "KP 9");
- break;
- case XK_Shift_L:
- sprintf(keyStr, "LShift");
- break;
- case XK_Control_L:
- sprintf(keyStr, "LControl");
- break;
- case XK_F1:
- sprintf(keyStr, "F1");
- break;
- case XK_F2:
- sprintf(keyStr, "F2");
- break;
- case XK_F3:
- sprintf(keyStr, "F3");
- break;
- case XK_F4:
- sprintf(keyStr, "F4");
- break;
- case XK_F5:
- sprintf(keyStr, "F5");
- break;
- case XK_F6:
- sprintf(keyStr, "F6");
- break;
- case XK_F7:
- sprintf(keyStr, "F7");
- break;
- case XK_F8:
- sprintf(keyStr, "F8");
- break;
- case XK_F9:
- sprintf(keyStr, "F9");
- break;
- case XK_F10:
- sprintf(keyStr, "F10");
- break;
- case XK_F11:
- sprintf(keyStr, "F11");
- break;
- case XK_F12:
- sprintf(keyStr, "F12");
- break;
- default:
- sprintf(keyStr, "%c", toupper(keycode));
- }
+ switch (keycode)
+ {
+ case XK_Insert:
+ sprintf(keyStr, "INSERT");
+ break;
+ case XK_Delete:
+ sprintf(keyStr, "DELETE");
+ break;
+ case XK_Home:
+ sprintf(keyStr, "HOME");
+ break;
+ case XK_End:
+ sprintf(keyStr, "END");
+ break;
+ case XK_Prior:
+ sprintf(keyStr, "PAGEUP");
+ break;
+ case XK_Next:
+ sprintf(keyStr, "PAGEDOWN");
+ break;
+ case XK_Left:
+ sprintf(keyStr, "LEFT");
+ break;
+ case XK_Up:
+ sprintf(keyStr, "UP");
+ break;
+ case XK_Right:
+ sprintf(keyStr, "RIGHT");
+ break;
+ case XK_Down:
+ sprintf(keyStr, "DOWN");
+ break;
+ case XK_Return:
+ sprintf(keyStr, "RETURN");
+ break;
+ case XK_Escape:
+ sprintf(keyStr, "ESCAPE");
+ break;
+ case XK_Caps_Lock:
+ sprintf(keyStr, "CAPSLOCK");
+ break;
+ case XK_BackSpace:
+ sprintf(keyStr, "BACKSPACE");
+ break;
+ case XK_Tab:
+ sprintf(keyStr, "TAB");
+ break;
+ case XK_KP_Enter:
+ sprintf(keyStr, "KP ENTER");
+ break;
+ case XK_KP_Left:
+ sprintf(keyStr, "KP LEFT");
+ break;
+ case XK_KP_Up:
+ sprintf(keyStr, "KP UP");
+ break;
+ case XK_KP_Right:
+ sprintf(keyStr, "KP RIGHT");
+ break;
+ case XK_KP_Down:
+ sprintf(keyStr, "KP DOWN");
+ break;
+ case XK_KP_Insert:
+ sprintf(keyStr, "KP Insert");
+ break;
+ case XK_KP_Delete:
+ sprintf(keyStr, "KP Delete");
+ break;
+ case XK_KP_Page_Down:
+ sprintf(keyStr, "KP Page Down");
+ break;
+ case XK_KP_Page_Up:
+ sprintf(keyStr, "KP Page Up");
+ break;
+ case XK_KP_Separator:
+ sprintf(keyStr, "KP Separator");
+ break;
+ case XK_KP_Home:
+ sprintf(keyStr, "KP Home");
+ break;
+ case XK_KP_End:
+ sprintf(keyStr, "KP End");
+ break;
+ case XK_KP_Subtract:
+ sprintf(keyStr, "KP -");
+ break;
+ case XK_KP_Add:
+ sprintf(keyStr, "KP +");
+ break;
+ case XK_KP_Multiply:
+ sprintf(keyStr, "KP *");
+ break;
+ case XK_KP_Divide:
+ sprintf(keyStr, "KP /");
+ break;
+ case XK_KP_Decimal:
+ sprintf(keyStr, "KP .");
+ break;
+ case XK_KP_0:
+ sprintf(keyStr, "KP 0");
+ break;
+ case XK_KP_1:
+ sprintf(keyStr, "KP 1");
+ break;
+ case XK_KP_2:
+ sprintf(keyStr, "KP 2");
+ break;
+ case XK_KP_3:
+ sprintf(keyStr, "KP 3");
+ break;
+ case XK_KP_4:
+ sprintf(keyStr, "KP 4");
+ break;
+ case XK_KP_5:
+ sprintf(keyStr, "KP 5");
+ break;
+ case XK_KP_6:
+ sprintf(keyStr, "KP 6");
+ break;
+ case XK_KP_7:
+ sprintf(keyStr, "KP 7");
+ break;
+ case XK_KP_8:
+ sprintf(keyStr, "KP 8");
+ break;
+ case XK_KP_9:
+ sprintf(keyStr, "KP 9");
+ break;
+ case XK_Shift_L:
+ sprintf(keyStr, "LShift");
+ break;
+ case XK_Control_L:
+ sprintf(keyStr, "LControl");
+ break;
+ case XK_F1:
+ sprintf(keyStr, "F1");
+ break;
+ case XK_F2:
+ sprintf(keyStr, "F2");
+ break;
+ case XK_F3:
+ sprintf(keyStr, "F3");
+ break;
+ case XK_F4:
+ sprintf(keyStr, "F4");
+ break;
+ case XK_F5:
+ sprintf(keyStr, "F5");
+ break;
+ case XK_F6:
+ sprintf(keyStr, "F6");
+ break;
+ case XK_F7:
+ sprintf(keyStr, "F7");
+ break;
+ case XK_F8:
+ sprintf(keyStr, "F8");
+ break;
+ case XK_F9:
+ sprintf(keyStr, "F9");
+ break;
+ case XK_F10:
+ sprintf(keyStr, "F10");
+ break;
+ case XK_F11:
+ sprintf(keyStr, "F11");
+ break;
+ case XK_F12:
+ sprintf(keyStr, "F12");
+ break;
+ default:
+ sprintf(keyStr, "%c", toupper(keycode));
+ }
}
}
diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt
index 6ed8e29c6b..89b6828281 100644
--- a/Source/Core/VideoCommon/CMakeLists.txt
+++ b/Source/Core/VideoCommon/CMakeLists.txt
@@ -3,7 +3,6 @@ set(SRCS Src/BPFunctions.cpp
Src/BPStructs.cpp
Src/CPMemory.cpp
Src/CommandProcessor.cpp
- Src/DLCache.cpp
Src/Debugger.cpp
Src/Fifo.cpp
Src/FPSCounter.cpp
@@ -17,6 +16,7 @@ set(SRCS Src/BPFunctions.cpp
Src/OpcodeDecoding.cpp
Src/OpenCL.cpp
Src/OpenCL/OCLTextureDecoder.cpp
+ Src/PerfQueryBase.cpp
Src/PixelEngine.cpp
Src/PixelShaderGen.cpp
Src/PixelShaderManager.cpp
@@ -24,7 +24,6 @@ set(SRCS Src/BPFunctions.cpp
Src/Statistics.cpp
Src/TextureCacheBase.cpp
Src/TextureConversionShader.cpp
- Src/TextureDecoder.cpp
Src/VertexLoader.cpp
Src/VertexLoaderManager.cpp
Src/VertexLoader_Color.cpp
@@ -41,6 +40,14 @@ set(SRCS Src/BPFunctions.cpp
Src/memcpy_amd.cpp)
set(LIBS core)
+
+if(NOT _M_GENERIC)
+ set(SRCS ${SRCS} Src/x64TextureDecoder.cpp
+ Src/x64DLCache.cpp)
+else()
+ set(SRCS ${SRCS} Src/GenericTextureDecoder.cpp
+ Src/GenericDLCache.cpp)
+endif()
if(NOT ${CL} STREQUAL CL-NOTFOUND)
list(APPEND LIBS ${CL})
endif()
diff --git a/Source/Core/VideoCommon/Src/AVIDump.cpp b/Source/Core/VideoCommon/Src/AVIDump.cpp
index c172903b5d..fefb09fecb 100644
--- a/Source/Core/VideoCommon/Src/AVIDump.cpp
+++ b/Source/Core/VideoCommon/Src/AVIDump.cpp
@@ -157,9 +157,21 @@ void AVIDump::Stop()
NOTICE_LOG(VIDEO, "Stop");
}
-void AVIDump::AddFrame(char *data)
+void AVIDump::AddFrame(const u8* data, int w, int h)
{
- AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
+ static bool shown_error = false;
+ if ((w != m_bitmap.biWidth || h != m_bitmap.biHeight) && !shown_error)
+ {
+ PanicAlert("You have resized the window while dumping frames.\n"
+ "Nothing sane can be done to handle this.\n"
+ "Your video will likely be broken.");
+ shown_error = true;
+
+ m_bitmap.biWidth = w;
+ m_bitmap.biHeight = h;
+ }
+
+ AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, const_cast<u8*>(data), m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
m_totalBytes += m_byteBuffer;
// Close the recording if the file is more than 2gb
// VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
@@ -298,9 +310,9 @@ bool AVIDump::CreateFile()
return true;
}
-void AVIDump::AddFrame(uint8_t *data, int width, int height)
+void AVIDump::AddFrame(const u8* data, int width, int height)
{
- avpicture_fill((AVPicture *)s_BGRFrame, data, PIX_FMT_BGR24, width, height);
+ avpicture_fill((AVPicture *)s_BGRFrame, const_cast<u8*>(data), PIX_FMT_BGR24, width, height);
// Convert image from BGR24 to desired pixel format, and scale to initial
// width and height
diff --git a/Source/Core/VideoCommon/Src/AVIDump.h b/Source/Core/VideoCommon/Src/AVIDump.h
index e74df05db4..08ab6be254 100644
--- a/Source/Core/VideoCommon/Src/AVIDump.h
+++ b/Source/Core/VideoCommon/Src/AVIDump.h
@@ -24,6 +24,8 @@
#include <stdint.h>
#endif
+#include "CommonTypes.h"
+
class AVIDump
{
private:
@@ -36,11 +38,11 @@ class AVIDump
public:
#ifdef _WIN32
static bool Start(HWND hWnd, int w, int h);
- static void AddFrame(char *data);
#else
static bool Start(int w, int h);
- static void AddFrame(uint8_t *data, int width, int height);
#endif
+ static void AddFrame(const u8* data, int width, int height);
+
static void Stop();
};
diff --git a/Source/Core/VideoCommon/Src/BPFunctions.cpp b/Source/Core/VideoCommon/Src/BPFunctions.cpp
index cddeae3000..8dd24f4ed1 100644
--- a/Source/Core/VideoCommon/Src/BPFunctions.cpp
+++ b/Source/Core/VideoCommon/Src/BPFunctions.cpp
@@ -236,7 +236,7 @@ bool GetConfig(const int &type)
case CONFIG_DISABLEFOG:
return g_ActiveConfig.bDisableFog;
case CONFIG_SHOWEFBREGIONS:
- return false;
+ return g_ActiveConfig.bShowEFBCopyRegions;
default:
PanicAlert("GetConfig Error: Unknown Config Type!");
return false;
@@ -248,6 +248,7 @@ u8 *GetPointer(const u32 &address)
return Memory::GetPointer(address);
}
+// Never used. All backends call SetSamplerState in VertexManager::Flush
void SetTextureMode(const BPCmd &bp)
{
g_renderer->SetSamplerState(bp.address & 3, (bp.address & 0xE0) == 0xA0);
diff --git a/Source/Core/VideoCommon/Src/BPMemory.h b/Source/Core/VideoCommon/Src/BPMemory.h
index 85e95f4f8b..1a29439b36 100644
--- a/Source/Core/VideoCommon/Src/BPMemory.h
+++ b/Source/Core/VideoCommon/Src/BPMemory.h
@@ -62,7 +62,7 @@
#define BPMEM_COPYFILTER1 0x54
#define BPMEM_CLEARBBOX1 0x55
#define BPMEM_CLEARBBOX2 0x56
-#define BPMEM_UNKNOWN_57 0x57
+#define BPMEM_CLEAR_PIXEL_PERF 0x57
#define BPMEM_REVBITS 0x58
#define BPMEM_SCISSOROFFSET 0x59
#define BPMEM_PRELOAD_ADDR 0x60
@@ -93,7 +93,7 @@
#define BPMEM_TEV_ALPHA_ENV 0xC1 // 0xC1 + (2 * 16)
#define BPMEM_TEV_REGISTER_L 0xE0 // 0xE0 + (2 * 4)
#define BPMEM_TEV_REGISTER_H 0xE1 // 0xE1 + (2 * 4)
-#define BPMEM_FOGRANGE 0xE8
+#define BPMEM_FOGRANGE 0xE8 // 0xE8 + 6
#define BPMEM_FOGPARAM0 0xEE
#define BPMEM_FOGBMAGNITUDE 0xEF
#define BPMEM_FOGBEXPONENT 0xF0
@@ -197,55 +197,55 @@ enum AlphaOp
union IND_MTXA
{
- struct
- {
- s32 ma : 11;
- s32 mb : 11;
- u32 s0 : 2; // bits 0-1 of scale factor
- u32 rid : 8;
- };
- u32 hex;
+ struct
+ {
+ s32 ma : 11;
+ s32 mb : 11;
+ u32 s0 : 2; // bits 0-1 of scale factor
+ u32 rid : 8;
+ };
+ u32 hex;
};
union IND_MTXB
{
- struct
- {
- s32 mc : 11;
- s32 md : 11;
- u32 s1 : 2; // bits 2-3 of scale factor
- u32 rid : 8;
- };
- u32 hex;
+ struct
+ {
+ s32 mc : 11;
+ s32 md : 11;
+ u32 s1 : 2; // bits 2-3 of scale factor
+ u32 rid : 8;
+ };
+ u32 hex;
};
union IND_MTXC
{
- struct
- {
- s32 me : 11;
- s32 mf : 11;
- u32 s2 : 2; // bits 4-5 of scale factor
- u32 rid : 8;
- };
- u32 hex;
+ struct
+ {
+ s32 me : 11;
+ s32 mf : 11;
+ u32 s2 : 2; // bits 4-5 of scale factor
+ u32 rid : 8;
+ };
+ u32 hex;
};
struct IND_MTX
{
- IND_MTXA col0;
- IND_MTXB col1;
- IND_MTXC col2;
+ IND_MTXA col0;
+ IND_MTXB col1;
+ IND_MTXC col2;
};
union IND_IMASK
{
- struct
- {
- u32 mask : 24;
- u32 rid : 8;
- };
- u32 hex;
+ struct
+ {
+ u32 mask : 24;
+ u32 rid : 8;
+ };
+ u32 hex;
};
#define TEVSELCC_CPREV 0
@@ -276,48 +276,48 @@ union IND_IMASK
struct TevStageCombiner
{
- union ColorCombiner
- {
- struct //abc=8bit,d=10bit
- {
- u32 d : 4; // TEVSELCC_X
- u32 c : 4; // TEVSELCC_X
- u32 b : 4; // TEVSELCC_X
- u32 a : 4; // TEVSELCC_X
-
- u32 bias : 2;
- u32 op : 1;
- u32 clamp : 1;
-
- u32 shift : 2;
- u32 dest : 2; //1,2,3
-
- };
- u32 hex;
- };
- union AlphaCombiner
- {
- struct
- {
- u32 rswap : 2;
- u32 tswap : 2;
- u32 d : 3; // TEVSELCA_
- u32 c : 3; // TEVSELCA_
- u32 b : 3; // TEVSELCA_
- u32 a : 3; // TEVSELCA_
-
- u32 bias : 2; //GXTevBias
- u32 op : 1;
- u32 clamp : 1;
-
- u32 shift : 2;
- u32 dest : 2; //1,2,3
- };
- u32 hex;
- };
-
- ColorCombiner colorC;
- AlphaCombiner alphaC;
+ union ColorCombiner
+ {
+ struct //abc=8bit,d=10bit
+ {
+ u32 d : 4; // TEVSELCC_X
+ u32 c : 4; // TEVSELCC_X
+ u32 b : 4; // TEVSELCC_X
+ u32 a : 4; // TEVSELCC_X
+
+ u32 bias : 2;
+ u32 op : 1;
+ u32 clamp : 1;
+
+ u32 shift : 2;
+ u32 dest : 2; //1,2,3
+
+ };
+ u32 hex;
+ };
+ union AlphaCombiner
+ {
+ struct
+ {
+ u32 rswap : 2;
+ u32 tswap : 2;
+ u32 d : 3; // TEVSELCA_
+ u32 c : 3; // TEVSELCA_
+ u32 b : 3; // TEVSELCA_
+ u32 a : 3; // TEVSELCA_
+
+ u32 bias : 2; //GXTevBias
+ u32 op : 1;
+ u32 clamp : 1;
+
+ u32 shift : 2;
+ u32 dest : 2; //1,2,3
+ };
+ u32 hex;
+ };
+
+ ColorCombiner colorC;
+ AlphaCombiner alphaC;
};
#define ITF_8 0
@@ -356,93 +356,93 @@ struct TevStageCombiner
// GXSetTevIndirect(tevstage+1, indstage, 0, 3, realmat+4, 6, 6, 1, 0, 0)
// GXSetTevIndirect(tevstage+2, indstage, 0, 0, 0, 0, 0, 1, 0, 0)
-union TevStageIndirect
-{
- // if mid, sw, tw, and addprev are 0, then no indirect stage is used, mask = 0x17fe00
- struct
- {
- u32 bt : 2; // indirect tex stage ID
- u32 fmt : 2; // format: ITF_X
- u32 bias : 3; // ITB_X
- u32 bs : 2; // ITBA_X, indicates which coordinate will become the 'bump alpha'
- u32 mid : 4; // matrix id to multiply offsets with
- u32 sw : 3; // ITW_X, wrapping factor for S of regular coord
- u32 tw : 3; // ITW_X, wrapping factor for T of regular coord
- u32 lb_utclod : 1; // use modified or unmodified texture coordinates for LOD computation
- u32 fb_addprev : 1; // 1 if the texture coordinate results from the previous TEV stage should be added
- u32 pad0 : 3;
- u32 rid : 8;
- };
- struct
- {
- u32 hex : 21;
- u32 unused : 11;
- };
-
- bool IsActive() { return (hex&0x17fe00)!=0; }
-};
-
-union TwoTevStageOrders
-{
- struct
- {
- u32 texmap0 : 3; // indirect tex stage texmap
- u32 texcoord0 : 3;
- u32 enable0 : 1; // 1 if should read from texture
- u32 colorchan0 : 3; // RAS1_CC_X
-
- u32 pad0 : 2;
-
- u32 texmap1 : 3;
- u32 texcoord1 : 3;
- u32 enable1 : 1; // 1 if should read from texture
- u32 colorchan1 : 3; // RAS1_CC_X
-
- u32 pad1 : 2;
- u32 rid : 8;
- };
- u32 hex;
- int getTexMap(int i){return i?texmap1:texmap0;}
- int getTexCoord(int i){return i?texcoord1:texcoord0;}
- int getEnable(int i){return i?enable1:enable0;}
- int getColorChan(int i){return i?colorchan1:colorchan0;}
-};
+ union TevStageIndirect
+ {
+ // if mid, sw, tw, and addprev are 0, then no indirect stage is used, mask = 0x17fe00
+ struct
+ {
+ u32 bt : 2; // indirect tex stage ID
+ u32 fmt : 2; // format: ITF_X
+ u32 bias : 3; // ITB_X
+ u32 bs : 2; // ITBA_X, indicates which coordinate will become the 'bump alpha'
+ u32 mid : 4; // matrix id to multiply offsets with
+ u32 sw : 3; // ITW_X, wrapping factor for S of regular coord
+ u32 tw : 3; // ITW_X, wrapping factor for T of regular coord
+ u32 lb_utclod : 1; // use modified or unmodified texture coordinates for LOD computation
+ u32 fb_addprev : 1; // 1 if the texture coordinate results from the previous TEV stage should be added
+ u32 pad0 : 3;
+ u32 rid : 8;
+ };
+ struct
+ {
+ u32 hex : 21;
+ u32 unused : 11;
+ };
+
+ bool IsActive() { return (hex&0x17fe00)!=0; }
+ };
+
+ union TwoTevStageOrders
+ {
+ struct
+ {
+ u32 texmap0 : 3; // indirect tex stage texmap
+ u32 texcoord0 : 3;
+ u32 enable0 : 1; // 1 if should read from texture
+ u32 colorchan0 : 3; // RAS1_CC_X
+
+ u32 pad0 : 2;
+
+ u32 texmap1 : 3;
+ u32 texcoord1 : 3;
+ u32 enable1 : 1; // 1 if should read from texture
+ u32 colorchan1 : 3; // RAS1_CC_X
+
+ u32 pad1 : 2;
+ u32 rid : 8;
+ };
+ u32 hex;
+ int getTexMap(int i){return i?texmap1:texmap0;}
+ int getTexCoord(int i){return i?texcoord1:texcoord0;}
+ int getEnable(int i){return i?enable1:enable0;}
+ int getColorChan(int i){return i?colorchan1:colorchan0;}
+ };
union TEXSCALE
{
- struct
- {
- u32 ss0 : 4; // indirect tex stage 0, 2^(-ss0)
- u32 ts0 : 4; // indirect tex stage 0
- u32 ss1 : 4; // indirect tex stage 1
- u32 ts1 : 4; // indirect tex stage 1
- u32 pad : 8;
- u32 rid : 8;
- };
- u32 hex;
+ struct
+ {
+ u32 ss0 : 4; // indirect tex stage 0, 2^(-ss0)
+ u32 ts0 : 4; // indirect tex stage 0
+ u32 ss1 : 4; // indirect tex stage 1
+ u32 ts1 : 4; // indirect tex stage 1
+ u32 pad : 8;
+ u32 rid : 8;
+ };
+ u32 hex;
- float getScaleS(int i){return 1.0f/(float)(1<<(i?ss1:ss0));}
- float getScaleT(int i){return 1.0f/(float)(1<<(i?ts1:ts0));}
+ float getScaleS(int i){return 1.0f/(float)(1<<(i?ss1:ss0));}
+ float getScaleT(int i){return 1.0f/(float)(1<<(i?ts1:ts0));}
};
union RAS1_IREF
{
- struct
- {
- u32 bi0 : 3; // indirect tex stage 0 ntexmap
- u32 bc0 : 3; // indirect tex stage 0 ntexcoord
- u32 bi1 : 3;
- u32 bc1 : 3;
- u32 bi2 : 3;
- u32 bc3 : 3;
- u32 bi4 : 3;
- u32 bc4 : 3;
- u32 rid : 8;
- };
- u32 hex;
+ struct
+ {
+ u32 bi0 : 3; // indirect tex stage 0 ntexmap
+ u32 bc0 : 3; // indirect tex stage 0 ntexcoord
+ u32 bi1 : 3;
+ u32 bc1 : 3;
+ u32 bi2 : 3;
+ u32 bc3 : 3;
+ u32 bi4 : 3;
+ u32 bc4 : 3;
+ u32 rid : 8;
+ };
+ u32 hex;
- u32 getTexCoord(int i) { return (hex>>(6*i+3))&3; }
- u32 getTexMap(int i) { return (hex>>(6*i))&3; }
+ u32 getTexCoord(int i) { return (hex>>(6*i+3))&3; }
+ u32 getTexMap(int i) { return (hex>>(6*i))&3; }
};
@@ -450,97 +450,97 @@ union RAS1_IREF
union TexMode0
{
- struct
- {
- u32 wrap_s : 2;
- u32 wrap_t : 2;
- u32 mag_filter : 1;
- u32 min_filter : 3;
- u32 diag_lod : 1;
- s32 lod_bias : 8;
+ struct
+ {
+ u32 wrap_s : 2;
+ u32 wrap_t : 2;
+ u32 mag_filter : 1;
+ u32 min_filter : 3;
+ u32 diag_lod : 1;
+ s32 lod_bias : 8;
u32 pad0 : 2;
- u32 max_aniso : 2;
- u32 lod_clamp : 1;
- };
- u32 hex;
+ u32 max_aniso : 2;
+ u32 lod_clamp : 1;
+ };
+ u32 hex;
};
union TexMode1
{
- struct
- {
- u32 min_lod : 8;
- u32 max_lod : 8;
- };
- u32 hex;
+ struct
+ {
+ u32 min_lod : 8;
+ u32 max_lod : 8;
+ };
+ u32 hex;
};
union TexImage0
{
- struct
- {
- u32 width : 10; //actually w-1
- u32 height : 10; //actually h-1
- u32 format : 4;
- };
- u32 hex;
+ struct
+ {
+ u32 width : 10; //actually w-1
+ u32 height : 10; //actually h-1
+ u32 format : 4;
+ };
+ u32 hex;
};
union TexImage1
{
- struct
- {
- u32 tmem_even : 15; // tmem line index for even LODs
- u32 cache_width : 3;
- u32 cache_height : 3;
- u32 image_type : 1; // 1 if this texture is managed manually (0 means we'll autofetch the texture data whenever it changes)
- };
- u32 hex;
+ struct
+ {
+ u32 tmem_even : 15; // tmem line index for even LODs
+ u32 cache_width : 3;
+ u32 cache_height : 3;
+ u32 image_type : 1; // 1 if this texture is managed manually (0 means we'll autofetch the texture data whenever it changes)
+ };
+ u32 hex;
};
union TexImage2
{
- struct
- {
- u32 tmem_odd : 15; // tmem line index for odd LODs
- u32 cache_width : 3;
- u32 cache_height : 3;
- };
- u32 hex;
+ struct
+ {
+ u32 tmem_odd : 15; // tmem line index for odd LODs
+ u32 cache_width : 3;
+ u32 cache_height : 3;
+ };
+ u32 hex;
};
union TexImage3
{
- struct
- {
- u32 image_base: 24; //address in memory >> 5 (was 20 for GC)
- };
- u32 hex;
+ struct
+ {
+ u32 image_base: 24; //address in memory >> 5 (was 20 for GC)
+ };
+ u32 hex;
};
union TexTLUT
{
- struct
- {
- u32 tmem_offset : 10;
- u32 tlut_format : 2;
- };
- u32 hex;
+ struct
+ {
+ u32 tmem_offset : 10;
+ u32 tlut_format : 2;
+ };
+ u32 hex;
};
union ZTex1
{
- struct
- {
- u32 bias : 24;
- };
- u32 hex;
+ struct
+ {
+ u32 bias : 24;
+ };
+ u32 hex;
};
union ZTex2
{
- struct
- {
- u32 type : 2; // TEV_Z_TYPE_X
- u32 op : 2; // GXZTexOp
- };
- u32 hex;
+ struct
+ {
+ u32 type : 2; // TEV_Z_TYPE_X
+ u32 op : 2; // GXZTexOp
+ };
+ u32 hex;
};
// Z-texture types (formats)
@@ -555,14 +555,14 @@ union ZTex2
struct FourTexUnits
{
- TexMode0 texMode0[4];
- TexMode1 texMode1[4];
- TexImage0 texImage0[4];
- TexImage1 texImage1[4];
- TexImage2 texImage2[4];
- TexImage3 texImage3[4];
- TexTLUT texTlut[4];
- u32 unknown[4];
+ TexMode0 texMode0[4];
+ TexMode1 texMode1[4];
+ TexImage0 texImage0[4];
+ TexImage1 texImage1[4];
+ TexImage2 texImage2[4];
+ TexImage3 texImage3[4];
+ TexTLUT texTlut[4];
+ u32 unknown[4];
};
@@ -571,51 +571,51 @@ struct FourTexUnits
union GenMode
{
- struct
- {
- u32 numtexgens : 4; // 0xF
- u32 numcolchans : 5; // 0x1E0
- u32 ms_en : 1; // 0x200
- u32 numtevstages : 4; // 0x3C00
- u32 cullmode : 2; // 0xC000
- u32 numindstages : 3; // 0x30000
- u32 zfreeze : 5; //0x3C0000
- };
- u32 hex;
+ struct
+ {
+ u32 numtexgens : 4; // 0xF
+ u32 numcolchans : 5; // 0x1E0
+ u32 ms_en : 1; // 0x200
+ u32 numtevstages : 4; // 0x3C00
+ u32 cullmode : 2; // 0xC000
+ u32 numindstages : 3; // 0x30000
+ u32 zfreeze : 5; //0x3C0000
+ };
+ u32 hex;
};
union LPSize
{
- struct
- {
- u32 linesize : 8; // in 1/6th pixels
- u32 pointsize : 8; // in 1/6th pixels
- u32 lineoff : 3;
- u32 pointoff : 3;
- u32 lineaspect : 1; // interlacing: adjust for pixels having AR of 1/2
- u32 padding : 1;
- };
- u32 hex;
+ struct
+ {
+ u32 linesize : 8; // in 1/6th pixels
+ u32 pointsize : 8; // in 1/6th pixels
+ u32 lineoff : 3;
+ u32 pointoff : 3;
+ u32 lineaspect : 1; // interlacing: adjust for pixels having AR of 1/2
+ u32 padding : 1;
+ };
+ u32 hex;
};
union X12Y12
{
- struct
- {
- u32 y : 12;
- u32 x : 12;
- };
- u32 hex;
+ struct
+ {
+ u32 y : 12;
+ u32 x : 12;
+ };
+ u32 hex;
};
union X10Y10
{
- struct
- {
- u32 x : 10;
- u32 y : 10;
- };
- u32 hex;
+ struct
+ {
+ u32 x : 10;
+ u32 y : 10;
+ };
+ u32 hex;
};
@@ -623,59 +623,59 @@ union X10Y10
union BlendMode
{
- struct
- {
- u32 blendenable : 1;
- u32 logicopenable : 1;
- u32 dither : 1;
- u32 colorupdate : 1;
- u32 alphaupdate : 1;
- u32 dstfactor : 3; //BLEND_ONE, BLEND_INV_SRc etc
- u32 srcfactor : 3;
- u32 subtract : 1;
- u32 logicmode : 4;
- };
- u32 hex;
+ struct
+ {
+ u32 blendenable : 1;
+ u32 logicopenable : 1;
+ u32 dither : 1;
+ u32 colorupdate : 1;
+ u32 alphaupdate : 1;
+ u32 dstfactor : 3; //BLEND_ONE, BLEND_INV_SRc etc
+ u32 srcfactor : 3;
+ u32 subtract : 1;
+ u32 logicmode : 4;
+ };
+ u32 hex;
};
union FogParam0
{
- struct
- {
- u32 mantissa : 11;
- u32 exponent : 8;
- u32 sign : 1;
- };
+ struct
+ {
+ u32 mantissa : 11;
+ u32 exponent : 8;
+ u32 sign : 1;
+ };
- float GetA() {
+ float GetA() {
union { u32 i; float f; } dummy;
- dummy.i = ((u32)sign << 31) | ((u32)exponent << 23) | ((u32)mantissa << 12); // scale mantissa from 11 to 23 bits
+ dummy.i = ((u32)sign << 31) | ((u32)exponent << 23) | ((u32)mantissa << 12); // scale mantissa from 11 to 23 bits
return dummy.f;
}
- u32 hex;
+ u32 hex;
};
union FogParam3
{
- struct
- {
- u32 c_mant : 11;
- u32 c_exp : 8;
- u32 c_sign : 1;
- u32 proj : 1; // 0 - perspective, 1 - orthographic
- u32 fsel : 3; // 0 - off, 2 - linear, 4 - exp, 5 - exp2, 6 - backward exp, 7 - backward exp2
- };
-
- // amount to subtract from eyespacez after range adjustment
- float GetC() {
+ struct
+ {
+ u32 c_mant : 11;
+ u32 c_exp : 8;
+ u32 c_sign : 1;
+ u32 proj : 1; // 0 - perspective, 1 - orthographic
+ u32 fsel : 3; // 0 - off, 2 - linear, 4 - exp, 5 - exp2, 6 - backward exp, 7 - backward exp2
+ };
+
+ // amount to subtract from eyespacez after range adjustment
+ float GetC() {
union { u32 i; float f; } dummy;
dummy.i = ((u32)c_sign << 31) | ((u32)c_exp << 23) | ((u32)c_mant << 12); // scale mantissa from 11 to 23 bits
return dummy.f;
}
- u32 hex;
+ u32 hex;
};
union FogRangeKElement
@@ -686,6 +686,9 @@ union FogRangeKElement
u32 LO : 12;
u32 regid : 8;
};
+
+ // TODO: Which scaling coefficient should we use here? This is just a guess!
+ float GetValue(int i) { return (i ? HI : LO) / 256.f; }
u32 HEX;
};
@@ -695,7 +698,7 @@ struct FogRangeParams
{
struct
{
- u32 Center : 10;
+ u32 Center : 10; // viewport center + 342
u32 Enabled : 1;
u32 unused : 13;
u32 regid : 8;
@@ -708,44 +711,44 @@ struct FogRangeParams
// final eq: ze = A/(B_MAG - (Zs>>B_SHF));
struct FogParams
{
- FogParam0 a;
- u32 b_magnitude;
- u32 b_shift; // b's exp + 1?
- FogParam3 c_proj_fsel;
+ FogParam0 a;
+ u32 b_magnitude;
+ u32 b_shift; // b's exp + 1?
+ FogParam3 c_proj_fsel;
- union FogColor
- {
- struct
- {
- u32 b : 8;
- u32 g : 8;
- u32 r : 8;
- };
- u32 hex;
- };
+ union FogColor
+ {
+ struct
+ {
+ u32 b : 8;
+ u32 g : 8;
+ u32 r : 8;
+ };
+ u32 hex;
+ };
- FogColor color; //0:b 8:g 16:r - nice!
+ FogColor color; //0:b 8:g 16:r - nice!
};
union ZMode
{
- struct
- {
- u32 testenable : 1;
- u32 func : 3;
- u32 updateenable : 1; //size?
- };
- u32 hex;
+ struct
+ {
+ u32 testenable : 1;
+ u32 func : 3;
+ u32 updateenable : 1; //size?
+ };
+ u32 hex;
};
union ConstantAlpha
{
- struct
- {
- u32 alpha : 8;
- u32 enable : 1;
- };
- u32 hex;
+ struct
+ {
+ u32 alpha : 8;
+ u32 enable : 1;
+ };
+ u32 hex;
};
union FieldMode
@@ -789,15 +792,15 @@ union FieldMask
union PE_CONTROL
{
- struct
- {
- u32 pixel_format : 3; // PIXELFMT_X
- u32 zformat : 3; // Z Compression for 16bit Z format
- u32 early_ztest : 1; // 1: before tex stage
- u32 unused : 17;
- u32 rid : 8;
- };
- u32 hex;
+ struct
+ {
+ u32 pixel_format : 3; // PIXELFMT_X
+ u32 zformat : 3; // Z Compression for 16bit Z format
+ u32 early_ztest : 1; // 1: before tex stage
+ u32 unused : 17;
+ u32 rid : 8;
+ };
+ u32 hex;
};
@@ -805,69 +808,69 @@ union PE_CONTROL
union TCInfo
{
- struct
- {
- u32 scale_minus_1 : 16;
- u32 range_bias : 1;
- u32 cylindric_wrap : 1;
+ struct
+ {
+ u32 scale_minus_1 : 16;
+ u32 range_bias : 1;
+ u32 cylindric_wrap : 1;
// These bits only have effect in the s field of TCoordInfo
u32 line_offset : 1;
u32 point_offset : 1;
- };
- u32 hex;
+ };
+ u32 hex;
};
struct TCoordInfo
{
- TCInfo s;
- TCInfo t;
+ TCInfo s;
+ TCInfo t;
};
union ColReg
{
- u32 hex;
- struct
- {
- s32 a : 11;
- u32 : 1;
- s32 b : 11;
- u32 type : 1;
- };
+ u32 hex;
+ struct
+ {
+ s32 a : 11;
+ u32 : 1;
+ s32 b : 11;
+ u32 type : 1;
+ };
};
struct TevReg
{
- ColReg low;
- ColReg high;
+ ColReg low;
+ ColReg high;
};
union TevKSel
{
- struct {
- u32 swap1 : 2;
- u32 swap2 : 2;
- u32 kcsel0 : 5;
- u32 kasel0 : 5;
- u32 kcsel1 : 5;
- u32 kasel1 : 5;
- };
- u32 hex;
+ struct {
+ u32 swap1 : 2;
+ u32 swap2 : 2;
+ u32 kcsel0 : 5;
+ u32 kasel0 : 5;
+ u32 kcsel1 : 5;
+ u32 kasel1 : 5;
+ };
+ u32 hex;
- int getKC(int i) {return i?kcsel1:kcsel0;}
- int getKA(int i) {return i?kasel1:kasel0;}
+ int getKC(int i) {return i?kcsel1:kcsel0;}
+ int getKA(int i) {return i?kasel1:kasel0;}
};
union AlphaTest
{
- struct
- {
- u32 ref0 : 8;
- u32 ref1 : 8;
- u32 comp0 : 3;
- u32 comp1 : 3;
- u32 logic : 2;
- };
- u32 hex;
+ struct
+ {
+ u32 ref0 : 8;
+ u32 ref1 : 8;
+ u32 comp0 : 3;
+ u32 comp1 : 3;
+ u32 logic : 2;
+ };
+ u32 hex;
enum TEST_RESULT
{
@@ -881,22 +884,22 @@ union AlphaTest
union UPE_Copy
{
- u32 Hex;
- struct
- {
- u32 clamp0 : 1; // if set clamp top
+ u32 Hex;
+ struct
+ {
+ u32 clamp0 : 1; // if set clamp top
u32 clamp1 : 1; // if set clamp bottom
- u32 yuv : 1; // if set, color conversion from RGB to YUV
- u32 target_pixel_format : 4; // realformat is (fmt/2)+((fmt&1)*8).... for some reason the msb is the lsb (pattern: cycling right shift)
- u32 gamma : 2; // gamma correction.. 0 = 1.0 ; 1 = 1.7 ; 2 = 2.2 ; 3 is reserved
- u32 half_scale : 1; // "mipmap" filter... 0 = no filter (scale 1:1) ; 1 = box filter (scale 2:1)
- u32 scale_invert : 1; // if set vertical scaling is on
- u32 clear : 1;
+ u32 yuv : 1; // if set, color conversion from RGB to YUV
+ u32 target_pixel_format : 4; // realformat is (fmt/2)+((fmt&1)*8).... for some reason the msb is the lsb (pattern: cycling right shift)
+ u32 gamma : 2; // gamma correction.. 0 = 1.0 ; 1 = 1.7 ; 2 = 2.2 ; 3 is reserved
+ u32 half_scale : 1; // "mipmap" filter... 0 = no filter (scale 1:1) ; 1 = box filter (scale 2:1)
+ u32 scale_invert : 1; // if set vertical scaling is on
+ u32 clear : 1;
u32 frame_to_field : 2; // 0 progressive ; 1 is reserved ; 2 = interlaced (even lines) ; 3 = interlaced 1 (odd lines)
- u32 copy_to_xfb : 1;
- u32 intensity_fmt : 1; // if set, is an intensity format (I4,I8,IA4,IA8)
- u32 auto_conv : 1; // if 0 automatic color conversion by texture format and pixel type
- };
+ u32 copy_to_xfb : 1;
+ u32 intensity_fmt : 1; // if set, is an intensity format (I4,I8,IA4,IA8)
+ u32 auto_conv : 1; // if 0 automatic color conversion by texture format and pixel type
+ };
u32 tp_realFormat() {
return target_pixel_format / 2 + (target_pixel_format & 1) * 8;
}
@@ -934,68 +937,68 @@ struct BPCmd
struct BPMemory
{
- GenMode genMode;
- u32 display_copy_filter[4]; // 01-04
- u32 unknown; // 05
- // indirect matrices (set by GXSetIndTexMtx, selected by TevStageIndirect::mid)
- // abc form a 2x3 offset matrix, there's 3 such matrices
- // the 3 offset matrices can either be indirect type, S-type, or T-type
- // 6bit scale factor s is distributed across IND_MTXA/B/C.
- // before using matrices scale by 2^-(s-17)
- IND_MTX indmtx[3];//06-0e GXSetIndTexMtx, 2x3 matrices
- IND_IMASK imask;//0f
- TevStageIndirect tevind[16];//10 GXSetTevIndirect
- X12Y12 scissorTL; //20
- X12Y12 scissorBR; //21
- LPSize lineptwidth; //22 line and point width
- u32 sucounter; //23
- u32 rascounter; //24
- TEXSCALE texscale[2]; //25-26 GXSetIndTexCoordScale
- RAS1_IREF tevindref; //27 GXSetIndTexOrder
- TwoTevStageOrders tevorders[8]; //28-2F
- TCoordInfo texcoords[8]; //0x30 s,t,s,t,s,t,s,t...
- ZMode zmode; //40
- BlendMode blendmode; //41
- ConstantAlpha dstalpha; //42
- PE_CONTROL zcontrol; //43 GXSetZCompLoc, GXPixModeSync
- FieldMask fieldmask; //44
- u32 drawdone; //45, bit1=1 if end of list
- u32 unknown5; //46 clock?
- u32 petoken; //47
- u32 petokenint; // 48
- X10Y10 copyTexSrcXY; // 49
- X10Y10 copyTexSrcWH; // 4a
- u32 copyTexDest; //4b// 4b == CopyAddress (GXDispCopy and GXTexCopy use it)
- u32 unknown6; //4c
- u32 copyMipMapStrideChannels; // 4d usually set to 4 when dest is single channel, 8 when dest is 2 channel, 16 when dest is RGBA
- // also, doubles whenever mipmap box filter option is set (excent on RGBA). Probably to do with number of bytes to look at when smoothing
- u32 dispcopyyscale; //4e
- u32 clearcolorAR; //4f
- u32 clearcolorGB; //50
- u32 clearZValue; //51
- UPE_Copy triggerEFBCopy; //52
- u32 copyfilter[2]; //53,54
- u32 boundbox0;//55
- u32 boundbox1;//56
- u32 unknown7[2];//57,58
- X10Y10 scissorOffset; //59
- u32 unknown8[6]; //5a,5b,5c,5d, 5e,5f
- BPS_TmemConfig tmem_config; // 60-66
- u32 metric; //67
- FieldMode fieldmode;//68
- u32 unknown10[7];//69-6F
- u32 unknown11[16];//70-7F
- FourTexUnits tex[2]; //80-bf
- TevStageCombiner combiners[16]; //0xC0-0xDF
- TevReg tevregs[4]; //0xE0
- FogRangeParams fogRange;
- FogParams fog; //0xEE,0xEF,0xF0,0xF1,0xF2
- AlphaTest alpha_test; //0xF3
- ZTex1 ztex1; //0xf4,0xf5
- ZTex2 ztex2;
- TevKSel tevksel[8];//0xf6,0xf7,f8,f9,fa,fb,fc,fd
- u32 bpMask; //0xFE
- u32 unknown18; //ff
+ GenMode genMode;
+ u32 display_copy_filter[4]; // 01-04
+ u32 unknown; // 05
+ // indirect matrices (set by GXSetIndTexMtx, selected by TevStageIndirect::mid)
+ // abc form a 2x3 offset matrix, there's 3 such matrices
+ // the 3 offset matrices can either be indirect type, S-type, or T-type
+ // 6bit scale factor s is distributed across IND_MTXA/B/C.
+ // before using matrices scale by 2^-(s-17)
+ IND_MTX indmtx[3];//06-0e GXSetIndTexMtx, 2x3 matrices
+ IND_IMASK imask;//0f
+ TevStageIndirect tevind[16];//10 GXSetTevIndirect
+ X12Y12 scissorTL; //20
+ X12Y12 scissorBR; //21
+ LPSize lineptwidth; //22 line and point width
+ u32 sucounter; //23
+ u32 rascounter; //24
+ TEXSCALE texscale[2]; //25-26 GXSetIndTexCoordScale
+ RAS1_IREF tevindref; //27 GXSetIndTexOrder
+ TwoTevStageOrders tevorders[8]; //28-2F
+ TCoordInfo texcoords[8]; //0x30 s,t,s,t,s,t,s,t...
+ ZMode zmode; //40
+ BlendMode blendmode; //41
+ ConstantAlpha dstalpha; //42
+ PE_CONTROL zcontrol; //43 GXSetZCompLoc, GXPixModeSync
+ FieldMask fieldmask; //44
+ u32 drawdone; //45, bit1=1 if end of list
+ u32 unknown5; //46 clock?
+ u32 petoken; //47
+ u32 petokenint; // 48
+ X10Y10 copyTexSrcXY; // 49
+ X10Y10 copyTexSrcWH; // 4a
+ u32 copyTexDest; //4b// 4b == CopyAddress (GXDispCopy and GXTexCopy use it)
+ u32 unknown6; //4c
+ u32 copyMipMapStrideChannels; // 4d usually set to 4 when dest is single channel, 8 when dest is 2 channel, 16 when dest is RGBA
+ // also, doubles whenever mipmap box filter option is set (excent on RGBA). Probably to do with number of bytes to look at when smoothing
+ u32 dispcopyyscale; //4e
+ u32 clearcolorAR; //4f
+ u32 clearcolorGB; //50
+ u32 clearZValue; //51
+ UPE_Copy triggerEFBCopy; //52
+ u32 copyfilter[2]; //53,54
+ u32 boundbox0;//55
+ u32 boundbox1;//56
+ u32 unknown7[2];//57,58
+ X10Y10 scissorOffset; //59
+ u32 unknown8[6]; //5a,5b,5c,5d, 5e,5f
+ BPS_TmemConfig tmem_config; // 60-66
+ u32 metric; //67
+ FieldMode fieldmode;//68
+ u32 unknown10[7];//69-6F
+ u32 unknown11[16];//70-7F
+ FourTexUnits tex[2]; //80-bf
+ TevStageCombiner combiners[16]; //0xC0-0xDF
+ TevReg tevregs[4]; //0xE0
+ FogRangeParams fogRange; // 0xE8
+ FogParams fog; //0xEE,0xEF,0xF0,0xF1,0xF2
+ AlphaTest alpha_test; //0xF3
+ ZTex1 ztex1; //0xf4,0xf5
+ ZTex2 ztex2;
+ TevKSel tevksel[8];//0xf6,0xf7,f8,f9,fa,fb,fc,fd
+ u32 bpMask; //0xFE
+ u32 unknown18; //ff
};
#pragma pack()
diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp
index 0d7d741a92..9580eea447 100644
--- a/Source/Core/VideoCommon/Src/BPStructs.cpp
+++ b/Source/Core/VideoCommon/Src/BPStructs.cpp
@@ -31,6 +31,7 @@
#include "VertexShaderManager.h"
#include "Thread.h"
#include "HW/Memmap.h"
+#include "PerfQueryBase.h"
using namespace BPFunctions;
@@ -62,7 +63,6 @@ void RenderToXFB(const BPCmd &bp, const EFBRectangle &rc, float yScale, float xf
{
Renderer::RenderToXFB(xfbAddr, dstWidth, dstHeight, rc, gamma);
}
-
void BPWritten(const BPCmd& bp)
{
/*
@@ -144,7 +144,8 @@ void BPWritten(const BPCmd& bp)
|| bp.address == BPMEM_LOADTLUT0
|| bp.address == BPMEM_LOADTLUT1
|| bp.address == BPMEM_TEXINVALIDATE
- || bp.address == BPMEM_PRELOAD_MODE))
+ || bp.address == BPMEM_PRELOAD_MODE
+ || bp.address == BPMEM_CLEAR_PIXEL_PERF))
{
return;
}
@@ -212,7 +213,7 @@ void BPWritten(const BPCmd& bp)
if (bp.changes & 4)
SetDitherMode();
// Set Blending Mode
- if (bp.changes & 0xFE1)
+ if (bp.changes & 0xFF1)
SetBlendMode();
// Set Color Mask
if (bp.changes & 0x18)
@@ -224,6 +225,8 @@ void BPWritten(const BPCmd& bp)
{
PRIM_LOG("constalpha: alp=%d, en=%d", bpmem.dstalpha.alpha, bpmem.dstalpha.enable);
PixelShaderManager::SetDestAlpha(bpmem.dstalpha);
+ if(bp.changes & 0x100)
+ SetBlendMode();
break;
}
// This is called when the game is done drawing the new frame (eg: like in DX: Begin(); Draw(); End();)
@@ -455,9 +458,11 @@ void BPWritten(const BPCmd& bp)
break;
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();
+ if(bp.changes & 7) {
+ SetBlendMode(); // dual source could be activated by changing to PIXELFMT_RGBA6_Z24
+ g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel
+ }
break;
case BPMEM_MIPMAP_STRIDE: // MipMap Stride Channel
@@ -484,9 +489,10 @@ void BPWritten(const BPCmd& bp)
case BPMEM_IND_IMASK: // Index Mask ?
case BPMEM_REVBITS: // Always set to 0x0F when GX_InitRevBits() is called.
break;
-
- case BPMEM_UNKNOWN_57: // Sunshine alternates this register between values 0x000 and 0xAAA
- DEBUG_LOG(VIDEO, "Unknown BP Reg 0x57: %08x", bp.newvalue);
+
+ case BPMEM_CLEAR_PIXEL_PERF:
+ // GXClearPixMetric writes 0xAAA here, Sunshine alternates this register between values 0x000 and 0xAAA
+ g_perf_query->ResetQuery();
break;
case BPMEM_PRELOAD_ADDR:
@@ -574,8 +580,6 @@ void BPWritten(const BPCmd& bp)
// ------------------------
case BPMEM_TX_SETMODE0: // (0x90 for linear)
case BPMEM_TX_SETMODE0_4:
- // Shouldn't need to call this here, we call it for each active texture right before rendering
- SetTextureMode(bp);
break;
case BPMEM_TX_SETMODE1:
@@ -718,14 +722,6 @@ void BPReload()
SetColorMask();
OnPixelFormatChange();
{
- BPCmd bp = {BPMEM_TX_SETMODE0, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_TX_SETMODE0])};
- SetTextureMode(bp);
- }
- {
- BPCmd bp = {BPMEM_TX_SETMODE0_4, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_TX_SETMODE0_4])};
- SetTextureMode(bp);
- }
- {
BPCmd bp = {BPMEM_FIELDMASK, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_FIELDMASK])};
SetInterlacingMode(bp);
}
diff --git a/Source/Core/VideoCommon/Src/CPMemory.h b/Source/Core/VideoCommon/Src/CPMemory.h
index c4a24ba7a4..145f18aca7 100644
--- a/Source/Core/VideoCommon/Src/CPMemory.h
+++ b/Source/Core/VideoCommon/Src/CPMemory.h
@@ -25,18 +25,18 @@ enum
{
ARRAY_POSITION = 0,
ARRAY_NORMAL = 1,
- ARRAY_COLOR = 2,
- ARRAY_COLOR2 = 3,
- ARRAY_TEXCOORD0 = 4,
+ ARRAY_COLOR = 2,
+ ARRAY_COLOR2 = 3,
+ ARRAY_TEXCOORD0 = 4,
};
// Vertex components
enum
{
NOT_PRESENT = 0,
- DIRECT = 1,
- INDEX8 = 2,
- INDEX16 = 3,
+ DIRECT = 1,
+ INDEX8 = 2,
+ INDEX16 = 3,
};
enum
@@ -74,14 +74,14 @@ union TVtxDesc
// 0: not present
// 1: present
u32 PosMatIdx : 1;
- u32 Tex0MatIdx : 1;
- u32 Tex1MatIdx : 1;
- u32 Tex2MatIdx : 1;
- u32 Tex3MatIdx : 1;
- u32 Tex4MatIdx : 1;
- u32 Tex5MatIdx : 1;
- u32 Tex6MatIdx : 1;
- u32 Tex7MatIdx : 1;
+ u32 Tex0MatIdx : 1;
+ u32 Tex1MatIdx : 1;
+ u32 Tex2MatIdx : 1;
+ u32 Tex3MatIdx : 1;
+ u32 Tex4MatIdx : 1;
+ u32 Tex5MatIdx : 1;
+ u32 Tex6MatIdx : 1;
+ u32 Tex7MatIdx : 1;
// 00: not present
// 01: direct
@@ -89,156 +89,156 @@ union TVtxDesc
// 11: 16 bit index
u32 Position : 2;
u32 Normal : 2;
- u32 Color0 : 2;
- u32 Color1 : 2;
- u32 Tex0Coord : 2;
- u32 Tex1Coord : 2;
- u32 Tex2Coord : 2;
- u32 Tex3Coord : 2;
- u32 Tex4Coord : 2;
- u32 Tex5Coord : 2;
- u32 Tex6Coord : 2;
- u32 Tex7Coord : 2;
+ u32 Color0 : 2;
+ u32 Color1 : 2;
+ u32 Tex0Coord : 2;
+ u32 Tex1Coord : 2;
+ u32 Tex2Coord : 2;
+ u32 Tex3Coord : 2;
+ u32 Tex4Coord : 2;
+ u32 Tex5Coord : 2;
+ u32 Tex6Coord : 2;
+ u32 Tex7Coord : 2;
u32 :31;
};
- struct {
- u32 Hex0, Hex1;
- };
+ struct {
+ u32 Hex0, Hex1;
+ };
};
union UVAT_group0
{
- u32 Hex;
- struct
- {
- // 0:8
- u32 PosElements : 1;
- u32 PosFormat : 3;
- u32 PosFrac : 5;
- // 9:12
- u32 NormalElements : 1;
- u32 NormalFormat : 3;
- // 13:16
- u32 Color0Elements : 1;
- u32 Color0Comp : 3;
- // 17:20
- u32 Color1Elements : 1;
- u32 Color1Comp : 3;
- // 21:29
- u32 Tex0CoordElements : 1;
- u32 Tex0CoordFormat : 3;
- u32 Tex0Frac : 5;
- // 30:31
- u32 ByteDequant : 1;
- u32 NormalIndex3 : 1;
- };
+ u32 Hex;
+ struct
+ {
+ // 0:8
+ u32 PosElements : 1;
+ u32 PosFormat : 3;
+ u32 PosFrac : 5;
+ // 9:12
+ u32 NormalElements : 1;
+ u32 NormalFormat : 3;
+ // 13:16
+ u32 Color0Elements : 1;
+ u32 Color0Comp : 3;
+ // 17:20
+ u32 Color1Elements : 1;
+ u32 Color1Comp : 3;
+ // 21:29
+ u32 Tex0CoordElements : 1;
+ u32 Tex0CoordFormat : 3;
+ u32 Tex0Frac : 5;
+ // 30:31
+ u32 ByteDequant : 1;
+ u32 NormalIndex3 : 1;
+ };
};
union UVAT_group1
{
- u32 Hex;
- struct
- {
- // 0:8
- u32 Tex1CoordElements : 1;
- u32 Tex1CoordFormat : 3;
- u32 Tex1Frac : 5;
- // 9:17
- u32 Tex2CoordElements : 1;
- u32 Tex2CoordFormat : 3;
- u32 Tex2Frac : 5;
- // 18:26
- u32 Tex3CoordElements : 1;
- u32 Tex3CoordFormat : 3;
- u32 Tex3Frac : 5;
- // 27:30
- u32 Tex4CoordElements : 1;
- u32 Tex4CoordFormat : 3;
- //
- u32 : 1;
- };
+ u32 Hex;
+ struct
+ {
+ // 0:8
+ u32 Tex1CoordElements : 1;
+ u32 Tex1CoordFormat : 3;
+ u32 Tex1Frac : 5;
+ // 9:17
+ u32 Tex2CoordElements : 1;
+ u32 Tex2CoordFormat : 3;
+ u32 Tex2Frac : 5;
+ // 18:26
+ u32 Tex3CoordElements : 1;
+ u32 Tex3CoordFormat : 3;
+ u32 Tex3Frac : 5;
+ // 27:30
+ u32 Tex4CoordElements : 1;
+ u32 Tex4CoordFormat : 3;
+ //
+ u32 : 1;
+ };
};
union UVAT_group2
{
- u32 Hex;
- struct
- {
- // 0:4
- u32 Tex4Frac : 5;
- // 5:13
- u32 Tex5CoordElements : 1;
- u32 Tex5CoordFormat : 3;
- u32 Tex5Frac : 5;
- // 14:22
- u32 Tex6CoordElements : 1;
- u32 Tex6CoordFormat : 3;
- u32 Tex6Frac : 5;
- // 23:31
- u32 Tex7CoordElements : 1;
- u32 Tex7CoordFormat : 3;
- u32 Tex7Frac : 5;
- };
+ u32 Hex;
+ struct
+ {
+ // 0:4
+ u32 Tex4Frac : 5;
+ // 5:13
+ u32 Tex5CoordElements : 1;
+ u32 Tex5CoordFormat : 3;
+ u32 Tex5Frac : 5;
+ // 14:22
+ u32 Tex6CoordElements : 1;
+ u32 Tex6CoordFormat : 3;
+ u32 Tex6Frac : 5;
+ // 23:31
+ u32 Tex7CoordElements : 1;
+ u32 Tex7CoordFormat : 3;
+ u32 Tex7Frac : 5;
+ };
};
struct ColorAttr
{
- u8 Elements;
- u8 Comp;
+ u8 Elements;
+ u8 Comp;
};
struct TexAttr
{
- u8 Elements;
- u8 Format;
- u8 Frac;
+ u8 Elements;
+ u8 Format;
+ u8 Frac;
};
struct TVtxAttr
-{
- u8 PosElements;
- u8 PosFormat;
- u8 PosFrac;
- u8 NormalElements;
- u8 NormalFormat;
- ColorAttr color[2];
- TexAttr texCoord[8];
- u8 ByteDequant;
- u8 NormalIndex3;
+{
+ u8 PosElements;
+ u8 PosFormat;
+ u8 PosFrac;
+ u8 NormalElements;
+ u8 NormalFormat;
+ ColorAttr color[2];
+ TexAttr texCoord[8];
+ u8 ByteDequant;
+ u8 NormalIndex3;
};
// Matrix indices
union TMatrixIndexA
{
- struct
- {
- u32 PosNormalMtxIdx : 6;
- u32 Tex0MtxIdx : 6;
- u32 Tex1MtxIdx : 6;
- u32 Tex2MtxIdx : 6;
- u32 Tex3MtxIdx : 6;
- };
- struct
- {
- u32 Hex : 30;
- u32 unused : 2;
- };
+ struct
+ {
+ u32 PosNormalMtxIdx : 6;
+ u32 Tex0MtxIdx : 6;
+ u32 Tex1MtxIdx : 6;
+ u32 Tex2MtxIdx : 6;
+ u32 Tex3MtxIdx : 6;
+ };
+ struct
+ {
+ u32 Hex : 30;
+ u32 unused : 2;
+ };
};
union TMatrixIndexB
{
- struct
- {
- u32 Tex4MtxIdx : 6;
- u32 Tex5MtxIdx : 6;
- u32 Tex6MtxIdx : 6;
- u32 Tex7MtxIdx : 6;
- };
- struct
- {
- u32 Hex : 24;
- u32 unused : 8;
- };
+ struct
+ {
+ u32 Tex4MtxIdx : 6;
+ u32 Tex5MtxIdx : 6;
+ u32 Tex6MtxIdx : 6;
+ u32 Tex7MtxIdx : 6;
+ };
+ struct
+ {
+ u32 Hex : 24;
+ u32 unused : 8;
+ };
};
#pragma pack()
diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp
index a4dddf537f..dacec67823 100644
--- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp
+++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp
@@ -32,6 +32,8 @@
#include "HW/GPFifo.h"
#include "HW/Memmap.h"
#include "DLCache.h"
+#include "HW/SystemTimers.h"
+#include "Core.h"
namespace CommandProcessor
{
@@ -57,12 +59,15 @@ static bool bProcessFifoAllDistance = false;
volatile bool isPossibleWaitingSetDrawDone = false;
volatile bool isHiWatermarkActive = false;
+volatile bool isLoWatermarkActive = false;
volatile bool interruptSet= false;
volatile bool interruptWaiting= false;
volatile bool interruptTokenWaiting = false;
volatile bool interruptFinishWaiting = false;
volatile bool waitingForPEInterruptDisable = false;
+volatile u32 VITicks = CommandProcessor::m_cpClockOrigin;
+
bool IsOnThread()
{
return SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread;
@@ -88,6 +93,7 @@ void DoState(PointerWrap &p)
p.Do(bProcessFifoToLoWatermark);
p.Do(bProcessFifoAllDistance);
p.Do(isHiWatermarkActive);
+ p.Do(isLoWatermarkActive);
p.Do(isPossibleWaitingSetDrawDone);
p.Do(interruptSet);
p.Do(interruptWaiting);
@@ -119,7 +125,7 @@ void Init()
m_tokenReg = 0;
memset(&fifo,0,sizeof(fifo));
- fifo.CPCmdIdle = 1 ;
+ fifo.CPCmdIdle = 1;
fifo.CPReadIdle = 1;
fifo.bFF_Breakpoint = 0;
fifo.bFF_HiWatermark = 0;
@@ -136,8 +142,9 @@ void Init()
bProcessFifoAllDistance = false;
isPossibleWaitingSetDrawDone = false;
isHiWatermarkActive = false;
+ isLoWatermarkActive = false;
- et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
+ et_UpdateInterrupts = CoreTiming::RegisterEvent("CPInterrupt", UpdateInterrupts_Wrapper);
}
void Read16(u16& _rReturnValue, const u32 _Address)
@@ -294,7 +301,6 @@ void Read16(u16& _rReturnValue, const u32 _Address)
void Write16(const u16 _Value, const u32 _Address)
{
-
INFO_LOG(COMMANDPROCESSOR, "(write16): 0x%04x @ 0x%08x",_Value,_Address);
switch (_Address & 0xFFF)
@@ -319,7 +325,7 @@ void Write16(const u16 _Value, const u32 _Address)
case CLEAR_REGISTER:
{
UCPClearReg tmpCtrl(_Value);
- m_CPClearReg.Hex = tmpCtrl.Hex;
+ m_CPClearReg.Hex = tmpCtrl.Hex;
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x", _Value);
SetCpClearRegister();
}
@@ -405,9 +411,10 @@ void Write16(const u16 _Value, const u32 _Address)
{
GPFifo::ResetGatherPipe();
ResetVideoBuffer();
- }else
+ }
+ else
{
- ResetVideoBuffer();
+ ResetVideoBuffer();
}
IncrementCheckContextId();
DEBUG_LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
@@ -455,13 +462,12 @@ void STACKALIGN GatherPipeBursted()
ProcessFifoAllDistance();
waitingForPEInterruptDisable = false;
}
-
}
return;
}
if (IsOnThread())
- SetOverflowStatusFromGatherPipe();
+ SetCpStatus(true);
// update the fifo-pointer
if (fifo.CPWritePointer >= fifo.CPEnd)
@@ -485,11 +491,11 @@ void STACKALIGN GatherPipeBursted()
void UpdateInterrupts(u64 userdata)
{
- if (userdata)
+ if (userdata)
{
interruptSet = true;
- INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
- ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
+ INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
+ ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
}
else
{
@@ -497,7 +503,7 @@ void UpdateInterrupts(u64 userdata)
INFO_LOG(COMMANDPROCESSOR,"Interrupt cleared");
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false);
}
- interruptWaiting = false;
+ interruptWaiting = false;
}
void UpdateInterruptsFromVideoBackend(u64 userdata)
@@ -511,73 +517,75 @@ void AbortFrame()
}
-void SetOverflowStatusFromGatherPipe()
+void SetCpStatus(bool isCPUThread)
{
+ // overflow & underflow check
fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
- isHiWatermarkActive = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt && m_CPCtrlReg.GPReadEnable;
+ fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
- if (isHiWatermarkActive)
+ // breakpoint
+ if (!isCPUThread)
{
- interruptSet = true;
- INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
- ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
- }
-}
-
-void SetCpStatus()
-{
- // overflow & underflow check
- fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
- fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
-
- // breakpoint
- if (fifo.bFF_BPEnable)
- {
- if (fifo.CPBreakpoint == fifo.CPReadPointer)
- {
- if (!fifo.bFF_Breakpoint)
+ if (fifo.bFF_BPEnable)
+ {
+ if (fifo.CPBreakpoint == fifo.CPReadPointer)
+ {
+ if (!fifo.bFF_Breakpoint)
+ {
+ INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
+ fifo.bFF_Breakpoint = true;
+ IncrementCheckContextId();
+ }
+ }
+ else
{
- INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
- fifo.bFF_Breakpoint = true;
- IncrementCheckContextId();
+ if (fifo.bFF_Breakpoint)
+ INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer);
+ fifo.bFF_Breakpoint = false;
}
- }
+ }
else
{
if (fifo.bFF_Breakpoint)
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer);
- fifo.bFF_Breakpoint = false;
+ fifo.bFF_Breakpoint = false;
}
- }
- else
- {
- if (fifo.bFF_Breakpoint)
- INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer);
- fifo.bFF_Breakpoint = false;
- }
+ }
bool bpInt = fifo.bFF_Breakpoint && fifo.bFF_BPInt;
bool ovfInt = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt;
bool undfInt = fifo.bFF_LoWatermark && fifo.bFF_LoWatermarkInt;
-
+
bool interrupt = (bpInt || ovfInt || undfInt) && m_CPCtrlReg.GPReadEnable;
- isHiWatermarkActive = ovfInt && m_CPCtrlReg.GPReadEnable;
+ isHiWatermarkActive = ovfInt && m_CPCtrlReg.GPReadEnable;
+ isLoWatermarkActive = undfInt && m_CPCtrlReg.GPReadEnable;
- if (interrupt != interruptSet && !interruptWaiting)
- {
- u64 userdata = interrupt?1:0;
- if (IsOnThread())
- {
- if(!interrupt || bpInt || undfInt)
+ if (interrupt != interruptSet && !interruptWaiting)
+ {
+ u64 userdata = interrupt?1:0;
+ if (IsOnThread())
+ {
+ if (!interrupt || bpInt || undfInt || ovfInt)
{
- interruptWaiting = true;
- CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
+ if (!isCPUThread)
+ {
+ // GPU thread:
+ interruptWaiting = true;
+ CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
+ }
+ else
+ {
+ // CPU thread:
+ interruptSet = interrupt;
+ INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
+ ProcessorInterface::SetInterrupt(INT_CAUSE_CP, interrupt);
+ }
}
- }
- else
- CommandProcessor::UpdateInterrupts(userdata);
- }
+ }
+ else
+ CommandProcessor::UpdateInterrupts(userdata);
+ }
}
void ProcessFifoToLoWatermark()
@@ -596,7 +604,7 @@ void ProcessFifoAllDistance()
if (IsOnThread())
{
while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
- fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt())
+ fifo.CPReadWriteDistance && !AtBreakpoint())
Common::YieldCPU();
}
bProcessFifoAllDistance = false;
@@ -617,15 +625,11 @@ void SetCpStatusRegister()
{
// Here always there is one fifo attached to the GPU
m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint;
- m_CPStatusReg.ReadIdle = !fifo.CPReadWriteDistance || (fifo.CPReadPointer == fifo.CPWritePointer) || (fifo.CPReadPointer == fifo.CPBreakpoint) ;
- m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance;
+ m_CPStatusReg.ReadIdle = !fifo.CPReadWriteDistance || AtBreakpoint() || (fifo.CPReadPointer == fifo.CPWritePointer);
+ m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance || AtBreakpoint() || !fifo.bFF_GPReadEnable;
m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark;
m_CPStatusReg.OverflowHiWatermark = fifo.bFF_HiWatermark;
- // HACK to compensate for slow response to PE interrupts in Time Splitters: Future Perfect
- if (IsOnThread())
- PixelEngine::ResumeWaitingForPEInterrupt();
-
INFO_LOG(COMMANDPROCESSOR,"\t Read from STATUS_REGISTER : %04x", m_CPStatusReg.Hex);
DEBUG_LOG(COMMANDPROCESSOR, "(r) status: iBP %s | fReadIdle %s | fCmdIdle %s | iOvF %s | iUndF %s"
, m_CPStatusReg.Breakpoint ? "ON" : "OFF"
@@ -638,14 +642,11 @@ void SetCpStatusRegister()
void SetCpControlRegister()
{
- // If the new fifo is being attached We make sure there wont be SetFinish event pending.
- // This protection fix eternal darkness booting, because the second SetFinish event when it is booting
- // seems invalid or has a bug and hang the game.
-
+ // If the new fifo is being attached, force an exception check
+ // This fixes the hang while booting Eternal Darkness
if (!fifo.bFF_GPReadEnable && m_CPCtrlReg.GPReadEnable && !m_CPCtrlReg.BPEnable)
{
- ProcessFifoEvents();
- PixelEngine::ResetSetFinish();
+ CoreTiming::ForceExceptionCheck(0);
}
fifo.bFF_BPInt = m_CPCtrlReg.BPInt;
@@ -693,4 +694,12 @@ void SetCpClearRegister()
// }
}
+void Update()
+{
+ while (VITicks > m_cpClockOrigin && fifo.isGpuReadingData && IsOnThread())
+ Common::YieldCPU();
+
+ if (fifo.isGpuReadingData)
+ Common::AtomicAdd(VITicks, SystemTimers::GetTicksPerSecond() / 10000);
+}
} // end of namespace CommandProcessor
diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.h b/Source/Core/VideoCommon/Src/CommandProcessor.h
index 5d31453537..5aa49ac3e8 100644
--- a/Source/Core/VideoCommon/Src/CommandProcessor.h
+++ b/Source/Core/VideoCommon/Src/CommandProcessor.h
@@ -31,6 +31,7 @@ namespace CommandProcessor
extern SCPFifoStruct fifo; //This one is shared between gfx thread and emulator thread.
extern volatile bool isPossibleWaitingSetDrawDone; //This one is used for sync gfx thread and emulator thread.
extern volatile bool isHiWatermarkActive;
+extern volatile bool isLoWatermarkActive;
extern volatile bool interruptSet;
extern volatile bool interruptWaiting;
extern volatile bool interruptTokenWaiting;
@@ -140,6 +141,9 @@ union UCPClearReg
UCPClearReg(u16 _hex) {Hex = _hex; }
};
+// Can be any number, low enough to not be below the number of clocks executed by the GPU per CP_PERIOD
+const static u32 m_cpClockOrigin = 200000;
+
// Init
void Init();
void Shutdown();
@@ -151,7 +155,7 @@ void Write16(const u16 _Data, const u32 _Address);
void Read32(u32& _rReturnValue, const u32 _Address);
void Write32(const u32 _Data, const u32 _Address);
-void SetCpStatus();
+void SetCpStatus(bool isCPUThread = false);
void GatherPipeBursted();
void UpdateInterrupts(u64 userdata);
void UpdateInterruptsFromVideoBackend(u64 userdata);
@@ -161,11 +165,14 @@ bool AllowIdleSkipping();
void SetCpClearRegister();
void SetCpControlRegister();
void SetCpStatusRegister();
-void SetOverflowStatusFromGatherPipe();
void ProcessFifoToLoWatermark();
void ProcessFifoAllDistance();
void ProcessFifoEvents();
void AbortFrame();
+
+void Update();
+extern volatile u32 VITicks;
+
} // namespace CommandProcessor
#endif // _COMMANDPROCESSOR_H
diff --git a/Source/Core/VideoCommon/Src/DataReader.h b/Source/Core/VideoCommon/Src/DataReader.h
index 06668f8bbc..03061229c0 100644
--- a/Source/Core/VideoCommon/Src/DataReader.h
+++ b/Source/Core/VideoCommon/Src/DataReader.h
@@ -20,6 +20,8 @@
#ifndef _DATAREADER_H
#define _DATAREADER_H
+#include "VertexManagerBase.h"
+
extern u8* g_pVideoData;
#if _M_SSE >= 0x301 && !(defined __GNUC__ && !defined __SSSE3__)
@@ -31,43 +33,63 @@ __forceinline void DataSkip(u32 skip)
g_pVideoData += skip;
}
+// probably unnecessary
+template <int count>
+__forceinline void DataSkip()
+{
+ g_pVideoData += count;
+}
+
+template <typename T>
+__forceinline T DataPeek(int _uOffset)
+{
+ auto const result = Common::FromBigEndian(*reinterpret_cast<T*>(g_pVideoData + _uOffset));
+ return result;
+}
+
+// TODO: kill these
__forceinline u8 DataPeek8(int _uOffset)
{
- return g_pVideoData[_uOffset];
+ return DataPeek<u8>(_uOffset);
}
__forceinline u16 DataPeek16(int _uOffset)
{
- return Common::swap16(*(u16*)&g_pVideoData[_uOffset]);
+ return DataPeek<u16>(_uOffset);
}
__forceinline u32 DataPeek32(int _uOffset)
{
- return Common::swap32(*(u32*)&g_pVideoData[_uOffset]);
+ return DataPeek<u32>(_uOffset);
+}
+
+template <typename T>
+__forceinline T DataRead()
+{
+ auto const result = DataPeek<T>(0);
+ DataSkip<sizeof(T)>();
+ return result;
}
+// TODO: kill these
__forceinline u8 DataReadU8()
{
- return *g_pVideoData++;
+ return DataRead<u8>();
}
__forceinline s8 DataReadS8()
{
- return (s8)(*g_pVideoData++);
+ return DataRead<s8>();
}
__forceinline u16 DataReadU16()
{
- u16 tmp = Common::swap16(*(u16*)g_pVideoData);
- g_pVideoData += 2;
- return tmp;
+ return DataRead<u16>();
}
__forceinline u32 DataReadU32()
{
- u32 tmp = Common::swap32(*(u32*)g_pVideoData);
- g_pVideoData += 4;
- return tmp;
+ return DataRead<u32>();
}
typedef void (*DataReadU32xNfunc)(u32 *buf);
@@ -120,58 +142,16 @@ __forceinline u32 DataReadU32Unswapped()
return tmp;
}
-template<class T>
-__forceinline T DataRead()
-{
- T tmp = *(T*)g_pVideoData;
- g_pVideoData += sizeof(T);
- return tmp;
-}
-
-template <>
-__forceinline u16 DataRead()
-{
- u16 tmp = Common::swap16(*(u16*)g_pVideoData);
- g_pVideoData += 2;
- return tmp;
-}
-
-template <>
-__forceinline s16 DataRead()
-{
- s16 tmp = (s16)Common::swap16(*(u16*)g_pVideoData);
- g_pVideoData += 2;
- return tmp;
-}
-
-template <>
-__forceinline u32 DataRead()
-{
- u32 tmp = (u32)Common::swap32(*(u32*)g_pVideoData);
- g_pVideoData += 4;
- return tmp;
-}
-
-template <>
-__forceinline s32 DataRead()
-{
- s32 tmp = (s32)Common::swap32(*(u32*)g_pVideoData);
- g_pVideoData += 4;
- return tmp;
-}
-
-__forceinline float DataReadF32()
+__forceinline u8* DataGetPosition()
{
- union {u32 i; float f;} temp;
- temp.i = Common::swap32(*(u32*)g_pVideoData);
- g_pVideoData += 4;
- float tmp = temp.f;
- return tmp;
+ return g_pVideoData;
}
-__forceinline u8* DataGetPosition()
+template <typename T>
+__forceinline void DataWrite(T data)
{
- return g_pVideoData;
+ *(T*)VertexManager::s_pCurBufferPointer = data;
+ VertexManager::s_pCurBufferPointer += sizeof(T);
}
#endif
diff --git a/Source/Core/VideoCommon/Src/EmuWindow.cpp b/Source/Core/VideoCommon/Src/EmuWindow.cpp
index cbb0bc31ac..bf9da4190b 100644
--- a/Source/Core/VideoCommon/Src/EmuWindow.cpp
+++ b/Source/Core/VideoCommon/Src/EmuWindow.cpp
@@ -80,7 +80,7 @@ void FreeLookInput( UINT iMsg, WPARAM wParam )
static bool mouseLookEnabled = false;
static bool mouseMoveEnabled = false;
static float lastMouse[2];
- POINT point;
+ POINT point;
switch(iMsg)
{
case WM_USER_KEYDOWN:
@@ -133,7 +133,7 @@ void FreeLookInput( UINT iMsg, WPARAM wParam )
lastMouse[1] = (float)point.y;
mouseLookEnabled= true;
break;
- case WM_MBUTTONDOWN:
+ case WM_MBUTTONDOWN:
GetCursorPos(&point);
lastMouse[0] = (float)point.x;
lastMouse[1] = (float)point.y;
@@ -205,10 +205,6 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
OnKeyDown(lParam);
FreeLookInput((u32)wParam, lParam);
}
- else if (wParam == WIIMOTE_DISCONNECT)
- {
- PostMessage(m_hParent, WM_USER, wParam, lParam);
- }
break;
// Called when a screensaver wants to show up while this window is active
diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp
index 50aa21ebbf..c7d39844c8 100644
--- a/Source/Core/VideoCommon/Src/Fifo.cpp
+++ b/Source/Core/VideoCommon/Src/Fifo.cpp
@@ -26,6 +26,7 @@
#include "Fifo.h"
#include "HW/Memmap.h"
#include "Core.h"
+#include "CoreTiming.h"
volatile bool g_bSkipCurrentFrame = false;
extern u8* g_pVideoData;
@@ -42,10 +43,10 @@ static int size = 0;
void Fifo_DoState(PointerWrap &p)
{
- p.DoArray(videoBuffer, FIFO_SIZE);
- p.Do(size);
- p.DoPointer(g_pVideoData, videoBuffer);
- p.Do(g_bSkipCurrentFrame);
+ p.DoArray(videoBuffer, FIFO_SIZE);
+ p.Do(size);
+ p.DoPointer(g_pVideoData, videoBuffer);
+ p.Do(g_bSkipCurrentFrame);
}
void Fifo_PauseAndLock(bool doLock, bool unpauseOnUnlock)
@@ -68,21 +69,22 @@ void Fifo_PauseAndLock(bool doLock, bool unpauseOnUnlock)
void Fifo_Init()
-{
- videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE);
+{
+ videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE);
size = 0;
GpuRunningState = false;
+ Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin);
}
void Fifo_Shutdown()
{
if (GpuRunningState) PanicAlert("Fifo shutting down while active");
- FreeMemoryPages(videoBuffer, FIFO_SIZE);
+ FreeMemoryPages(videoBuffer, FIFO_SIZE);
}
u8* GetVideoBufferStartPtr()
{
- return videoBuffer;
+ return videoBuffer;
}
u8* GetVideoBufferEndPtr()
@@ -117,20 +119,20 @@ void EmulatorState(bool running)
// Description: RunGpuLoop() sends data through this function.
void ReadDataFromFifo(u8* _uData, u32 len)
{
- if (size + len >= FIFO_SIZE)
- {
+ if (size + len >= FIFO_SIZE)
+ {
int pos = (int)(g_pVideoData - videoBuffer);
size -= pos;
- if (size + len > FIFO_SIZE)
- {
- PanicAlert("FIFO out of bounds (sz = %i, at %08x)", size, pos);
- }
- memmove(&videoBuffer[0], &videoBuffer[pos], size);
+ if (size + len > FIFO_SIZE)
+ {
+ PanicAlert("FIFO out of bounds (sz = %i, len = %i at %08x)", size, len, pos);
+ }
+ memmove(&videoBuffer[0], &videoBuffer[pos], size);
g_pVideoData = videoBuffer;
- }
+ }
// Copy new video instructions to videoBuffer for future use in rendering the new picture
- memcpy(videoBuffer + size, _uData, len);
- size += len;
+ memcpy(videoBuffer + size, _uData, len);
+ size += len;
}
void ResetVideoBuffer()
@@ -147,39 +149,50 @@ void RunGpuLoop()
std::lock_guard<std::mutex> lk(m_csHWVidOccupied);
GpuRunningState = true;
SCPFifoStruct &fifo = CommandProcessor::fifo;
+ u32 cyclesExecuted = 0;
while (GpuRunningState)
{
g_video_backend->PeekMessages();
VideoFifo_CheckAsyncRequest();
-
+
CommandProcessor::SetCpStatus();
+
+ Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin);
+
// check if we are able to run this buffer
- while (GpuRunningState && !CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt())
+ while (GpuRunningState && !CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint())
{
if (!GpuRunningState) break;
fifo.isGpuReadingData = true;
CommandProcessor::isPossibleWaitingSetDrawDone = fifo.bFF_GPLinkEnable ? true : false;
-
- u32 readPtr = fifo.CPReadPointer;
- u8 *uData = Memory::GetPointer(readPtr);
- if (readPtr == fifo.CPEnd) readPtr = fifo.CPBase;
+ if (Common::AtomicLoad(CommandProcessor::VITicks) > CommandProcessor::m_cpClockOrigin || !Core::g_CoreStartupParameter.bSyncGPU)
+ {
+ u32 readPtr = fifo.CPReadPointer;
+ u8 *uData = Memory::GetPointer(readPtr);
+
+ if (readPtr == fifo.CPEnd) readPtr = fifo.CPBase;
else readPtr += 32;
-
- _assert_msg_(COMMANDPROCESSOR, (s32)fifo.CPReadWriteDistance - 32 >= 0 ,
- "Negative fifo.CPReadWriteDistance = %i in FIFO Loop !\nThat can produce inestabilty in the game. Please report it.", fifo.CPReadWriteDistance - 32);
-
- ReadDataFromFifo(uData, 32);
-
- OpcodeDecoder_Run(g_bSkipCurrentFrame);
-
- Common::AtomicStore(fifo.CPReadPointer, readPtr);
- Common::AtomicAdd(fifo.CPReadWriteDistance, -32);
- if((GetVideoBufferEndPtr() - g_pVideoData) == 0)
- Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);
+
+ _assert_msg_(COMMANDPROCESSOR, (s32)fifo.CPReadWriteDistance - 32 >= 0 ,
+ "Negative fifo.CPReadWriteDistance = %i in FIFO Loop !\nThat can produce instabilty in the game. Please report it.", fifo.CPReadWriteDistance - 32);
+
+ ReadDataFromFifo(uData, 32);
+
+ cyclesExecuted = OpcodeDecoder_Run(g_bSkipCurrentFrame);
+
+ if (Common::AtomicLoad(CommandProcessor::VITicks) > cyclesExecuted && Core::g_CoreStartupParameter.bSyncGPU)
+ Common::AtomicAdd(CommandProcessor::VITicks, -(s32)cyclesExecuted);
+
+ Common::AtomicStore(fifo.CPReadPointer, readPtr);
+ Common::AtomicAdd(fifo.CPReadWriteDistance, -32);
+ if((GetVideoBufferEndPtr() - g_pVideoData) == 0)
+ Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);
+ }
+
CommandProcessor::SetCpStatus();
// This call is pretty important in DualCore mode and must be called in the FIFO Loop.
@@ -188,12 +201,18 @@ void RunGpuLoop()
VideoFifo_CheckAsyncRequest();
CommandProcessor::isPossibleWaitingSetDrawDone = false;
}
-
+
fifo.isGpuReadingData = false;
-
if (EmuRunningState)
+ {
+ // NOTE(jsd): Calling SwitchToThread() on Windows 7 x64 is a hot spot, according to profiler.
+ // See https://docs.google.com/spreadsheet/ccc?key=0Ah4nh0yGtjrgdFpDeF9pS3V6RUotRVE3S3J4TGM1NlE#gid=0
+ // for benchmark details.
+#if 0
Common::YieldCPU();
+#endif
+ }
else
{
// While the emu is paused, we still handle async requests then sleep.
@@ -217,23 +236,23 @@ bool AtBreakpoint()
void RunGpu()
{
- SCPFifoStruct &fifo = CommandProcessor::fifo;
- while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() )
- {
- u8 *uData = Memory::GetPointer(fifo.CPReadPointer);
-
- SaveSSEState();
- LoadDefaultSSEState();
- ReadDataFromFifo(uData, 32);
- OpcodeDecoder_Run(g_bSkipCurrentFrame);
- LoadSSEState();
+ SCPFifoStruct &fifo = CommandProcessor::fifo;
+ while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() )
+ {
+ u8 *uData = Memory::GetPointer(fifo.CPReadPointer);
- //DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base");
+ FPURoundMode::SaveSIMDState();
+ FPURoundMode::LoadDefaultSIMDState();
+ ReadDataFromFifo(uData, 32);
+ OpcodeDecoder_Run(g_bSkipCurrentFrame);
+ FPURoundMode::LoadSIMDState();
- if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase;
- else fifo.CPReadPointer += 32;
+ //DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base");
- fifo.CPReadWriteDistance -= 32;
- }
- CommandProcessor::SetCpStatus();
+ if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase;
+ else fifo.CPReadPointer += 32;
+
+ fifo.CPReadWriteDistance -= 32;
+ }
+ CommandProcessor::SetCpStatus();
}
diff --git a/Source/Core/VideoCommon/Src/Fifo.h b/Source/Core/VideoCommon/Src/Fifo.h
index 75e7d782f5..f465db8f85 100644
--- a/Source/Core/VideoCommon/Src/Fifo.h
+++ b/Source/Core/VideoCommon/Src/Fifo.h
@@ -23,7 +23,7 @@
class PointerWrap;
-#define FIFO_SIZE (1024*1024)
+#define FIFO_SIZE (2*1024*1024)
extern volatile bool g_bSkipCurrentFrame;
diff --git a/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp
index c883714daf..335344e229 100644
--- a/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp
+++ b/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp
@@ -60,12 +60,12 @@ const XFBSourceBase* const* FramebufferManagerBase::GetRealXFBSource(u32 xfbAddr
m_realXFBSource->texHeight = fbHeight;
// TODO: stuff only used by OGL... :/
- // OpenGL texture coordinates originate at the lower left, which is why
- // sourceRc.top = fbHeight and sourceRc.bottom = 0.
- m_realXFBSource->sourceRc.left = 0;
- m_realXFBSource->sourceRc.top = fbHeight;
- m_realXFBSource->sourceRc.right = fbWidth;
- m_realXFBSource->sourceRc.bottom = 0;
+ // OpenGL texture coordinates originate at the lower left, which is why
+ // sourceRc.top = fbHeight and sourceRc.bottom = 0.
+ m_realXFBSource->sourceRc.left = 0;
+ m_realXFBSource->sourceRc.top = fbHeight;
+ m_realXFBSource->sourceRc.right = fbWidth;
+ m_realXFBSource->sourceRc.bottom = 0;
// Decode YUYV data from GameCube RAM
m_realXFBSource->DecodeToTexture(xfbAddr, fbWidth, fbHeight);
@@ -163,13 +163,9 @@ void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHe
// keep stale XFB data from being used
ReplaceVirtualXFB();
-
- g_renderer->ResetAPIState(); // reset any game specific settings
// Copy EFB data to XFB and restore render target again
vxfb->xfbSource->CopyEFB(Gamma);
-
- g_renderer->RestoreAPIState();
}
FramebufferManagerBase::VirtualXFBListType::iterator FramebufferManagerBase::FindVirtualXFB(u32 xfbAddr, u32 width, u32 height)
diff --git a/Source/Core/VideoCommon/Src/GenericDLCache.cpp b/Source/Core/VideoCommon/Src/GenericDLCache.cpp
new file mode 100644
index 0000000000..d6826bbbde
--- /dev/null
+++ b/Source/Core/VideoCommon/Src/GenericDLCache.cpp
@@ -0,0 +1,52 @@
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+// TODO: Handle cache-is-full condition :p
+
+
+#include "Common.h"
+#include "DLCache.h"
+
+namespace DLCache
+{
+
+void Init()
+{
+}
+
+void Shutdown()
+{
+}
+
+void Clear()
+{
+}
+
+void ProgressiveCleanup()
+{
+}
+} // namespace
+
+// NOTE - outside the namespace on purpose.
+bool HandleDisplayList(u32 address, u32 size)
+{
+ return false;
+}
+
+void IncrementCheckContextId()
+{
+}
diff --git a/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp b/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp
new file mode 100644
index 0000000000..c5d14bfe9e
--- /dev/null
+++ b/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp
@@ -0,0 +1,2210 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+//#include "VideoCommon.h" // to get debug logs
+
+#include "CPUDetect.h"
+#include "TextureDecoder.h"
+#include "OpenCL.h"
+#include "OpenCL/OCLTextureDecoder.h"
+#include "VideoConfig.h"
+
+#include "LookUpTables.h"
+
+#include <cmath>
+
+
+
+bool TexFmt_Overlay_Enable=false;
+bool TexFmt_Overlay_Center=false;
+
+extern const char* texfmt[];
+extern const unsigned char sfont_map[];
+extern const unsigned char sfont_raw[][9*10];
+
+// TRAM
+// STATE_TO_SAVE
+ GC_ALIGNED16(u8 texMem[TMEM_SIZE]);
+
+
+// Gamecube/Wii texture decoder
+
+// Decodes all known Gamecube/Wii texture formats.
+// by ector
+
+int TexDecoder_GetTexelSizeInNibbles(int format)
+{
+ switch (format & 0x3f) {
+ case GX_TF_I4: return 1;
+ case GX_TF_I8: return 2;
+ case GX_TF_IA4: return 2;
+ case GX_TF_IA8: return 4;
+ case GX_TF_RGB565: return 4;
+ case GX_TF_RGB5A3: return 4;
+ case GX_TF_RGBA8: return 8;
+ case GX_TF_C4: return 1;
+ case GX_TF_C8: return 2;
+ case GX_TF_C14X2: return 4;
+ case GX_TF_CMPR: return 1;
+ case GX_CTF_R4: return 1;
+ case GX_CTF_RA4: return 2;
+ case GX_CTF_RA8: return 4;
+ case GX_CTF_YUVA8: return 8;
+ case GX_CTF_A8: return 2;
+ case GX_CTF_R8: return 2;
+ case GX_CTF_G8: return 2;
+ case GX_CTF_B8: return 2;
+ case GX_CTF_RG8: return 4;
+ case GX_CTF_GB8: return 4;
+
+ case GX_TF_Z8: return 2;
+ case GX_TF_Z16: return 4;
+ case GX_TF_Z24X8: return 8;
+
+ case GX_CTF_Z4: return 1;
+ case GX_CTF_Z8M: return 2;
+ case GX_CTF_Z8L: return 2;
+ case GX_CTF_Z16L: return 4;
+ default: return 1;
+ }
+}
+
+int TexDecoder_GetTextureSizeInBytes(int width, int height, int format)
+{
+ return (width * height * TexDecoder_GetTexelSizeInNibbles(format)) / 2;
+}
+
+int TexDecoder_GetBlockWidthInTexels(u32 format)
+{
+ switch (format)
+ {
+ case GX_TF_I4: return 8;
+ case GX_TF_I8: return 8;
+ case GX_TF_IA4: return 8;
+ case GX_TF_IA8: return 4;
+ case GX_TF_RGB565: return 4;
+ case GX_TF_RGB5A3: return 4;
+ case GX_TF_RGBA8: return 4;
+ case GX_TF_C4: return 8;
+ case GX_TF_C8: return 8;
+ case GX_TF_C14X2: return 4;
+ case GX_TF_CMPR: return 8;
+ case GX_CTF_R4: return 8;
+ case GX_CTF_RA4: return 8;
+ case GX_CTF_RA8: return 4;
+ case GX_CTF_A8: return 8;
+ case GX_CTF_R8: return 8;
+ case GX_CTF_G8: return 8;
+ case GX_CTF_B8: return 8;
+ case GX_CTF_RG8: return 4;
+ case GX_CTF_GB8: return 4;
+ case GX_TF_Z8: return 8;
+ case GX_TF_Z16: return 4;
+ case GX_TF_Z24X8: return 4;
+ case GX_CTF_Z4: return 8;
+ case GX_CTF_Z8M: return 8;
+ case GX_CTF_Z8L: return 8;
+ case GX_CTF_Z16L: return 4;
+ default:
+ ERROR_LOG(VIDEO, "Unsupported Texture Format (%08x)! (GetBlockWidthInTexels)", format);
+ return 8;
+ }
+}
+
+int TexDecoder_GetBlockHeightInTexels(u32 format)
+{
+ switch (format)
+ {
+ case GX_TF_I4: return 8;
+ case GX_TF_I8: return 4;
+ case GX_TF_IA4: return 4;
+ case GX_TF_IA8: return 4;
+ case GX_TF_RGB565: return 4;
+ case GX_TF_RGB5A3: return 4;
+ case GX_TF_RGBA8: return 4;
+ case GX_TF_C4: return 8;
+ case GX_TF_C8: return 4;
+ case GX_TF_C14X2: return 4;
+ case GX_TF_CMPR: return 8;
+ case GX_CTF_R4: return 8;
+ case GX_CTF_RA4: return 4;
+ case GX_CTF_RA8: return 4;
+ case GX_CTF_A8: return 4;
+ case GX_CTF_R8: return 4;
+ case GX_CTF_G8: return 4;
+ case GX_CTF_B8: return 4;
+ case GX_CTF_RG8: return 4;
+ case GX_CTF_GB8: return 4;
+ case GX_TF_Z8: return 4;
+ case GX_TF_Z16: return 4;
+ case GX_TF_Z24X8: return 4;
+ case GX_CTF_Z4: return 8;
+ case GX_CTF_Z8M: return 4;
+ case GX_CTF_Z8L: return 4;
+ case GX_CTF_Z16L: return 4;
+ default:
+ ERROR_LOG(VIDEO, "Unsupported Texture Format (%08x)! (GetBlockHeightInTexels)", format);
+ return 4;
+ }
+}
+
+//returns bytes
+int TexDecoder_GetPaletteSize(int format)
+{
+ switch (format)
+ {
+ case GX_TF_C4: return 16 * 2;
+ case GX_TF_C8: return 256 * 2;
+ case GX_TF_C14X2: return 16384 * 2;
+ default:
+ return 0;
+ }
+}
+
+static inline u32 decodeIA8(u16 val)
+{
+ int a = val >> 8;
+ int i = val & 0xFF;
+ return (a << 24) | (i << 16) | (i << 8) | i;
+}
+
+static inline u32 decode5A3(u16 val)
+{
+ int r,g,b,a;
+ if ((val & 0x8000))
+ {
+ a = 0xFF;
+ r = Convert5To8((val >> 10) & 0x1F);
+ g = Convert5To8((val >> 5) & 0x1F);
+ b = Convert5To8(val & 0x1F);
+ }
+ else
+ {
+ a = Convert3To8((val >> 12) & 0x7);
+ r = Convert4To8((val >> 8) & 0xF);
+ g = Convert4To8((val >> 4) & 0xF);
+ b = Convert4To8(val & 0xF);
+ }
+ return (a << 24) | (r << 16) | (g << 8) | b;
+}
+
+static inline u32 decode5A3RGBA(u16 val)
+{
+ int r,g,b,a;
+ if ((val&0x8000))
+ {
+ r=Convert5To8((val>>10) & 0x1f);
+ g=Convert5To8((val>>5 ) & 0x1f);
+ b=Convert5To8((val ) & 0x1f);
+ a=0xFF;
+ }
+ else
+ {
+ a=Convert3To8((val>>12) & 0x7);
+ r=Convert4To8((val>>8 ) & 0xf);
+ g=Convert4To8((val>>4 ) & 0xf);
+ b=Convert4To8((val ) & 0xf);
+ }
+ return r | (g<<8) | (b << 16) | (a << 24);
+}
+
+static inline u32 decode565RGBA(u16 val)
+{
+ int r,g,b,a;
+ r=Convert5To8((val>>11) & 0x1f);
+ g=Convert6To8((val>>5 ) & 0x3f);
+ b=Convert5To8((val ) & 0x1f);
+ a=0xFF;
+ return r | (g<<8) | (b << 16) | (a << 24);
+}
+
+static inline u32 decodeIA8Swapped(u16 val)
+{
+ int a = val & 0xFF;
+ int i = val >> 8;
+ return i | (i<<8) | (i<<16) | (a<<24);
+}
+
+
+
+struct DXTBlock
+{
+ u16 color1;
+ u16 color2;
+ u8 lines[4];
+};
+
+//inline void decodebytesC4(u32 *dst, const u8 *src, int numbytes, int tlutaddr, int tlutfmt)
+inline void decodebytesC4_5A3_To_BGRA32(u32 *dst, const u8 *src, int tlutaddr)
+{
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 4; x++)
+ {
+ u8 val = src[x];
+ *dst++ = decode5A3(Common::swap16(tlut[val >> 4]));
+ *dst++ = decode5A3(Common::swap16(tlut[val & 0xF]));
+ }
+}
+
+inline void decodebytesC4_5A3_To_rgba32(u32 *dst, const u8 *src, int tlutaddr)
+{
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 4; x++)
+ {
+ u8 val = src[x];
+ *dst++ = decode5A3RGBA(Common::swap16(tlut[val >> 4]));
+ *dst++ = decode5A3RGBA(Common::swap16(tlut[val & 0xF]));
+ }
+}
+
+inline void decodebytesC4_To_Raw16(u16* dst, const u8* src, int tlutaddr)
+{
+ u16* tlut = (u16*)(texMem+tlutaddr);
+ for (int x = 0; x < 4; x++)
+ {
+ u8 val = src[x];
+ *dst++ = Common::swap16(tlut[val >> 4]);
+ *dst++ = Common::swap16(tlut[val & 0xF]);
+ }
+}
+
+inline void decodebytesC4IA8_To_RGBA(u32* dst, const u8* src, int tlutaddr)
+{
+ u16* tlut = (u16*)(texMem+tlutaddr);
+ for (int x = 0; x < 4; x++)
+ {
+ u8 val = src[x];
+ *dst++ = decodeIA8Swapped(tlut[val >> 4]);
+ *dst++ = decodeIA8Swapped(tlut[val & 0xF]);
+ }
+}
+
+inline void decodebytesC4RGB565_To_RGBA(u32* dst, const u8* src, int tlutaddr)
+{
+ u16* tlut = (u16*)(texMem+tlutaddr);
+ for (int x = 0; x < 4; x++)
+ {
+ u8 val = src[x];
+ *dst++ = decode565RGBA(Common::swap16(tlut[val >> 4]));
+ *dst++ = decode565RGBA(Common::swap16(tlut[val & 0xF]));
+ }
+}
+
+//inline void decodebytesC8(u32 *dst, const u8 *src, int numbytes, int tlutaddr, int tlutfmt)
+inline void decodebytesC8_5A3_To_BGRA32(u32 *dst, const u8 *src, int tlutaddr)
+{
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 8; x++)
+ {
+ u8 val = src[x];
+ *dst++ = decode5A3(Common::swap16(tlut[val]));
+ }
+}
+
+inline void decodebytesC8_5A3_To_RGBA32(u32 *dst, const u8 *src, int tlutaddr)
+{
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 8; x++)
+ {
+ u8 val = src[x];
+ *dst++ = decode5A3RGBA(Common::swap16(tlut[val]));
+ }
+}
+
+inline void decodebytesC8_To_Raw16(u16* dst, const u8* src, int tlutaddr)
+{
+ u16* tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 8; x++)
+ {
+ u8 val = src[x];
+ *dst++ = Common::swap16(tlut[val]);
+ }
+}
+
+inline void decodebytesC8IA8_To_RGBA(u32* dst, const u8* src, int tlutaddr)
+{
+ u16* tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 8; x++)
+ {
+ *dst++ = decodeIA8Swapped(tlut[src[x]]);
+ }
+}
+
+inline void decodebytesC8RGB565_To_RGBA(u32* dst, const u8* src, int tlutaddr)
+{
+ u16* tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 8; x++)
+ {
+ *dst++ = decode565RGBA(Common::swap16(tlut[src[x]]));
+ }
+}
+
+inline void decodebytesC14X2_5A3_To_BGRA32(u32 *dst, const u16 *src, int tlutaddr)
+{
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 4; x++)
+ {
+ u16 val = Common::swap16(src[x]);
+ *dst++ = decode5A3(Common::swap16(tlut[(val & 0x3FFF)]));
+ }
+}
+
+inline void decodebytesC14X2_5A3_To_RGBA(u32 *dst, const u16 *src, int tlutaddr)
+{
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 4; x++)
+ {
+ u16 val = Common::swap16(src[x]);
+ *dst++ = decode5A3RGBA(Common::swap16(tlut[(val & 0x3FFF)]));
+ }
+}
+
+inline void decodebytesC14X2_To_Raw16(u16* dst, const u16* src, int tlutaddr)
+{
+ u16* tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 4; x++)
+ {
+ u16 val = Common::swap16(src[x]);
+ *dst++ = Common::swap16(tlut[(val & 0x3FFF)]);
+ }
+}
+
+inline void decodebytesC14X2IA8_To_RGBA(u32* dst, const u16* src, int tlutaddr)
+{
+ u16* tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 4; x++)
+ {
+ u16 val = Common::swap16(src[x]);
+ *dst++ = decodeIA8Swapped(tlut[(val & 0x3FFF)]);
+ }
+}
+
+inline void decodebytesC14X2rgb565_To_RGBA(u32* dst, const u16* src, int tlutaddr)
+{
+ u16* tlut = (u16*)(texMem + tlutaddr);
+ for (int x = 0; x < 4; x++)
+ {
+ u16 val = Common::swap16(src[x]);
+ *dst++ = decode565RGBA(Common::swap16(tlut[(val & 0x3FFF)]));
+ }
+}
+
+// Needs more speed.
+inline void decodebytesIA4(u16 *dst, const u8 *src)
+{
+ for (int x = 0; x < 8; x++)
+ {
+ const u8 val = src[x];
+ u8 a = Convert4To8(val >> 4);
+ u8 l = Convert4To8(val & 0xF);
+ dst[x] = (a << 8) | l;
+ }
+}
+
+inline void decodebytesIA4RGBA(u32 *dst, const u8 *src)
+{
+ for (int x = 0; x < 8; x++)
+ {
+ const u8 val = src[x];
+ u8 a = Convert4To8(val >> 4);
+ u8 l = Convert4To8(val & 0xF);
+ dst[x] = (a << 24) | l << 16 | l << 8 | l;
+ }
+}
+
+inline void decodebytesRGB5A3(u32 *dst, const u16 *src)
+{
+#if 0
+ for (int x = 0; x < 4; x++)
+ dst[x] = decode5A3(Common::swap16(src[x]));
+#else
+ dst[0] = decode5A3(Common::swap16(src[0]));
+ dst[1] = decode5A3(Common::swap16(src[1]));
+ dst[2] = decode5A3(Common::swap16(src[2]));
+ dst[3] = decode5A3(Common::swap16(src[3]));
+#endif
+}
+
+inline void decodebytesRGB5A3rgba(u32 *dst, const u16 *src)
+{
+#if 0
+ for (int x = 0; x < 4; x++)
+ dst[x] = decode5A3RGBA(Common::swap16(src[x]));
+#else
+ dst[0] = decode5A3RGBA(Common::swap16(src[0]));
+ dst[1] = decode5A3RGBA(Common::swap16(src[1]));
+ dst[2] = decode5A3RGBA(Common::swap16(src[2]));
+ dst[3] = decode5A3RGBA(Common::swap16(src[3]));
+#endif
+}
+
+// This one is used by many video formats. It'd therefore be good if it was fast.
+// Needs more speed.
+inline void decodebytesARGB8_4(u32 *dst, const u16 *src, const u16 *src2)
+{
+#if 0
+ for (int x = 0; x < 4; x++)
+ dst[x] = Common::swap32((src2[x] << 16) | src[x]);
+#else
+ dst[0] = Common::swap32((src2[0] << 16) | src[0]);
+ dst[1] = Common::swap32((src2[1] << 16) | src[1]);
+ dst[2] = Common::swap32((src2[2] << 16) | src[2]);
+ dst[3] = Common::swap32((src2[3] << 16) | src[3]);
+#endif
+
+ // This can probably be done in a few SSE pack/unpack instructions + pshufb
+ // some unpack instruction x2:
+ // ABABABABABABABAB 1212121212121212 ->
+ // AB12AB12AB12AB12 AB12AB12AB12AB12
+ // 2x pshufb->
+ // 21BA21BA21BA21BA 21BA21BA21BA21BA
+ // and we are done.
+}
+
+inline void decodebytesARGB8_4ToRgba(u32 *dst, const u16 *src, const u16 * src2)
+{
+#if 0
+ for (int x = 0; x < 4; x++) {
+ dst[x] = ((src[x] & 0xFF) << 24) | ((src[x] & 0xFF00)>>8) | (src2[x] << 8);
+ }
+#else
+ dst[0] = ((src[0] & 0xFF) << 24) | ((src[0] & 0xFF00)>>8) | (src2[0] << 8);
+ dst[1] = ((src[1] & 0xFF) << 24) | ((src[1] & 0xFF00)>>8) | (src2[1] << 8);
+ dst[2] = ((src[2] & 0xFF) << 24) | ((src[2] & 0xFF00)>>8) | (src2[2] << 8);
+ dst[3] = ((src[3] & 0xFF) << 24) | ((src[3] & 0xFF00)>>8) | (src2[3] << 8);
+#endif
+}
+
+inline u32 makecol(int r, int g, int b, int a)
+{
+ return (a << 24)|(r << 16)|(g << 8)|b;
+}
+
+inline u32 makeRGBA(int r, int g, int b, int a)
+{
+ return (a<<24)|(b<<16)|(g<<8)|r;
+}
+
+void decodeDXTBlock(u32 *dst, const DXTBlock *src, int pitch)
+{
+ // S3TC Decoder (Note: GCN decodes differently from PC so we can't use native support)
+ // Needs more speed.
+ u16 c1 = Common::swap16(src->color1);
+ u16 c2 = Common::swap16(src->color2);
+ int blue1 = Convert5To8(c1 & 0x1F);
+ int blue2 = Convert5To8(c2 & 0x1F);
+ int green1 = Convert6To8((c1 >> 5) & 0x3F);
+ int green2 = Convert6To8((c2 >> 5) & 0x3F);
+ int red1 = Convert5To8((c1 >> 11) & 0x1F);
+ int red2 = Convert5To8((c2 >> 11) & 0x1F);
+ int colors[4];
+ colors[0] = makecol(red1, green1, blue1, 255);
+ colors[1] = makecol(red2, green2, blue2, 255);
+ if (c1 > c2)
+ {
+ int blue3 = ((blue2 - blue1) >> 1) - ((blue2 - blue1) >> 3);
+ int green3 = ((green2 - green1) >> 1) - ((green2 - green1) >> 3);
+ int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3);
+ colors[2] = makecol(red1 + red3, green1 + green3, blue1 + blue3, 255);
+ colors[3] = makecol(red2 - red3, green2 - green3, blue2 - blue3, 255);
+ }
+ else
+ {
+ colors[2] = makecol((red1 + red2 + 1) / 2, // Average
+ (green1 + green2 + 1) / 2,
+ (blue1 + blue2 + 1) / 2, 255);
+ colors[3] = makecol(red2, green2, blue2, 0); // Color2 but transparent
+ }
+
+ for (int y = 0; y < 4; y++)
+ {
+ int val = src->lines[y];
+ for (int x = 0; x < 4; x++)
+ {
+ dst[x] = colors[(val >> 6) & 3];
+ val <<= 2;
+ }
+ dst += pitch;
+ }
+}
+
+void decodeDXTBlockRGBA(u32 *dst, const DXTBlock *src, int pitch)
+{
+ // S3TC Decoder (Note: GCN decodes differently from PC so we can't use native support)
+ // Needs more speed.
+ u16 c1 = Common::swap16(src->color1);
+ u16 c2 = Common::swap16(src->color2);
+ int blue1 = Convert5To8(c1 & 0x1F);
+ int blue2 = Convert5To8(c2 & 0x1F);
+ int green1 = Convert6To8((c1 >> 5) & 0x3F);
+ int green2 = Convert6To8((c2 >> 5) & 0x3F);
+ int red1 = Convert5To8((c1 >> 11) & 0x1F);
+ int red2 = Convert5To8((c2 >> 11) & 0x1F);
+ int colors[4];
+ colors[0] = makeRGBA(red1, green1, blue1, 255);
+ colors[1] = makeRGBA(red2, green2, blue2, 255);
+ if (c1 > c2)
+ {
+ int blue3 = ((blue2 - blue1) >> 1) - ((blue2 - blue1) >> 3);
+ int green3 = ((green2 - green1) >> 1) - ((green2 - green1) >> 3);
+ int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3);
+ colors[2] = makeRGBA(red1 + red3, green1 + green3, blue1 + blue3, 255);
+ colors[3] = makeRGBA(red2 - red3, green2 - green3, blue2 - blue3, 255);
+ }
+ else
+ {
+ colors[2] = makeRGBA((red1 + red2 + 1) / 2, // Average
+ (green1 + green2 + 1) / 2,
+ (blue1 + blue2 + 1) / 2, 255);
+ colors[3] = makeRGBA(red2, green2, blue2, 0); // Color2 but transparent
+ }
+
+ for (int y = 0; y < 4; y++)
+ {
+ int val = src->lines[y];
+ for (int x = 0; x < 4; x++)
+ {
+ dst[x] = colors[(val >> 6) & 3];
+ val <<= 2;
+ }
+ dst += pitch;
+ }
+}
+
+#if 0 // TODO - currently does not handle transparency correctly and causes problems when texture dimensions are not multiples of 8
+static void copyDXTBlock(u8* dst, const u8* src)
+{
+ ((u16*)dst)[0] = Common::swap16(((u16*)src)[0]);
+ ((u16*)dst)[1] = Common::swap16(((u16*)src)[1]);
+ u32 pixels = ((u32*)src)[1];
+ // A bit of trickiness here: the row are in the same order
+ // between the two formats, but the ordering within the rows
+ // is reversed.
+ pixels = ((pixels >> 4) & 0x0F0F0F0F) | ((pixels << 4) & 0xF0F0F0F0);
+ pixels = ((pixels >> 2) & 0x33333333) | ((pixels << 2) & 0xCCCCCCCC);
+ ((u32*)dst)[1] = pixels;
+}
+#endif
+
+static PC_TexFormat GetPCFormatFromTLUTFormat(int tlutfmt)
+{
+ switch (tlutfmt)
+ {
+ case 0: return PC_TEX_FMT_IA8; // IA8
+ case 1: return PC_TEX_FMT_RGB565; // RGB565
+ case 2: return PC_TEX_FMT_BGRA32; // RGB5A3: This TLUT format requires
+ // extra work to decode.
+ }
+ return PC_TEX_FMT_NONE; // Error
+}
+
+PC_TexFormat GetPC_TexFormat(int texformat, int tlutfmt)
+{
+ switch (texformat)
+ {
+ case GX_TF_C4:
+ return GetPCFormatFromTLUTFormat(tlutfmt);
+ case GX_TF_I4:
+ return PC_TEX_FMT_IA8;
+ case GX_TF_I8: // speed critical
+ return PC_TEX_FMT_IA8;
+ case GX_TF_C8:
+ return GetPCFormatFromTLUTFormat(tlutfmt);
+ case GX_TF_IA4:
+ return PC_TEX_FMT_IA4_AS_IA8;
+ case GX_TF_IA8:
+ return PC_TEX_FMT_IA8;
+ case GX_TF_C14X2:
+ return GetPCFormatFromTLUTFormat(tlutfmt);
+ case GX_TF_RGB565:
+ return PC_TEX_FMT_RGB565;
+ case GX_TF_RGB5A3:
+ return PC_TEX_FMT_BGRA32;
+ case GX_TF_RGBA8: // speed critical
+ return PC_TEX_FMT_BGRA32;
+ case GX_TF_CMPR: // speed critical
+ // The metroid games use this format almost exclusively.
+ {
+ return PC_TEX_FMT_BGRA32;
+ }
+ }
+
+ // The "copy" texture formats, too?
+ return PC_TEX_FMT_NONE;
+}
+
+
+//switch endianness, unswizzle
+//TODO: to save memory, don't blindly convert everything to argb8888
+//also ARGB order needs to be swapped later, to accommodate modern hardware better
+//need to add DXT support too
+PC_TexFormat TexDecoder_Decode_real(u8 *dst, const u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt)
+{
+ const int Wsteps4 = (width + 3) / 4;
+ const int Wsteps8 = (width + 7) / 8;
+
+ switch (texformat)
+ {
+ case GX_TF_C4:
+ if (tlutfmt == 2)
+ {
+ // Special decoding is required for TLUT format 5A3
+ for (int y = 0; y < height; y += 8)
+ for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = yStep * 8; iy < 8; iy++, xStep++)
+ decodebytesC4_5A3_To_BGRA32((u32*)dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr);
+ }
+ else
+ {
+ for (int y = 0; y < height; y += 8)
+ for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = yStep * 8; iy < 8; iy++, xStep++)
+ decodebytesC4_To_Raw16((u16*)dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr);
+ }
+ return GetPCFormatFromTLUTFormat(tlutfmt);
+ case GX_TF_I4:
+ {
+ for (int y = 0; y < height; y += 8)
+ for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = yStep * 8 ; iy < 8; iy++,xStep++)
+ for (int ix = 0; ix < 4; ix++)
+ {
+ int val = src[4 * xStep + ix];
+ dst[(y + iy) * width + x + ix * 2] = Convert4To8(val >> 4);
+ dst[(y + iy) * width + x + ix * 2 + 1] = Convert4To8(val & 0xF);
+ }
+ }
+ return PC_TEX_FMT_I4_AS_I8;
+ case GX_TF_I8: // speed critical
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ ((u64*)(dst + (y + iy) * width + x))[0] = ((u64*)(src + 8 * xStep))[0];
+ }
+ return PC_TEX_FMT_I8;
+ case GX_TF_C8:
+ if (tlutfmt == 2)
+ {
+ // Special decoding is required for TLUT format 5A3
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesC8_5A3_To_BGRA32((u32*)dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr);
+ }
+ else
+ {
+
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesC8_To_Raw16((u16*)dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr);
+ }
+ }
+ return GetPCFormatFromTLUTFormat(tlutfmt);
+ case GX_TF_IA4:
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesIA4((u16*)dst + (y + iy) * width + x, src + 8 * xStep);
+ }
+ return PC_TEX_FMT_IA4_AS_IA8;
+ case GX_TF_IA8:
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++)
+ for (int iy = 0, xStep = yStep * 4; iy < 4; iy++, xStep++)
+ {
+ u16 *ptr = (u16 *)dst + (y + iy) * width + x;
+ u16 *s = (u16 *)(src + 8 * xStep);
+ for(int j = 0; j < 4; j++)
+ *ptr++ = Common::swap16(*s++);
+ }
+ }
+ return PC_TEX_FMT_IA8;
+ case GX_TF_C14X2:
+ if (tlutfmt == 2)
+ {
+ // Special decoding is required for TLUT format 5A3
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesC14X2_5A3_To_BGRA32((u32*)dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr);
+ }
+ else
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesC14X2_To_Raw16((u16*)dst + (y + iy) * width + x,(u16*)(src + 8 * xStep), tlutaddr);
+ }
+ return GetPCFormatFromTLUTFormat(tlutfmt);
+ case GX_TF_RGB565:
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ {
+ u16 *ptr = (u16 *)dst + (y + iy) * width + x;
+ u16 *s = (u16 *)(src + 8 * xStep);
+ for(int j = 0; j < 4; j++)
+ *ptr++ = Common::swap16(*s++);
+ }
+ }
+ return PC_TEX_FMT_RGB565;
+ case GX_TF_RGB5A3:
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ //decodebytesRGB5A3((u32*)dst+(y+iy)*width+x, (u16*)src, 4);
+ decodebytesRGB5A3((u32*)dst+(y+iy)*width+x, (u16*)(src + 8 * xStep));
+ }
+ return PC_TEX_FMT_BGRA32;
+ case GX_TF_RGBA8: // speed critical
+ {
+ for (int y = 0; y < height; y += 4)
+ {
+ for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++)
+ {
+ const u8* src2 = src + 64 * yStep;
+ for (int iy = 0; iy < 4; iy++)
+ decodebytesARGB8_4((u32*)dst + (y+iy)*width + x, (u16*)src2 + 4 * iy, (u16*)src2 + 4 * iy + 16);
+ }
+ }
+ }
+ return PC_TEX_FMT_BGRA32;
+ case GX_TF_CMPR: // speed critical
+ // The metroid games use this format almost exclusively.
+ {
+#if 0 // TODO - currently does not handle transparency correctly and causes problems when texture dimensions are not multiples of 8
+ // 11111111 22222222 55555555 66666666
+ // 33333333 44444444 77777777 88888888
+ for (int y = 0; y < height; y += 8)
+ {
+ for (int x = 0; x < width; x += 8)
+ {
+ copyDXTBlock(dst+(y/2)*width+x*2, src);
+ src += 8;
+ copyDXTBlock(dst+(y/2)*width+x*2+8, src);
+ src += 8;
+ copyDXTBlock(dst+(y/2+2)*width+x*2, src);
+ src += 8;
+ copyDXTBlock(dst+(y/2+2)*width+x*2+8, src);
+ src += 8;
+ }
+ }
+ return PC_TEX_FMT_DXT1;
+#else
+ for (int y = 0; y < height; y += 8)
+ {
+ for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++)
+ {
+ const u8* src2 = src + 4 * sizeof(DXTBlock) * yStep;
+ decodeDXTBlock((u32*)dst + y * width + x, (DXTBlock*)src2, width);
+ src2 += sizeof(DXTBlock);
+ decodeDXTBlock((u32*)dst + y * width + x + 4, (DXTBlock*)src2, width);
+ src2 += sizeof(DXTBlock);
+ decodeDXTBlock((u32*)dst + (y + 4) * width + x, (DXTBlock*)src2, width);
+ src2 += sizeof(DXTBlock);
+ decodeDXTBlock((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src2, width);
+ }
+ }
+#endif
+ return PC_TEX_FMT_BGRA32;
+ }
+ }
+
+ // The "copy" texture formats, too?
+ return PC_TEX_FMT_NONE;
+}
+
+
+
+// JSD 01/06/11:
+// TODO: we really should ensure BOTH the source and destination addresses are aligned to 16-byte boundaries to
+// squeeze out a little more performance. _mm_loadu_si128/_mm_storeu_si128 is slower than _mm_load_si128/_mm_store_si128
+// because they work on unaligned addresses. The processor is free to make the assumption that addresses are multiples
+// of 16 in the aligned case.
+// TODO: complete SSE2 optimization of less often used texture formats.
+// TODO: refactor algorithms using _mm_loadl_epi64 unaligned loads to prefer 128-bit aligned loads.
+
+PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int height, int texformat, int tlutaddr, int tlutfmt)
+{
+
+ const int Wsteps4 = (width + 3) / 4;
+ const int Wsteps8 = (width + 7) / 8;
+
+ switch (texformat)
+ {
+ case GX_TF_C4:
+ if (tlutfmt == 2)
+ {
+ // Special decoding is required for TLUT format 5A3
+ for (int y = 0; y < height; y += 8)
+ for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8,yStep++)
+ for (int iy = 0, xStep = 8 * yStep; iy < 8; iy++,xStep++)
+ decodebytesC4_5A3_To_rgba32(dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr);
+ }
+ else if(tlutfmt == 0)
+ {
+ for (int y = 0; y < height; y += 8)
+ for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8,yStep++)
+ for (int iy = 0, xStep = 8 * yStep; iy < 8; iy++,xStep++)
+ decodebytesC4IA8_To_RGBA(dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr);
+ }
+ else
+ {
+ for (int y = 0; y < height; y += 8)
+ for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8,yStep++)
+ for (int iy = 0, xStep = 8 * yStep; iy < 8; iy++,xStep++)
+ decodebytesC4RGB565_To_RGBA(dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr);
+ }
+ break;
+ case GX_TF_I4:
+ {
+ // Reference C implementation:
+ for (int y = 0; y < height; y += 8)
+ for (int x = 0; x < width; x += 8)
+ for (int iy = 0; iy < 8; iy++, src += 4)
+ for (int ix = 0; ix < 4; ix++)
+ {
+ int val = src[ix];
+ u8 i1 = Convert4To8(val >> 4);
+ u8 i2 = Convert4To8(val & 0xF);
+ memset(dst+(y + iy) * width + x + ix * 2 , i1,4);
+ memset(dst+(y + iy) * width + x + ix * 2 + 1 , i2,4);
+ }
+ }
+ break;
+ case GX_TF_I8: // speed critical
+ {
+ // Reference C implementation
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0; x < width; x += 8)
+ for (int iy = 0; iy < 4; ++iy, src += 8)
+ {
+ u32 * newdst = dst + (y + iy)*width+x;
+ const u8 * newsrc = src;
+ u8 srcval;
+
+ srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = newsrc[0]; newdst[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ }
+ }
+ break;
+ case GX_TF_C8:
+ if (tlutfmt == 2)
+ {
+ // Special decoding is required for TLUT format 5A3
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesC8_5A3_To_RGBA32((u32*)dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr);
+ }
+ else if(tlutfmt == 0)
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesC8IA8_To_RGBA(dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr);
+ }
+ else
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesC8RGB565_To_RGBA(dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr);
+
+ }
+ break;
+ case GX_TF_IA4:
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesIA4RGBA(dst + (y + iy) * width + x, src + 8 * xStep);
+ }
+ break;
+ case GX_TF_IA8:
+ {
+ // Reference C implementation:
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0; x < width; x += 4)
+ for (int iy = 0; iy < 4; iy++, src += 8)
+ {
+ u32 *ptr = dst + (y + iy) * width + x;
+ u16 *s = (u16 *)src;
+ ptr[0] = decodeIA8Swapped(s[0]);
+ ptr[1] = decodeIA8Swapped(s[1]);
+ ptr[2] = decodeIA8Swapped(s[2]);
+ ptr[3] = decodeIA8Swapped(s[3]);
+ }
+ }
+ break;
+ case GX_TF_C14X2:
+ if (tlutfmt == 2)
+ {
+ // Special decoding is required for TLUT format 5A3
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesC14X2_5A3_To_BGRA32(dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr);
+ }
+ else if (tlutfmt == 0)
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesC14X2IA8_To_RGBA(dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr);
+ }
+ else
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ decodebytesC14X2rgb565_To_RGBA(dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr);
+ }
+ break;
+ case GX_TF_RGB565:
+ {
+ // Reference C implementation.
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0; x < width; x += 4)
+ for (int iy = 0; iy < 4; iy++, src += 8)
+ {
+ u32 *ptr = dst + (y + iy) * width + x;
+ u16 *s = (u16 *)src;
+ for(int j = 0; j < 4; j++)
+ *ptr++ = decode565RGBA(Common::swap16(*s++));
+ }
+ }
+ break;
+ case GX_TF_RGB5A3:
+ {
+ // Reference C implementation:
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0; x < width; x += 4)
+ for (int iy = 0; iy < 4; iy++, src += 8)
+ decodebytesRGB5A3rgba(dst+(y+iy)*width+x, (u16*)src);
+ }
+ break;
+ case GX_TF_RGBA8: // speed critical
+ {
+ // Reference C implementation.
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0; x < width; x += 4)
+ {
+ for (int iy = 0; iy < 4; iy++)
+ decodebytesARGB8_4ToRgba(dst + (y+iy)*width + x, (u16*)src + 4 * iy, (u16*)src + 4 * iy + 16);
+ src += 64;
+ }
+ }
+ break;
+ case GX_TF_CMPR: // speed critical
+ // The metroid games use this format almost exclusively.
+ {
+ for (int y = 0; y < height; y += 8)
+ {
+ for (int x = 0; x < width; x += 8)
+ {
+ decodeDXTBlockRGBA((u32*)dst + y * width + x, (DXTBlock*)src, width);
+ src += sizeof(DXTBlock);
+ decodeDXTBlockRGBA((u32*)dst + y * width + x + 4, (DXTBlock*)src, width);
+ src += sizeof(DXTBlock);
+ decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x, (DXTBlock*)src, width);
+ src += sizeof(DXTBlock);
+ decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src, width);
+ src += sizeof(DXTBlock);
+ }
+ }
+ break;
+ }
+ }
+
+ // The "copy" texture formats, too?
+ return PC_TEX_FMT_RGBA32;
+}
+
+
+
+
+void TexDecoder_SetTexFmtOverlayOptions(bool enable, bool center)
+{
+ TexFmt_Overlay_Enable = enable;
+ TexFmt_Overlay_Center = center;
+}
+
+PC_TexFormat TexDecoder_Decode(u8 *dst, const u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt,bool rgbaOnly)
+{
+ PC_TexFormat retval = TexDecoder_Decode_OpenCL(dst, src,
+ width, height, texformat, tlutaddr, tlutfmt, rgbaOnly);
+ if (retval == PC_TEX_FMT_NONE)
+ retval = rgbaOnly ? TexDecoder_Decode_RGBA((u32*)dst, src,
+ width, height, texformat, tlutaddr, tlutfmt)
+ : TexDecoder_Decode_real(dst, src,
+ width, height, texformat, tlutaddr, tlutfmt);
+
+ if ((!TexFmt_Overlay_Enable)|| (retval == PC_TEX_FMT_NONE))
+ return retval;
+
+ int w = min(width, 40);
+ int h = min(height, 10);
+
+ int xoff = (width - w) >> 1;
+ int yoff = (height - h) >> 1;
+
+ if (!TexFmt_Overlay_Center)
+ {
+ xoff=0;
+ yoff=0;
+ }
+
+ const char* fmt = texfmt[texformat&15];
+ while (*fmt)
+ {
+ int xcnt = 0;
+ int nchar = sfont_map[(int)*fmt];
+
+ const unsigned char *ptr = sfont_raw[nchar]; // each char is up to 9x10
+
+ for (int x = 0; x < 9;x++)
+ {
+ if (ptr[x] == 0x78)
+ break;
+ xcnt++;
+ }
+
+ for (int y=0; y < 10; y++)
+ {
+ for (int x=0; x < xcnt; x++)
+ {
+ switch(retval)
+ {
+ case PC_TEX_FMT_I8:
+ {
+ // TODO: Is this an acceptable way to draw in I8?
+ u8 *dtp = (u8*)dst;
+ dtp[(y + yoff) * width + x + xoff] = ptr[x] ? 0xFF : 0x88;
+ break;
+ }
+ case PC_TEX_FMT_IA8:
+ case PC_TEX_FMT_IA4_AS_IA8:
+ {
+ u16 *dtp = (u16*)dst;
+ dtp[(y + yoff) * width + x + xoff] = ptr[x] ? 0xFFFF : 0xFF00;
+ break;
+ }
+ case PC_TEX_FMT_RGB565:
+ {
+ u16 *dtp = (u16*)dst;
+ dtp[(y + yoff)*width + x + xoff] = ptr[x] ? 0xFFFF : 0x0000;
+ break;
+ }
+ default:
+ case PC_TEX_FMT_BGRA32:
+ {
+ int *dtp = (int*)dst;
+ dtp[(y + yoff) * width + x + xoff] = ptr[x] ? 0xFFFFFFFF : 0xFF000000;
+ break;
+ }
+ }
+ }
+ ptr += 9;
+ }
+ xoff += xcnt;
+ fmt++;
+ }
+
+ return retval;
+}
+
+
+
+void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth, int texformat, int tlutaddr, int tlutfmt)
+{
+ /* General formula for computing texture offset
+ //
+ u16 sBlk = s / blockWidth;
+ u16 tBlk = t / blockHeight;
+ u16 widthBlks = (width / blockWidth) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) * blockWidth * blockHeight;
+ u16 blkS = s & (blockWidth - 1);
+ u16 blkT = t & (blockHeight - 1);
+ u32 blkOff = blkT * blockWidth + blkS;
+ */
+
+ switch (texformat)
+ {
+ case GX_TF_C4:
+ {
+ u16 sBlk = s >> 3;
+ u16 tBlk = t >> 3;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5;
+ u16 blkS = s & 7;
+ u16 blkT = t & 7;
+ u32 blkOff = (blkT << 3) + blkS;
+
+ int rs = (blkOff & 1)?0:4;
+ u32 offset = base + (blkOff >> 1);
+
+ u8 val = (*(src + offset) >> rs) & 0xF;
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+
+ switch (tlutfmt)
+ {
+ case 0:
+ *((u32*)dst) = decodeIA8Swapped(tlut[val]);
+ break;
+ case 1:
+ *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
+ break;
+ case 2:
+ *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val]));
+ break;
+ }
+ }
+ break;
+ case GX_TF_I4:
+ {
+ u16 sBlk = s >> 3;
+ u16 tBlk = t >> 3;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5;
+ u16 blkS = s & 7;
+ u16 blkT = t & 7;
+ u32 blkOff = (blkT << 3) + blkS;
+
+ int rs = (blkOff & 1)?0:4;
+ u32 offset = base + (blkOff >> 1);
+
+ u8 val = (*(src + offset) >> rs) & 0xF;
+ val = Convert4To8(val);
+ dst[0] = val;
+ dst[1] = val;
+ dst[2] = val;
+ dst[3] = val;
+ }
+ break;
+ case GX_TF_I8:
+ {
+ u16 sBlk = s >> 3;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5;
+ u16 blkS = s & 7;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 3) + blkS;
+
+ u8 val = *(src + base + blkOff);
+ dst[0] = val;
+ dst[1] = val;
+ dst[2] = val;
+ dst[3] = val;
+ }
+ break;
+ case GX_TF_C8:
+ {
+ u16 sBlk = s >> 3;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5;
+ u16 blkS = s & 7;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 3) + blkS;
+
+ u8 val = *(src + base + blkOff);
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+
+ switch (tlutfmt)
+ {
+ case 0:
+ *((u32*)dst) = decodeIA8Swapped(tlut[val]);
+ break;
+ case 1:
+ *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
+ break;
+ case 2:
+ *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val]));
+ break;
+ }
+ }
+ break;
+ case GX_TF_IA4:
+ {
+ u16 sBlk = s >> 3;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5;
+ u16 blkS = s & 7;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 3) + blkS;
+
+ u8 val = *(src + base + blkOff);
+ const u8 a = Convert4To8(val>>4);
+ const u8 l = Convert4To8(val&0xF);
+ dst[0] = l;
+ dst[1] = l;
+ dst[2] = l;
+ dst[3] = a;
+ }
+ break;
+ case GX_TF_IA8:
+ {
+ u16 sBlk = s >> 2;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 2) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 4;
+ u16 blkS = s & 3;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 2) + blkS;
+
+ u32 offset = (base + blkOff) << 1;
+ const u16* valAddr = (u16*)(src + offset);
+
+ *((u32*)dst) = decodeIA8Swapped(*valAddr);
+ }
+ break;
+ case GX_TF_C14X2:
+ {
+ u16 sBlk = s >> 2;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 2) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 4;
+ u16 blkS = s & 3;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 2) + blkS;
+
+ u32 offset = (base + blkOff) << 1;
+ const u16* valAddr = (u16*)(src + offset);
+
+ u16 val = Common::swap16(*valAddr) & 0x3FFF;
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+
+ switch (tlutfmt)
+ {
+ case 0:
+ *((u32*)dst) = decodeIA8Swapped(tlut[val]);
+ break;
+ case 1:
+ *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
+ break;
+ case 2:
+ *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val]));
+ break;
+ }
+ }
+ break;
+ case GX_TF_RGB565:
+ {
+ u16 sBlk = s >> 2;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 2) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 4;
+ u16 blkS = s & 3;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 2) + blkS;
+
+ u32 offset = (base + blkOff) << 1;
+ const u16* valAddr = (u16*)(src + offset);
+
+ *((u32*)dst) = decode565RGBA(Common::swap16(*valAddr));
+ }
+ break;
+ case GX_TF_RGB5A3:
+ {
+ u16 sBlk = s >> 2;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 2) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 4;
+ u16 blkS = s & 3;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 2) + blkS;
+
+ u32 offset = (base + blkOff) << 1;
+ const u16* valAddr = (u16*)(src + offset);
+
+ *((u32*)dst) = decode5A3RGBA(Common::swap16(*valAddr));
+ }
+ break;
+ case GX_TF_RGBA8:
+ {
+ u16 sBlk = s >> 2;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 2) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5; // shift by 5 is correct
+ u16 blkS = s & 3;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 2) + blkS;
+
+ u32 offset = (base + blkOff) << 1 ;
+ const u8* valAddr = src + offset;
+
+ dst[3] = valAddr[0];
+ dst[0] = valAddr[1];
+ dst[1] = valAddr[32];
+ dst[2] = valAddr[33];
+ }
+ break;
+ case GX_TF_CMPR:
+ {
+ u16 sDxt = s >> 2;
+ u16 tDxt = t >> 2;
+
+ u16 sBlk = sDxt >> 1;
+ u16 tBlk = tDxt >> 1;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 2;
+ u16 blkS = sDxt & 1;
+ u16 blkT = tDxt & 1;
+ u32 blkOff = (blkT << 1) + blkS;
+
+ u32 offset = (base + blkOff) << 3;
+
+ const DXTBlock* dxtBlock = (const DXTBlock*)(src + offset);
+
+ u16 c1 = Common::swap16(dxtBlock->color1);
+ u16 c2 = Common::swap16(dxtBlock->color2);
+ int blue1 = Convert5To8(c1 & 0x1F);
+ int blue2 = Convert5To8(c2 & 0x1F);
+ int green1 = Convert6To8((c1 >> 5) & 0x3F);
+ int green2 = Convert6To8((c2 >> 5) & 0x3F);
+ int red1 = Convert5To8((c1 >> 11) & 0x1F);
+ int red2 = Convert5To8((c2 >> 11) & 0x1F);
+
+ u16 ss = s & 3;
+ u16 tt = t & 3;
+
+ int colorSel = dxtBlock->lines[tt];
+ int rs = 6 - (ss << 1);
+ colorSel = (colorSel >> rs) & 3;
+ colorSel |= c1 > c2?0:4;
+
+ u32 color = 0;
+
+ switch (colorSel)
+ {
+ case 0:
+ case 4:
+ color = makeRGBA(red1, green1, blue1, 255);
+ break;
+ case 1:
+ case 5:
+ color = makeRGBA(red2, green2, blue2, 255);
+ break;
+ case 2:
+ color = makeRGBA(red1+(red2-red1)/3, green1+(green2-green1)/3, blue1+(blue2-blue1)/3, 255);
+ break;
+ case 3:
+ color = makeRGBA(red2+(red1-red2)/3, green2+(green1-green2)/3, blue2+(blue1-blue2)/3, 255);
+ break;
+ case 6:
+ color = makeRGBA((int)ceil((float)(red1+red2)/2), (int)ceil((float)(green1+green2)/2), (int)ceil((float)(blue1+blue2)/2), 255);
+ break;
+ case 7:
+ color = makeRGBA(red2, green2, blue2, 0);
+ break;
+ }
+
+ *((u32*)dst) = color;
+ }
+ break;
+ }
+}
+
+void TexDecoder_DecodeTexelRGBA8FromTmem(u8 *dst, const u8 *src_ar, const u8* src_gb, int s, int t, int imageWidth)
+{
+ u16 sBlk = s >> 2;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 2) + 1; // TODO: Looks wrong. Shouldn't this be ((imageWidth-1)>>2)+1 ?
+ u32 base_ar = (tBlk * widthBlks + sBlk) << 4;
+ u32 base_gb = (tBlk * widthBlks + sBlk) << 4;
+ u16 blkS = s & 3;
+ u16 blkT = t & 3;
+ u32 blk_off = (blkT << 2) + blkS;
+
+ u32 offset_ar = (base_ar + blk_off) << 1;
+ u32 offset_gb = (base_gb + blk_off) << 1;
+ const u8* val_addr_ar = src_ar + offset_ar;
+ const u8* val_addr_gb = src_gb + offset_gb;
+
+ dst[3] = val_addr_ar[0]; // A
+ dst[0] = val_addr_ar[1]; // R
+ dst[1] = val_addr_gb[0]; // G
+ dst[2] = val_addr_gb[1]; // B
+}
+
+PC_TexFormat TexDecoder_DecodeRGBA8FromTmem(u8* dst, const u8 *src_ar, const u8 *src_gb, int width, int height)
+{
+ // TODO for someone who cares: Make this less slow!
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x)
+ {
+ TexDecoder_DecodeTexelRGBA8FromTmem(dst, src_ar, src_gb, x, y, width-1);
+ dst += 4;
+ }
+
+ return PC_TEX_FMT_RGBA32;
+}
+
+const char* texfmt[] = {
+ // pixel
+ "I4", "I8", "IA4", "IA8",
+ "RGB565", "RGB5A3", "RGBA8", "0x07",
+ "C4", "C8", "C14X2", "0x0B",
+ "0x0C", "0x0D", "CMPR", "0x0F",
+ // Z-buffer
+ "0x10", "Z8", "0x12", "Z16",
+ "0x14", "0x15", "Z24X8", "0x17",
+ "0x18", "0x19", "0x1A", "0x1B",
+ "0x1C", "0x1D", "0x1E", "0x1F",
+ // pixel + copy
+ "CR4", "0x21", "CRA4", "CRA8",
+ "0x24", "0x25", "CYUVA8", "CA8",
+ "CR8", "CG8", "CB8", "CRG8",
+ "CGB8", "0x2D", "0x2E", "0x2F",
+ // Z + copy
+ "CZ4", "0x31", "0x32", "0x33",
+ "0x34", "0x35", "0x36", "0x37",
+ "0x38", "CZ8M", "CZ8L", "0x3B",
+ "CZ16L", "0x3D", "0x3E", "0x3F",
+};
+
+const unsigned char sfont_map[] = {
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,10,10,10,10,
+ 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,
+ 26,27,28,29,30,31,32,33,34,35,36,10,10,10,10,10,
+ 10,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
+ 52,53,54,55,56,57,58,59,60,61,62,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+};
+
+const unsigned char sfont_raw[][9*10] = {
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78,
+ },
+};
diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp
index 23b0e73427..52d48fc547 100644
--- a/Source/Core/VideoCommon/Src/ImageWrite.cpp
+++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp
@@ -25,22 +25,22 @@
struct TGA_HEADER
{
- u8 identsize; // size of ID field that follows 18 u8 header (0 usually)
- u8 colourmaptype; // type of colour map 0=none, 1=has palette
- u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
-
- s16 colourmapstart; // first colour map entry in palette
- s16 colourmaplength; // number of colours in palette
- u8 colourmapbits; // number of bits per palette entry 15,16,24,32
-
- s16 xstart; // image x origin
- s16 ystart; // image y origin
- s16 width; // image width in pixels
- s16 height; // image height in pixels
- u8 bits; // image bits per pixel 8,16,24,32
- u8 descriptor; // image descriptor bits (vh flip bits)
-
- // pixel data follows header
+ u8 identsize; // size of ID field that follows 18 u8 header (0 usually)
+ u8 colourmaptype; // type of colour map 0=none, 1=has palette
+ u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
+
+ s16 colourmapstart; // first colour map entry in palette
+ s16 colourmaplength; // number of colours in palette
+ u8 colourmapbits; // number of bits per palette entry 15,16,24,32
+
+ s16 xstart; // image x origin
+ s16 ystart; // image y origin
+ s16 width; // image width in pixels
+ s16 height; // image height in pixels
+ u8 bits; // image bits per pixel 8,16,24,32
+ u8 descriptor; // image descriptor bits (vh flip bits)
+
+ // pixel data follows header
};
#pragma pack(pop)
@@ -53,7 +53,7 @@ bool SaveTGA(const char* filename, int width, int height, void* pdata)
return false;
_assert_(sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18);
-
+
memset(&hdr, 0, sizeof(hdr));
hdr.imagetype = 2;
hdr.bits = 32;
@@ -69,7 +69,8 @@ bool SaveTGA(const char* filename, int width, int height, void* pdata)
bool SaveData(const char* filename, const char* data)
{
- std::ofstream f(filename, std::ios::binary);
+ std::ofstream f;
+ OpenFStream(f, filename, std::ios::binary);
f << data;
return true;
diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.cpp b/Source/Core/VideoCommon/Src/IndexGenerator.cpp
index 8053114fae..aa1a971687 100644
--- a/Source/Core/VideoCommon/Src/IndexGenerator.cpp
+++ b/Source/Core/VideoCommon/Src/IndexGenerator.cpp
@@ -15,6 +15,9 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+#include <cstddef>
+
+#include "Common.h"
#include "IndexGenerator.h"
/*
@@ -27,24 +30,18 @@ QUAD simulator
*/
//Init
-u16 *IndexGenerator::Tptr = 0;
-u16 *IndexGenerator::BASETptr = 0;
-u16 *IndexGenerator::Lptr = 0;
-u16 *IndexGenerator::BASELptr = 0;
-u16 *IndexGenerator::Pptr = 0;
-u16 *IndexGenerator::BASEPptr = 0;
-int IndexGenerator::numT = 0;
-int IndexGenerator::numL = 0;
-int IndexGenerator::numP = 0;
-int IndexGenerator::index = 0;
-int IndexGenerator::Tadds = 0;
-int IndexGenerator::Ladds = 0;
-int IndexGenerator::Padds = 0;
-IndexGenerator::IndexPrimitiveType IndexGenerator::LastTPrimitive = Prim_None;
-IndexGenerator::IndexPrimitiveType IndexGenerator::LastLPrimitive = Prim_None;
-bool IndexGenerator::used = false;
-
-void IndexGenerator::Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr)
+u16 *IndexGenerator::Tptr;
+u16 *IndexGenerator::BASETptr;
+u16 *IndexGenerator::Lptr;
+u16 *IndexGenerator::BASELptr;
+u16 *IndexGenerator::Pptr;
+u16 *IndexGenerator::BASEPptr;
+u32 IndexGenerator::numT;
+u32 IndexGenerator::numL;
+u32 IndexGenerator::numP;
+u32 IndexGenerator::index;
+
+void IndexGenerator::Start(u16* Triangleptr, u16* Lineptr, u16* Pointptr)
{
Tptr = Triangleptr;
Lptr = Lineptr;
@@ -56,288 +53,123 @@ void IndexGenerator::Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr)
numT = 0;
numL = 0;
numP = 0;
- Tadds = 0;
- Ladds = 0;
- Padds = 0;
- LastTPrimitive = Prim_None;
- LastLPrimitive = Prim_None;
}
-// Triangles
-void IndexGenerator::AddList(int numVerts)
+
+void IndexGenerator::AddIndices(int primitive, u32 numVerts)
{
- //if we have no vertices return
- if(numVerts <= 0) return;
- int numTris = numVerts / 3;
- if (!numTris)
+ //switch (primitive)
+ //{
+ //case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVerts); break;
+ //case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVerts); break;
+ //case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVerts); break;
+ //case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVerts); break;
+ //case GX_DRAW_LINES: IndexGenerator::AddLineList(numVerts); break;
+ //case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVerts); break;
+ //case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVerts); break;
+ //}
+
+ static void (*const primitive_table[])(u32) =
{
- //if we have less than 3 verts
- if(numVerts == 1)
- {
- // discard
- index++;
- return;
- }
- else
- {
- //we have two verts render a degenerated triangle
- numTris = 1;
- *Tptr++ = index;
- *Tptr++ = index+1;
- *Tptr++ = index;
- }
- }
- else
- {
- for (int i = 0; i < numTris; i++)
- {
- *Tptr++ = index+i*3;
- *Tptr++ = index+i*3+1;
- *Tptr++ = index+i*3+2;
- }
- int baseRemainingverts = numVerts - numVerts % 3;
- switch (numVerts % 3)
- {
- case 2:
- //whe have 2 remaining verts use strip method
- *Tptr++ = index + baseRemainingverts - 1;
- *Tptr++ = index + baseRemainingverts;
- *Tptr++ = index + baseRemainingverts + 1;
- numTris++;
- break;
- case 1:
- //whe have 1 remaining verts use strip method this is only a conjeture
- *Tptr++ = index + baseRemainingverts - 2;
- *Tptr++ = index + baseRemainingverts - 1;
- *Tptr++ = index + baseRemainingverts;
- numTris++;
- break;
- default:
- break;
- };
- }
+ IndexGenerator::AddQuads,
+ NULL,
+ IndexGenerator::AddList,
+ IndexGenerator::AddStrip,
+ IndexGenerator::AddFan,
+ IndexGenerator::AddLineList,
+ IndexGenerator::AddLineStrip,
+ IndexGenerator::AddPoints,
+ };
+
+ primitive_table[primitive](numVerts);
index += numVerts;
- numT += numTris;
- Tadds++;
- LastTPrimitive = Prim_List;
}
-void IndexGenerator::AddStrip(int numVerts)
+// Triangles
+__forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 index3)
{
- if(numVerts <= 0) return;
- int numTris = numVerts - 2;
- if (numTris < 1)
- {
- //if we have less than 3 verts
- if(numVerts == 1)
- {
- // discard
- index++;
- return;
- }
- else
- {
- //we have two verts render a degenerated triangle
- numTris = 1;
- *Tptr++ = index;
- *Tptr++ = index+1;
- *Tptr++ = index;
- }
- }
- else
- {
- bool wind = false;
- for (int i = 0; i < numTris; i++)
- {
- *Tptr++ = index+i;
- *Tptr++ = index+i+(wind?2:1);
- *Tptr++ = index+i+(wind?1:2);
- wind = !wind;
- }
- }
- index += numVerts;
- numT += numTris;
- Tadds++;
- LastTPrimitive = Prim_Strip;
+ *Tptr++ = index1;
+ *Tptr++ = index2;
+ *Tptr++ = index3;
+
+ ++numT;
}
-void IndexGenerator::AddFan(int numVerts)
+
+void IndexGenerator::AddList(u32 const numVerts)
{
- if(numVerts <= 0) return;
- int numTris = numVerts - 2;
- if (numTris < 1)
+ auto const numTris = numVerts / 3;
+ for (u32 i = 0; i != numTris; ++i)
{
- //if we have less than 3 verts
- if(numVerts == 1)
- {
- //Discard
- index++;
- return;
- }
- else
- {
- //we have two verts render a degenerated triangle
- numTris = 1;
- *Tptr++ = index;
- *Tptr++ = index+1;
- *Tptr++ = index;
- }
+ WriteTriangle(index + i * 3, index + i * 3 + 1, index + i * 3 + 2);
}
- else
- {
- for (int i = 0; i < numTris; i++)
- {
- *Tptr++ = index;
- *Tptr++ = index+i+1;
- *Tptr++ = index+i+2;
- }
- }
- index += numVerts;
- numT += numTris;
- Tadds++;
- LastTPrimitive = Prim_Fan;
}
-void IndexGenerator::AddQuads(int numVerts)
+void IndexGenerator::AddStrip(u32 const numVerts)
{
- if(numVerts <= 0) return;
- int numTris = (numVerts/4)*2;
- if (numTris == 0)
+ bool wind = false;
+ for (u32 i = 2; i < numVerts; ++i)
{
- //if we have less than 3 verts
- if(numVerts == 1)
- {
- //discard
- index++;
- return;
- }
- else
- {
- if(numVerts == 2)
- {
- //we have two verts render a degenerated triangle
- numTris = 1;
- *Tptr++ = index;
- *Tptr++ = index + 1;
- *Tptr++ = index;
- }
- else
- {
- //we have 3 verts render a full triangle
- numTris = 1;
- *Tptr++ = index;
- *Tptr++ = index + 1;
- *Tptr++ = index + 2;
- }
- }
+ WriteTriangle(
+ index + i - 2,
+ index + i - !wind,
+ index + i - wind);
+
+ wind ^= true;
}
- else
+}
+
+void IndexGenerator::AddFan(u32 numVerts)
+{
+ for (u32 i = 2; i < numVerts; ++i)
{
- for (int i = 0; i < numTris / 2; i++)
- {
- *Tptr++ = index+i*4;
- *Tptr++ = index+i*4+1;
- *Tptr++ = index+i*4+2;
- *Tptr++ = index+i*4;
- *Tptr++ = index+i*4+2;
- *Tptr++ = index+i*4+3;
- }
- int baseRemainingverts = numVerts - numVerts % 4;
- switch (numVerts % 4)
- {
- case 3:
- //whe have 3 remaining verts use strip method
- *Tptr++ = index + baseRemainingverts;
- *Tptr++ = index + baseRemainingverts + 1;
- *Tptr++ = index + baseRemainingverts + 2;
- numTris++;
- break;
- case 2:
- //whe have 2 remaining verts use strip method
- *Tptr++ = index + baseRemainingverts - 1;
- *Tptr++ = index + baseRemainingverts;
- *Tptr++ = index + baseRemainingverts + 1;
- numTris++;
- break;
- case 1:
- //whe have 1 remaining verts use strip method this is only a conjeture
- *Tptr++ = index + baseRemainingverts - 2;
- *Tptr++ = index + baseRemainingverts - 1;
- *Tptr++ = index + baseRemainingverts;
- numTris++;
- break;
- default:
- break;
- };
+ WriteTriangle(index, index + i - 1, index + i);
}
- index += numVerts;
- numT += numTris;
- Tadds++;
- LastTPrimitive = Prim_List;
}
-
-//Lines
-void IndexGenerator::AddLineList(int numVerts)
+void IndexGenerator::AddQuads(u32 numVerts)
{
- if(numVerts <= 0) return;
- int numLines = numVerts / 2;
- if (!numLines)
+ auto const numQuads = numVerts / 4;
+ for (u32 i = 0; i != numQuads; ++i)
{
- //Discard
- index++;
- return;
+ WriteTriangle(index + i * 4, index + i * 4 + 1, index + i * 4 + 2);
+ WriteTriangle(index + i * 4, index + i * 4 + 2, index + i * 4 + 3);
}
- else
+}
+
+// Lines
+void IndexGenerator::AddLineList(u32 numVerts)
+{
+ auto const numLines = numVerts / 2;
+ for (u32 i = 0; i != numLines; ++i)
{
- for (int i = 0; i < numLines; i++)
- {
- *Lptr++ = index+i*2;
- *Lptr++ = index+i*2+1;
- }
- if((numVerts & 1) != 0)
- {
- //use line strip for remaining vert
- *Lptr++ = index + numLines * 2 - 1;
- *Lptr++ = index + numLines * 2;
- }
+ *Lptr++ = index + i * 2;
+ *Lptr++ = index + i * 2 + 1;
+ ++numL;
}
- index += numVerts;
- numL += numLines;
- Ladds++;
- LastLPrimitive = Prim_List;
}
-void IndexGenerator::AddLineStrip(int numVerts)
+void IndexGenerator::AddLineStrip(u32 numVerts)
{
- int numLines = numVerts - 1;
- if (numLines <= 0)
+ for (u32 i = 1; i < numVerts; ++i)
{
- if(numVerts == 1)
- {
- index++;
- }
- return;
+ *Lptr++ = index + i - 1;
+ *Lptr++ = index + i;
+ ++numL;
}
- for (int i = 0; i < numLines; i++)
+}
+
+// Points
+void IndexGenerator::AddPoints(u32 numVerts)
+{
+ for (u32 i = 0; i != numVerts; ++i)
{
- *Lptr++ = index+i;
- *Lptr++ = index+i+1;
+ *Pptr++ = index + i;
+ ++numP;
}
- index += numVerts;
- numL += numLines;
- Ladds++;
- LastLPrimitive = Prim_Strip;
}
-
-//Points
-void IndexGenerator::AddPoints(int numVerts)
+u32 IndexGenerator::GetRemainingIndices()
{
- for (int i = 0; i < numVerts; i++)
- {
- *Pptr++ = index+i;
- }
- index += numVerts;
- numP += numVerts;
- Padds++;
+ u32 max_index = 65535;
+ return max_index - index;
}
diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.h b/Source/Core/VideoCommon/Src/IndexGenerator.h
index d1ed143d98..f14d3ae026 100644
--- a/Source/Core/VideoCommon/Src/IndexGenerator.h
+++ b/Source/Core/VideoCommon/Src/IndexGenerator.h
@@ -25,53 +25,60 @@
class IndexGenerator
{
public:
- //Init
+ // Init
static void Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr);
- //Triangles
- static void AddList(int numVerts);
- static void AddStrip(int numVerts);
- static void AddFan(int numVerts);
- static void AddQuads(int numVerts);
- //Lines
- static void AddLineList(int numVerts);
- static void AddLineStrip(int numVerts);
- //Points
- static void AddPoints(int numVerts);
- //Interface
- static int GetNumTriangles() {used = true; return numT;}
- static int GetNumLines() {used = true;return numL;}
- static int GetNumPoints() {used = true;return numP;}
- static int GetNumVerts() {return index;} //returns numprimitives
- static int GetNumAdds() {return Tadds + Ladds + Padds;}
- static int GetTriangleindexLen() {return (int)(Tptr - BASETptr);}
- static int GetLineindexLen() {return (int)(Lptr - BASELptr);}
- static int GetPointindexLen() {return (int)(Pptr - BASEPptr);}
+ static void AddIndices(int primitive, u32 numVertices);
+
+ // Interface
+ static u32 GetNumTriangles() {return numT;}
+ static u32 GetNumLines() {return numL;}
+ static u32 GetNumPoints() {return numP;}
+
+ // returns numprimitives
+ static u32 GetNumVerts() {return index;}
+
+ static u32 GetTriangleindexLen() {return (u32)(Tptr - BASETptr);}
+ static u32 GetLineindexLen() {return (u32)(Lptr - BASELptr);}
+ static u32 GetPointindexLen() {return (u32)(Pptr - BASEPptr);}
+
+ static u32 GetRemainingIndices();
+/*
enum IndexPrimitiveType
{
Prim_None = 0,
Prim_List,
Prim_Strip,
Prim_Fan
- } ;
+ };
+*/
private:
+ // Triangles
+ static void AddList(u32 numVerts);
+ static void AddStrip(u32 numVerts);
+ static void AddFan(u32 numVerts);
+ static void AddQuads(u32 numVerts);
+
+ // Lines
+ static void AddLineList(u32 numVerts);
+ static void AddLineStrip(u32 numVerts);
+
+ // Points
+ static void AddPoints(u32 numVerts);
+
+ static void WriteTriangle(u32 index1, u32 index2, u32 index3);
+
static u16 *Tptr;
static u16 *BASETptr;
static u16 *Lptr;
static u16 *BASELptr;
static u16 *Pptr;
static u16 *BASEPptr;
- static int numT;
- static int numL;
- static int numP;
- static int index;
- static int Tadds;
- static int Ladds;
- static int Padds;
- static IndexPrimitiveType LastTPrimitive;
- static IndexPrimitiveType LastLPrimitive;
- static bool used;
-
+ // TODO: redundant variables
+ static u32 numT;
+ static u32 numL;
+ static u32 numP;
+ static u32 index;
};
#endif // _INDEXGENERATOR_H
diff --git a/Source/Core/VideoCommon/Src/LightingShaderGen.cpp b/Source/Core/VideoCommon/Src/LightingShaderGen.cpp
index f32e5dfeee..2b717bdba6 100644
--- a/Source/Core/VideoCommon/Src/LightingShaderGen.cpp
+++ b/Source/Core/VideoCommon/Src/LightingShaderGen.cpp
@@ -47,13 +47,13 @@ char *GenerateLightShader(char *p, int index, const LitChannel& chan, const char
// atten disabled
switch (chan.diffusefunc) {
case LIGHTDIF_NONE:
- WRITE(p, "lacc.%s += %s.lights[%d].col.%s;\n", swizzle, lightsName, index, swizzle);
+ WRITE(p, "lacc.%s += %s[%d].%s;\n", swizzle, lightsName, index * 5, swizzle);
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
- WRITE(p, "ldir = normalize(%s.lights[%d].pos.xyz - pos.xyz);\n", lightsName, index);
- WRITE(p, "lacc.%s += %sdot(ldir, _norm0)) * %s.lights[%d].col.%s;\n",
- swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(", lightsName, index, swizzle);
+ WRITE(p, "ldir = normalize(%s[%d + 3].xyz - pos.xyz);\n", lightsName, index * 5);
+ WRITE(p, "lacc.%s += %sdot(ldir, _norm0)) * %s[%d].%s;\n",
+ swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(", lightsName, index * 5, swizzle);
break;
default: _assert_(0);
}
@@ -62,32 +62,32 @@ char *GenerateLightShader(char *p, int index, const LitChannel& chan, const char
if (chan.attnfunc == 3)
{ // spot
- WRITE(p, "ldir = %s.lights[%d].pos.xyz - pos.xyz;\n", lightsName, index);
+ WRITE(p, "ldir = %s[%d + 3].xyz - pos.xyz;\n", lightsName, index * 5);
WRITE(p, "dist2 = dot(ldir, ldir);\n"
"dist = sqrt(dist2);\n"
"ldir = ldir / dist;\n"
- "attn = max(0.0f, dot(ldir, %s.lights[%d].dir.xyz));\n", lightsName, index);
- WRITE(p, "attn = max(0.0f, dot(%s.lights[%d].cosatt.xyz, float3(1.0f, attn, attn*attn))) / dot(%s.lights[%d].distatt.xyz, float3(1.0f,dist,dist2));\n", lightsName, index, lightsName, index);
+ "attn = max(0.0f, dot(ldir, %s[%d + 4].xyz));\n", lightsName, index * 5);
+ WRITE(p, "attn = max(0.0f, dot(%s[%d + 1].xyz, float3(1.0f, attn, attn*attn))) / dot(%s[%d + 2].xyz, float3(1.0f,dist,dist2));\n", lightsName, index * 5, lightsName, index * 5);
}
else if (chan.attnfunc == 1)
{ // specular
- WRITE(p, "ldir = normalize(%s.lights[%d].pos.xyz);\n", lightsName, index);
- WRITE(p, "attn = (dot(_norm0,ldir) >= 0.0f) ? max(0.0f, dot(_norm0, %s.lights[%d].dir.xyz)) : 0.0f;\n", lightsName, index);
- WRITE(p, "attn = max(0.0f, dot(%s.lights[%d].cosatt.xyz, float3(1,attn,attn*attn))) / dot(%s.lights[%d].distatt.xyz, float3(1,attn,attn*attn));\n", lightsName, index, lightsName, index);
+ WRITE(p, "ldir = normalize(%s[%d + 3].xyz);\n", lightsName, index * 5);
+ WRITE(p, "attn = (dot(_norm0,ldir) >= 0.0f) ? max(0.0f, dot(_norm0, %s[%d + 4].xyz)) : 0.0f;\n", lightsName, index * 5);
+ WRITE(p, "attn = max(0.0f, dot(%s[%d + 1].xyz, float3(1,attn,attn*attn))) / dot(%s[%d + 2].xyz, float3(1,attn,attn*attn));\n", lightsName, index * 5, lightsName, index * 5);
}
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
- WRITE(p, "lacc.%s += attn * %s.lights[%d].col.%s;\n", swizzle, lightsName, index, swizzle);
+ WRITE(p, "lacc.%s += attn * %s[%d].%s;\n", swizzle, lightsName, index * 5, swizzle);
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
- WRITE(p, "lacc.%s += attn * %sdot(ldir, _norm0)) * %s.lights[%d].col.%s;\n",
+ WRITE(p, "lacc.%s += attn * %sdot(ldir, _norm0)) * %s[%d].%s;\n",
swizzle,
chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(",
lightsName,
- index,
+ index * 5,
swizzle);
break;
default: _assert_(0);
@@ -120,7 +120,7 @@ char *GenerateLightingShader(char *p, int components, const char* materialsName,
WRITE(p, "mat = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
}
else // from color
- WRITE(p, "mat = %s.C%d;\n", materialsName, j+2);
+ WRITE(p, "mat = %s[%d];\n", materialsName, j+2);
if (color.enablelighting) {
if (color.ambsource) { // from vertex
@@ -132,7 +132,7 @@ char *GenerateLightingShader(char *p, int components, const char* materialsName,
WRITE(p, "lacc = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
}
else // from color
- WRITE(p, "lacc = %s.C%d;\n", materialsName, j);
+ WRITE(p, "lacc = %s[%d];\n", materialsName, j);
}
else
{
@@ -149,7 +149,7 @@ char *GenerateLightingShader(char *p, int components, const char* materialsName,
else WRITE(p, "mat.w = 1.0f;\n");
}
else // from color
- WRITE(p, "mat.w = %s.C%d.w;\n", materialsName, j+2);
+ WRITE(p, "mat.w = %s[%d].w;\n", materialsName, j+2);
}
if (alpha.enablelighting)
@@ -163,7 +163,7 @@ char *GenerateLightingShader(char *p, int components, const char* materialsName,
WRITE(p, "lacc.w = 0.0f;\n");
}
else // from color
- WRITE(p, "lacc.w = %s.C%d.w;\n", materialsName, j);
+ WRITE(p, "lacc.w = %s[%d].w;\n", materialsName, j);
}
else
{
diff --git a/Source/Core/VideoCommon/Src/MainBase.cpp b/Source/Core/VideoCommon/Src/MainBase.cpp
index 726ef71b38..1472367f21 100644
--- a/Source/Core/VideoCommon/Src/MainBase.cpp
+++ b/Source/Core/VideoCommon/Src/MainBase.cpp
@@ -21,6 +21,10 @@ volatile u32 s_swapRequested = false;
u32 s_efbAccessRequested = false;
volatile u32 s_FifoShuttingDown = false;
+std::condition_variable s_perf_query_cond;
+std::mutex s_perf_query_lock;
+static volatile bool s_perf_query_requested;
+
static volatile struct
{
u32 xfbAddr;
@@ -169,6 +173,43 @@ u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32
return 0;
}
+static bool QueryResultIsReady()
+{
+ return !s_perf_query_requested || s_FifoShuttingDown;
+}
+
+void VideoFifo_CheckPerfQueryRequest()
+{
+ if (s_perf_query_requested)
+ {
+ g_perf_query->FlushResults();
+
+ {
+ std::lock_guard<std::mutex> lk(s_perf_query_lock);
+ s_perf_query_requested = false;
+ }
+
+ s_perf_query_cond.notify_one();
+ }
+}
+
+u32 VideoBackendHardware::Video_GetQueryResult(PerfQueryType type)
+{
+ // TODO: Is this check sane?
+ if (!g_perf_query->IsFlushed())
+ {
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
+ {
+ s_perf_query_requested = true;
+ std::unique_lock<std::mutex> lk(s_perf_query_lock);
+ s_perf_query_cond.wait(lk, QueryResultIsReady);
+ }
+ else
+ g_perf_query->FlushResults();
+ }
+
+ return g_perf_query->GetQueryResult(type);
+}
void VideoBackendHardware::InitializeShared()
{
@@ -176,6 +217,7 @@ void VideoBackendHardware::InitializeShared()
s_swapRequested = 0;
s_efbAccessRequested = 0;
+ s_perf_query_requested = false;
s_FifoShuttingDown = 0;
memset((void*)&s_beginFieldArgs, 0, sizeof(s_beginFieldArgs));
memset(&s_accessEFBArgs, 0, sizeof(s_accessEFBArgs));
@@ -186,6 +228,11 @@ void VideoBackendHardware::InitializeShared()
// Run from the CPU thread
void VideoBackendHardware::DoState(PointerWrap& p)
{
+ bool software = false;
+ p.Do(software);
+ if (p.GetMode() == PointerWrap::MODE_READ && software == true)
+ // change mode to abort load of incompatible save state.
+ p.SetMode(PointerWrap::MODE_VERIFY);
VideoCommon_DoState(p);
p.DoMarker("VideoCommon");
@@ -233,6 +280,7 @@ void VideoFifo_CheckAsyncRequest()
{
VideoFifo_CheckSwapRequest();
VideoFifo_CheckEFBAccess();
+ VideoFifo_CheckPerfQueryRequest();
}
void VideoBackendHardware::Video_GatherPipeBursted()
diff --git a/Source/Core/VideoCommon/Src/NativeVertexFormat.h b/Source/Core/VideoCommon/Src/NativeVertexFormat.h
index 02184fde1c..1340991b21 100644
--- a/Source/Core/VideoCommon/Src/NativeVertexFormat.h
+++ b/Source/Core/VideoCommon/Src/NativeVertexFormat.h
@@ -102,7 +102,7 @@ public:
virtual void SetupVertexPointers() = 0;
virtual void EnableComponents(u32 components) {}
- int GetVertexStride() const { return vertex_stride; }
+ u32 GetVertexStride() const { return vertex_stride; }
// TODO: move this under private:
u32 m_components; // VB_HAS_X. Bitmask telling what vertex components are present.
diff --git a/Source/Core/VideoCommon/Src/OnScreenDisplay.h b/Source/Core/VideoCommon/Src/OnScreenDisplay.h
index 3777e2b5d3..80187b8ac3 100644
--- a/Source/Core/VideoCommon/Src/OnScreenDisplay.h
+++ b/Source/Core/VideoCommon/Src/OnScreenDisplay.h
@@ -22,7 +22,7 @@ namespace OSD
{
// On-screen message display
-void AddMessage(const char* str, u32 ms);
+void AddMessage(const char* str, u32 ms = 2000);
void DrawMessages(); // draw the current messages on the screen. Only call once per frame.
void ClearMessages();
diff --git a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
index 4f7f86d655..92d596b774 100644
--- a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
+++ b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
@@ -123,7 +123,7 @@ void InterpretDisplayList(u32 address, u32 size)
Statistics::SwapDL();
}
- // reset to the old pointer
+ // reset to the old pointer
g_pVideoData = old_pVideoData;
}
@@ -136,74 +136,114 @@ void ExecuteDisplayList(u32 address, u32 size)
InterpretDisplayList(address, size);
}
-bool FifoCommandRunnable()
+u32 FifoCommandRunnable(u32 &command_size)
{
+ u32 cycleTime = 0;
u32 buffer_size = (u32)(GetVideoBufferEndPtr() - g_pVideoData);
- if (buffer_size == 0)
- return false; // can't peek
+ if (buffer_size == 0)
+ return 0; // can't peek
u8 cmd_byte = DataPeek8(0);
- u32 command_size = 0;
- switch (cmd_byte)
- {
- case GX_NOP: // Hm, this means that we scan over nop streams pretty slowly...
+ switch (cmd_byte)
+ {
+ case GX_NOP: // Hm, this means that we scan over nop streams pretty slowly...
+ command_size = 1;
+ cycleTime = 6;
+ break;
case GX_CMD_INVL_VC: // Invalidate Vertex Cache - no parameters
- case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
- command_size = 1;
- break;
-
- case GX_LOAD_BP_REG:
- command_size = 5;
- break;
-
- case GX_LOAD_CP_REG:
- command_size = 6;
- break;
-
- case GX_LOAD_INDX_A:
- case GX_LOAD_INDX_B:
- case GX_LOAD_INDX_C:
- case GX_LOAD_INDX_D:
- command_size = 5;
- break;
-
- case GX_CMD_CALL_DL:
- command_size = 9;
- break;
-
- case GX_LOAD_XF_REG:
- {
- // check if we can read the header
- if (buffer_size >= 5)
- {
- command_size = 1 + 4;
- u32 Cmd2 = DataPeek32(1);
- int transfer_size = ((Cmd2 >> 16) & 15) + 1;
- command_size += transfer_size * 4;
- }
- else
+ command_size = 1;
+ cycleTime = 6;
+ break;
+ case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
+ command_size = 1;
+ cycleTime = 6;
+ break;
+
+ case GX_LOAD_BP_REG:
+ command_size = 5;
+ cycleTime = 12;
+ break;
+
+ case GX_LOAD_CP_REG:
+ command_size = 6;
+ cycleTime = 12;
+ break;
+
+ case GX_LOAD_INDX_A:
+ case GX_LOAD_INDX_B:
+ case GX_LOAD_INDX_C:
+ case GX_LOAD_INDX_D:
+ command_size = 5;
+ cycleTime = 6; // TODO
+ break;
+
+ case GX_CMD_CALL_DL:
+ {
+ // FIXME: Calculate the cycle time of the display list.
+ //u32 address = DataPeek32(1);
+ //u32 size = DataPeek32(5);
+ //u8* old_pVideoData = g_pVideoData;
+ //u8* startAddress = Memory::GetPointer(address);
+
+ //// Avoid the crash if Memory::GetPointer failed ..
+ //if (startAddress != 0)
+ //{
+ // g_pVideoData = startAddress;
+ // u8 *end = g_pVideoData + size;
+ // u32 step = 0;
+ // while (g_pVideoData < end)
+ // {
+ // cycleTime += FifoCommandRunnable(step);
+ // g_pVideoData += step;
+ // }
+ //}
+ //else
+ //{
+ // cycleTime = 45;
+ //}
+
+ //// reset to the old pointer
+ //g_pVideoData = old_pVideoData;
+ command_size = 9;
+ cycleTime = 45; // This is unverified
+ }
+ break;
+
+ case GX_LOAD_XF_REG:
+ {
+ // check if we can read the header
+ if (buffer_size >= 5)
{
- return false;
- }
- }
- break;
-
- default:
- if (cmd_byte & 0x80)
- {
- // check if we can read the header
- if (buffer_size >= 3)
+ command_size = 1 + 4;
+ u32 Cmd2 = DataPeek32(1);
+ int transfer_size = ((Cmd2 >> 16) & 15) + 1;
+ command_size += transfer_size * 4;
+ cycleTime = 18 + 6 * transfer_size;
+ }
+ else
{
- command_size = 1 + 2;
- u16 numVertices = DataPeek16(1);
+ return 0;
+ }
+ }
+ break;
+
+ default:
+ if (cmd_byte & 0x80)
+ {
+ // check if we can read the header
+ if (buffer_size >= 3)
+ {
+ command_size = 1 + 2;
+ u16 numVertices = DataPeek16(1);
command_size += numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK);
- }
+ cycleTime = 1600; // This depends on the number of pixels rendered
+ }
else
- {
- return false;
- }
- }
+ {
+ return 0;
+ }
+ }
else
{
// TODO(Omega): Maybe dump FIFO to file on this error
@@ -218,7 +258,7 @@ bool FifoCommandRunnable()
Host_SysMessage(szTemp);
INFO_LOG(VIDEO, "%s", szTemp);
{
- SCPFifoStruct &fifo = CommandProcessor::fifo;
+ SCPFifoStruct &fifo = CommandProcessor::fifo;
char szTmp[512];
// sprintf(szTmp, "Illegal command %02x (at %08x)",cmd_byte,g_pDataReader->GetPtr());
@@ -243,197 +283,205 @@ bool FifoCommandRunnable()
Host_SysMessage(szTmp);
INFO_LOG(VIDEO, "%s", szTmp);
}
- }
- break;
- }
-
- if (command_size > buffer_size)
- return false;
+ }
+ break;
+ }
+
+ if (command_size > buffer_size)
+ return 0;
- // INFO_LOG("OP detected: cmd_byte 0x%x size %i buffer %i",cmd_byte, command_size, buffer_size);
+ // INFO_LOG("OP detected: cmd_byte 0x%x size %i buffer %i",cmd_byte, command_size, buffer_size);
+ if (cycleTime == 0)
+ cycleTime = 6;
- return true;
+ return cycleTime;
+}
+
+u32 FifoCommandRunnable()
+{
+ u32 command_size = 0;
+ return FifoCommandRunnable(command_size);
}
static void Decode()
{
- u8 *opcodeStart = g_pVideoData;
-
- int cmd_byte = DataReadU8();
- switch (cmd_byte)
- {
- case GX_NOP:
- break;
-
- case GX_LOAD_CP_REG: //0x08
- {
- u8 sub_cmd = DataReadU8();
- u32 value = DataReadU32();
- LoadCPReg(sub_cmd, value);
+ u8 *opcodeStart = g_pVideoData;
+
+ int cmd_byte = DataReadU8();
+ switch (cmd_byte)
+ {
+ case GX_NOP:
+ break;
+
+ case GX_LOAD_CP_REG: //0x08
+ {
+ u8 sub_cmd = DataReadU8();
+ u32 value = DataReadU32();
+ LoadCPReg(sub_cmd, value);
INCSTAT(stats.thisFrame.numCPLoads);
- }
- break;
+ }
+ break;
- case GX_LOAD_XF_REG:
- {
- u32 Cmd2 = DataReadU32();
- int transfer_size = ((Cmd2 >> 16) & 15) + 1;
+ case GX_LOAD_XF_REG:
+ {
+ u32 Cmd2 = DataReadU32();
+ int transfer_size = ((Cmd2 >> 16) & 15) + 1;
u32 xf_address = Cmd2 & 0xFFFF;
GC_ALIGNED128(u32 data_buffer[16]);
DataReadU32xFuncs[transfer_size-1](data_buffer);
- LoadXFReg(transfer_size, xf_address, data_buffer);
+ LoadXFReg(transfer_size, xf_address, data_buffer);
INCSTAT(stats.thisFrame.numXFLoads);
- }
- break;
-
- case GX_LOAD_INDX_A: //used for position matrices
- LoadIndexedXF(DataReadU32(), 0xC);
- break;
- case GX_LOAD_INDX_B: //used for normal matrices
- LoadIndexedXF(DataReadU32(), 0xD);
- break;
- case GX_LOAD_INDX_C: //used for postmatrices
- LoadIndexedXF(DataReadU32(), 0xE);
- break;
- case GX_LOAD_INDX_D: //used for lights
- LoadIndexedXF(DataReadU32(), 0xF);
- break;
-
- case GX_CMD_CALL_DL:
- {
- u32 address = DataReadU32();
- u32 count = DataReadU32();
- ExecuteDisplayList(address, count);
- }
- break;
-
- case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
+ }
+ break;
+
+ case GX_LOAD_INDX_A: //used for position matrices
+ LoadIndexedXF(DataReadU32(), 0xC);
+ break;
+ case GX_LOAD_INDX_B: //used for normal matrices
+ LoadIndexedXF(DataReadU32(), 0xD);
+ break;
+ case GX_LOAD_INDX_C: //used for postmatrices
+ LoadIndexedXF(DataReadU32(), 0xE);
+ break;
+ case GX_LOAD_INDX_D: //used for lights
+ LoadIndexedXF(DataReadU32(), 0xF);
+ break;
+
+ case GX_CMD_CALL_DL:
+ {
+ u32 address = DataReadU32();
+ u32 count = DataReadU32();
+ ExecuteDisplayList(address, count);
+ }
+ break;
+
+ case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
DEBUG_LOG(VIDEO, "GX 0x44: %08x", cmd_byte);
- break;
+ break;
- case GX_CMD_INVL_VC: // Invalidate Vertex Cache
- DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
- break;
+ case GX_CMD_INVL_VC: // Invalidate Vertex Cache
+ DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
+ break;
- case GX_LOAD_BP_REG: //0x61
- {
+ case GX_LOAD_BP_REG: //0x61
+ {
u32 bp_cmd = DataReadU32();
- LoadBPReg(bp_cmd);
+ LoadBPReg(bp_cmd);
INCSTAT(stats.thisFrame.numBPLoads);
- }
- break;
-
- // draw primitives
- default:
- if (cmd_byte & 0x80)
- {
- // load vertices (use computed vertex size from FifoCommandRunnable above)
+ }
+ break;
+
+ // draw primitives
+ default:
+ if (cmd_byte & 0x80)
+ {
+ // load vertices (use computed vertex size from FifoCommandRunnable above)
u16 numVertices = DataReadU16();
VertexLoaderManager::RunVertices(
cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7)
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
numVertices);
- }
- else
- {
+ }
+ else
+ {
ERROR_LOG(VIDEO, "OpcodeDecoding::Decode: Illegal command %02x", cmd_byte);
- break;
- }
- break;
- }
+ break;
+ }
+ break;
+ }
// Display lists get added directly into the FIFO stream
if (g_bRecordFifoData && cmd_byte != GX_CMD_CALL_DL)
- FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, g_pVideoData - opcodeStart);
+ FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, u32(g_pVideoData - opcodeStart));
}
static void DecodeSemiNop()
{
- u8 *opcodeStart = g_pVideoData;
-
- int cmd_byte = DataReadU8();
- switch (cmd_byte)
- {
- case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
- case GX_CMD_INVL_VC: // Invalidate Vertex Cache
- case GX_NOP:
+ u8 *opcodeStart = g_pVideoData;
+
+ int cmd_byte = DataReadU8();
+ switch (cmd_byte)
+ {
+ case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
+ case GX_CMD_INVL_VC: // Invalidate Vertex Cache
+ case GX_NOP:
break;
case GX_LOAD_CP_REG: //0x08
// We have to let CP writes through because they determine the size of vertices.
- {
- u8 sub_cmd = DataReadU8();
- u32 value = DataReadU32();
- LoadCPReg(sub_cmd, value);
- INCSTAT(stats.thisFrame.numCPLoads);
- }
- break;
-
- case GX_LOAD_XF_REG:
- {
- u32 Cmd2 = DataReadU32();
- int transfer_size = ((Cmd2 >> 16) & 15) + 1;
- u32 address = Cmd2 & 0xFFFF;
- GC_ALIGNED128(u32 data_buffer[16]);
- DataReadU32xFuncs[transfer_size-1](data_buffer);
- LoadXFReg(transfer_size, address, data_buffer);
- INCSTAT(stats.thisFrame.numXFLoads);
- }
- break;
-
- case GX_LOAD_INDX_A: //used for position matrices
- LoadIndexedXF(DataReadU32(), 0xC);
- break;
- case GX_LOAD_INDX_B: //used for normal matrices
- LoadIndexedXF(DataReadU32(), 0xD);
- break;
- case GX_LOAD_INDX_C: //used for postmatrices
- LoadIndexedXF(DataReadU32(), 0xE);
- break;
- case GX_LOAD_INDX_D: //used for lights
- LoadIndexedXF(DataReadU32(), 0xF);
- break;
-
- case GX_CMD_CALL_DL:
+ {
+ u8 sub_cmd = DataReadU8();
+ u32 value = DataReadU32();
+ LoadCPReg(sub_cmd, value);
+ INCSTAT(stats.thisFrame.numCPLoads);
+ }
+ break;
+
+ case GX_LOAD_XF_REG:
+ {
+ u32 Cmd2 = DataReadU32();
+ int transfer_size = ((Cmd2 >> 16) & 15) + 1;
+ u32 address = Cmd2 & 0xFFFF;
+ GC_ALIGNED128(u32 data_buffer[16]);
+ DataReadU32xFuncs[transfer_size-1](data_buffer);
+ LoadXFReg(transfer_size, address, data_buffer);
+ INCSTAT(stats.thisFrame.numXFLoads);
+ }
+ break;
+
+ case GX_LOAD_INDX_A: //used for position matrices
+ LoadIndexedXF(DataReadU32(), 0xC);
+ break;
+ case GX_LOAD_INDX_B: //used for normal matrices
+ LoadIndexedXF(DataReadU32(), 0xD);
+ break;
+ case GX_LOAD_INDX_C: //used for postmatrices
+ LoadIndexedXF(DataReadU32(), 0xE);
+ break;
+ case GX_LOAD_INDX_D: //used for lights
+ LoadIndexedXF(DataReadU32(), 0xF);
+ break;
+
+ case GX_CMD_CALL_DL:
// Hm, wonder if any games put tokens in display lists - in that case,
// we'll have to parse them too.
- DataSkip(8);
- break;
+ DataSkip(8);
+ break;
- case GX_LOAD_BP_REG: //0x61
+ case GX_LOAD_BP_REG: //0x61
// We have to let BP writes through because they set tokens and stuff.
// TODO: Call a much simplified LoadBPReg instead.
- {
+ {
u32 bp_cmd = DataReadU32();
- LoadBPReg(bp_cmd);
+ LoadBPReg(bp_cmd);
INCSTAT(stats.thisFrame.numBPLoads);
- }
- break;
-
- // draw primitives
- default:
- if (cmd_byte & 0x80)
- {
- // load vertices (use computed vertex size from FifoCommandRunnable above)
+ }
+ break;
+
+ // draw primitives
+ default:
+ if (cmd_byte & 0x80)
+ {
+ // load vertices (use computed vertex size from FifoCommandRunnable above)
u16 numVertices = DataReadU16();
DataSkip(numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK));
- }
- else
- {
+ }
+ else
+ {
ERROR_LOG(VIDEO, "OpcodeDecoding::Decode: Illegal command %02x", cmd_byte);
- break;
- }
- break;
- }
+ break;
+ }
+ break;
+ }
if (g_bRecordFifoData && cmd_byte != GX_CMD_CALL_DL)
- FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, g_pVideoData - opcodeStart);
+ FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, u32(g_pVideoData - opcodeStart));
}
void OpcodeDecoder_Init()
-{
+{
g_pVideoData = GetVideoBufferStartPtr();
#if _M_SSE >= 0x301
@@ -446,8 +494,8 @@ void OpcodeDecoder_Init()
if (g_Config.bEnableOpenCL)
{
- OpenCL::Initialize();
- TexDecoder_OpenCL_Initialize();
+ OpenCL::Initialize();
+ TexDecoder_OpenCL_Initialize();
}
}
@@ -456,21 +504,20 @@ void OpcodeDecoder_Shutdown()
{
if (g_Config.bEnableOpenCL)
{
- TexDecoder_OpenCL_Shutdown();
- OpenCL::Destroy();
+ TexDecoder_OpenCL_Shutdown();
+ OpenCL::Destroy();
}
}
-void OpcodeDecoder_Run(bool skipped_frame)
+u32 OpcodeDecoder_Run(bool skipped_frame)
{
- if (!skipped_frame)
- {
- while (FifoCommandRunnable())
- Decode();
- }
- else
+ u32 totalCycles = 0;
+ u32 cycles = FifoCommandRunnable();
+ while (cycles > 0)
{
- while (FifoCommandRunnable())
- DecodeSemiNop();
+ skipped_frame ? DecodeSemiNop() : Decode();
+ totalCycles += cycles;
+ cycles = FifoCommandRunnable();
}
+ return totalCycles;
}
diff --git a/Source/Core/VideoCommon/Src/OpcodeDecoding.h b/Source/Core/VideoCommon/Src/OpcodeDecoding.h
index f2e9cd1321..b825809705 100644
--- a/Source/Core/VideoCommon/Src/OpcodeDecoding.h
+++ b/Source/Core/VideoCommon/Src/OpcodeDecoding.h
@@ -44,12 +44,12 @@
#define GX_DRAW_LINES 0x5 // 0xA8
#define GX_DRAW_LINE_STRIP 0x6 // 0xB0
#define GX_DRAW_POINTS 0x7 // 0xB8
-#define GX_DRAW_NONE 0x1; //Tis is a fake value to used in the backends
+#define GX_DRAW_NONE 0x1; //Tis is a fake value to used in the backends
extern bool g_bRecordFifoData;
void OpcodeDecoder_Init();
void OpcodeDecoder_Shutdown();
-void OpcodeDecoder_Run(bool skipped_frame);
+u32 OpcodeDecoder_Run(bool skipped_frame);
void ExecuteDisplayList(u32 address, u32 size);
#endif // _OPCODE_DECODING_H
diff --git a/Source/Core/VideoCommon/Src/OpenCL.cpp b/Source/Core/VideoCommon/Src/OpenCL.cpp
index 0fc18017af..202c0c4b41 100644
--- a/Source/Core/VideoCommon/Src/OpenCL.cpp
+++ b/Source/Core/VideoCommon/Src/OpenCL.cpp
@@ -148,25 +148,25 @@ cl_program CompileProgram(const char *Kernel)
// Build the program executable
err = clBuildProgram(program , 0, NULL, NULL, NULL, NULL);
if(err != CL_SUCCESS) {
- HandleCLError(err, "Error: failed to build program");
+ HandleCLError(err, "Error: failed to build program");
char *buildlog = NULL;
- size_t buildlog_size = 0;
+ size_t buildlog_size = 0;
clGetProgramBuildInfo(program, OpenCL::device_id, CL_PROGRAM_BUILD_LOG, 0, NULL, &buildlog_size);
- buildlog = new char[buildlog_size + 1];
- err = clGetProgramBuildInfo(program, OpenCL::device_id, CL_PROGRAM_BUILD_LOG, buildlog_size, buildlog, NULL);
- buildlog[buildlog_size] = 0;
-
- if(err != CL_SUCCESS)
- {
- HandleCLError(err, "Error: can't get build log");
- } else
- {
- ERROR_LOG(COMMON, "Error log:\n%s\n", buildlog);
- }
-
- delete[] buildlog;
+ buildlog = new char[buildlog_size + 1];
+ err = clGetProgramBuildInfo(program, OpenCL::device_id, CL_PROGRAM_BUILD_LOG, buildlog_size, buildlog, NULL);
+ buildlog[buildlog_size] = 0;
+
+ if(err != CL_SUCCESS)
+ {
+ HandleCLError(err, "Error: can't get build log");
+ } else
+ {
+ ERROR_LOG(COMMON, "Error log:\n%s\n", buildlog);
+ }
+
+ delete[] buildlog;
return NULL;
}
diff --git a/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp b/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp
index 440e69efd6..db70640fbb 100644
--- a/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp
+++ b/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp
@@ -98,7 +98,7 @@ void TexDecoder_OpenCL_Initialize()
size_t nDevices = 0;
cl_device_id *devices = NULL;
size_t *binary_sizes = NULL;
- char **binaries = NULL;
+ char **binaries = NULL;
std::string filename;
char dolphin_rev[HEADER_SIZE];
@@ -132,7 +132,7 @@ void TexDecoder_OpenCL_Initialize()
{
OpenCL::HandleCLError(err, "clCreateProgramWithBinary");
}
-
+
if (!err)
{
err = clBuildProgram(g_program, 1, &OpenCL::device_id, NULL, NULL, NULL);
diff --git a/Source/Core/VideoCommon/Src/PerfQueryBase.cpp b/Source/Core/VideoCommon/Src/PerfQueryBase.cpp
new file mode 100644
index 0000000000..c537d176f6
--- /dev/null
+++ b/Source/Core/VideoCommon/Src/PerfQueryBase.cpp
@@ -0,0 +1,3 @@
+#include "PerfQueryBase.h"
+
+PerfQueryBase* g_perf_query = 0;
diff --git a/Source/Core/VideoCommon/Src/PerfQueryBase.h b/Source/Core/VideoCommon/Src/PerfQueryBase.h
new file mode 100644
index 0000000000..b979449edb
--- /dev/null
+++ b/Source/Core/VideoCommon/Src/PerfQueryBase.h
@@ -0,0 +1,54 @@
+#ifndef _PERFQUERY_BASE_H_
+#define _PERFQUERY_BASE_H_
+
+#include "CommonTypes.h"
+
+enum PerfQueryType
+{
+ PQ_ZCOMP_INPUT_ZCOMPLOC = 0,
+ PQ_ZCOMP_OUTPUT_ZCOMPLOC,
+ PQ_ZCOMP_INPUT,
+ PQ_ZCOMP_OUTPUT,
+ PQ_BLEND_INPUT,
+ PQ_EFB_COPY_CLOCKS,
+ PQ_NUM_MEMBERS
+};
+
+enum PerfQueryGroup
+{
+ PQG_ZCOMP_ZCOMPLOC,
+ PQG_ZCOMP,
+ PQG_EFB_COPY_CLOCKS,
+ PQG_NUM_MEMBERS,
+};
+
+class PerfQueryBase
+{
+public:
+ PerfQueryBase() {};
+ virtual ~PerfQueryBase() {}
+
+ // Begin querying the specified value for the following host GPU commands
+ virtual void EnableQuery(PerfQueryGroup type) {}
+
+ // Stop querying the specified value for the following host GPU commands
+ virtual void DisableQuery(PerfQueryGroup type) {}
+
+ // Reset query counters to zero and drop any pending queries
+ virtual void ResetQuery() {}
+
+ // Return the measured value for the specified query type
+ // NOTE: Called from CPU thread
+ virtual u32 GetQueryResult(PerfQueryType type) { return 0; }
+
+ // Request the value of any pending queries - causes a pipeline flush and thus should be used carefully!
+ virtual void FlushResults() {}
+
+ // True if there are no further pending query results
+ // NOTE: Called from CPU thread
+ virtual bool IsFlushed() const { return true; }
+};
+
+extern PerfQueryBase* g_perf_query;
+
+#endif // _PERFQUERY_H_
diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp
index a488e52b42..b014148d8d 100644
--- a/Source/Core/VideoCommon/Src/PixelEngine.cpp
+++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp
@@ -28,10 +28,12 @@
#include "ConfigManager.h"
#include "PixelEngine.h"
+#include "RenderBase.h"
#include "CommandProcessor.h"
#include "HW/ProcessorInterface.h"
#include "DLCache.h"
#include "State.h"
+
namespace PixelEngine
{
@@ -110,22 +112,22 @@ static UPEAlphaReadReg m_AlphaRead;
static UPECtrlReg m_Control;
//static u16 m_Token; // token value most recently encountered
-static bool g_bSignalTokenInterrupt;
-static bool g_bSignalFinishInterrupt;
+volatile u32 g_bSignalTokenInterrupt;
+volatile u32 g_bSignalFinishInterrupt;
static int et_SetTokenOnMainThread;
static int et_SetFinishOnMainThread;
-volatile bool interruptSetToken = false;
-volatile bool interruptSetFinish = false;
+volatile u32 interruptSetToken = 0;
+volatile u32 interruptSetFinish = 0;
u16 bbox[4];
bool bbox_active;
enum
{
- INT_CAUSE_PE_TOKEN = 0x200, // GP Token
- INT_CAUSE_PE_FINISH = 0x400, // GP Finished
+ INT_CAUSE_PE_TOKEN = 0x200, // GP Token
+ INT_CAUSE_PE_FINISH = 0x400, // GP Finished
};
void DoState(PointerWrap &p)
@@ -161,10 +163,10 @@ void Init()
m_AlphaModeConf.Hex = 0;
m_AlphaRead.Hex = 0;
- g_bSignalTokenInterrupt = false;
- g_bSignalFinishInterrupt = false;
- interruptSetToken = false;
- interruptSetFinish = false;
+ g_bSignalTokenInterrupt = 0;
+ g_bSignalFinishInterrupt = 0;
+ interruptSetToken = 0;
+ interruptSetFinish = 0;
et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread);
et_SetFinishOnMainThread = CoreTiming::RegisterEvent("SetFinish", SetFinish_OnMainThread);
@@ -211,7 +213,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
break;
case PE_TOKEN_REG:
- _uReturnValue = CommandProcessor::fifo.PEToken;
+ _uReturnValue = Common::AtomicLoad(*(volatile u32*)&CommandProcessor::fifo.PEToken);
INFO_LOG(PIXELENGINE, "(r16) TOKEN_REG : %04x", _uReturnValue);
break;
@@ -255,23 +257,59 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
break;
}
- case PE_PERF_0L:
- case PE_PERF_0H:
- case PE_PERF_1L:
- case PE_PERF_1H:
- case PE_PERF_2L:
- case PE_PERF_2H:
- case PE_PERF_3L:
- case PE_PERF_3H:
- case PE_PERF_4L:
- case PE_PERF_4H:
- case PE_PERF_5L:
- case PE_PERF_5H:
- INFO_LOG(PIXELENGINE, "(r16) perf counter @ %08x", _iAddress);
- // git r90a2096a24f4 (svn r3663) added the PE_PERF cases, without setting
- // _uReturnValue to anything, this reverts to the previous behaviour which allows
- // The timer in SMS:Scrubbing Serena Beach to countdown correctly
- _uReturnValue = 1;
+ // NOTE(neobrain): only PE_PERF_ZCOMP_OUTPUT is implemented in D3D11, but the other values shouldn't be contradictionary to the value of that register (i.e. INPUT registers should always be greater or equal to their corresponding OUTPUT registers).
+ case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L:
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) & 0xFFFF;
+ break;
+
+ case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H:
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) >> 16;
+ break;
+
+ case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L:
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) & 0xFFFF;
+ break;
+
+ case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H:
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) >> 16;
+ break;
+
+ case PE_PERF_ZCOMP_INPUT_L:
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT) & 0xFFFF;
+ break;
+
+ case PE_PERF_ZCOMP_INPUT_H:
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT) >> 16;
+ break;
+
+ case PE_PERF_ZCOMP_OUTPUT_L:
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT) & 0xFFFF;
+ break;
+
+ case PE_PERF_ZCOMP_OUTPUT_H:
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT) >> 16;
+ break;
+
+ case PE_PERF_BLEND_INPUT_L:
+ // Super Mario Sunshine uses this register in episode 6 of Sirena Beach:
+ // The amount of remaining goop is determined by checking how many pixels reach the blending stage.
+ // Once this register falls below a particular value (around 0x90), the game regards the challenge finished.
+ // In very old builds, Dolphin only returned 0. That caused the challenge to be immediately finished without any goop being cleaned (the timer just didn't even start counting from 3:00:00).
+ // Later builds returned 1 for the high register. That caused the timer to actually count down, but made the challenge unbeatable because the game always thought you didn't clear any goop at all.
+ // Note that currently this functionality is only implemented in the D3D11 backend.
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_BLEND_INPUT) & 0xFFFF;
+ break;
+
+ case PE_PERF_BLEND_INPUT_H:
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_BLEND_INPUT) >> 16;
+ break;
+
+ case PE_PERF_EFB_COPY_CLOCKS_L:
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_EFB_COPY_CLOCKS) & 0xFFFF;
+ break;
+
+ case PE_PERF_EFB_COPY_CLOCKS_H:
+ _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_EFB_COPY_CLOCKS) >> 16;
break;
default:
@@ -312,8 +350,8 @@ void Write16(const u16 _iValue, const u32 _iAddress)
{
UPECtrlReg tmpCtrl(_iValue);
- if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = false;
- if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = false;
+ if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = 0;
+ if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = 0;
m_Control.PETokenEnable = tmpCtrl.PETokenEnable;
m_Control.PEFinishEnable = tmpCtrl.PEFinishEnable;
@@ -359,14 +397,14 @@ void UpdateInterrupts()
void UpdateTokenInterrupt(bool active)
{
- ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active);
- interruptSetToken = active;
+ ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active);
+ Common::AtomicStore(interruptSetToken, active ? 1 : 0);
}
void UpdateFinishInterrupt(bool active)
{
- ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
- interruptSetFinish = active;
+ ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
+ Common::AtomicStore(interruptSetFinish, active ? 1 : 0);
}
// TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate).
@@ -376,20 +414,23 @@ void UpdateFinishInterrupt(bool active)
// Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP
void SetToken_OnMainThread(u64 userdata, int cyclesLate)
{
- //if (userdata >> 16)
- //{
- g_bSignalTokenInterrupt = true;
- //_dbg_assert_msg_(PIXELENGINE, (CommandProcessor::fifo.PEToken == (userdata&0xFFFF)), "WTF? BPMEM_PE_TOKEN_INT_ID's token != BPMEM_PE_TOKEN_ID's token" );
- INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken);
+ // XXX: No 16-bit atomic store available, so cheat and use 32-bit.
+ // That's what we've always done. We're counting on fifo.PEToken to be
+ // 4-byte padded.
+ Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, userdata & 0xffff);
+ INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken);
+ if (userdata >> 16)
+ {
+ Common::AtomicStore(*(volatile u32*)&g_bSignalTokenInterrupt, 1);
UpdateInterrupts();
- CommandProcessor::interruptTokenWaiting = false;
- IncrementCheckContextId();
- //}
+ }
+ CommandProcessor::interruptTokenWaiting = false;
+ IncrementCheckContextId();
}
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
{
- g_bSignalFinishInterrupt = 1;
+ Common::AtomicStore(*(volatile u32*)&g_bSignalFinishInterrupt, 1);
UpdateInterrupts();
CommandProcessor::interruptFinishWaiting = false;
CommandProcessor::isPossibleWaitingSetDrawDone = false;
@@ -399,23 +440,13 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
// THIS IS EXECUTED FROM VIDEO THREAD
void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
{
- // TODO?: set-token-value and set-token-INT could be merged since set-token-INT own the token value.
if (_bSetTokenAcknowledge) // set token INT
{
-
- Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token);
- CommandProcessor::interruptTokenWaiting = true;
- CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
- }
- else // set token value
- {
- // we do it directly from videoThread because of
- // Super Monkey Ball
- // XXX: No 16-bit atomic store available, so cheat and use 32-bit.
- // That's what we've always done. We're counting on fifo.PEToken to be
- // 4-byte padded.
- Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token);
+ Common::AtomicStore(*(volatile u32*)&g_bSignalTokenInterrupt, 1);
}
+
+ CommandProcessor::interruptTokenWaiting = true;
+ CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
IncrementCheckContextId();
}
@@ -438,7 +469,6 @@ void ResetSetFinish()
{
UpdateFinishInterrupt(false);
g_bSignalFinishInterrupt = false;
-
}
else
{
@@ -452,8 +482,7 @@ void ResetSetToken()
if (g_bSignalTokenInterrupt)
{
UpdateTokenInterrupt(false);
- g_bSignalTokenInterrupt = false;
-
+ g_bSignalTokenInterrupt = 0;
}
else
{
@@ -461,17 +490,4 @@ void ResetSetToken()
}
CommandProcessor::interruptTokenWaiting = false;
}
-
-bool WaitingForPEInterrupt()
-{
- return !CommandProcessor::waitingForPEInterruptDisable && (CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || interruptSetFinish || interruptSetToken);
-}
-
-void ResumeWaitingForPEInterrupt()
-{
- interruptSetFinish = false;
- interruptSetToken = false;
- CommandProcessor::interruptFinishWaiting = false;
- CommandProcessor::interruptTokenWaiting = false;
-}
} // end of namespace PixelEngine
diff --git a/Source/Core/VideoCommon/Src/PixelEngine.h b/Source/Core/VideoCommon/Src/PixelEngine.h
index 64f959009f..f34621774c 100644
--- a/Source/Core/VideoCommon/Src/PixelEngine.h
+++ b/Source/Core/VideoCommon/Src/PixelEngine.h
@@ -24,31 +24,32 @@ class PointerWrap;
// internal hardware addresses
enum
{
- PE_ZCONF = 0x00, // Z Config
- PE_ALPHACONF = 0x02, // Alpha Config
- PE_DSTALPHACONF = 0x04, // Destination Alpha Config
- PE_ALPHAMODE = 0x06, // Alpha Mode Config
- PE_ALPHAREAD = 0x08, // Alpha Read
+ PE_ZCONF = 0x00, // Z Config
+ PE_ALPHACONF = 0x02, // Alpha Config
+ PE_DSTALPHACONF = 0x04, // Destination Alpha Config
+ PE_ALPHAMODE = 0x06, // Alpha Mode Config
+ PE_ALPHAREAD = 0x08, // Alpha Read
PE_CTRL_REGISTER = 0x0a, // Control
- PE_TOKEN_REG = 0x0e, // Token
+ PE_TOKEN_REG = 0x0e, // Token
PE_BBOX_LEFT = 0x10, // Flip Left
PE_BBOX_RIGHT = 0x12, // Flip Right
PE_BBOX_TOP = 0x14, // Flip Top
PE_BBOX_BOTTOM = 0x16, // Flip Bottom
- // These have not yet been RE:d. They are the perf counters.
- PE_PERF_0L = 0x18,
- PE_PERF_0H = 0x1a,
- PE_PERF_1L = 0x1c,
- PE_PERF_1H = 0x1e,
- PE_PERF_2L = 0x20,
- PE_PERF_2H = 0x22,
- PE_PERF_3L = 0x24,
- PE_PERF_3H = 0x26,
- PE_PERF_4L = 0x28,
- PE_PERF_4H = 0x2a,
- PE_PERF_5L = 0x2c,
- PE_PERF_5H = 0x2e,
+ // NOTE: Order not verified
+ // These indicate the number of quads that are being used as input/output for each particular stage
+ PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L = 0x18,
+ PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H = 0x1a,
+ PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L = 0x1c,
+ PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H = 0x1e,
+ PE_PERF_ZCOMP_INPUT_L = 0x20,
+ PE_PERF_ZCOMP_INPUT_H = 0x22,
+ PE_PERF_ZCOMP_OUTPUT_L = 0x24,
+ PE_PERF_ZCOMP_OUTPUT_H = 0x26,
+ PE_PERF_BLEND_INPUT_L = 0x28,
+ PE_PERF_BLEND_INPUT_H = 0x2a,
+ PE_PERF_EFB_COPY_CLOCKS_L = 0x2c,
+ PE_PERF_EFB_COPY_CLOCKS_H = 0x2e,
};
namespace PixelEngine
@@ -80,8 +81,6 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
void SetFinish(void);
void ResetSetFinish(void);
void ResetSetToken(void);
-bool WaitingForPEInterrupt();
-void ResumeWaitingForPEInterrupt();
// Bounding box functionality. Paper Mario (both) are a couple of the few games that use it.
extern u16 bbox[4];
diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp
index 448501aad0..d863a6e0a9 100644
--- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp
+++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp
@@ -173,7 +173,7 @@ void GetPixelShaderId(PIXELSHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 compo
*ptr++ = components;
}
- uid->num_values = ptr - uid->values;
+ uid->num_values = int(ptr - uid->values);
}
void GetSafePixelShaderId(PIXELSHADERUIDSAFE *uid, DSTALPHA_MODE dstAlphaMode, u32 components)
@@ -205,7 +205,7 @@ void GetSafePixelShaderId(PIXELSHADERUIDSAFE *uid, DSTALPHA_MODE dstAlphaMode, u
*ptr++ = bpmem.tevindref.hex; // 31
- for (unsigned int i = 0; i < bpmem.genMode.numtevstages+1u; ++i) // up to 16 times
+ for (u32 i = 0; i < bpmem.genMode.numtevstages+1u; ++i) // up to 16 times
{
*ptr++ = bpmem.combiners[i].colorC.hex; // 32+5*i
*ptr++ = bpmem.combiners[i].alphaC.hex; // 33+5*i
@@ -252,7 +252,8 @@ void ValidatePixelShaderIDs(API_TYPE api, PIXELSHADERUIDSAFE old_id, const std::
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%spsuid_mismatch_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << msg;
file << "\n\nOld shader code:\n" << old_code;
file << "\n\nNew shader code:\n" << new_code;
@@ -275,7 +276,7 @@ void ValidatePixelShaderIDs(API_TYPE api, PIXELSHADERUIDSAFE old_id, const std::
static void WriteStage(char *&p, int n, API_TYPE ApiType);
static void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType);
// static void WriteAlphaCompare(char *&p, int num, int comp);
-static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode);
+static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode, bool per_pixel_depth);
static void WriteFog(char *&p);
static const char *tevKSelTableC[] = // KCSEL
@@ -373,38 +374,38 @@ static const char *tevOpTable[] = { // TEV
static const char *tevCInputTable[] = // CC
{
- "(prev.rgb)", // CPREV,
+ "(prev.rgb)", // CPREV,
"(prev.aaa)", // APREV,
- "(c0.rgb)", // C0,
+ "(c0.rgb)", // C0,
"(c0.aaa)", // A0,
- "(c1.rgb)", // C1,
+ "(c1.rgb)", // C1,
"(c1.aaa)", // A1,
- "(c2.rgb)", // C2,
+ "(c2.rgb)", // C2,
"(c2.aaa)", // A2,
- "(textemp.rgb)", // TEXC,
+ "(textemp.rgb)", // TEXC,
"(textemp.aaa)", // TEXA,
- "(rastemp.rgb)", // RASC,
+ "(rastemp.rgb)", // RASC,
"(rastemp.aaa)", // RASA,
"float3(1.0f, 1.0f, 1.0f)", // ONE
- "float3(0.5f, 0.5f, 0.5f)", // HALF
- "(konsttemp.rgb)", //"konsttemp.rgb", // KONST
+ "float3(0.5f, 0.5f, 0.5f)", // HALF
+ "(konsttemp.rgb)", //"konsttemp.rgb", // KONST
"float3(0.0f, 0.0f, 0.0f)", // ZERO
///aded extra values to map clamped values
- "(cprev.rgb)", // CPREV,
- "(cprev.aaa)", // APREV,
- "(cc0.rgb)", // C0,
- "(cc0.aaa)", // A0,
- "(cc1.rgb)", // C1,
- "(cc1.aaa)", // A1,
- "(cc2.rgb)", // C2,
- "(cc2.aaa)", // A2,
- "(textemp.rgb)", // TEXC,
+ "(cprev.rgb)", // CPREV,
+ "(cprev.aaa)", // APREV,
+ "(cc0.rgb)", // C0,
+ "(cc0.aaa)", // A0,
+ "(cc1.rgb)", // C1,
+ "(cc1.aaa)", // A1,
+ "(cc2.rgb)", // C2,
+ "(cc2.aaa)", // A2,
+ "(textemp.rgb)", // TEXC,
"(textemp.aaa)", // TEXA,
- "(crastemp.rgb)", // RASC,
- "(crastemp.aaa)", // RASA,
+ "(crastemp.rgb)", // RASC,
+ "(crastemp.aaa)", // RASA,
"float3(1.0f, 1.0f, 1.0f)", // ONE
- "float3(0.5f, 0.5f, 0.5f)", // HALF
- "(ckonsttemp.rgb)", //"konsttemp.rgb", // KONST
+ "float3(0.5f, 0.5f, 0.5f)", // HALF
+ "(ckonsttemp.rgb)", //"konsttemp.rgb", // KONST
"float3(0.0f, 0.0f, 0.0f)", // ZERO
"PADERROR1", "PADERROR2", "PADERROR3", "PADERROR4"
};
@@ -424,7 +425,7 @@ static const char *tevAInputTable[] = // CA
"cc0", // A0,
"cc1", // A1,
"cc2", // A2,
- "textemp", // TEXA,
+ "textemp", // TEXA,
"crastemp", // RASA,
"ckonsttemp", // KONST, (hw1 had quarter)
"float4(0.0f, 0.0f, 0.0f, 0.0f)", // ZERO
@@ -439,8 +440,8 @@ static const char *tevRasTable[] =
"ERROR13", //2
"ERROR14", //3
"ERROR15", //4
- "alphabump", // use bump alpha
- "(alphabump*(255.0f/248.0f))", //normalized
+ "float4(alphabump,alphabump,alphabump,alphabump)", // use bump alpha
+ "(float4(alphabump,alphabump,alphabump,alphabump)*(255.0f/248.0f))", //normalized
"float4(0.0f, 0.0f, 0.0f, 0.0f)", // zero
};
@@ -484,6 +485,24 @@ static void BuildSwapModeTable()
}
}
+const char* WriteRegister(API_TYPE ApiType, const char *prefix, const u32 num)
+{
+ if (ApiType == API_OPENGL)
+ return ""; // Nothing to do here
+ static char result[64];
+ sprintf(result, " : register(%s%d)", prefix, num);
+ return result;
+}
+
+const char *WriteLocation(API_TYPE ApiType)
+{
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ return "";
+ static char result[64];
+ sprintf(result, "uniform ");
+ return result;
+}
+
const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components)
{
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
@@ -493,6 +512,8 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
int numStages = bpmem.genMode.numtevstages + 1;
int numTexgen = bpmem.genMode.numtexgens;
+ bool per_pixel_depth = bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.early_ztest && bpmem.zmode.testenable;
+
char *p = text;
WRITE(p, "//Pixel Shader for TEV stages\n");
WRITE(p, "//%i TEV stages, %i texgens, XXX IND stages\n",
@@ -507,138 +528,216 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
nIndirectStagesUsed |= 1 << bpmem.tevind[i].bt;
}
}
- // Declare samplers
- if(ApiType != API_D3D11)
+ if (ApiType == API_OPENGL)
{
- WRITE(p, "uniform sampler2D ");
+
+ // A function here
+ // Fmod implementation gleaned from Nvidia
+ // At http://http.developer.nvidia.com/Cg/fmod.html
+ WRITE(p, "float fmod( float x, float y )\n");
+ WRITE(p, "{\n");
+ WRITE(p, "\tfloat z = fract( abs( x / y) ) * abs( y );\n");
+ WRITE(p, "\treturn (x < 0) ? -z : z;\n");
+ WRITE(p, "}\n");
+
+ for (int i = 0; i < 8; ++i)
+ WRITE(p, "uniform sampler2D samp%d;\n", i);
}
else
{
- WRITE(p, "sampler ");
- }
+ // Declare samplers
+ if (ApiType != API_D3D11)
+ {
+ WRITE(p, "uniform sampler2D ");
+ }
+ else
+ {
+ WRITE(p, "sampler ");
+ }
- bool bfirst = true;
- for (int i = 0; i < 8; ++i)
- {
- WRITE(p, "%s samp%d : register(s%d)", bfirst?"":",", i, i);
- bfirst = false;
- }
- WRITE(p, ";\n");
- if(ApiType == API_D3D11)
- {
- WRITE(p, "Texture2D ");
- bfirst = true;
+ bool bfirst = true;
for (int i = 0; i < 8; ++i)
{
- WRITE(p, "%s Tex%d : register(t%d)", bfirst?"":",", i, i);
+ WRITE(p, "%s samp%d %s", bfirst?"":",", i, WriteRegister(ApiType, "s", i));
bfirst = false;
}
WRITE(p, ";\n");
+ if (ApiType == API_D3D11)
+ {
+ WRITE(p, "Texture2D ");
+ bfirst = true;
+ for (int i = 0; i < 8; ++i)
+ {
+ WRITE(p, "%s Tex%d : register(t%d)", bfirst?"":",", i, i);
+ bfirst = false;
+ }
+ WRITE(p, ";\n");
+ }
}
WRITE(p, "\n");
-
- WRITE(p, "uniform float4 " I_COLORS"[4] : register(c%d);\n", C_COLORS);
- WRITE(p, "uniform float4 " I_KCOLORS"[4] : register(c%d);\n", C_KCOLORS);
- WRITE(p, "uniform float4 " I_ALPHA"[1] : register(c%d);\n", C_ALPHA);
- WRITE(p, "uniform float4 " I_TEXDIMS"[8] : register(c%d);\n", C_TEXDIMS);
- WRITE(p, "uniform float4 " I_ZBIAS"[2] : register(c%d);\n", C_ZBIAS);
- WRITE(p, "uniform float4 " I_INDTEXSCALE"[2] : register(c%d);\n", C_INDTEXSCALE);
- WRITE(p, "uniform float4 " I_INDTEXMTX"[6] : register(c%d);\n", C_INDTEXMTX);
- WRITE(p, "uniform float4 " I_FOG"[3] : register(c%d);\n", C_FOG);
-
- if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
- {
- WRITE(p,"typedef struct { float4 col; float4 cosatt; float4 distatt; float4 pos; float4 dir; } Light;\n");
- WRITE(p,"typedef struct { Light lights[8]; } s_" I_PLIGHTS";\n");
- WRITE(p, "uniform s_" I_PLIGHTS" " I_PLIGHTS" : register(c%d);\n", C_PLIGHTS);
- WRITE(p, "typedef struct { float4 C0, C1, C2, C3; } s_" I_PMATERIALS";\n");
- WRITE(p, "uniform s_" I_PMATERIALS" " I_PMATERIALS" : register(c%d);\n", C_PMATERIALS);
- }
-
- WRITE(p, "void main(\n");
- if(ApiType != API_D3D11)
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ WRITE(p, "layout(std140) uniform PSBlock {\n");
+
+ WRITE(p, "\t%sfloat4 " I_COLORS"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_COLORS));
+ WRITE(p, "\t%sfloat4 " I_KCOLORS"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_KCOLORS));
+ WRITE(p, "\t%sfloat4 " I_ALPHA"[1] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_ALPHA));
+ WRITE(p, "\t%sfloat4 " I_TEXDIMS"[8] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_TEXDIMS));
+ WRITE(p, "\t%sfloat4 " I_ZBIAS"[2] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_ZBIAS));
+ WRITE(p, "\t%sfloat4 " I_INDTEXSCALE"[2] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_INDTEXSCALE));
+ WRITE(p, "\t%sfloat4 " I_INDTEXMTX"[6] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_INDTEXMTX));
+ WRITE(p, "\t%sfloat4 " I_FOG"[3] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_FOG));
+
+ // For pixel lighting
+ WRITE(p, "\t%sfloat4 " I_PLIGHTS"[40] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_PLIGHTS));
+ WRITE(p, "\t%sfloat4 " I_PMATERIALS"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_PMATERIALS));
+
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ WRITE(p, "};\n");
+
+ if (ApiType == API_OPENGL)
{
- WRITE(p, " out float4 ocol0 : COLOR0,%s%s\n in float4 rawpos : %s,\n",
- dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : COLOR1," : "",
- "\n out float depth : DEPTH,",
- ApiType & API_OPENGL ? "WPOS" : ApiType & API_D3D9_SM20 ? "POSITION" : "VPOS");
+ WRITE(p, "out float4 ocol0;\n");
+ if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
+ WRITE(p, "out float4 ocol1;\n");
+
+ if (per_pixel_depth)
+ WRITE(p, "#define depth gl_FragDepth\n");
+ WRITE(p, "float4 rawpos = gl_FragCoord;\n");
+
+ WRITE(p, "VARYIN float4 colors_02;\n");
+ WRITE(p, "VARYIN float4 colors_12;\n");
+ WRITE(p, "float4 colors_0 = colors_02;\n");
+ WRITE(p, "float4 colors_1 = colors_12;\n");
+
+ // compute window position if needed because binding semantic WPOS is not widely supported
+ // Let's set up attributes
+ if (xfregs.numTexGen.numTexGens < 7)
+ {
+ for (int i = 0; i < 8; ++i)
+ {
+ WRITE(p, "VARYIN float3 uv%d_2;\n", i);
+ WRITE(p, "float3 uv%d = uv%d_2;\n", i, i);
+ }
+ WRITE(p, "VARYIN float4 clipPos_2;\n");
+ WRITE(p, "float4 clipPos = clipPos_2;\n");
+ if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
+ {
+ WRITE(p, "VARYIN float4 Normal_2;\n");
+ WRITE(p, "float4 Normal = Normal_2;\n");
+ }
+ }
+ else
+ {
+ // wpos is in w of first 4 texcoords
+ if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
+ {
+ for (int i = 0; i < 8; ++i)
+ {
+ WRITE(p, "VARYIN float4 uv%d_2;\n", i);
+ WRITE(p, "float4 uv%d = uv%d_2;\n", i, i);
+ }
+ }
+ else
+ {
+ for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
+ {
+ WRITE(p, "VARYIN float%d uv%d_2;\n", i < 4 ? 4 : 3 , i);
+ WRITE(p, "float%d uv%d = uv%d_2;\n", i < 4 ? 4 : 3 , i, i);
+ }
+ }
+ WRITE(p, "float4 clipPos;\n");
+ }
+ WRITE(p, "void main()\n{\n");
}
else
{
- WRITE(p, " out float4 ocol0 : SV_Target0,%s%s\n in float4 rawpos : SV_Position,\n",
- dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : SV_Target1," : "",
- "\n out float depth : SV_Depth,");
- }
+ WRITE(p, "void main(\n");
+ if (ApiType != API_D3D11)
+ {
+ WRITE(p, " out float4 ocol0 : COLOR0,%s%s\n in float4 rawpos : %s,\n",
+ dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : COLOR1," : "",
+ per_pixel_depth ? "\n out float depth : DEPTH," : "",
+ ApiType & API_D3D9_SM20 ? "POSITION" : "VPOS");
+ }
+ else
+ {
+ WRITE(p, " out float4 ocol0 : SV_Target0,%s%s\n in float4 rawpos : SV_Position,\n",
+ dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : SV_Target1," : "",
+ per_pixel_depth ? "\n out float depth : SV_Depth," : "");
+ }
- WRITE(p, " in float4 colors_0 : COLOR0,\n");
- WRITE(p, " in float4 colors_1 : COLOR1");
+ WRITE(p, " in float4 colors_0 : COLOR0,\n");
+ WRITE(p, " in float4 colors_1 : COLOR1");
- // compute window position if needed because binding semantic WPOS is not widely supported
- if (numTexgen < 7)
- {
- for (int i = 0; i < numTexgen; ++i)
- WRITE(p, ",\n in float3 uv%d : TEXCOORD%d", i, i);
- WRITE(p, ",\n in float4 clipPos : TEXCOORD%d", numTexgen);
- if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
- WRITE(p, ",\n in float4 Normal : TEXCOORD%d", numTexgen + 1);
- }
- else
- {
- // wpos is in w of first 4 texcoords
- if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
+ // compute window position if needed because binding semantic WPOS is not widely supported
+ if (numTexgen < 7)
{
- for (int i = 0; i < 8; ++i)
- WRITE(p, ",\n in float4 uv%d : TEXCOORD%d", i, i);
+ for (int i = 0; i < numTexgen; ++i)
+ WRITE(p, ",\n in float3 uv%d : TEXCOORD%d", i, i);
+ WRITE(p, ",\n in float4 clipPos : TEXCOORD%d", numTexgen);
+ if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
+ WRITE(p, ",\n in float4 Normal : TEXCOORD%d", numTexgen + 1);
+ WRITE(p, " ) {\n");
}
else
{
- for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
- WRITE(p, ",\n in float%d uv%d : TEXCOORD%d", i < 4 ? 4 : 3 , i, i);
+ // wpos is in w of first 4 texcoords
+ if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
+ {
+ for (int i = 0; i < 8; ++i)
+ WRITE(p, ",\n in float4 uv%d : TEXCOORD%d", i, i);
+ }
+ else
+ {
+ for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
+ WRITE(p, ",\n in float%d uv%d : TEXCOORD%d", i < 4 ? 4 : 3 , i, i);
+ }
+ WRITE(p, " ) {\n");
+ WRITE(p, "\tfloat4 clipPos = float4(0.0f, 0.0f, 0.0f, 0.0f);");
}
}
- WRITE(p, " ) {\n");
WRITE(p, " float4 c0 = " I_COLORS"[1], c1 = " I_COLORS"[2], c2 = " I_COLORS"[3], prev = float4(0.0f, 0.0f, 0.0f, 0.0f), textemp = float4(0.0f, 0.0f, 0.0f, 0.0f), rastemp = float4(0.0f, 0.0f, 0.0f, 0.0f), konsttemp = float4(0.0f, 0.0f, 0.0f, 0.0f);\n"
" float3 comp16 = float3(1.0f, 255.0f, 0.0f), comp24 = float3(1.0f, 255.0f, 255.0f*255.0f);\n"
- " float4 alphabump=float4(0.0f,0.0f,0.0f,0.0f);\n"
+ " float alphabump=0.0f;\n"
" float3 tevcoord=float3(0.0f, 0.0f, 0.0f);\n"
" float2 wrappedcoord=float2(0.0f,0.0f), tempcoord=float2(0.0f,0.0f);\n"
" float4 cc0=float4(0.0f,0.0f,0.0f,0.0f), cc1=float4(0.0f,0.0f,0.0f,0.0f);\n"
" float4 cc2=float4(0.0f,0.0f,0.0f,0.0f), cprev=float4(0.0f,0.0f,0.0f,0.0f);\n"
" float4 crastemp=float4(0.0f,0.0f,0.0f,0.0f),ckonsttemp=float4(0.0f,0.0f,0.0f,0.0f);\n\n");
- if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
+ if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
{
if (xfregs.numTexGen.numTexGens < 7)
{
- WRITE(p,"float3 _norm0 = normalize(Normal.xyz);\n\n");
- WRITE(p,"float3 pos = float3(clipPos.x,clipPos.y,Normal.w);\n");
+ WRITE(p,"\tfloat3 _norm0 = normalize(Normal.xyz);\n\n");
+ WRITE(p,"\tfloat3 pos = float3(clipPos.x,clipPos.y,Normal.w);\n");
}
else
{
- WRITE(p," float3 _norm0 = normalize(float3(uv4.w,uv5.w,uv6.w));\n\n");
- WRITE(p,"float3 pos = float3(uv0.w,uv1.w,uv7.w);\n");
+ WRITE(p,"\tfloat3 _norm0 = normalize(float3(uv4.w,uv5.w,uv6.w));\n\n");
+ WRITE(p,"\tfloat3 pos = float3(uv0.w,uv1.w,uv7.w);\n");
}
- WRITE(p, "float4 mat, lacc;\n"
- "float3 ldir, h;\n"
- "float dist, dist2, attn;\n");
+ WRITE(p, "\tfloat4 mat, lacc;\n"
+ "\tfloat3 ldir, h;\n"
+ "\tfloat dist, dist2, attn;\n");
p = GenerateLightingShader(p, components, I_PMATERIALS, I_PLIGHTS, "colors_", "colors_");
}
if (numTexgen < 7)
- WRITE(p, "clipPos = float4(rawpos.x, rawpos.y, clipPos.z, clipPos.w);\n");
+ WRITE(p, "\tclipPos = float4(rawpos.x, rawpos.y, clipPos.z, clipPos.w);\n");
else
- WRITE(p, "float4 clipPos = float4(rawpos.x, rawpos.y, uv2.w, uv3.w);\n");
+ WRITE(p, "\tclipPos = float4(rawpos.x, rawpos.y, uv2.w, uv3.w);\n");
// HACK to handle cases where the tex gen is not enabled
if (numTexgen == 0)
{
- WRITE(p, "float3 uv0 = float3(0.0f, 0.0f, 0.0f);\n");
+ WRITE(p, "\tfloat3 uv0 = float3(0.0f, 0.0f, 0.0f);\n");
}
else
{
@@ -647,8 +746,8 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
// optional perspective divides
if (xfregs.texMtxInfo[i].projection == XF_TEXPROJ_STQ)
{
- WRITE(p, "if (uv%d.z)", i);
- WRITE(p, " uv%d.xy = uv%d.xy / uv%d.z;\n", i, i, i);
+ WRITE(p, "\tif (uv%d.z != 0.0f)", i);
+ WRITE(p, "\t\tuv%d.xy = uv%d.xy / uv%d.z;\n", i, i, i);
}
WRITE(p, "uv%d.xy = uv%d.xy * " I_TEXDIMS"[%d].zw;\n", i, i, i);
@@ -656,16 +755,16 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
}
// indirect texture map lookup
- for(u32 i = 0; i < bpmem.genMode.numindstages; ++i)
+ for (u32 i = 0; i < bpmem.genMode.numindstages; ++i)
{
if (nIndirectStagesUsed & (1<<i))
{
int texcoord = bpmem.tevindref.getTexCoord(i);
if (texcoord < numTexgen)
- WRITE(p, "tempcoord = uv%d.xy * " I_INDTEXSCALE"[%d].%s;\n", texcoord, i/2, (i&1)?"zw":"xy");
+ WRITE(p, "\ttempcoord = uv%d.xy * " I_INDTEXSCALE"[%d].%s;\n", texcoord, i/2, (i&1)?"zw":"xy");
else
- WRITE(p, "tempcoord = float2(0.0f, 0.0f);\n");
+ WRITE(p, "\ttempcoord = float2(0.0f, 0.0f);\n");
char buffer[32];
sprintf(buffer, "float3 indtex%d", i);
@@ -686,36 +785,42 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
for (int i = 0; i < numStages; i++)
WriteStage(p, i, ApiType); //build the equation for this stage
- if(numStages)
+ if (numStages)
{
// The results of the last texenv stage are put onto the screen,
// regardless of the used destination register
if(bpmem.combiners[numStages - 1].colorC.dest != 0)
{
bool retrieveFromAuxRegister = !RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].ColorNeedOverflowControl && RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].AuxStored;
- WRITE(p, "prev.rgb = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevCOutputTable[bpmem.combiners[numStages - 1].colorC.dest]);
+ WRITE(p, "\tprev.rgb = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevCOutputTable[bpmem.combiners[numStages - 1].colorC.dest]);
RegisterStates[0].ColorNeedOverflowControl = RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].ColorNeedOverflowControl;
}
if(bpmem.combiners[numStages - 1].alphaC.dest != 0)
{
bool retrieveFromAuxRegister = !RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AlphaNeedOverflowControl && RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AuxStored;
- WRITE(p, "prev.a = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevAOutputTable[bpmem.combiners[numStages - 1].alphaC.dest]);
+ WRITE(p, "\tprev.a = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevAOutputTable[bpmem.combiners[numStages - 1].alphaC.dest]);
RegisterStates[0].AlphaNeedOverflowControl = RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AlphaNeedOverflowControl;
}
}
// emulation of unsigned 8 overflow when casting if needed
if(RegisterStates[0].AlphaNeedOverflowControl || RegisterStates[0].ColorNeedOverflowControl)
- WRITE(p, "prev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
+ WRITE(p, "\tprev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
AlphaTest::TEST_RESULT Pretest = bpmem.alpha_test.TestResult();
if (Pretest == AlphaTest::UNDETERMINED)
- WriteAlphaTest(p, ApiType, dstAlphaMode);
+ WriteAlphaTest(p, ApiType, dstAlphaMode, per_pixel_depth);
+
// the screen space depth value = far z + (clip z / clip w) * z range
- WRITE(p, "float zCoord = " I_ZBIAS"[1].x + (clipPos.z / clipPos.w) * " I_ZBIAS"[1].y;\n");
+ if(ApiType == API_OPENGL || ApiType == API_D3D11)
+ WRITE(p, "float zCoord = rawpos.z;\n");
+ else
+ // dx9 doesn't support 4 component position, so we have to calculate it again
+ WRITE(p, "float zCoord = " I_ZBIAS"[1].x + (clipPos.z / clipPos.w) * " I_ZBIAS"[1].y;\n");
- // Note: depth textures are disabled if early depth test is enabled
- if (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.early_ztest && bpmem.zmode.testenable)
+ // depth texture can safely be ignored if the result won't be written to the depth buffer (early_ztest) and isn't used for fog either
+ bool skip_ztexture = !per_pixel_depth && !bpmem.fog.c_proj_fsel.fsel;
+ if (bpmem.ztex2.op != ZTEXTURE_DISABLE && !skip_ztexture)
{
// use the texture input of the last texture stage (textemp), hopefully this has been read and is in correct format...
WRITE(p, "zCoord = dot(" I_ZBIAS"[0].xyzw, textemp.xyzw) + " I_ZBIAS"[1].w %s;\n",
@@ -725,15 +830,18 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
WRITE(p, "zCoord = zCoord * (16777215.0f/16777216.0f);\n");
WRITE(p, "zCoord = frac(zCoord);\n");
WRITE(p, "zCoord = zCoord * (16777216.0f/16777215.0f);\n");
+
+ // Note: depth texture out put is only written to depth buffer if late depth test is used
+ if (per_pixel_depth)
+ WRITE(p, "depth = zCoord;\n");
}
- WRITE(p, "depth = zCoord;\n");
if (dstAlphaMode == DSTALPHA_ALPHA_PASS)
- WRITE(p, " ocol0 = float4(prev.rgb, " I_ALPHA"[0].a);\n");
+ WRITE(p, "\tocol0 = float4(prev.rgb, " I_ALPHA"[0].a);\n");
else
{
WriteFog(p);
- WRITE(p, " ocol0 = prev;\n");
+ WRITE(p, "\tocol0 = prev;\n");
}
// On D3D11, use dual-source color blending to perform dst alpha in a
@@ -741,9 +849,9 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
{
// Colors will be blended against the alpha from ocol1...
- WRITE(p, " ocol1 = ocol0;\n");
+ WRITE(p, "\tocol1 = prev;\n");
// ...and the alpha from ocol0 will be written to the framebuffer.
- WRITE(p, " ocol0.a = " I_ALPHA"[0].a;\n");
+ WRITE(p, "\tocol0.a = " I_ALPHA"[0].a;\n");
}
WRITE(p, "}\n");
@@ -852,10 +960,10 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
WRITE(p, "float2 indtevtrans%d = " I_INDTEXMTX"[%d].ww * uv%d.xy * indtevcrd%d.yy;\n", n, mtxidx, texcoord, n);
}
else
- WRITE(p, "float2 indtevtrans%d = 0;\n", n);
+ WRITE(p, "float2 indtevtrans%d = float2(0.0f, 0.0f);\n", n);
}
else
- WRITE(p, "float2 indtevtrans%d = 0;\n", n);
+ WRITE(p, "float2 indtevtrans%d = float2(0.0f, 0.0f);\n", n);
// ---------
// Wrapping
@@ -901,10 +1009,10 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
if (bpmem.tevorders[n/2].getEnable(n&1))
{
- if(!bHasIndStage)
+ if (!bHasIndStage)
{
// calc tevcord
- if(bHasTexCoord)
+ if (bHasTexCoord)
WRITE(p, "tevcoord.xy = uv%d.xy;\n", texcoord);
else
WRITE(p, "tevcoord.xy = float2(0.0f, 0.0f);\n");
@@ -924,7 +1032,7 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
int kc = bpmem.tevksel[n / 2].getKC(n & 1);
int ka = bpmem.tevksel[n / 2].getKA(n & 1);
WRITE(p, "konsttemp = float4(%s, %s);\n", tevKSelTableC[kc], tevKSelTableA[ka]);
- if(kc > 7 || ka > 7)
+ if (kc > 7 || ka > 7)
{
WRITE(p, "ckonsttemp = frac(konsttemp * (255.0f/256.0f)) * (256.0f/255.0f);\n");
}
@@ -1023,7 +1131,7 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
if (cc.shift > TEVSCALE_1)
WRITE(p, "%s*(", tevScaleTable[cc.shift]);
- if(!(cc.d == TEVCOLORARG_ZERO && cc.op == TEVOP_ADD))
+ if (!(cc.d == TEVCOLORARG_ZERO && cc.op == TEVOP_ADD))
WRITE(p, "%s%s", tevCInputTable[cc.d], tevOpTable[cc.op]);
if (cc.a == cc.b)
@@ -1073,7 +1181,7 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
if (ac.shift > TEVSCALE_1)
WRITE(p, "%s*(", tevScaleTable[ac.shift]);
- if(!(ac.d == TEVALPHAARG_ZERO && ac.op == TEVOP_ADD))
+ if (!(ac.d == TEVALPHAARG_ZERO && ac.op == TEVOP_ADD))
WRITE(p, "%s.a%s", tevAInputTable[ac.d], tevOpTable[ac.op]);
if (ac.a == ac.b)
@@ -1089,7 +1197,7 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
WRITE(p, "%s",tevBiasTable[ac.bias]);
- if (ac.shift>0)
+ if (ac.shift > 0)
WRITE(p, ")");
}
@@ -1114,7 +1222,7 @@ void SampleTexture(char *&p, const char *destination, const char *texcoords, con
if (ApiType == API_D3D11)
WRITE(p, "%s=Tex%d.Sample(samp%d,%s.xy * " I_TEXDIMS"[%d].xy).%s;\n", destination, texmap,texmap, texcoords, texmap, texswap);
else
- WRITE(p, "%s=tex2D(samp%d,%s.xy * " I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap);
+ WRITE(p, "%s=%s(samp%d,%s.xy * " I_TEXDIMS"[%d].xy).%s;\n", destination, ApiType == API_OPENGL ? "texture" : "tex2D", texmap, texcoords, texmap, texswap);
}
static const char *tevAlphaFuncsTable[] =
@@ -1137,7 +1245,7 @@ static const char *tevAlphaFunclogicTable[] =
" == " // xnor
};
-static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode)
+static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode, bool per_pixel_depth)
{
static const char *alphaRef[2] =
{
@@ -1145,8 +1253,9 @@ static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode
I_ALPHA"[0].g"
};
+
// using discard then return works the same in cg and dx9 but not in dx11
- WRITE(p, "if(!( ");
+ WRITE(p, "\tif(!( ");
int compindex = bpmem.alpha_test.comp0;
WRITE(p, tevAlphaFuncsTable[compindex],alphaRef[0]);//lookup the first component from the alpha function table
@@ -1157,10 +1266,11 @@ static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode
WRITE(p, tevAlphaFuncsTable[compindex],alphaRef[1]);//lookup the second component from the alpha function table
WRITE(p, ")) {\n");
- WRITE(p, "ocol0 = 0;\n");
+ WRITE(p, "\t\tocol0 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
- WRITE(p, "ocol1 = 0;\n");
- WRITE(p, "depth = 1.f;\n");
+ WRITE(p, "\t\tocol1 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
+ if(per_pixel_depth)
+ WRITE(p, "depth = 1.f;\n");
// HAXX: zcomploc (aka early_ztest) is a way to control whether depth test is done before
// or after texturing and alpha test. PC GPUs have no way to support this
@@ -1174,9 +1284,9 @@ static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode
// we don't have a choice.
if (!(bpmem.zcontrol.early_ztest && bpmem.zmode.updateenable))
{
- WRITE(p, "discard;\n");
+ WRITE(p, "\t\tdiscard;\n");
if (ApiType != API_D3D11)
- WRITE(p, "return;\n");
+ WRITE(p, "\t\treturn;\n");
}
WRITE(p, "}\n");
@@ -1188,52 +1298,51 @@ static const char *tevFogFuncsTable[] =
"", //?
"", //Linear
"", //?
- " fog = 1.0f - pow(2.0f, -8.0f * fog);\n", //exp
- " fog = 1.0f - pow(2.0f, -8.0f * fog * fog);\n", //exp2
- " fog = pow(2.0f, -8.0f * (1.0f - fog));\n", //backward exp
- " fog = 1.0f - fog;\n fog = pow(2.0f, -8.0f * fog * fog);\n" //backward exp2
+ "\tfog = 1.0f - pow(2.0f, -8.0f * fog);\n", //exp
+ "\tfog = 1.0f - pow(2.0f, -8.0f * fog * fog);\n", //exp2
+ "\tfog = pow(2.0f, -8.0f * (1.0f - fog));\n", //backward exp
+ "\tfog = 1.0f - fog;\n fog = pow(2.0f, -8.0f * fog * fog);\n" //backward exp2
};
static void WriteFog(char *&p)
{
- if(bpmem.fog.c_proj_fsel.fsel == 0)return;//no Fog
+ if (bpmem.fog.c_proj_fsel.fsel == 0)
+ return; // no Fog
if (bpmem.fog.c_proj_fsel.proj == 0)
{
// perspective
// ze = A/(B - (Zs >> B_SHF)
- WRITE (p, " float ze = " I_FOG"[1].x / (" I_FOG"[1].y - (zCoord / " I_FOG"[1].w));\n");
+ WRITE (p, "\tfloat ze = " I_FOG"[1].x / (" I_FOG"[1].y - (zCoord / " I_FOG"[1].w));\n");
}
else
{
// orthographic
// ze = a*Zs (here, no B_SHF)
- WRITE (p, " float ze = " I_FOG"[1].x * zCoord;\n");
+ WRITE (p, "\tfloat ze = " I_FOG"[1].x * zCoord;\n");
}
// x_adjust = sqrt((x-center)^2 + k^2)/k
// ze *= x_adjust
//this is complitly teorical as the real hard seems to use a table intead of calculate the values.
- if(bpmem.fogRange.Base.Enabled)
+ if (bpmem.fogRange.Base.Enabled)
{
- WRITE (p, " float x_adjust = (2.0f * (clipPos.x / " I_FOG"[2].y)) - 1.0f - " I_FOG"[2].x;\n");
- WRITE (p, " x_adjust = sqrt(x_adjust * x_adjust + " I_FOG"[2].z * " I_FOG"[2].z) / " I_FOG"[2].z;\n");
- WRITE (p, " ze *= x_adjust;\n");
+ WRITE (p, "\tfloat x_adjust = (2.0f * (clipPos.x / " I_FOG"[2].y)) - 1.0f - " I_FOG"[2].x;\n");
+ WRITE (p, "\tx_adjust = sqrt(x_adjust * x_adjust + " I_FOG"[2].z * " I_FOG"[2].z) / " I_FOG"[2].z;\n");
+ WRITE (p, "\tze *= x_adjust;\n");
}
- WRITE (p, " float fog = saturate(ze - " I_FOG"[1].z);\n");
+ WRITE (p, "\tfloat fog = saturate(ze - " I_FOG"[1].z);\n");
- if(bpmem.fog.c_proj_fsel.fsel > 3)
+ if (bpmem.fog.c_proj_fsel.fsel > 3)
{
WRITE(p, "%s", tevFogFuncsTable[bpmem.fog.c_proj_fsel.fsel]);
}
else
{
- if(bpmem.fog.c_proj_fsel.fsel != 2)
+ if (bpmem.fog.c_proj_fsel.fsel != 2)
WARN_LOG(VIDEO, "Unknown Fog Type! %08x", bpmem.fog.c_proj_fsel.fsel);
}
- WRITE(p, " prev.rgb = lerp(prev.rgb," I_FOG"[0].rgb,fog);\n");
-
-
+ WRITE(p, "\tprev.rgb = lerp(prev.rgb, " I_FOG"[0].rgb, fog);\n");
}
diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.h b/Source/Core/VideoCommon/Src/PixelShaderGen.h
index 9c8bfce256..7896bc93e0 100644
--- a/Source/Core/VideoCommon/Src/PixelShaderGen.h
+++ b/Source/Core/VideoCommon/Src/PixelShaderGen.h
@@ -28,8 +28,8 @@
#define I_INDTEXSCALE "cindscale"
#define I_INDTEXMTX "cindmtx"
#define I_FOG "cfog"
-#define I_PLIGHTS "cLights"
-#define I_PMATERIALS "cmtrl"
+#define I_PLIGHTS "cPLights"
+#define I_PMATERIALS "cPmtrl"
#define C_COLORMATRIX 0 // 0
#define C_COLORS 0 // 0
@@ -47,6 +47,19 @@
#define PIXELSHADERUID_MAX_VALUES 70
#define PIXELSHADERUID_MAX_VALUES_SAFE 115
+// Annoying sure, can be removed once we get up to GLSL ~1.3
+const s_svar PSVar_Loc[] = { {I_COLORS, C_COLORS, 4 },
+ {I_KCOLORS, C_KCOLORS, 4 },
+ {I_ALPHA, C_ALPHA, 1 },
+ {I_TEXDIMS, C_TEXDIMS, 8 },
+ {I_ZBIAS , C_ZBIAS, 2 },
+ {I_INDTEXSCALE , C_INDTEXSCALE, 2 },
+ {I_INDTEXMTX, C_INDTEXMTX, 6 },
+ {I_FOG, C_FOG, 3 },
+ {I_PLIGHTS, C_PLIGHTS, 40 },
+ {I_PMATERIALS, C_PMATERIALS, 4 },
+ };
+
// DO NOT make anything in this class virtual.
template<bool safe>
class _PIXELSHADERUID
diff --git a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp
index eaaf99fbc8..ad84f6876e 100644
--- a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp
+++ b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp
@@ -85,61 +85,63 @@ void PixelShaderManager::Shutdown()
void PixelShaderManager::SetConstants()
{
- for (int i = 0; i < 2; ++i)
+ if (g_ActiveConfig.backend_info.APIType == API_OPENGL && !g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ Dirty();
+ for (int i = 0; i < 2; ++i)
{
- if (s_nColorsChanged[i])
+ if (s_nColorsChanged[i])
{
- int baseind = i ? C_KCOLORS : C_COLORS;
- for (int j = 0; j < 4; ++j)
+ int baseind = i ? C_KCOLORS : C_COLORS;
+ for (int j = 0; j < 4; ++j)
{
- if (s_nColorsChanged[i] & (1 << j))
- SetPSConstant4fv(baseind+j, &lastRGBAfull[i][j][0]);
- }
- s_nColorsChanged[i] = 0;
- }
- }
-
- if (s_nTexDimsChanged)
+ if (s_nColorsChanged[i] & (1 << j))
+ SetPSConstant4fv(baseind+j, &lastRGBAfull[i][j][0]);
+ }
+ s_nColorsChanged[i] = 0;
+ }
+ }
+
+ if (s_nTexDimsChanged)
{
- for (int i = 0; i < 8; ++i)
+ for (int i = 0; i < 8; ++i)
{
- if (s_nTexDimsChanged & (1<<i))
+ if (s_nTexDimsChanged & (1<<i))
SetPSTextureDims(i);
- }
- s_nTexDimsChanged = 0;
- }
+ }
+ s_nTexDimsChanged = 0;
+ }
- if (s_bAlphaChanged)
+ if (s_bAlphaChanged)
{
SetPSConstant4f(C_ALPHA, (lastAlpha&0xff)/255.0f, ((lastAlpha>>8)&0xff)/255.0f, 0, ((lastAlpha>>16)&0xff)/255.0f);
s_bAlphaChanged = false;
- }
+ }
if (s_bZTextureTypeChanged)
{
- float ftemp[4];
- switch (bpmem.ztex2.type)
+ float ftemp[4];
+ switch (bpmem.ztex2.type)
{
- case 0:
- // 8 bits
- ftemp[0] = 0; ftemp[1] = 0; ftemp[2] = 0; ftemp[3] = 255.0f/16777215.0f;
- break;
- case 1:
- // 16 bits
- ftemp[0] = 255.0f/16777215.0f; ftemp[1] = 0; ftemp[2] = 0; ftemp[3] = 65280.0f/16777215.0f;
- break;
- case 2:
- // 24 bits
+ case 0:
+ // 8 bits
+ ftemp[0] = 0; ftemp[1] = 0; ftemp[2] = 0; ftemp[3] = 255.0f/16777215.0f;
+ break;
+ case 1:
+ // 16 bits
+ ftemp[0] = 255.0f/16777215.0f; ftemp[1] = 0; ftemp[2] = 0; ftemp[3] = 65280.0f/16777215.0f;
+ break;
+ case 2:
+ // 24 bits
ftemp[0] = 16711680.0f/16777215.0f; ftemp[1] = 65280.0f/16777215.0f; ftemp[2] = 255.0f/16777215.0f; ftemp[3] = 0;
- break;
- }
+ break;
+ }
SetPSConstant4fv(C_ZBIAS, ftemp);
s_bZTextureTypeChanged = false;
}
if (s_bZBiasChanged || s_bDepthRangeChanged)
{
- // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
+ // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
// [0] = width/2
// [1] = height/2
// [2] = 16777215 * (farz - nearz)
@@ -150,78 +152,78 @@ void PixelShaderManager::SetConstants()
//ERROR_LOG("pixel=%x,%x, bias=%x\n", bpmem.zcontrol.pixel_format, bpmem.ztex2.type, lastZBias);
SetPSConstant4f(C_ZBIAS+1, xfregs.viewport.farZ / 16777216.0f, xfregs.viewport.zRange / 16777216.0f, 0, (float)(lastZBias)/16777215.0f);
s_bZBiasChanged = s_bDepthRangeChanged = false;
- }
+ }
- // indirect incoming texture scales
- if (s_nIndTexScaleChanged)
+ // indirect incoming texture scales
+ if (s_nIndTexScaleChanged)
{
// set as two sets of vec4s, each containing S and T of two ind stages.
- float f[8];
+ float f[8];
- if (s_nIndTexScaleChanged & 0x03)
+ if (s_nIndTexScaleChanged & 0x03)
{
- for (u32 i = 0; i < 2; ++i)
+ for (u32 i = 0; i < 2; ++i)
{
- f[2 * i] = bpmem.texscale[0].getScaleS(i & 1);
- f[2 * i + 1] = bpmem.texscale[0].getScaleT(i & 1);
- PRIM_LOG("tex indscale%d: %f %f\n", i, f[2 * i], f[2 * i + 1]);
- }
+ f[2 * i] = bpmem.texscale[0].getScaleS(i & 1);
+ f[2 * i + 1] = bpmem.texscale[0].getScaleT(i & 1);
+ PRIM_LOG("tex indscale%d: %f %f\n", i, f[2 * i], f[2 * i + 1]);
+ }
SetPSConstant4fv(C_INDTEXSCALE, f);
- }
-
- if (s_nIndTexScaleChanged & 0x0c) {
- for (u32 i = 2; i < 4; ++i) {
- f[2 * i] = bpmem.texscale[1].getScaleS(i & 1);
- f[2 * i + 1] = bpmem.texscale[1].getScaleT(i & 1);
- PRIM_LOG("tex indscale%d: %f %f\n", i, f[2 * i], f[2 * i + 1]);
- }
+ }
+
+ if (s_nIndTexScaleChanged & 0x0c) {
+ for (u32 i = 2; i < 4; ++i) {
+ f[2 * i] = bpmem.texscale[1].getScaleS(i & 1);
+ f[2 * i + 1] = bpmem.texscale[1].getScaleT(i & 1);
+ PRIM_LOG("tex indscale%d: %f %f\n", i, f[2 * i], f[2 * i + 1]);
+ }
SetPSConstant4fv(C_INDTEXSCALE+1, &f[4]);
- }
+ }
- s_nIndTexScaleChanged = 0;
- }
+ s_nIndTexScaleChanged = 0;
+ }
- if (s_nIndTexMtxChanged)
+ if (s_nIndTexMtxChanged)
{
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 3; ++i)
{
- if (s_nIndTexMtxChanged & (1 << i))
+ if (s_nIndTexMtxChanged & (1 << i))
{
- int scale = ((u32)bpmem.indmtx[i].col0.s0 << 0) |
- ((u32)bpmem.indmtx[i].col1.s1 << 2) |
- ((u32)bpmem.indmtx[i].col2.s2 << 4);
- float fscale = powf(2.0f, (float)(scale - 17)) / 1024.0f;
-
- // xyz - static matrix
- // TODO w - dynamic matrix scale / 256...... somehow / 4 works better
- // rev 2972 - now using / 256.... verify that this works
+ int scale = ((u32)bpmem.indmtx[i].col0.s0 << 0) |
+ ((u32)bpmem.indmtx[i].col1.s1 << 2) |
+ ((u32)bpmem.indmtx[i].col2.s2 << 4);
+ float fscale = powf(2.0f, (float)(scale - 17)) / 1024.0f;
+
+ // xyz - static matrix
+ // TODO w - dynamic matrix scale / 256...... somehow / 4 works better
+ // rev 2972 - now using / 256.... verify that this works
SetPSConstant4f(C_INDTEXMTX + 2 * i,
- bpmem.indmtx[i].col0.ma * fscale,
+ bpmem.indmtx[i].col0.ma * fscale,
bpmem.indmtx[i].col1.mc * fscale,
bpmem.indmtx[i].col2.me * fscale,
fscale * 4.0f);
- SetPSConstant4f(C_INDTEXMTX + 2 * i + 1,
- bpmem.indmtx[i].col0.mb * fscale,
+ SetPSConstant4f(C_INDTEXMTX + 2 * i + 1,
+ bpmem.indmtx[i].col0.mb * fscale,
bpmem.indmtx[i].col1.md * fscale,
bpmem.indmtx[i].col2.mf * fscale,
fscale * 4.0f);
- PRIM_LOG("indmtx%d: scale=%f, mat=(%f %f %f; %f %f %f)\n",
- i, 1024.0f*fscale,
- bpmem.indmtx[i].col0.ma * fscale, bpmem.indmtx[i].col1.mc * fscale, bpmem.indmtx[i].col2.me * fscale,
- bpmem.indmtx[i].col0.mb * fscale, bpmem.indmtx[i].col1.md * fscale, bpmem.indmtx[i].col2.mf * fscale);
- }
- }
- s_nIndTexMtxChanged = 0;
- }
+ PRIM_LOG("indmtx%d: scale=%f, mat=(%f %f %f; %f %f %f)\n",
+ i, 1024.0f*fscale,
+ bpmem.indmtx[i].col0.ma * fscale, bpmem.indmtx[i].col1.mc * fscale, bpmem.indmtx[i].col2.me * fscale,
+ bpmem.indmtx[i].col0.mb * fscale, bpmem.indmtx[i].col1.md * fscale, bpmem.indmtx[i].col2.mf * fscale);
+ }
+ }
+ s_nIndTexMtxChanged = 0;
+ }
- if (s_bFogColorChanged)
+ if (s_bFogColorChanged)
{
SetPSConstant4f(C_FOG, bpmem.fog.color.r / 255.0f, bpmem.fog.color.g / 255.0f, bpmem.fog.color.b / 255.0f, 0);
s_bFogColorChanged = false;
- }
+ }
- if (s_bFogParamChanged)
+ if (s_bFogParamChanged)
{
if(!g_ActiveConfig.bDisableFog)
{
@@ -234,8 +236,8 @@ void PixelShaderManager::SetConstants()
else
SetPSConstant4f(C_FOG + 1, 0.0, 1.0, 0.0, 1.0);
- s_bFogParamChanged = false;
- }
+ s_bFogParamChanged = false;
+ }
if (s_bFogRangeAdjustChanged)
{
@@ -339,11 +341,11 @@ void PixelShaderManager::SetConstants()
void PixelShaderManager::SetPSTextureDims(int texid)
{
- // texdims.xy are reciprocals of the real texture dimensions
- // texdims.zw are the scaled dimensions
- float fdims[4];
+ // texdims.xy are reciprocals of the real texture dimensions
+ // texdims.zw are the scaled dimensions
+ float fdims[4];
- TCoordInfo& tc = bpmem.texcoords[texid];
+ TCoordInfo& tc = bpmem.texcoords[texid];
fdims[0] = 1.0f / (float)(lastTexDims[texid] & 0xffff);
fdims[1] = 1.0f / (float)((lastTexDims[texid] >> 16) & 0xfff);
fdims[2] = (float)(tc.s.scale_minus_1 + 1);
@@ -357,7 +359,7 @@ void PixelShaderManager::SetPSTextureDims(int texid)
// and update it when the shader constant is set, only.
void PixelShaderManager::SetColorChanged(int type, int num, bool high)
{
- float *pf = &lastRGBAfull[type][num][0];
+ float *pf = &lastRGBAfull[type][num][0];
if (!high) {
int r = bpmem.tevregs[num].low.a;
int a = bpmem.tevregs[num].low.b;
@@ -369,60 +371,61 @@ void PixelShaderManager::SetColorChanged(int type, int num, bool high)
pf[1] = (float)g * (1.0f / 255.0f);
pf[2] = (float)b * (1.0f / 255.0f);
}
- s_nColorsChanged[type] |= 1 << num;
- PRIM_LOG("pixel %scolor%d: %f %f %f %f\n", type?"k":"", num, pf[0], pf[1], pf[2], pf[3]);
+ s_nColorsChanged[type] |= 1 << num;
+ PRIM_LOG("pixel %scolor%d: %f %f %f %f\n", type?"k":"", num, pf[0], pf[1], pf[2], pf[3]);
}
void PixelShaderManager::SetAlpha(const AlphaTest& alpha)
{
- if ((alpha.hex & 0xffff) != lastAlpha)
+ if ((alpha.hex & 0xffff) != lastAlpha)
{
- lastAlpha = (lastAlpha & ~0xffff) | (alpha.hex & 0xffff);
- s_bAlphaChanged = true;
- }
+ lastAlpha = (lastAlpha & ~0xffff) | (alpha.hex & 0xffff);
+ s_bAlphaChanged = true;
+ }
}
void PixelShaderManager::SetDestAlpha(const ConstantAlpha& alpha)
{
- if (alpha.alpha != (lastAlpha >> 16))
+ if (alpha.alpha != (lastAlpha >> 16))
{
- lastAlpha = (lastAlpha & ~0xff0000) | ((alpha.hex & 0xff) << 16);
- s_bAlphaChanged = true;
- }
+ lastAlpha = (lastAlpha & ~0xff0000) | ((alpha.hex & 0xff) << 16);
+ s_bAlphaChanged = true;
+ }
}
void PixelShaderManager::SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt)
{
- u32 wh = width | (height << 16) | (wraps << 28) | (wrapt << 30);
- if (lastTexDims[texmapid] != wh)
+ u32 wh = width | (height << 16) | (wraps << 28) | (wrapt << 30);
+ if (lastTexDims[texmapid] != wh)
{
- lastTexDims[texmapid] = wh;
+ lastTexDims[texmapid] = wh;
s_nTexDimsChanged |= 1 << texmapid;
- }
+ }
}
void PixelShaderManager::SetZTextureBias(u32 bias)
{
- if (lastZBias != bias)
+ if (lastZBias != bias)
{
- s_bZBiasChanged = true;
- lastZBias = bias;
- }
+ s_bZBiasChanged = true;
+ lastZBias = bias;
+ }
}
void PixelShaderManager::SetViewportChanged()
{
s_bDepthRangeChanged = true;
+ s_bFogRangeAdjustChanged = true; // TODO: Shouldn't be necessary with an accurate fog range adjust implementation
}
void PixelShaderManager::SetIndTexScaleChanged(u8 stagemask)
{
- s_nIndTexScaleChanged |= stagemask;
+ s_nIndTexScaleChanged |= stagemask;
}
void PixelShaderManager::SetIndMatrixChanged(int matrixidx)
{
- s_nIndTexMtxChanged |= 1 << matrixidx;
+ s_nIndTexMtxChanged |= 1 << matrixidx;
}
void PixelShaderManager::SetZTextureTypeChanged()
@@ -432,22 +435,22 @@ void PixelShaderManager::SetZTextureTypeChanged()
void PixelShaderManager::SetTexCoordChanged(u8 texmapid)
{
- s_nTexDimsChanged |= 1 << texmapid;
+ s_nTexDimsChanged |= 1 << texmapid;
}
void PixelShaderManager::SetFogColorChanged()
{
- s_bFogColorChanged = true;
+ s_bFogColorChanged = true;
}
void PixelShaderManager::SetFogParamChanged()
{
- s_bFogParamChanged = true;
+ s_bFogParamChanged = true;
}
void PixelShaderManager::SetFogRangeAdjustChanged()
{
- s_bFogRangeAdjustChanged = true;
+ s_bFogRangeAdjustChanged = true;
}
void PixelShaderManager::SetColorMatrix(const float* pmatrix)
diff --git a/Source/Core/VideoCommon/Src/PixelShaderManager.h b/Source/Core/VideoCommon/Src/PixelShaderManager.h
index 12d749c871..8e663653f8 100644
--- a/Source/Core/VideoCommon/Src/PixelShaderManager.h
+++ b/Source/Core/VideoCommon/Src/PixelShaderManager.h
@@ -54,7 +54,6 @@ public:
static void SetColorMatrix(const float* pmatrix);
static void InvalidateXFRange(int start, int end);
static void SetMaterialColorChanged(int index);
-
};
diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp
index 8e1d012fa2..90a09aec43 100644
--- a/Source/Core/VideoCommon/Src/RenderBase.cpp
+++ b/Source/Core/VideoCommon/Src/RenderBase.cpp
@@ -83,7 +83,9 @@ unsigned int Renderer::efb_scale_denominatorY = 1;
unsigned int Renderer::ssaa_multiplier = 1;
-Renderer::Renderer() : frame_data(NULL), bLastFrameDumped(false)
+Renderer::Renderer()
+ : frame_data()
+ , bLastFrameDumped(false)
{
UpdateActiveConfig();
TextureCache::OnConfigChanged(g_ActiveConfig);
@@ -110,7 +112,6 @@ Renderer::~Renderer()
if (pFrameDump.IsOpen())
pFrameDump.Close();
#endif
- delete[] frame_data;
}
void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma)
diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h
index 5376577cbd..55678f3f5a 100644
--- a/Source/Core/VideoCommon/Src/RenderBase.h
+++ b/Source/Core/VideoCommon/Src/RenderBase.h
@@ -52,6 +52,15 @@ public:
Renderer();
virtual ~Renderer();
+ enum PixelPerfQuery {
+ PP_ZCOMP_INPUT_ZCOMPLOC,
+ PP_ZCOMP_OUTPUT_ZCOMPLOC,
+ PP_ZCOMP_INPUT,
+ PP_ZCOMP_OUTPUT,
+ PP_BLEND_INPUT,
+ PP_EFB_COPY_CLOCKS
+ };
+
virtual void SetColorMask() = 0;
virtual void SetBlendMode(bool forceUpdate) = 0;
virtual void SetScissorRect(const TargetRectangle& rc) = 0;
@@ -147,7 +156,7 @@ protected:
#else
File::IOFile pFrameDump;
#endif
- char* frame_data;
+ std::vector<u8> frame_data;
bool bLastFrameDumped;
// The framebuffer size
diff --git a/Source/Core/VideoCommon/Src/Statistics.cpp b/Source/Core/VideoCommon/Src/Statistics.cpp
index 202769c55f..5f3240f44e 100644
--- a/Source/Core/VideoCommon/Src/Statistics.cpp
+++ b/Source/Core/VideoCommon/Src/Statistics.cpp
@@ -53,8 +53,8 @@ char *Statistics::ToString(char *ptr)
ptr+=sprintf(ptr,"pshaders (unique, delete cache first): %i\n",stats.numUniquePixelShaders);
ptr+=sprintf(ptr,"vshaders created: %i\n",stats.numVertexShadersCreated);
ptr+=sprintf(ptr,"vshaders alive: %i\n",stats.numVertexShadersAlive);
- ptr+=sprintf(ptr,"dlists called: %i\n",stats.numDListsCalled);
- ptr+=sprintf(ptr,"dlists called(f): %i\n",stats.thisFrame.numDListsCalled);
+ ptr+=sprintf(ptr,"dlists called: %i\n",stats.numDListsCalled);
+ ptr+=sprintf(ptr,"dlists called(f): %i\n",stats.thisFrame.numDListsCalled);
ptr+=sprintf(ptr,"dlists alive: %i\n",stats.numDListsAlive);
ptr+=sprintf(ptr,"primitive joins: %i\n",stats.thisFrame.numPrimitiveJoins);
ptr+=sprintf(ptr,"draw calls: %i\n",stats.thisFrame.numDrawCalls);
diff --git a/Source/Core/VideoCommon/Src/Statistics.h b/Source/Core/VideoCommon/Src/Statistics.h
index e173bfc682..fac7691b35 100644
--- a/Source/Core/VideoCommon/Src/Statistics.h
+++ b/Source/Core/VideoCommon/Src/Statistics.h
@@ -24,20 +24,20 @@
struct Statistics
{
- int numPixelShadersCreated;
- int numPixelShadersAlive;
- int numVertexShadersCreated;
- int numVertexShadersAlive;
+ int numPixelShadersCreated;
+ int numPixelShadersAlive;
+ int numVertexShadersCreated;
+ int numVertexShadersAlive;
- int numTexturesCreated;
- int numTexturesAlive;
+ int numTexturesCreated;
+ int numTexturesAlive;
- int numRenderTargetsCreated;
- int numRenderTargetsAlive;
-
- int numDListsCalled;
- int numDListsCreated;
- int numDListsAlive;
+ int numRenderTargetsCreated;
+ int numRenderTargetsAlive;
+
+ int numDListsCalled;
+ int numDListsCreated;
+ int numDListsAlive;
int numVertexLoaders;
@@ -52,30 +52,30 @@ struct Statistics
std::vector<EFBRectangle> efb_regions;
- struct ThisFrame
- {
- int numBPLoads;
- int numCPLoads;
- int numXFLoads;
-
- int numBPLoadsInDL;
- int numCPLoadsInDL;
- int numXFLoadsInDL;
-
- int numDLs;
- int numPrims;
- int numDLPrims;
- int numShaderChanges;
-
- int numPrimitiveJoins;
- int numDrawCalls;
- int numIndexedDrawCalls;
- int numBufferSplits;
+ struct ThisFrame
+ {
+ int numBPLoads;
+ int numCPLoads;
+ int numXFLoads;
+
+ int numBPLoadsInDL;
+ int numCPLoadsInDL;
+ int numXFLoadsInDL;
+
+ int numDLs;
+ int numPrims;
+ int numDLPrims;
+ int numShaderChanges;
+
+ int numPrimitiveJoins;
+ int numDrawCalls;
+ int numIndexedDrawCalls;
+ int numBufferSplits;
int numDListsCalled;
- };
- ThisFrame thisFrame;
- void ResetFrame();
+ };
+ ThisFrame thisFrame;
+ void ResetFrame();
static void SwapDL();
// Yeah, this is unsafe, but we really don't wanna faff around allocating
diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp
index fda4f21a7e..319c014f22 100644
--- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp
+++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp
@@ -56,7 +56,7 @@ TextureCache::TextureCache()
if (!temp)
temp = (u8*)AllocateAlignedMemory(temp_size, 16);
TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
- if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures)
+ if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures)
HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures);
}
@@ -129,7 +129,10 @@ void TextureCache::Cleanup()
TexCache::iterator tcend = textures.end();
while (iter != tcend)
{
- if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount) // TODO: Deleting EFB copies might not be a good idea here...
+ if ( frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount
+
+ // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted
+ && ! iter->second->IsEfbCopy() )
{
delete iter->second;
textures.erase(iter++);
@@ -722,7 +725,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
case 1: // R8
case 8: // R8
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1;
- cbufid = 13;
+ cbufid = 13;
break;
case 2: // RA4
@@ -743,11 +746,11 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
case 9: // G8
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
- cbufid = 17;
+ cbufid = 17;
break;
case 10: // B8
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
- cbufid = 18;
+ cbufid = 18;
break;
case 11: // RG8
@@ -756,7 +759,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
break;
case 12: // GB8
- colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f;
+ colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f;
cbufid = 20;
break;
@@ -828,9 +831,5 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
entry->frameCount = frameCount;
- g_renderer->ResetAPIState(); // reset any game specific settings
-
entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat);
-
- g_renderer->RestoreAPIState();
}
diff --git a/Source/Core/VideoCommon/Src/TextureConversionShader.cpp b/Source/Core/VideoCommon/Src/TextureConversionShader.cpp
index 2132a25258..5a81c9e7d5 100644
--- a/Source/Core/VideoCommon/Src/TextureConversionShader.cpp
+++ b/Source/Core/VideoCommon/Src/TextureConversionShader.cpp
@@ -26,6 +26,7 @@
#include "PixelShaderGen.h"
#include "BPMemory.h"
#include "RenderBase.h"
+#include "VideoConfig.h"
#define WRITE p+=sprintf
@@ -38,23 +39,23 @@ namespace TextureConversionShader
u16 GetEncodedSampleCount(u32 format)
{
- switch (format) {
- case GX_TF_I4: return 8;
+ switch (format) {
+ case GX_TF_I4: return 8;
case GX_TF_I8: return 4;
case GX_TF_IA4: return 4;
- case GX_TF_IA8: return 2;
+ case GX_TF_IA8: return 2;
case GX_TF_RGB565: return 2;
case GX_TF_RGB5A3: return 2;
case GX_TF_RGBA8: return 1;
case GX_CTF_R4: return 8;
- case GX_CTF_RA4: return 4;
- case GX_CTF_RA8: return 2;
- case GX_CTF_A8: return 4;
- case GX_CTF_R8: return 4;
- case GX_CTF_G8: return 4;
- case GX_CTF_B8: return 4;
- case GX_CTF_RG8: return 2;
- case GX_CTF_GB8: return 2;
+ case GX_CTF_RA4: return 4;
+ case GX_CTF_RA8: return 2;
+ case GX_CTF_A8: return 4;
+ case GX_CTF_R8: return 4;
+ case GX_CTF_G8: return 4;
+ case GX_CTF_B8: return 4;
+ case GX_CTF_RG8: return 2;
+ case GX_CTF_GB8: return 2;
case GX_TF_Z8: return 4;
case GX_TF_Z16: return 2;
case GX_TF_Z24X8: return 1;
@@ -62,23 +63,35 @@ u16 GetEncodedSampleCount(u32 format)
case GX_CTF_Z8M: return 4;
case GX_CTF_Z8L: return 4;
case GX_CTF_Z16L: return 2;
- default: return 1;
- }
+ default: return 1;
+ }
+}
+
+const char* WriteRegister(API_TYPE ApiType, const char *prefix, const u32 num)
+{
+ if (ApiType == API_OPENGL)
+ return ""; // Once we switch to GLSL 1.3 we can do something here
+ static char result[64];
+ sprintf(result, " : register(%s%d)", prefix, num);
+ return result;
}
// block dimensions : widthStride, heightStride
// texture dims : width, height, x offset, y offset
void WriteSwizzler(char*& p, u32 format, API_TYPE ApiType)
{
- WRITE(p, "uniform float4 blkDims : register(c%d);\n", C_COLORMATRIX);
- WRITE(p, "uniform float4 textureDims : register(c%d);\n", C_COLORMATRIX + 1);
+ // [0] left, top, right, bottom of source rectangle within source texture
+ // [1] width and height of destination texture in pixels
+ // Two were merged for GLSL
+ WRITE(p, "uniform float4 " I_COLORS"[2] %s;\n", WriteRegister(ApiType, "c", C_COLORS));
- float blkW = (float)TexDecoder_GetBlockWidthInTexels(format);
+ float blkW = (float)TexDecoder_GetBlockWidthInTexels(format);
float blkH = (float)TexDecoder_GetBlockHeightInTexels(format);
float samples = (float)GetEncodedSampleCount(format);
- if(ApiType == API_OPENGL)
+ if (ApiType == API_OPENGL)
{
- WRITE(p,"uniform samplerRECT samp0 : register(s0);\n");
+ WRITE(p, "#define samp0 samp9\n");
+ WRITE(p, "uniform sampler2DRect samp0;\n");
}
else if (ApiType & API_D3D9)
{
@@ -87,23 +100,31 @@ void WriteSwizzler(char*& p, u32 format, API_TYPE ApiType)
else
{
WRITE(p,"sampler samp0 : register(s0);\n");
- WRITE(p, "Texture2D Tex0 : register(t0);\n");
+ WRITE(p, "Texture2D Tex0 : register(t0);\n");
}
-
- WRITE(p,"void main(\n");
- if(ApiType != API_D3D11)
+ if (ApiType == API_OPENGL)
{
- WRITE(p," out float4 ocol0 : COLOR0,\n");
+ WRITE(p, " out float4 ocol0;\n");
+ WRITE(p, " in float2 uv0;\n");
+ WRITE(p, "void main()\n");
}
else
{
- WRITE(p," out float4 ocol0 : SV_Target,\n");
+ WRITE(p,"void main(\n");
+ if (ApiType != API_D3D11)
+ {
+ WRITE(p," out float4 ocol0 : COLOR0,\n");
+ }
+ else
+ {
+ WRITE(p," out float4 ocol0 : SV_Target,\n");
+ }
+ WRITE(p," in float2 uv0 : TEXCOORD0)\n");
}
-
- WRITE(p," in float2 uv0 : TEXCOORD0)\n"
- "{\n"
- " float2 sampleUv;\n"
+
+ WRITE(p, "{\n"
+ " float2 sampleUv;\n"
" float2 uv1 = floor(uv0);\n");
WRITE(p, " uv1.x = uv1.x * %f;\n", samples);
@@ -113,7 +134,7 @@ void WriteSwizzler(char*& p, u32 format, API_TYPE ApiType)
WRITE(p, " float yl = floor(uv1.y / %f);\n", blkH);
WRITE(p, " float yb = yl * %f;\n", blkH);
WRITE(p, " float yoff = uv1.y - yb;\n");
- WRITE(p, " float xp = uv1.x + (yoff * textureDims.x);\n");
+ WRITE(p, " float xp = uv1.x + (yoff * " I_COLORS"[1].x);\n");
WRITE(p, " float xel = floor(xp / %f);\n", blkW);
WRITE(p, " float xb = floor(xel / %f);\n", blkH);
WRITE(p, " float xoff = xel - (xb * %f);\n", blkH);
@@ -121,34 +142,37 @@ void WriteSwizzler(char*& p, u32 format, API_TYPE ApiType)
WRITE(p, " sampleUv.x = xib + (xb * %f);\n", blkW);
WRITE(p, " sampleUv.y = yb + xoff;\n");
- WRITE(p, " sampleUv = sampleUv * blkDims.xy;\n");
+ WRITE(p, " sampleUv = sampleUv * " I_COLORS"[0].xy;\n");
+
+ if (ApiType == API_OPENGL)
+ WRITE(p," sampleUv.y = " I_COLORS"[1].y - sampleUv.y;\n");
- if(ApiType == API_OPENGL)
- WRITE(p," sampleUv.y = textureDims.y - sampleUv.y;\n");
-
- WRITE(p, " sampleUv = sampleUv + textureDims.zw;\n");
+ WRITE(p, " sampleUv = sampleUv + " I_COLORS"[1].zw;\n");
- if(ApiType != API_OPENGL)
+ if (ApiType != API_OPENGL)
{
WRITE(p, " sampleUv = sampleUv + float2(0.0f,1.0f);\n");// still to determine the reason for this
- WRITE(p, " sampleUv = sampleUv / blkDims.zw;\n");
- }
+ WRITE(p, " sampleUv = sampleUv / " I_COLORS"[0].zw;\n");
+ }
}
// block dimensions : widthStride, heightStride
// texture dims : width, height, x offset, y offset
void Write32BitSwizzler(char*& p, u32 format, API_TYPE ApiType)
-{
- WRITE(p, "uniform float4 blkDims : register(c%d);\n", C_COLORMATRIX);
- WRITE(p, "uniform float4 textureDims : register(c%d);\n", C_COLORMATRIX + 1);
+{
+ // [0] left, top, right, bottom of source rectangle within source texture
+ // [1] width and height of destination texture in pixels
+ // Two were merged for GLSL
+ WRITE(p, "uniform float4 " I_COLORS"[2] %s;\n", WriteRegister(ApiType, "c", C_COLORS));
- float blkW = (float)TexDecoder_GetBlockWidthInTexels(format);
+ float blkW = (float)TexDecoder_GetBlockWidthInTexels(format);
float blkH = (float)TexDecoder_GetBlockHeightInTexels(format);
// 32 bit textures (RGBA8 and Z24) are store in 2 cache line increments
- if(ApiType == API_OPENGL)
+ if (ApiType == API_OPENGL)
{
- WRITE(p,"uniform samplerRECT samp0 : register(s0);\n");
+ WRITE(p, "#define samp0 samp9\n");
+ WRITE(p, "uniform sampler2DRect samp0;\n");
}
else if (ApiType & API_D3D9)
{
@@ -157,53 +181,61 @@ void Write32BitSwizzler(char*& p, u32 format, API_TYPE ApiType)
else
{
WRITE(p,"sampler samp0 : register(s0);\n");
- WRITE(p, "Texture2D Tex0 : register(t0);\n");
+ WRITE(p, "Texture2D Tex0 : register(t0);\n");
}
-
- WRITE(p,"void main(\n");
- if(ApiType != API_D3D11)
+ if (ApiType == API_OPENGL)
{
- WRITE(p," out float4 ocol0 : COLOR0,\n");
+ WRITE(p, " out float4 ocol0;\n");
+ WRITE(p, " in float2 uv0;\n");
+ WRITE(p, "void main()\n");
}
else
{
- WRITE(p," out float4 ocol0 : SV_Target,\n");
+ WRITE(p,"void main(\n");
+ if(ApiType != API_D3D11)
+ {
+ WRITE(p," out float4 ocol0 : COLOR0,\n");
+ }
+ else
+ {
+ WRITE(p," out float4 ocol0 : SV_Target,\n");
+ }
+ WRITE(p," in float2 uv0 : TEXCOORD0)\n");
}
-
- WRITE(p," in float2 uv0 : TEXCOORD0)\n"
- "{\n"
- " float2 sampleUv;\n"
+
+
+ WRITE(p, "{\n"
+ " float2 sampleUv;\n"
" float2 uv1 = floor(uv0);\n");
-
+
WRITE(p, " float yl = floor(uv1.y / %f);\n", blkH);
WRITE(p, " float yb = yl * %f;\n", blkH);
WRITE(p, " float yoff = uv1.y - yb;\n");
- WRITE(p, " float xp = uv1.x + (yoff * textureDims.x);\n");
+ WRITE(p, " float xp = uv1.x + (yoff * " I_COLORS"[1].x);\n");
WRITE(p, " float xel = floor(xp / 2);\n");
WRITE(p, " float xb = floor(xel / %f);\n", blkH);
WRITE(p, " float xoff = xel - (xb * %f);\n", blkH);
-
+
WRITE(p, " float x2 = uv1.x * 2;\n");
WRITE(p, " float xl = floor(x2 / %f);\n", blkW);
WRITE(p, " float xib = x2 - (xl * %f);\n", blkW);
WRITE(p, " float halfxb = floor(xb / 2);\n");
-
WRITE(p, " sampleUv.x = xib + (halfxb * %f);\n", blkW);
WRITE(p, " sampleUv.y = yb + xoff;\n");
- WRITE(p, " sampleUv = sampleUv * blkDims.xy;\n");
-
- if(ApiType == API_OPENGL)
- WRITE(p," sampleUv.y = textureDims.y - sampleUv.y;\n");
-
- WRITE(p, " sampleUv = sampleUv + textureDims.zw;\n");
-
- if(ApiType != API_OPENGL)
+ WRITE(p, " sampleUv = sampleUv * " I_COLORS"[0].xy;\n");
+
+ if (ApiType == API_OPENGL)
+ WRITE(p," sampleUv.y = " I_COLORS"[1].y - sampleUv.y;\n");
+
+ WRITE(p, " sampleUv = sampleUv + " I_COLORS"[1].zw;\n");
+
+ if (ApiType != API_OPENGL)
{
WRITE(p, " sampleUv = sampleUv + float2(0.0f,1.0f);\n");// still to determine the reason for this
- WRITE(p, " sampleUv = sampleUv / blkDims.zw;\n");
- }
+ WRITE(p, " sampleUv = sampleUv / " I_COLORS"[0].zw;\n");
+ }
}
void WriteSampleColor(char*& p, const char* colorComp, const char* dest, API_TYPE ApiType)
@@ -214,14 +246,14 @@ void WriteSampleColor(char*& p, const char* colorComp, const char* dest, API_TYP
else if (ApiType == API_D3D11)
texSampleOpName = "tex0.Sample";
else
- texSampleOpName = "texRECT";
+ texSampleOpName = "texture2DRect";
// the increment of sampleUv.x is delayed, so we perform it here. see WriteIncrementSampleX.
const char* texSampleIncrementUnit;
- if(ApiType != API_OPENGL)
- texSampleIncrementUnit = "blkDims.x / blkDims.z";
+ if (ApiType != API_OPENGL)
+ texSampleIncrementUnit = I_COLORS"[0].x / " I_COLORS"[0].z";
else
- texSampleIncrementUnit = "blkDims.x";
+ texSampleIncrementUnit = I_COLORS"[0].x";
WRITE(p, " %s = %s(samp0, sampleUv + float2(%d * (%s), 0)).%s;\n",
dest, texSampleOpName, s_incrementSampleXCount, texSampleIncrementUnit, colorComp);
@@ -229,7 +261,7 @@ void WriteSampleColor(char*& p, const char* colorComp, const char* dest, API_TYP
void WriteColorToIntensity(char*& p, const char* src, const char* dest)
{
- if(!IntensityConstantAdded)
+ if (!IntensityConstantAdded)
{
WRITE(p, " float4 IntensityConst = float4(0.257f,0.504f,0.098f,0.0625f);\n");
IntensityConstantAdded = true;
@@ -263,7 +295,7 @@ void WriteToBitDepth(char*& p, u8 depth, const char* src, const char* dest)
WRITE(p, " %s = floor(%s * %ff);\n", dest, src, result);
}
-void WriteEncoderEnd(char* p)
+void WriteEncoderEnd(char* p, API_TYPE ApiType)
{
WRITE(p, "}\n");
IntensityConstantAdded = false;
@@ -272,65 +304,65 @@ void WriteEncoderEnd(char* p)
void WriteI8Encoder(char* p, API_TYPE ApiType)
{
- WriteSwizzler(p, GX_TF_I8,ApiType);
+ WriteSwizzler(p, GX_TF_I8, ApiType);
WRITE(p, " float3 texSample;\n");
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "ocol0.b");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "ocol0.g");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "ocol0.r");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "ocol0.a");
WRITE(p, " ocol0.rgba += IntensityConst.aaaa;\n"); // see WriteColorToIntensity
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteI4Encoder(char* p, API_TYPE ApiType)
{
- WriteSwizzler(p, GX_TF_I4,ApiType);
+ WriteSwizzler(p, GX_TF_I4, ApiType);
WRITE(p, " float3 texSample;\n");
WRITE(p, " float4 color0;\n");
WRITE(p, " float4 color1;\n");
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "color0.b");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "color1.b");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "color0.g");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "color1.g");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "color0.r");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "color1.r");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "color0.a");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgb", "texSample",ApiType);
+ WriteSampleColor(p, "rgb", "texSample", ApiType);
WriteColorToIntensity(p, "texSample", "color1.a");
WRITE(p, " color0.rgba += IntensityConst.aaaa;\n");
@@ -340,51 +372,51 @@ void WriteI4Encoder(char* p, API_TYPE ApiType)
WriteToBitDepth(p, 4, "color1", "color1");
WRITE(p, " ocol0 = (color0 * 16.0f + color1) / 255.0f;\n");
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteIA8Encoder(char* p,API_TYPE ApiType)
{
- WriteSwizzler(p, GX_TF_IA8,ApiType);
+ WriteSwizzler(p, GX_TF_IA8, ApiType);
WRITE(p, " float4 texSample;\n");
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
WRITE(p, " ocol0.b = texSample.a;\n");
WriteColorToIntensity(p, "texSample", "ocol0.g");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
WRITE(p, " ocol0.r = texSample.a;\n");
WriteColorToIntensity(p, "texSample", "ocol0.a");
WRITE(p, " ocol0.ga += IntensityConst.aa;\n");
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteIA4Encoder(char* p,API_TYPE ApiType)
{
- WriteSwizzler(p, GX_TF_IA4,ApiType);
+ WriteSwizzler(p, GX_TF_IA4, ApiType);
WRITE(p, " float4 texSample;\n");
WRITE(p, " float4 color0;\n");
WRITE(p, " float4 color1;\n");
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
WRITE(p, " color0.b = texSample.a;\n");
WriteColorToIntensity(p, "texSample", "color1.b");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
WRITE(p, " color0.g = texSample.a;\n");
WriteColorToIntensity(p, "texSample", "color1.g");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
WRITE(p, " color0.r = texSample.a;\n");
WriteColorToIntensity(p, "texSample", "color1.r");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
WRITE(p, " color0.a = texSample.a;\n");
WriteColorToIntensity(p, "texSample", "color1.a");
@@ -394,20 +426,19 @@ void WriteIA4Encoder(char* p,API_TYPE ApiType)
WriteToBitDepth(p, 4, "color1", "color1");
WRITE(p, " ocol0 = (color0 * 16.0f + color1) / 255.0f;\n");
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteRGB565Encoder(char* p,API_TYPE ApiType)
{
- WriteSwizzler(p, GX_TF_RGB565,ApiType);
-
- WriteSampleColor(p, "rgb", "float3 texSample0",ApiType);
- WriteIncrementSampleX(p,ApiType);
- WriteSampleColor(p, "rgb", "float3 texSample1",ApiType);
-
- WRITE(p, " float2 texRs = {texSample0.r, texSample1.r};\n");
- WRITE(p, " float2 texGs = {texSample0.g, texSample1.g};\n");
- WRITE(p, " float2 texBs = {texSample0.b, texSample1.b};\n");
+ WriteSwizzler(p, GX_TF_RGB565, ApiType);
+
+ WriteSampleColor(p, "rgb", "float3 texSample0", ApiType);
+ WriteIncrementSampleX(p, ApiType);
+ WriteSampleColor(p, "rgb", "float3 texSample1", ApiType);
+ WRITE(p, " float2 texRs = float2(texSample0.r, texSample1.r);\n");
+ WRITE(p, " float2 texGs = float2(texSample0.g, texSample1.g);\n");
+ WRITE(p, " float2 texBs = float2(texSample0.b, texSample1.b);\n");
WriteToBitDepth(p, 6, "texGs", "float2 gInt");
WRITE(p, " float2 gUpper = floor(gInt / 8.0f);\n");
@@ -419,25 +450,25 @@ void WriteRGB565Encoder(char* p,API_TYPE ApiType)
WRITE(p, " ocol0.ga = ocol0.ga + gLower * 32.0f;\n");
WRITE(p, " ocol0 = ocol0 / 255.0f;\n");
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteRGB5A3Encoder(char* p,API_TYPE ApiType)
{
- WriteSwizzler(p, GX_TF_RGB5A3,ApiType);
+ WriteSwizzler(p, GX_TF_RGB5A3, ApiType);
WRITE(p, " float4 texSample;\n");
WRITE(p, " float color0;\n");
WRITE(p, " float gUpper;\n");
WRITE(p, " float gLower;\n");
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
- // 0.8784 = 224 / 255 which is the maximum alpha value that can be represented in 3 bits
- WRITE(p, "if(texSample.a > 0.878f) {\n");
+ // 0.8784 = 224 / 255 which is the maximum alpha value that can be represented in 3 bits
+ WRITE(p, "if(texSample.a > 0.878f) {\n");
WriteToBitDepth(p, 5, "texSample.g", "color0");
- WRITE(p, " gUpper = floor(color0 / 8.0f);\n");
+ WRITE(p, " gUpper = floor(color0 / 8.0f);\n");
WRITE(p, " gLower = color0 - gUpper * 8.0f;\n");
WriteToBitDepth(p, 5, "texSample.r", "ocol0.b");
@@ -445,27 +476,27 @@ void WriteRGB5A3Encoder(char* p,API_TYPE ApiType)
WriteToBitDepth(p, 5, "texSample.b", "ocol0.g");
WRITE(p, " ocol0.g = ocol0.g + gLower * 32.0f;\n");
- WRITE(p, "} else {\n");
+ WRITE(p, "} else {\n");
- WriteToBitDepth(p, 4, "texSample.r", "ocol0.b");
- WriteToBitDepth(p, 4, "texSample.b", "ocol0.g");
+ WriteToBitDepth(p, 4, "texSample.r", "ocol0.b");
+ WriteToBitDepth(p, 4, "texSample.b", "ocol0.g");
- WriteToBitDepth(p, 3, "texSample.a", "color0");
- WRITE(p, "ocol0.b = ocol0.b + color0 * 16.0f;\n");
+ WriteToBitDepth(p, 3, "texSample.a", "color0");
+ WRITE(p, "ocol0.b = ocol0.b + color0 * 16.0f;\n");
WriteToBitDepth(p, 4, "texSample.g", "color0");
- WRITE(p, "ocol0.g = ocol0.g + color0 * 16.0f;\n");
+ WRITE(p, "ocol0.g = ocol0.g + color0 * 16.0f;\n");
- WRITE(p, "}\n");
+ WRITE(p, "}\n");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
- WRITE(p, "if(texSample.a > 0.878f) {\n");
+ WRITE(p, "if(texSample.a > 0.878f) {\n");
WriteToBitDepth(p, 5, "texSample.g", "color0");
- WRITE(p, " gUpper = floor(color0 / 8.0f);\n");
+ WRITE(p, " gUpper = floor(color0 / 8.0f);\n");
WRITE(p, " gLower = color0 - gUpper * 8.0f;\n");
WriteToBitDepth(p, 5, "texSample.r", "ocol0.r");
@@ -473,51 +504,51 @@ void WriteRGB5A3Encoder(char* p,API_TYPE ApiType)
WriteToBitDepth(p, 5, "texSample.b", "ocol0.a");
WRITE(p, " ocol0.a = ocol0.a + gLower * 32.0f;\n");
- WRITE(p, "} else {\n");
+ WRITE(p, "} else {\n");
- WriteToBitDepth(p, 4, "texSample.r", "ocol0.r");
- WriteToBitDepth(p, 4, "texSample.b", "ocol0.a");
+ WriteToBitDepth(p, 4, "texSample.r", "ocol0.r");
+ WriteToBitDepth(p, 4, "texSample.b", "ocol0.a");
- WriteToBitDepth(p, 3, "texSample.a", "color0");
- WRITE(p, "ocol0.r = ocol0.r + color0 * 16.0f;\n");
+ WriteToBitDepth(p, 3, "texSample.a", "color0");
+ WRITE(p, "ocol0.r = ocol0.r + color0 * 16.0f;\n");
WriteToBitDepth(p, 4, "texSample.g", "color0");
- WRITE(p, "ocol0.a = ocol0.a + color0 * 16.0f;\n");
+ WRITE(p, "ocol0.a = ocol0.a + color0 * 16.0f;\n");
- WRITE(p, "}\n");
+ WRITE(p, "}\n");
WRITE(p, " ocol0 = ocol0 / 255.0f;\n");
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteRGBA4443Encoder(char* p,API_TYPE ApiType)
{
- WriteSwizzler(p, GX_TF_RGB5A3,ApiType);
+ WriteSwizzler(p, GX_TF_RGB5A3, ApiType);
WRITE(p, " float4 texSample;\n");
WRITE(p, " float4 color0;\n");
WRITE(p, " float4 color1;\n");
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
WriteToBitDepth(p, 3, "texSample.a", "color0.b");
WriteToBitDepth(p, 4, "texSample.r", "color1.b");
WriteToBitDepth(p, 4, "texSample.g", "color0.g");
WriteToBitDepth(p, 4, "texSample.b", "color1.g");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
WriteToBitDepth(p, 3, "texSample.a", "color0.r");
WriteToBitDepth(p, 4, "texSample.r", "color1.r");
WriteToBitDepth(p, 4, "texSample.g", "color0.a");
WriteToBitDepth(p, 4, "texSample.b", "color1.a");
WRITE(p, " ocol0 = (color0 * 16.0f + color1) / 255.0f;\n");
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteRGBA8Encoder(char* p,API_TYPE ApiType)
{
- Write32BitSwizzler(p, GX_TF_RGBA8,ApiType);
+ Write32BitSwizzler(p, GX_TF_RGBA8, ApiType);
WRITE(p, " float cl1 = xb - (halfxb * 2);\n");
WRITE(p, " float cl0 = 1.0f - cl1;\n");
@@ -526,15 +557,15 @@ void WriteRGBA8Encoder(char* p,API_TYPE ApiType)
WRITE(p, " float4 color0;\n");
WRITE(p, " float4 color1;\n");
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
WRITE(p, " color0.b = texSample.a;\n");
WRITE(p, " color0.g = texSample.r;\n");
WRITE(p, " color1.b = texSample.g;\n");
WRITE(p, " color1.g = texSample.b;\n");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "rgba", "texSample",ApiType);
+ WriteSampleColor(p, "rgba", "texSample", ApiType);
WRITE(p, " color0.r = texSample.a;\n");
WRITE(p, " color0.a = texSample.r;\n");
WRITE(p, " color1.r = texSample.g;\n");
@@ -542,86 +573,86 @@ void WriteRGBA8Encoder(char* p,API_TYPE ApiType)
WRITE(p, " ocol0 = (cl0 * color0) + (cl1 * color1);\n");
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteC4Encoder(char* p, const char* comp,API_TYPE ApiType)
{
- WriteSwizzler(p, GX_CTF_R4,ApiType);
+ WriteSwizzler(p, GX_CTF_R4, ApiType);
WRITE(p, " float4 color0;\n");
WRITE(p, " float4 color1;\n");
- WriteSampleColor(p, comp, "color0.b",ApiType);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, comp, "color0.b", ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "color1.b",ApiType);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, comp, "color1.b", ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "color0.g",ApiType);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, comp, "color0.g", ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "color1.g",ApiType);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, comp, "color1.g", ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "color0.r",ApiType);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, comp, "color0.r", ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "color1.r",ApiType);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, comp, "color1.r", ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "color0.a",ApiType);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, comp, "color0.a", ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "color1.a",ApiType);
+ WriteSampleColor(p, comp, "color1.a", ApiType);
WriteToBitDepth(p, 4, "color0", "color0");
WriteToBitDepth(p, 4, "color1", "color1");
WRITE(p, " ocol0 = (color0 * 16.0f + color1) / 255.0f;\n");
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteC8Encoder(char* p, const char* comp,API_TYPE ApiType)
{
- WriteSwizzler(p, GX_CTF_R8,ApiType);
+ WriteSwizzler(p, GX_CTF_R8, ApiType);
- WriteSampleColor(p, comp, "ocol0.b",ApiType);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, comp, "ocol0.b", ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "ocol0.g",ApiType);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, comp, "ocol0.g", ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "ocol0.r",ApiType);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, comp, "ocol0.r", ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "ocol0.a",ApiType);
+ WriteSampleColor(p, comp, "ocol0.a", ApiType);
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteCC4Encoder(char* p, const char* comp,API_TYPE ApiType)
{
- WriteSwizzler(p, GX_CTF_RA4,ApiType);
+ WriteSwizzler(p, GX_CTF_RA4, ApiType);
WRITE(p, " float2 texSample;\n");
WRITE(p, " float4 color0;\n");
WRITE(p, " float4 color1;\n");
- WriteSampleColor(p, comp, "texSample",ApiType);
+ WriteSampleColor(p, comp, "texSample", ApiType);
WRITE(p, " color0.b = texSample.x;\n");
WRITE(p, " color1.b = texSample.y;\n");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "texSample",ApiType);
+ WriteSampleColor(p, comp, "texSample", ApiType);
WRITE(p, " color0.g = texSample.x;\n");
WRITE(p, " color1.g = texSample.y;\n");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "texSample",ApiType);
+ WriteSampleColor(p, comp, "texSample", ApiType);
WRITE(p, " color0.r = texSample.x;\n");
WRITE(p, " color1.r = texSample.y;\n");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "texSample",ApiType);
+ WriteSampleColor(p, comp, "texSample", ApiType);
WRITE(p, " color0.a = texSample.x;\n");
WRITE(p, " color1.a = texSample.y;\n");
@@ -629,158 +660,158 @@ void WriteCC4Encoder(char* p, const char* comp,API_TYPE ApiType)
WriteToBitDepth(p, 4, "color1", "color1");
WRITE(p, " ocol0 = (color0 * 16.0f + color1) / 255.0f;\n");
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteCC8Encoder(char* p, const char* comp, API_TYPE ApiType)
{
- WriteSwizzler(p, GX_CTF_RA8,ApiType);
+ WriteSwizzler(p, GX_CTF_RA8, ApiType);
- WriteSampleColor(p, comp, "ocol0.bg",ApiType);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, comp, "ocol0.bg", ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, comp, "ocol0.ra",ApiType);
+ WriteSampleColor(p, comp, "ocol0.ra", ApiType);
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteZ8Encoder(char* p, const char* multiplier,API_TYPE ApiType)
{
- WriteSwizzler(p, GX_CTF_Z8M,ApiType);
+ WriteSwizzler(p, GX_CTF_Z8M, ApiType);
- WRITE(p, " float depth;\n");
+ WRITE(p, " float depth;\n");
- WriteSampleColor(p, "b", "depth",ApiType);
- WRITE(p, "ocol0.b = frac(depth * %s);\n", multiplier);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, "b", "depth", ApiType);
+ WRITE(p, "ocol0.b = frac(depth * %s);\n", multiplier);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "b", "depth",ApiType);
- WRITE(p, "ocol0.g = frac(depth * %s);\n", multiplier);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, "b", "depth", ApiType);
+ WRITE(p, "ocol0.g = frac(depth * %s);\n", multiplier);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "b", "depth",ApiType);
- WRITE(p, "ocol0.r = frac(depth * %s);\n", multiplier);
- WriteIncrementSampleX(p,ApiType);
+ WriteSampleColor(p, "b", "depth", ApiType);
+ WRITE(p, "ocol0.r = frac(depth * %s);\n", multiplier);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "b", "depth",ApiType);
- WRITE(p, "ocol0.a = frac(depth * %s);\n", multiplier);
+ WriteSampleColor(p, "b", "depth", ApiType);
+ WRITE(p, "ocol0.a = frac(depth * %s);\n", multiplier);
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteZ16Encoder(char* p,API_TYPE ApiType)
{
- WriteSwizzler(p, GX_TF_Z16,ApiType);
+ WriteSwizzler(p, GX_TF_Z16, ApiType);
- WRITE(p, " float depth;\n");
- WRITE(p, " float3 expanded;\n");
+ WRITE(p, " float depth;\n");
+ WRITE(p, " float3 expanded;\n");
- // byte order is reversed
+ // byte order is reversed
- WriteSampleColor(p, "b", "depth",ApiType);
+ WriteSampleColor(p, "b", "depth", ApiType);
- WRITE(p, " depth *= 16777215.0f;\n");
- WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
- WRITE(p, " depth -= expanded.r * 256 * 256;\n");
- WRITE(p, " expanded.g = floor(depth / 256);\n");
+ WRITE(p, " depth *= 16777215.0f;\n");
+ WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
+ WRITE(p, " depth -= expanded.r * 256 * 256;\n");
+ WRITE(p, " expanded.g = floor(depth / 256);\n");
- WRITE(p, " ocol0.b = expanded.g / 255;\n");
- WRITE(p, " ocol0.g = expanded.r / 255;\n");
+ WRITE(p, " ocol0.b = expanded.g / 255;\n");
+ WRITE(p, " ocol0.g = expanded.r / 255;\n");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "b", "depth",ApiType);
+ WriteSampleColor(p, "b", "depth", ApiType);
- WRITE(p, " depth *= 16777215.0f;\n");
- WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
- WRITE(p, " depth -= expanded.r * 256 * 256;\n");
- WRITE(p, " expanded.g = floor(depth / 256);\n");
+ WRITE(p, " depth *= 16777215.0f;\n");
+ WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
+ WRITE(p, " depth -= expanded.r * 256 * 256;\n");
+ WRITE(p, " expanded.g = floor(depth / 256);\n");
- WRITE(p, " ocol0.r = expanded.g / 255;\n");
- WRITE(p, " ocol0.a = expanded.r / 255;\n");
+ WRITE(p, " ocol0.r = expanded.g / 255;\n");
+ WRITE(p, " ocol0.a = expanded.r / 255;\n");
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteZ16LEncoder(char* p,API_TYPE ApiType)
{
- WriteSwizzler(p, GX_CTF_Z16L,ApiType);
+ WriteSwizzler(p, GX_CTF_Z16L, ApiType);
- WRITE(p, " float depth;\n");
- WRITE(p, " float3 expanded;\n");
+ WRITE(p, " float depth;\n");
+ WRITE(p, " float3 expanded;\n");
- // byte order is reversed
+ // byte order is reversed
- WriteSampleColor(p, "b", "depth",ApiType);
+ WriteSampleColor(p, "b", "depth", ApiType);
- WRITE(p, " depth *= 16777215.0f;\n");
- WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
- WRITE(p, " depth -= expanded.r * 256 * 256;\n");
- WRITE(p, " expanded.g = floor(depth / 256);\n");
- WRITE(p, " depth -= expanded.g * 256;\n");
- WRITE(p, " expanded.b = depth;\n");
+ WRITE(p, " depth *= 16777215.0f;\n");
+ WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
+ WRITE(p, " depth -= expanded.r * 256 * 256;\n");
+ WRITE(p, " expanded.g = floor(depth / 256);\n");
+ WRITE(p, " depth -= expanded.g * 256;\n");
+ WRITE(p, " expanded.b = depth;\n");
- WRITE(p, " ocol0.b = expanded.b / 255;\n");
- WRITE(p, " ocol0.g = expanded.g / 255;\n");
+ WRITE(p, " ocol0.b = expanded.b / 255;\n");
+ WRITE(p, " ocol0.g = expanded.g / 255;\n");
- WriteIncrementSampleX(p,ApiType);
+ WriteIncrementSampleX(p, ApiType);
- WriteSampleColor(p, "b", "depth",ApiType);
+ WriteSampleColor(p, "b", "depth", ApiType);
- WRITE(p, " depth *= 16777215.0f;\n");
- WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
- WRITE(p, " depth -= expanded.r * 256 * 256;\n");
- WRITE(p, " expanded.g = floor(depth / 256);\n");
- WRITE(p, " depth -= expanded.g * 256;\n");
- WRITE(p, " expanded.b = depth;\n");
+ WRITE(p, " depth *= 16777215.0f;\n");
+ WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
+ WRITE(p, " depth -= expanded.r * 256 * 256;\n");
+ WRITE(p, " expanded.g = floor(depth / 256);\n");
+ WRITE(p, " depth -= expanded.g * 256;\n");
+ WRITE(p, " expanded.b = depth;\n");
- WRITE(p, " ocol0.r = expanded.b;\n");
- WRITE(p, " ocol0.a = expanded.g;\n");
+ WRITE(p, " ocol0.r = expanded.b;\n");
+ WRITE(p, " ocol0.a = expanded.g;\n");
- WriteEncoderEnd(p);
+ WriteEncoderEnd(p, ApiType);
}
void WriteZ24Encoder(char* p, API_TYPE ApiType)
{
- Write32BitSwizzler(p, GX_TF_Z24X8,ApiType);
+ Write32BitSwizzler(p, GX_TF_Z24X8, ApiType);
WRITE(p, " float cl = xb - (halfxb * 2);\n");
WRITE(p, " float depth0;\n");
- WRITE(p, " float depth1;\n");
- WRITE(p, " float3 expanded0;\n");
- WRITE(p, " float3 expanded1;\n");
-
- WriteSampleColor(p, "b", "depth0",ApiType);
- WriteIncrementSampleX(p,ApiType);
- WriteSampleColor(p, "b", "depth1",ApiType);
-
- for (int i = 0; i < 2; i++)
- {
- WRITE(p, " depth%i *= 16777215.0f;\n", i);
-
- WRITE(p, " expanded%i.r = floor(depth%i / (256 * 256));\n", i, i);
- WRITE(p, " depth%i -= expanded%i.r * 256 * 256;\n", i, i);
- WRITE(p, " expanded%i.g = floor(depth%i / 256);\n", i, i);
- WRITE(p, " depth%i -= expanded%i.g * 256;\n", i, i);
- WRITE(p, " expanded%i.b = depth%i;\n", i, i);
- }
-
- WRITE(p, " if(cl > 0.5f) {\n");
- // upper 16
- WRITE(p, " ocol0.b = expanded0.g / 255;\n");
- WRITE(p, " ocol0.g = expanded0.b / 255;\n");
- WRITE(p, " ocol0.r = expanded1.g / 255;\n");
- WRITE(p, " ocol0.a = expanded1.b / 255;\n");
- WRITE(p, " } else {\n");
- // lower 8
- WRITE(p, " ocol0.b = 1.0f;\n");
- WRITE(p, " ocol0.g = expanded0.r / 255;\n");
- WRITE(p, " ocol0.r = 1.0f;\n");
- WRITE(p, " ocol0.a = expanded1.r / 255;\n");
- WRITE(p, " }\n");
-
- WriteEncoderEnd(p);
+ WRITE(p, " float depth1;\n");
+ WRITE(p, " float3 expanded0;\n");
+ WRITE(p, " float3 expanded1;\n");
+
+ WriteSampleColor(p, "b", "depth0", ApiType);
+ WriteIncrementSampleX(p, ApiType);
+ WriteSampleColor(p, "b", "depth1", ApiType);
+
+ for (int i = 0; i < 2; i++)
+ {
+ WRITE(p, " depth%i *= 16777215.0f;\n", i);
+
+ WRITE(p, " expanded%i.r = floor(depth%i / (256 * 256));\n", i, i);
+ WRITE(p, " depth%i -= expanded%i.r * 256 * 256;\n", i, i);
+ WRITE(p, " expanded%i.g = floor(depth%i / 256);\n", i, i);
+ WRITE(p, " depth%i -= expanded%i.g * 256;\n", i, i);
+ WRITE(p, " expanded%i.b = depth%i;\n", i, i);
+ }
+
+ WRITE(p, " if(cl > 0.5f) {\n");
+ // upper 16
+ WRITE(p, " ocol0.b = expanded0.g / 255;\n");
+ WRITE(p, " ocol0.g = expanded0.b / 255;\n");
+ WRITE(p, " ocol0.r = expanded1.g / 255;\n");
+ WRITE(p, " ocol0.a = expanded1.b / 255;\n");
+ WRITE(p, " } else {\n");
+ // lower 8
+ WRITE(p, " ocol0.b = 1.0f;\n");
+ WRITE(p, " ocol0.g = expanded0.r / 255;\n");
+ WRITE(p, " ocol0.r = 1.0f;\n");
+ WRITE(p, " ocol0.a = expanded1.r / 255;\n");
+ WRITE(p, " }\n");
+
+ WriteEncoderEnd(p, ApiType);
}
const char *GenerateEncodingShader(u32 format,API_TYPE ApiType)
@@ -790,76 +821,76 @@ const char *GenerateEncodingShader(u32 format,API_TYPE ApiType)
char *p = text;
- switch(format)
+ switch (format)
{
case GX_TF_I4:
- WriteI4Encoder(p,ApiType);
+ WriteI4Encoder(p, ApiType);
break;
case GX_TF_I8:
- WriteI8Encoder(p,ApiType);
+ WriteI8Encoder(p, ApiType);
break;
case GX_TF_IA4:
- WriteIA4Encoder(p,ApiType);
+ WriteIA4Encoder(p, ApiType);
break;
case GX_TF_IA8:
- WriteIA8Encoder(p,ApiType);
+ WriteIA8Encoder(p, ApiType);
break;
case GX_TF_RGB565:
- WriteRGB565Encoder(p,ApiType);
+ WriteRGB565Encoder(p, ApiType);
break;
case GX_TF_RGB5A3:
- WriteRGB5A3Encoder(p,ApiType);
+ WriteRGB5A3Encoder(p, ApiType);
break;
case GX_TF_RGBA8:
- WriteRGBA8Encoder(p,ApiType);
+ WriteRGBA8Encoder(p, ApiType);
break;
case GX_CTF_R4:
- WriteC4Encoder(p, "r",ApiType);
+ WriteC4Encoder(p, "r", ApiType);
break;
case GX_CTF_RA4:
- WriteCC4Encoder(p, "ar",ApiType);
+ WriteCC4Encoder(p, "ar", ApiType);
break;
case GX_CTF_RA8:
- WriteCC8Encoder(p, "ar",ApiType);
+ WriteCC8Encoder(p, "ar", ApiType);
break;
case GX_CTF_A8:
- WriteC8Encoder(p, "a",ApiType);
+ WriteC8Encoder(p, "a", ApiType);
break;
case GX_CTF_R8:
- WriteC8Encoder(p, "r",ApiType);
+ WriteC8Encoder(p, "r", ApiType);
break;
case GX_CTF_G8:
- WriteC8Encoder(p, "g",ApiType);
+ WriteC8Encoder(p, "g", ApiType);
break;
case GX_CTF_B8:
- WriteC8Encoder(p, "b",ApiType);
+ WriteC8Encoder(p, "b", ApiType);
break;
case GX_CTF_RG8:
- WriteCC8Encoder(p, "rg",ApiType);
+ WriteCC8Encoder(p, "rg", ApiType);
break;
case GX_CTF_GB8:
- WriteCC8Encoder(p, "gb",ApiType);
+ WriteCC8Encoder(p, "gb", ApiType);
break;
case GX_TF_Z8:
- WriteC8Encoder(p, "b",ApiType);
+ WriteC8Encoder(p, "b", ApiType);
break;
case GX_TF_Z16:
- WriteZ16Encoder(p,ApiType);
+ WriteZ16Encoder(p, ApiType);
break;
case GX_TF_Z24X8:
- WriteZ24Encoder(p,ApiType);
+ WriteZ24Encoder(p, ApiType);
break;
case GX_CTF_Z4:
- WriteC4Encoder(p, "b",ApiType);
+ WriteC4Encoder(p, "b", ApiType);
break;
case GX_CTF_Z8M:
- WriteZ8Encoder(p, "256.0f",ApiType);
+ WriteZ8Encoder(p, "256.0f", ApiType);
break;
case GX_CTF_Z8L:
- WriteZ8Encoder(p, "65536.0f" ,ApiType);
+ WriteZ8Encoder(p, "65536.0f" , ApiType);
break;
case GX_CTF_Z16L:
- WriteZ16LEncoder(p,ApiType);
+ WriteZ16LEncoder(p, ApiType);
break;
default:
PanicAlert("Unknown texture copy format: 0x%x\n", format);
@@ -870,7 +901,7 @@ const char *GenerateEncodingShader(u32 format,API_TYPE ApiType)
PanicAlert("TextureConversionShader generator - buffer too small, canary has been eaten!");
setlocale(LC_NUMERIC, ""); // restore locale
- return text;
+ return text;
}
void SetShaderParameters(float width, float height, float offsetX, float offsetY, float widthStride, float heightStride,float buffW,float buffH)
diff --git a/Source/Core/VideoCommon/Src/TextureDecoder.h b/Source/Core/VideoCommon/Src/TextureDecoder.h
index fae70897f5..e9154763cb 100644
--- a/Source/Core/VideoCommon/Src/TextureDecoder.h
+++ b/Source/Core/VideoCommon/Src/TextureDecoder.h
@@ -27,41 +27,41 @@ extern GC_ALIGNED16(u8 texMem[TMEM_SIZE]);
enum TextureFormat
{
- GX_TF_I4 = 0x0,
- GX_TF_I8 = 0x1,
- GX_TF_IA4 = 0x2,
- GX_TF_IA8 = 0x3,
- GX_TF_RGB565 = 0x4,
- GX_TF_RGB5A3 = 0x5,
- GX_TF_RGBA8 = 0x6,
- GX_TF_C4 = 0x8,
- GX_TF_C8 = 0x9,
- GX_TF_C14X2 = 0xA,
- GX_TF_CMPR = 0xE,
+ GX_TF_I4 = 0x0,
+ GX_TF_I8 = 0x1,
+ GX_TF_IA4 = 0x2,
+ GX_TF_IA8 = 0x3,
+ GX_TF_RGB565 = 0x4,
+ GX_TF_RGB5A3 = 0x5,
+ GX_TF_RGBA8 = 0x6,
+ GX_TF_C4 = 0x8,
+ GX_TF_C8 = 0x9,
+ GX_TF_C14X2 = 0xA,
+ GX_TF_CMPR = 0xE,
- _GX_TF_CTF = 0x20, // copy-texture-format only (simply means linear?)
- _GX_TF_ZTF = 0x10, // Z-texture-format
+ _GX_TF_CTF = 0x20, // copy-texture-format only (simply means linear?)
+ _GX_TF_ZTF = 0x10, // Z-texture-format
- // these formats are also valid when copying targets
- GX_CTF_R4 = 0x0 | _GX_TF_CTF,
- GX_CTF_RA4 = 0x2 | _GX_TF_CTF,
- GX_CTF_RA8 = 0x3 | _GX_TF_CTF,
- GX_CTF_YUVA8 = 0x6 | _GX_TF_CTF,
- GX_CTF_A8 = 0x7 | _GX_TF_CTF,
- GX_CTF_R8 = 0x8 | _GX_TF_CTF,
- GX_CTF_G8 = 0x9 | _GX_TF_CTF,
- GX_CTF_B8 = 0xA | _GX_TF_CTF,
- GX_CTF_RG8 = 0xB | _GX_TF_CTF,
- GX_CTF_GB8 = 0xC | _GX_TF_CTF,
+ // these formats are also valid when copying targets
+ GX_CTF_R4 = 0x0 | _GX_TF_CTF,
+ GX_CTF_RA4 = 0x2 | _GX_TF_CTF,
+ GX_CTF_RA8 = 0x3 | _GX_TF_CTF,
+ GX_CTF_YUVA8 = 0x6 | _GX_TF_CTF,
+ GX_CTF_A8 = 0x7 | _GX_TF_CTF,
+ GX_CTF_R8 = 0x8 | _GX_TF_CTF,
+ GX_CTF_G8 = 0x9 | _GX_TF_CTF,
+ GX_CTF_B8 = 0xA | _GX_TF_CTF,
+ GX_CTF_RG8 = 0xB | _GX_TF_CTF,
+ GX_CTF_GB8 = 0xC | _GX_TF_CTF,
- GX_TF_Z8 = 0x1 | _GX_TF_ZTF,
- GX_TF_Z16 = 0x3 | _GX_TF_ZTF,
- GX_TF_Z24X8 = 0x6 | _GX_TF_ZTF,
+ GX_TF_Z8 = 0x1 | _GX_TF_ZTF,
+ GX_TF_Z16 = 0x3 | _GX_TF_ZTF,
+ GX_TF_Z24X8 = 0x6 | _GX_TF_ZTF,
- GX_CTF_Z4 = 0x0 | _GX_TF_ZTF | _GX_TF_CTF,
- GX_CTF_Z8M = 0x9 | _GX_TF_ZTF | _GX_TF_CTF,
- GX_CTF_Z8L = 0xA | _GX_TF_ZTF | _GX_TF_CTF,
- GX_CTF_Z16L = 0xC | _GX_TF_ZTF | _GX_TF_CTF,
+ GX_CTF_Z4 = 0x0 | _GX_TF_ZTF | _GX_TF_CTF,
+ GX_CTF_Z8M = 0x9 | _GX_TF_ZTF | _GX_TF_CTF,
+ GX_CTF_Z8L = 0xA | _GX_TF_ZTF | _GX_TF_CTF,
+ GX_CTF_Z16L = 0xC | _GX_TF_ZTF | _GX_TF_CTF,
};
int TexDecoder_GetTexelSizeInNibbles(int format);
diff --git a/Source/Core/VideoCommon/Src/VertexLoader.cpp b/Source/Core/VideoCommon/Src/VertexLoader.cpp
index 5bffab8ee7..5df495a44c 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader.cpp
+++ b/Source/Core/VideoCommon/Src/VertexLoader.cpp
@@ -23,7 +23,7 @@
#include "MemoryUtil.h"
#include "StringUtil.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "PixelEngine.h"
#include "Host.h"
@@ -43,8 +43,11 @@
//BBox
#include "XFMemory.h"
extern float GC_ALIGNED16(g_fProjectionMatrix[16]);
-
+#ifndef _M_GENERIC
+#ifndef __APPLE__
#define USE_JIT
+#endif
+#endif
#define COMPILED_CODE_SIZE 4096
@@ -72,6 +75,10 @@ int colElements[2];
float posScale;
float tcScale[8];
+// bbox must read vertex position, so convert it to this buffer
+static float s_bbox_vertex_buffer[3];
+static u8 *s_bbox_pCurBufferPointer_orig;
+
static const float fractionTable[32] = {
1.0f / (1U << 0), 1.0f / (1U << 1), 1.0f / (1U << 2), 1.0f / (1U << 3),
1.0f / (1U << 4), 1.0f / (1U << 5), 1.0f / (1U << 6), 1.0f / (1U << 7),
@@ -93,10 +100,21 @@ void LOADERDECL PosMtx_ReadDirect_UByte()
void LOADERDECL PosMtx_Write()
{
- *VertexManager::s_pCurBufferPointer++ = s_curposmtx;
- *VertexManager::s_pCurBufferPointer++ = 0;
- *VertexManager::s_pCurBufferPointer++ = 0;
- *VertexManager::s_pCurBufferPointer++ = 0;
+ DataWrite<u8>(s_curposmtx);
+ DataWrite<u8>(0);
+ DataWrite<u8>(0);
+ DataWrite<u8>(0);
+}
+
+void LOADERDECL UpdateBoundingBoxPrepare()
+{
+ if (!PixelEngine::bbox_active)
+ return;
+
+ // set our buffer as videodata buffer, so we will get a copy of the vertex positions
+ // this is a big hack, but so we can use the same converting function then without bbox
+ s_bbox_pCurBufferPointer_orig = VertexManager::s_pCurBufferPointer;
+ VertexManager::s_pCurBufferPointer = (u8*)s_bbox_vertex_buffer;
}
void LOADERDECL UpdateBoundingBox()
@@ -104,12 +122,16 @@ void LOADERDECL UpdateBoundingBox()
if (!PixelEngine::bbox_active)
return;
- // Truly evil hack, reading backwards from the write pointer. If we were writing to write-only
- // memory like we might have been with a D3D vertex buffer, this would have been a bad idea.
- float *data = (float *)(VertexManager::s_pCurBufferPointer - 12);
+ // reset videodata pointer
+ VertexManager::s_pCurBufferPointer = s_bbox_pCurBufferPointer_orig;
+
+ // copy vertex pointers
+ memcpy(VertexManager::s_pCurBufferPointer, s_bbox_vertex_buffer, 12);
+ VertexManager::s_pCurBufferPointer += 12;
+
// We must transform the just loaded point by the current world and projection matrix - in software.
// Then convert to screen space and update the bounding box.
- float p[3] = {data[0], data[1], data[2]};
+ float p[3] = {s_bbox_vertex_buffer[0], s_bbox_vertex_buffer[1], s_bbox_vertex_buffer[2]};
const float *world_matrix = (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4;
const float *proj_matrix = &g_fProjectionMatrix[0];
@@ -147,24 +169,22 @@ void LOADERDECL TexMtx_ReadDirect_UByte()
void LOADERDECL TexMtx_Write_Float()
{
- *(float*)VertexManager::s_pCurBufferPointer = (float)s_curtexmtx[s_texmtxwrite++];
- VertexManager::s_pCurBufferPointer += 4;
+ DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
}
void LOADERDECL TexMtx_Write_Float2()
{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = 0;
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)s_curtexmtx[s_texmtxwrite++];
- VertexManager::s_pCurBufferPointer += 8;
+ DataWrite(0.f);
+ DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
}
void LOADERDECL TexMtx_Write_Float4()
{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = 0;
- ((float*)VertexManager::s_pCurBufferPointer)[1] = 0;
- ((float*)VertexManager::s_pCurBufferPointer)[2] = s_curtexmtx[s_texmtxwrite++];
- ((float*)VertexManager::s_pCurBufferPointer)[3] = 0; // Just to fill out with 0.
- VertexManager::s_pCurBufferPointer += 16;
+ DataWrite(0.f);
+ DataWrite(0.f);
+ DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
+ // Just to fill out with 0.
+ DataWrite(0.f);
}
VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr)
@@ -182,14 +202,21 @@ VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr)
m_VtxDesc = vtx_desc;
SetVAT(vtx_attr.g0.Hex, vtx_attr.g1.Hex, vtx_attr.g2.Hex);
+ #ifdef USE_JIT
AllocCodeSpace(COMPILED_CODE_SIZE);
CompileVertexTranslator();
WriteProtect();
+ #else
+ CompileVertexTranslator();
+ #endif
+
}
VertexLoader::~VertexLoader()
{
+ #ifdef USE_JIT
FreeCodeSpace();
+ #endif
delete m_NativeFmt;
}
@@ -267,15 +294,16 @@ void VertexLoader::CompileVertexTranslator()
if (m_VtxDesc.Tex7MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); }
// Write vertex position loader
- WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
+ if(g_ActiveConfig.bUseBBox) {
+ WriteCall(UpdateBoundingBoxPrepare);
+ WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
+ WriteCall(UpdateBoundingBox);
+ } else {
+ WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
+ }
m_VertexSize += VertexLoader_Position::GetSize(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements);
nat_offset += 12;
- // OK, so we just got a point. Let's go back and read it for the bounding box.
-
- if(g_ActiveConfig.bUseBBox)
- WriteCall(UpdateBoundingBox);
-
// Normals
vtx_decl.num_normals = 0;
if (m_VtxDesc.Normal != NOT_PRESENT)
@@ -307,7 +335,7 @@ void VertexLoader::CompileVertexTranslator()
nat_offset += 12;
vtx_decl.normal_offset[2] = nat_offset;
nat_offset += 12;
- }
+ }
int numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE;
m_NativeFmt->m_components |= VB_HAS_NRM0;
@@ -339,7 +367,7 @@ void VertexLoader::CompileVertexTranslator()
default: _assert_(0); break;
}
break;
- case INDEX8:
+ case INDEX8:
m_VertexSize += 1;
switch (m_VtxAttr.color[i].Comp)
{
@@ -474,7 +502,8 @@ void VertexLoader::WriteCall(TPipelineFunction func)
m_PipelineStages[m_numPipelineStages++] = func;
#endif
}
-
+// ARMTODO: This should be done in a better way
+#ifndef _M_GENERIC
void VertexLoader::WriteGetVariable(int bits, OpArg dest, void *address)
{
#ifdef USE_JIT
@@ -498,8 +527,9 @@ void VertexLoader::WriteSetVariable(int bits, void *address, OpArg value)
#endif
#endif
}
+#endif
-void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
+int VertexLoader::SetupRunVertices(int vtx_attr_group, int primitive, int const count)
{
m_numLoadedVertices += count;
@@ -518,7 +548,7 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
{
// if cull mode is none, ignore triangles and quads
DataSkip(count * m_VertexSize);
- return;
+ return 0;
}
m_NativeFmt->EnableComponents(m_NativeFmt->m_components);
@@ -528,7 +558,7 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
m_VtxAttr.texCoord[0].Frac = g_VtxAttr[vtx_attr_group].g0.Tex0Frac;
m_VtxAttr.texCoord[1].Frac = g_VtxAttr[vtx_attr_group].g1.Tex1Frac;
m_VtxAttr.texCoord[2].Frac = g_VtxAttr[vtx_attr_group].g1.Tex2Frac;
- m_VtxAttr.texCoord[3].Frac = g_VtxAttr[vtx_attr_group].g1.Tex3Frac;
+ m_VtxAttr.texCoord[3].Frac = g_VtxAttr[vtx_attr_group].g1.Tex3Frac;
m_VtxAttr.texCoord[4].Frac = g_VtxAttr[vtx_attr_group].g2.Tex4Frac;
m_VtxAttr.texCoord[5].Frac = g_VtxAttr[vtx_attr_group].g2.Tex5Frac;
m_VtxAttr.texCoord[6].Frac = g_VtxAttr[vtx_attr_group].g2.Tex6Frac;
@@ -542,158 +572,49 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
for (int i = 0; i < 2; i++)
colElements[i] = m_VtxAttr.color[i].Elements;
- // if strips or fans, make sure all vertices can fit in buffer, otherwise flush
- int granularity = 1;
- switch (primitive) {
- case 3: // strip .. hm, weird
- case 4: // fan
- if (VertexManager::GetRemainingSize() < 3 * native_stride)
- VertexManager::Flush();
- break;
- case 6: // line strip
- if (VertexManager::GetRemainingSize() < 2 * native_stride)
- VertexManager::Flush();
- break;
- case 0: granularity = 4; break; // quads
- case 2: granularity = 3; break; // tris
- case 5: granularity = 2; break; // lines
- }
-
- int startv = 0, extraverts = 0;
- int v = 0;
-
- //int remainingVerts2 = VertexManager::GetRemainingVertices(primitive);
- while (v < count)
- {
- int remainingVerts = VertexManager::GetRemainingSize() / native_stride;
- //if (remainingVerts2 - v + startv < remainingVerts)
- //remainingVerts = remainingVerts2 - v + startv;
- if (remainingVerts < granularity) {
- INCSTAT(stats.thisFrame.numBufferSplits);
- // This buffer full - break current primitive and flush, to switch to the next buffer.
- u8* plastptr = VertexManager::s_pCurBufferPointer;
- if (v - startv > 0)
- VertexManager::AddVertices(primitive, v - startv + extraverts);
- VertexManager::Flush();
- //remainingVerts2 = VertexManager::GetRemainingVertices(primitive);
- // Why does this need to be so complicated?
- switch (primitive) {
- case 3: // triangle strip, copy last two vertices
- // a little trick since we have to keep track of signs
- if (v & 1) {
- memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-2*native_stride, native_stride);
- memcpy_gc(VertexManager::s_pCurBufferPointer+native_stride, plastptr-native_stride*2, 2*native_stride);
- VertexManager::s_pCurBufferPointer += native_stride*3;
- extraverts = 3;
- }
- else {
- memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*2, native_stride*2);
- VertexManager::s_pCurBufferPointer += native_stride*2;
- extraverts = 2;
- }
- break;
- case 4: // tri fan, copy first and last vert
- memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*(v-startv+extraverts), native_stride);
- VertexManager::s_pCurBufferPointer += native_stride;
- memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride);
- VertexManager::s_pCurBufferPointer += native_stride;
- extraverts = 2;
- break;
- case 6: // line strip
- memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride);
- VertexManager::s_pCurBufferPointer += native_stride;
- extraverts = 1;
- break;
- default:
- extraverts = 0;
- break;
- }
- startv = v;
- }
- int remainingPrims = remainingVerts / granularity;
- remainingVerts = remainingPrims * granularity;
- if (count - v < remainingVerts)
- remainingVerts = count - v;
-
- #ifdef USE_JIT
- if (remainingVerts > 0) {
- loop_counter = remainingVerts;
- ((void (*)())(void*)m_compiledCode)();
- }
- #else
- for (int s = 0; s < remainingVerts; s++)
- {
- tcIndex = 0;
- colIndex = 0;
- s_texmtxwrite = s_texmtxread = 0;
- for (int i = 0; i < m_numPipelineStages; i++)
- m_PipelineStages[i]();
- PRIM_LOG("\n");
- }
- #endif
- v += remainingVerts;
- }
-
- if (startv < count)
- VertexManager::AddVertices(primitive, count - startv + extraverts);
+ VertexManager::PrepareForAdditionalData(primitive, count, native_stride);
+
+ return count;
}
-
-
-
-void VertexLoader::RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data)
+void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int const count)
{
- m_numLoadedVertices += count;
+ auto const new_count = SetupRunVertices(vtx_attr_group, primitive, count);
+ ConvertVertices(new_count);
+ VertexManager::AddVertices(primitive, new_count);
+}
- // Flush if our vertex format is different from the currently set.
- if (g_nativeVertexFmt != NULL && g_nativeVertexFmt != m_NativeFmt)
- {
- // We really must flush here. It's possible that the native representations
- // of the two vtx formats are the same, but we have no way to easily check that
- // now.
- VertexManager::Flush();
- // Also move the Set() here?
+void VertexLoader::ConvertVertices ( int count )
+{
+#ifdef USE_JIT
+ if (count > 0) {
+ loop_counter = count;
+ ((void (*)())(void*)m_compiledCode)();
}
- g_nativeVertexFmt = m_NativeFmt;
-
- if (bpmem.genMode.cullmode == 3 && primitive < 5)
+#else
+ for (int s = 0; s < count; s++)
{
- // if cull mode is none, ignore triangles and quads
- DataSkip(count * m_VertexSize);
- return;
+ tcIndex = 0;
+ colIndex = 0;
+ s_texmtxwrite = s_texmtxread = 0;
+ for (int i = 0; i < m_numPipelineStages; i++)
+ m_PipelineStages[i]();
+ PRIM_LOG("\n");
}
+#endif
+}
- m_NativeFmt->EnableComponents(m_NativeFmt->m_components);
-
- // Load position and texcoord scale factors.
- m_VtxAttr.PosFrac = g_VtxAttr[vtx_attr_group].g0.PosFrac;
- m_VtxAttr.texCoord[0].Frac = g_VtxAttr[vtx_attr_group].g0.Tex0Frac;
- m_VtxAttr.texCoord[1].Frac = g_VtxAttr[vtx_attr_group].g1.Tex1Frac;
- m_VtxAttr.texCoord[2].Frac = g_VtxAttr[vtx_attr_group].g1.Tex2Frac;
- m_VtxAttr.texCoord[3].Frac = g_VtxAttr[vtx_attr_group].g1.Tex3Frac;
- m_VtxAttr.texCoord[4].Frac = g_VtxAttr[vtx_attr_group].g2.Tex4Frac;
- m_VtxAttr.texCoord[5].Frac = g_VtxAttr[vtx_attr_group].g2.Tex5Frac;
- m_VtxAttr.texCoord[6].Frac = g_VtxAttr[vtx_attr_group].g2.Tex6Frac;
- m_VtxAttr.texCoord[7].Frac = g_VtxAttr[vtx_attr_group].g2.Tex7Frac;
+void VertexLoader::RunCompiledVertices(int vtx_attr_group, int primitive, int const count, u8* Data)
+{
+ auto const new_count = SetupRunVertices(vtx_attr_group, primitive, count);
- pVtxAttr = &m_VtxAttr;
- posScale = fractionTable[m_VtxAttr.PosFrac];
- if (m_NativeFmt->m_components & VB_HAS_UVALL)
- for (int i = 0; i < 8; i++)
- tcScale[i] = fractionTable[m_VtxAttr.texCoord[i].Frac];
- for (int i = 0; i < 2; i++)
- colElements[i] = m_VtxAttr.color[i].Elements;
+ memcpy_gc(VertexManager::s_pCurBufferPointer, Data, native_stride * new_count);
+ VertexManager::s_pCurBufferPointer += native_stride * new_count;
+ DataSkip(new_count * m_VertexSize);
- if(VertexManager::GetRemainingSize() < native_stride * count)
- VertexManager::Flush();
- memcpy_gc(VertexManager::s_pCurBufferPointer, Data, native_stride * count);
- VertexManager::s_pCurBufferPointer += native_stride * count;
- DataSkip(count * m_VertexSize);
- VertexManager::AddVertices(primitive, count);
+ VertexManager::AddVertices(primitive, new_count);
}
-
-
void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2)
{
VAT vat;
@@ -724,7 +645,7 @@ void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2)
m_VtxAttr.texCoord[2].Frac = vat.g1.Tex2Frac;
m_VtxAttr.texCoord[3].Elements = vat.g1.Tex3CoordElements;
m_VtxAttr.texCoord[3].Format = vat.g1.Tex3CoordFormat;
- m_VtxAttr.texCoord[3].Frac = vat.g1.Tex3Frac;
+ m_VtxAttr.texCoord[3].Frac = vat.g1.Tex3Frac;
m_VtxAttr.texCoord[4].Elements = vat.g1.Tex4CoordElements;
m_VtxAttr.texCoord[4].Format = vat.g1.Tex4CoordFormat;
diff --git a/Source/Core/VideoCommon/Src/VertexLoader.h b/Source/Core/VideoCommon/Src/VertexLoader.h
index 98a57cb9ff..862eabff3e 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader.h
+++ b/Source/Core/VideoCommon/Src/VertexLoader.h
@@ -76,13 +76,20 @@ private:
}
};
+// ARMTODO: This should be done in a better way
+#ifndef _M_GENERIC
class VertexLoader : public Gen::XCodeBlock, NonCopyable
+#else
+class VertexLoader
+#endif
{
public:
VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr);
~VertexLoader();
int GetVertexSize() const {return m_VertexSize;}
+
+ int SetupRunVertices(int vtx_attr_group, int primitive, int const count);
void RunVertices(int vtx_attr_group, int primitive, int count);
void RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data);
@@ -119,11 +126,14 @@ private:
void SetVAT(u32 _group0, u32 _group1, u32 _group2);
void CompileVertexTranslator();
+ void ConvertVertices(int count);
void WriteCall(TPipelineFunction);
+#ifndef _M_GENERIC
void WriteGetVariable(int bits, Gen::OpArg dest, void *address);
void WriteSetVariable(int bits, void *address, Gen::OpArg dest);
-};
+#endif
+};
#endif
diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp b/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp
index 9cfa5efc31..fa1ecbe973 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp
+++ b/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp
@@ -15,9 +15,6 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-#ifndef _VERTEXLOADERCOLOR_H
-#define _VERTEXLOADERCOLOR_H
-
#include "Common.h"
#include "VideoCommon.h"
#include "LookUpTables.h"
@@ -37,8 +34,7 @@ extern int colElements[2];
__forceinline void _SetCol(u32 val)
{
- *(u32*)VertexManager::s_pCurBufferPointer = val;
- VertexManager::s_pCurBufferPointer += 4;
+ DataWrite(val);
colIndex++;
}
@@ -132,80 +128,65 @@ void LOADERDECL Color_ReadDirect_32b_8888()
_SetCol(col);
}
-
-
-void LOADERDECL Color_ReadIndex8_16b_565()
+template <typename I>
+void Color_ReadIndex_16b_565()
{
- u8 Index = DataReadU8();
+ auto const Index = DataRead<I>();
u16 val = Common::swap16(*(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex])));
_SetCol565(val);
}
-void LOADERDECL Color_ReadIndex8_24b_888()
+
+template <typename I>
+void Color_ReadIndex_24b_888()
{
- u8 Index = DataReadU8();
+ auto const Index = DataRead<I>();
const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
_SetCol(_Read24(iAddress));
}
-void LOADERDECL Color_ReadIndex8_32b_888x()
+
+template <typename I>
+void Color_ReadIndex_32b_888x()
{
- u8 Index = DataReadU8();
+ auto const Index = DataRead<I>();
const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
_SetCol(_Read24(iAddress));
}
-void LOADERDECL Color_ReadIndex8_16b_4444()
+
+template <typename I>
+void Color_ReadIndex_16b_4444()
{
- u8 Index = DataReadU8();
+ auto const Index = DataRead<I>();
u16 val = *(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]));
_SetCol4444(val);
}
-void LOADERDECL Color_ReadIndex8_24b_6666()
+
+template <typename I>
+void Color_ReadIndex_24b_6666()
{
- u8 Index = DataReadU8();
+ auto const Index = DataRead<I>();
const u8* pData = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]) - 1;
u32 val = Common::swap32(pData);
_SetCol6666(val);
}
-void LOADERDECL Color_ReadIndex8_32b_8888()
-{
- u8 Index = DataReadU8();
- const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
- _SetCol(_Read32(iAddress));
-}
-void LOADERDECL Color_ReadIndex16_16b_565()
-{
- u16 Index = DataReadU16();
- u16 val = Common::swap16(*(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex])));
- _SetCol565(val);
-}
-void LOADERDECL Color_ReadIndex16_24b_888()
-{
- u16 Index = DataReadU16();
- const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
- _SetCol(_Read24(iAddress));
-}
-void LOADERDECL Color_ReadIndex16_32b_888x()
-{
- u16 Index = DataReadU16();
- const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
- _SetCol(_Read24(iAddress));
-}
-void LOADERDECL Color_ReadIndex16_16b_4444()
-{
- u16 Index = DataReadU16();
- u16 val = *(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]));
- _SetCol4444(val);
-}
-void LOADERDECL Color_ReadIndex16_24b_6666()
-{
- u16 Index = DataReadU16();
- const u8 *pData = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]) - 1;
- u32 val = Common::swap32(pData);
- _SetCol6666(val);
-}
-void LOADERDECL Color_ReadIndex16_32b_8888()
+
+template <typename I>
+void Color_ReadIndex_32b_8888()
{
- u16 Index = DataReadU16();
+ auto const Index = DataRead<I>();
const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
_SetCol(_Read32(iAddress));
}
-#endif
+
+void LOADERDECL Color_ReadIndex8_16b_565() { Color_ReadIndex_16b_565<u8>(); }
+void LOADERDECL Color_ReadIndex8_24b_888() { Color_ReadIndex_24b_888<u8>(); }
+void LOADERDECL Color_ReadIndex8_32b_888x() { Color_ReadIndex_32b_888x<u8>(); }
+void LOADERDECL Color_ReadIndex8_16b_4444() { Color_ReadIndex_16b_4444<u8>(); }
+void LOADERDECL Color_ReadIndex8_24b_6666() { Color_ReadIndex_24b_6666<u8>(); }
+void LOADERDECL Color_ReadIndex8_32b_8888() { Color_ReadIndex_32b_8888<u8>(); }
+
+void LOADERDECL Color_ReadIndex16_16b_565() { Color_ReadIndex_16b_565<u16>(); }
+void LOADERDECL Color_ReadIndex16_24b_888() { Color_ReadIndex_24b_888<u16>(); }
+void LOADERDECL Color_ReadIndex16_32b_888x() { Color_ReadIndex_32b_888x<u16>(); }
+void LOADERDECL Color_ReadIndex16_16b_4444() { Color_ReadIndex_16b_4444<u16>(); }
+void LOADERDECL Color_ReadIndex16_24b_6666() { Color_ReadIndex_24b_6666<u16>(); }
+void LOADERDECL Color_ReadIndex16_32b_8888() { Color_ReadIndex_32b_8888<u16>(); }
diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp b/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp
index 830bd3de13..a5ea1981da 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp
+++ b/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp
@@ -22,6 +22,7 @@
#include "VertexManagerBase.h"
#include "CPUDetect.h"
#include <cmath>
+#include <limits>
#if _M_SSE >= 0x401
#include <smmintrin.h>
@@ -30,398 +31,174 @@
#include <tmmintrin.h>
#endif
+// warning: mapping buffer should be disabled to use this
#define LOG_NORM() // PRIM_LOG("norm: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-3], ((float*)VertexManager::s_pCurBufferPointer)[-2], ((float*)VertexManager::s_pCurBufferPointer)[-1]);
VertexLoader_Normal::Set VertexLoader_Normal::m_Table[NUM_NRM_TYPE][NUM_NRM_INDICES][NUM_NRM_ELEMENTS][NUM_NRM_FORMAT];
-void VertexLoader_Normal::Init(void)
-{
- // HACK is for signed instead of unsigned to prevent crashes.
- m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(3, Normal_DirectByte); //HACK
- m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(3, Normal_DirectByte);
- m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(6, Normal_DirectShort); //HACK
- m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(6, Normal_DirectShort);
- m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(12, Normal_DirectFloat);
- m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(9, Normal_DirectByte3); //HACK
- m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(9, Normal_DirectByte3);
- m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(18, Normal_DirectShort3); //HACK
- m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(18, Normal_DirectShort3);
- m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(36, Normal_DirectFloat3);
-
- m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(3, Normal_DirectByte); //HACK
- m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(3, Normal_DirectByte);
- m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(6, Normal_DirectShort); //HACK
- m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(6, Normal_DirectShort);
- m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(12, Normal_DirectFloat);
- m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(9, Normal_DirectByte3); //HACK
- m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(9, Normal_DirectByte3);
- m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(18, Normal_DirectShort3); //HACK
- m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(18, Normal_DirectShort3);
- m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(36, Normal_DirectFloat3);
-
- m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(1, Normal_Index8_Byte); //HACK
- m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(1, Normal_Index8_Byte);
- m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(1, Normal_Index8_Short); //HACK
- m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(1, Normal_Index8_Short);
- m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(1, Normal_Index8_Float);
- m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(1, Normal_Index8_Byte3_Indices1); //HACK
- m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(1, Normal_Index8_Byte3_Indices1);
- m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(1, Normal_Index8_Short3_Indices1); //HACK
- m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(1, Normal_Index8_Short3_Indices1);
- m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(1, Normal_Index8_Float3_Indices1);
-
- m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(1, Normal_Index8_Byte); //HACK
- m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(1, Normal_Index8_Byte);
- m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(1, Normal_Index8_Short); //HACK
- m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(1, Normal_Index8_Short);
- m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(1, Normal_Index8_Float);
- m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(3, Normal_Index8_Byte3_Indices3); //HACK
- m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(3, Normal_Index8_Byte3_Indices3);
- m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(3, Normal_Index8_Short3_Indices3); //HACK
- m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(3, Normal_Index8_Short3_Indices3);
- m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(3, Normal_Index8_Float3_Indices3);
-
- m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(2, Normal_Index16_Byte); //HACK
- m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(2, Normal_Index16_Byte);
- m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(2, Normal_Index16_Short); //HACK
- m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(2, Normal_Index16_Short);
- m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(2, Normal_Index16_Float);
- m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(2, Normal_Index16_Byte3_Indices1); //HACK
- m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(2, Normal_Index16_Byte3_Indices1);
- m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(2, Normal_Index16_Short3_Indices1); //HACK
- m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(2, Normal_Index16_Short3_Indices1);
- m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(2, Normal_Index16_Float3_Indices1);
-
- m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(2, Normal_Index16_Byte); //HACK
- m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(2, Normal_Index16_Byte);
- m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(2, Normal_Index16_Short); //HACK
- m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(2, Normal_Index16_Short);
- m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(2, Normal_Index16_Float);
- m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(6, Normal_Index16_Byte3_Indices3); //HACK
- m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(6, Normal_Index16_Byte3_Indices3);
- m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(6, Normal_Index16_Short3_Indices3); //HACK
- m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(6, Normal_Index16_Short3_Indices3);
- m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(6, Normal_Index16_Float3_Indices3);
-}
-
-unsigned int VertexLoader_Normal::GetSize(unsigned int _type,
- unsigned int _format, unsigned int _elements, unsigned int _index3)
+namespace
{
- return m_Table[_type][_index3][_elements][_format].gc_size;
-}
-
-TPipelineFunction VertexLoader_Normal::GetFunction(unsigned int _type,
- unsigned int _format, unsigned int _elements, unsigned int _index3)
-{
- TPipelineFunction pFunc = m_Table[_type][_index3][_elements][_format].function;
- return pFunc;
-}
-// This fracs are fixed acording to format
-#define S8FRAC 0.015625f; // 1.0f / (1U << 6)
-#define S16FRAC 0.00006103515625f; // 1.0f / (1U << 14)
-// --- Direct ---
-
-inline void ReadIndirectS8x3(const s8* pData)
+template <typename T>
+__forceinline float FracAdjust(T val)
{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = pData[0] * S8FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[1] = pData[1] * S8FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[2] = pData[2] * S8FRAC;
- VertexManager::s_pCurBufferPointer += 12;
- LOG_NORM();
-}
+ //auto const S8FRAC = 1.f / (1u << 6);
+ //auto const U8FRAC = 1.f / (1u << 7);
+ //auto const S16FRAC = 1.f / (1u << 14);
+ //auto const U16FRAC = 1.f / (1u << 15);
-inline void ReadIndirectS8x9(const s8* pData)
-{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = pData[0] * S8FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[1] = pData[1] * S8FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[2] = pData[2] * S8FRAC;
- LOG_NORM();
- ((float*)VertexManager::s_pCurBufferPointer)[3] = pData[3] * S8FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[4] = pData[4] * S8FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[5] = pData[5] * S8FRAC;
- LOG_NORM();
- ((float*)VertexManager::s_pCurBufferPointer)[6] = pData[6] * S8FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[7] = pData[7] * S8FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[8] = pData[8] * S8FRAC;
- LOG_NORM();
- VertexManager::s_pCurBufferPointer += 36;
+ // TODO: is this right?
+ return val / float(1u << (sizeof(T) * 8 - std::numeric_limits<T>::is_signed - 1));
}
-inline void ReadIndirectS16x3(const u16* pData)
-{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = ((s16)Common::swap16(pData[0])) * S16FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[1] = ((s16)Common::swap16(pData[1])) * S16FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[2] = ((s16)Common::swap16(pData[2])) * S16FRAC;
- VertexManager::s_pCurBufferPointer += 12;
- LOG_NORM()
-}
+template <>
+__forceinline float FracAdjust(float val)
+{ return val; }
-inline void ReadIndirectS16x9(const u16* pData)
+template <typename T, int N>
+__forceinline void ReadIndirect(const T* data)
{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = ((s16)Common::swap16(pData[0])) * S16FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[1] = ((s16)Common::swap16(pData[1])) * S16FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[2] = ((s16)Common::swap16(pData[2])) * S16FRAC;
- LOG_NORM()
- ((float*)VertexManager::s_pCurBufferPointer)[3] = ((s16)Common::swap16(pData[3])) * S16FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[4] = ((s16)Common::swap16(pData[4])) * S16FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[5] = ((s16)Common::swap16(pData[5])) * S16FRAC;
- LOG_NORM()
- ((float*)VertexManager::s_pCurBufferPointer)[6] = ((s16)Common::swap16(pData[6])) * S16FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[7] = ((s16)Common::swap16(pData[7])) * S16FRAC;
- ((float*)VertexManager::s_pCurBufferPointer)[8] = ((s16)Common::swap16(pData[8])) * S16FRAC;
- LOG_NORM()
- VertexManager::s_pCurBufferPointer += 36;
-}
+ static_assert(3 == N || 9 == N, "N is only sane as 3 or 9!");
-inline void ReadIndirectFloatx3(const u32* pData)
-{
- ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
- ((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]);
- ((u32*)VertexManager::s_pCurBufferPointer)[2] = Common::swap32(pData[2]);
- VertexManager::s_pCurBufferPointer += 12;
- LOG_NORM();
-}
+ for (int i = 0; i != N; ++i)
+ {
+ DataWrite(FracAdjust(Common::FromBigEndian(data[i])));
+ }
-inline void ReadIndirectFloatx9(const u32* pData)
-{
- ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
- ((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]);
- ((u32*)VertexManager::s_pCurBufferPointer)[2] = Common::swap32(pData[2]);
- LOG_NORM();
- ((u32*)VertexManager::s_pCurBufferPointer)[3] = Common::swap32(pData[3]);
- ((u32*)VertexManager::s_pCurBufferPointer)[4] = Common::swap32(pData[4]);
- ((u32*)VertexManager::s_pCurBufferPointer)[5] = Common::swap32(pData[5]);
LOG_NORM();
- ((u32*)VertexManager::s_pCurBufferPointer)[6] = Common::swap32(pData[6]);
- ((u32*)VertexManager::s_pCurBufferPointer)[7] = Common::swap32(pData[7]);
- ((u32*)VertexManager::s_pCurBufferPointer)[8] = Common::swap32(pData[8]);
- LOG_NORM();
- VertexManager::s_pCurBufferPointer += 36;
-}
-
-inline void ReadDirectS8x3()
-{
- const s8* Source = (const s8*)DataGetPosition();
- ReadIndirectS8x3(Source);
- DataSkip(3);
}
-inline void ReadDirectS8x9()
+template <typename T, int N>
+struct Normal_Direct
{
- const s8* Source = (const s8*)DataGetPosition();
- ReadIndirectS8x9(Source);
- DataSkip(9);
-}
-
-inline void ReadDirectS16x3()
-{
- const u16* Source = (const u16*)DataGetPosition();
- ReadIndirectS16x3(Source);
- DataSkip(6);
-}
-
-inline void ReadDirectS16x9()
-{
- const u16* Source = (const u16*)DataGetPosition();
- ReadIndirectS16x9(Source);
- DataSkip(18);
-}
-
-inline void ReadDirectFloatx3()
-{
- const u32* Source = (const u32*)DataGetPosition();
- ReadIndirectFloatx3(Source);
- DataSkip(12);
-}
-
-inline void ReadDirectFloatx9()
-{
- const u32* Source = (const u32*)DataGetPosition();
- ReadIndirectFloatx9(Source);
- DataSkip(36);
-}
-
-
-
-void LOADERDECL VertexLoader_Normal::Normal_DirectByte()
-{
- ReadDirectS8x3();
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_DirectShort()
-{
- ReadDirectS16x3();
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_DirectFloat()
-{
- ReadDirectFloatx3();
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_DirectByte3()
-{
- ReadDirectS8x9();
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_DirectShort3()
-{
- ReadDirectS16x9();
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_DirectFloat3()
-{
- ReadDirectFloatx9();
-}
-
-
-// --- Index8 ---
-
-void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte()
-{
- u8 Index = DataReadU8();
- const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectS8x3(pData);
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_Index8_Short()
-{
- u8 Index = DataReadU8();
- const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectS16x3(pData);
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_Index8_Float()
-{
- u8 Index = DataReadU8();
- const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectFloatx3(pData);
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte3_Indices1()
-{
- u8 Index = DataReadU8();
- const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectS8x9(pData);
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_Index8_Short3_Indices1()
-{
- u8 Index = DataReadU8();
- const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectS16x9(pData);
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_Index8_Float3_Indices1()
-{
- u8 Index = DataReadU8();
- const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectFloatx9(pData);
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte3_Indices3()
-{
- for (int i = 0; i < 3; i++)
+ static void LOADERDECL function()
{
- u8 Index = DataReadU8();
- const s8* pData = (const s8*)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i);
- ReadIndirectS8x3(pData);
- }
-}
+ auto const source = reinterpret_cast<const T*>(DataGetPosition());
+ ReadIndirect<T, N * 3>(source);
+ DataSkip<N * 3 * sizeof(T)>();
+ }
+ static const int size = sizeof(T) * N * 3;
+};
-void LOADERDECL VertexLoader_Normal::Normal_Index8_Short3_Indices3()
+template <typename I, typename T, int N, int Offset>
+__forceinline void Normal_Index_Offset()
{
- for (int i = 0; i < 3; i++)
- {
- u8 Index = DataReadU8();
- const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i);
- ReadIndirectS16x3(pData);
- }
+ static_assert(!std::numeric_limits<I>::is_signed, "Only unsigned I is sane!");
+
+ auto const index = DataRead<I>();
+ auto const data = reinterpret_cast<const T*>(cached_arraybases[ARRAY_NORMAL]
+ + (index * arraystrides[ARRAY_NORMAL]) + sizeof(T) * 3 * Offset);
+ ReadIndirect<T, N * 3>(data);
}
-void LOADERDECL VertexLoader_Normal::Normal_Index8_Float3_Indices3()
+template <typename I, typename T, int N>
+struct Normal_Index
{
- for (int i = 0; i < 3; i++)
+ static void LOADERDECL function()
{
- u8 Index = DataReadU8();
- const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i);
- ReadIndirectFloatx3(pData);
- }
-}
+ Normal_Index_Offset<I, T, N, 0>();
+ }
+ static const int size = sizeof(I);
+};
-// --- Index16 ---
-
-
-void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte()
-{
- u16 Index = DataReadU16();
- const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectS8x3(pData);
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_Index16_Short()
-{
- u16 Index = DataReadU16();
- const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectS16x3(pData);
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_Index16_Float()
-{
- u16 Index = DataReadU16();
- const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectFloatx3(pData);
-}
-
-void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte3_Indices1()
+template <typename I, typename T>
+struct Normal_Index_Indices3
{
- u16 Index = DataReadU16();
- const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectS8x9(pData);
-}
+ static void LOADERDECL function()
+ {
+ Normal_Index_Offset<I, T, 1, 0>();
+ Normal_Index_Offset<I, T, 1, 1>();
+ Normal_Index_Offset<I, T, 1, 2>();
+ }
-void LOADERDECL VertexLoader_Normal::Normal_Index16_Short3_Indices1()
-{
- u16 Index = DataReadU16();
- const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectS16x9(pData);
-}
+ static const int size = sizeof(I) * 3;
+};
-void LOADERDECL VertexLoader_Normal::Normal_Index16_Float3_Indices1()
-{
- u16 Index = DataReadU16();
- const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
- ReadIndirectFloatx9(pData);
}
-void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte3_Indices3()
+void VertexLoader_Normal::Init(void)
{
- for (int i = 0; i < 3; i++)
- {
- u16 Index = DataReadU16();
- const s8* pData = (const s8*)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i);
- ReadIndirectS8x3(pData);
- }
+ m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Normal_Direct<u8, 1>();
+ m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Normal_Direct<s8, 1>();
+ m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Normal_Direct<u16, 1>();
+ m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Normal_Direct<s16, 1>();
+ m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Normal_Direct<float, 1>();
+ m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Normal_Direct<u8, 3>();
+ m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Normal_Direct<s8, 3>();
+ m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Normal_Direct<u16, 3>();
+ m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Normal_Direct<s16, 3>();
+ m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Normal_Direct<float, 3>();
+
+ // Same as above
+ m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Normal_Direct<u8, 1>();
+ m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Normal_Direct<s8, 1>();
+ m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Normal_Direct<u16, 1>();
+ m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Normal_Direct<s16, 1>();
+ m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Normal_Direct<float, 1>();
+ m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Normal_Direct<u8, 3>();
+ m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Normal_Direct<s8, 3>();
+ m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Normal_Direct<u16, 3>();
+ m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Normal_Direct<s16, 3>();
+ m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Normal_Direct<float, 3>();
+
+ m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Normal_Index<u8, u8, 1>();
+ m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Normal_Index<u8, s8, 1>();
+ m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Normal_Index<u8, u16, 1>();
+ m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Normal_Index<u8, s16, 1>();
+ m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Normal_Index<u8, float, 1>();
+ m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Normal_Index<u8, u8, 3>();
+ m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Normal_Index<u8, s8, 3>();
+ m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Normal_Index<u8, u16, 3>();
+ m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Normal_Index<u8, s16, 3>();
+ m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Normal_Index<u8, float, 3>();
+
+ // Same as above for NRM_NBT
+ m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Normal_Index<u8, u8, 1>();
+ m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Normal_Index<u8, s8, 1>();
+ m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Normal_Index<u8, u16, 1>();
+ m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Normal_Index<u8, s16, 1>();
+ m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Normal_Index<u8, float, 1>();
+ m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Normal_Index_Indices3<u8, u8>();
+ m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Normal_Index_Indices3<u8, s8>();
+ m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Normal_Index_Indices3<u8, u16>();
+ m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Normal_Index_Indices3<u8, s16>();
+ m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Normal_Index_Indices3<u8, float>();
+
+ m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Normal_Index<u16, u8, 1>();
+ m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Normal_Index<u16, s8, 1>();
+ m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Normal_Index<u16, u16, 1>();
+ m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Normal_Index<u16, s16, 1>();
+ m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Normal_Index<u16, float, 1>();
+ m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Normal_Index<u16, u8, 3>();
+ m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Normal_Index<u16, s8, 3>();
+ m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Normal_Index<u16, u16, 3>();
+ m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Normal_Index<u16, s16, 3>();
+ m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Normal_Index<u16, float, 3>();
+
+ // Same as above for NRM_NBT
+ m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Normal_Index<u16, u8, 1>();
+ m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Normal_Index<u16, s8, 1>();
+ m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Normal_Index<u16, u16, 1>();
+ m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Normal_Index<u16, s16, 1>();
+ m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Normal_Index<u16, float, 1>();
+ m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Normal_Index_Indices3<u16, u8>();
+ m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Normal_Index_Indices3<u16, s8>();
+ m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Normal_Index_Indices3<u16, u16>();
+ m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Normal_Index_Indices3<u16, s16>();
+ m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Normal_Index_Indices3<u16, float>();
}
-void LOADERDECL VertexLoader_Normal::Normal_Index16_Short3_Indices3()
+unsigned int VertexLoader_Normal::GetSize(unsigned int _type,
+ unsigned int _format, unsigned int _elements, unsigned int _index3)
{
- for (int i = 0; i < 3; i++)
- {
- u16 Index = DataReadU16();
- const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i);
- ReadIndirectS16x3(pData);
- }
+ return m_Table[_type][_index3][_elements][_format].gc_size;
}
-void LOADERDECL VertexLoader_Normal::Normal_Index16_Float3_Indices3()
+TPipelineFunction VertexLoader_Normal::GetFunction(unsigned int _type,
+ unsigned int _format, unsigned int _elements, unsigned int _index3)
{
- for (int i = 0; i < 3; i++)
- {
- u16 Index = DataReadU16();
- const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i);
- ReadIndirectFloatx3(pData);
- }
+ TPipelineFunction pFunc = m_Table[_type][_index3][_elements][_format].function;
+ return pFunc;
}
diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Normal.h b/Source/Core/VideoCommon/Src/VertexLoader_Normal.h
index 934cd1ec43..a631ab9751 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader_Normal.h
+++ b/Source/Core/VideoCommon/Src/VertexLoader_Normal.h
@@ -25,43 +25,43 @@ class VertexLoader_Normal
{
public:
- // Init
- static void Init(void);
+ // Init
+ static void Init(void);
- // GetSize
- static unsigned int GetSize(unsigned int _type, unsigned int _format,
+ // GetSize
+ static unsigned int GetSize(unsigned int _type, unsigned int _format,
unsigned int _elements, unsigned int _index3);
- // GetFunction
- static TPipelineFunction GetFunction(unsigned int _type,
+ // GetFunction
+ static TPipelineFunction GetFunction(unsigned int _type,
unsigned int _format, unsigned int _elements, unsigned int _index3);
private:
- enum ENormalType
- {
- NRM_NOT_PRESENT = 0,
- NRM_DIRECT = 1,
- NRM_INDEX8 = 2,
- NRM_INDEX16 = 3,
- NUM_NRM_TYPE
- };
-
- enum ENormalFormat
- {
- FORMAT_UBYTE = 0,
- FORMAT_BYTE = 1,
- FORMAT_USHORT = 2,
- FORMAT_SHORT = 3,
- FORMAT_FLOAT = 4,
- NUM_NRM_FORMAT
- };
-
- enum ENormalElements
- {
- NRM_NBT = 0,
- NRM_NBT3 = 1,
- NUM_NRM_ELEMENTS
- };
+ enum ENormalType
+ {
+ NRM_NOT_PRESENT = 0,
+ NRM_DIRECT = 1,
+ NRM_INDEX8 = 2,
+ NRM_INDEX16 = 3,
+ NUM_NRM_TYPE
+ };
+
+ enum ENormalFormat
+ {
+ FORMAT_UBYTE = 0,
+ FORMAT_BYTE = 1,
+ FORMAT_USHORT = 2,
+ FORMAT_SHORT = 3,
+ FORMAT_FLOAT = 4,
+ NUM_NRM_FORMAT
+ };
+
+ enum ENormalElements
+ {
+ NRM_NBT = 0,
+ NRM_NBT3 = 1,
+ NUM_NRM_ELEMENTS
+ };
enum ENormalIndices
{
@@ -70,45 +70,20 @@ private:
NUM_NRM_INDICES
};
- struct Set {
- Set() {}
- Set(int gc_size_, TPipelineFunction function_) : gc_size(gc_size_), function(function_) {}
+ struct Set
+ {
+ template <typename T>
+ void operator=(const T&)
+ {
+ gc_size = T::size;
+ function = T::function;
+ }
+
int gc_size;
TPipelineFunction function;
-// int pc_size;
};
static Set m_Table[NUM_NRM_TYPE][NUM_NRM_INDICES][NUM_NRM_ELEMENTS][NUM_NRM_FORMAT];
-
- // direct
- static void LOADERDECL Normal_DirectByte();
- static void LOADERDECL Normal_DirectShort();
- static void LOADERDECL Normal_DirectFloat();
- static void LOADERDECL Normal_DirectByte3();
- static void LOADERDECL Normal_DirectShort3();
- static void LOADERDECL Normal_DirectFloat3();
-
- // index8
- static void LOADERDECL Normal_Index8_Byte();
- static void LOADERDECL Normal_Index8_Short();
- static void LOADERDECL Normal_Index8_Float();
- static void LOADERDECL Normal_Index8_Byte3_Indices1();
- static void LOADERDECL Normal_Index8_Short3_Indices1();
- static void LOADERDECL Normal_Index8_Float3_Indices1();
- static void LOADERDECL Normal_Index8_Byte3_Indices3();
- static void LOADERDECL Normal_Index8_Short3_Indices3();
- static void LOADERDECL Normal_Index8_Float3_Indices3();
-
- // index16
- static void LOADERDECL Normal_Index16_Byte();
- static void LOADERDECL Normal_Index16_Short();
- static void LOADERDECL Normal_Index16_Float();
- static void LOADERDECL Normal_Index16_Byte3_Indices1();
- static void LOADERDECL Normal_Index16_Short3_Indices1();
- static void LOADERDECL Normal_Index16_Float3_Indices1();
- static void LOADERDECL Normal_Index16_Byte3_Indices3();
- static void LOADERDECL Normal_Index16_Short3_Indices3();
- static void LOADERDECL Normal_Index16_Float3_Indices3();
};
#endif
diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp b/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp
index 06481f9ddf..fd902767be 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp
+++ b/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp
@@ -15,6 +15,8 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+#include <limits>
+
#include "Common.h"
#include "VideoCommon.h"
#include "VertexLoader.h"
@@ -71,101 +73,42 @@ MOVUPS(MOffset(EDI, 0), XMM0);
*/
-// ==============================================================================
-// Direct
-// ==============================================================================
-
-template <class T, bool three>
-void Pos_ReadDirect()
+template <typename T>
+float PosScale(T val)
{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(T)DataRead<T>() * posScale;
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(T)DataRead<T>() * posScale;
- if (three)
- ((float*)VertexManager::s_pCurBufferPointer)[2] = (float)(T)DataRead<T>() * posScale;
- else
- ((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f;
- LOG_VTX();
- VertexManager::s_pCurBufferPointer += 12;
+ return val * posScale;
}
-void LOADERDECL Pos_ReadDirect_UByte3() { Pos_ReadDirect<u8, true>(); }
-void LOADERDECL Pos_ReadDirect_Byte3() { Pos_ReadDirect<s8, true>(); }
-void LOADERDECL Pos_ReadDirect_UShort3() { Pos_ReadDirect<u16, true>(); }
-void LOADERDECL Pos_ReadDirect_Short3() { Pos_ReadDirect<s16, true>(); }
-void LOADERDECL Pos_ReadDirect_UByte2() { Pos_ReadDirect<u8, false>(); }
-void LOADERDECL Pos_ReadDirect_Byte2() { Pos_ReadDirect<s8, false>(); }
-void LOADERDECL Pos_ReadDirect_UShort2() { Pos_ReadDirect<u16, false>(); }
-void LOADERDECL Pos_ReadDirect_Short2() { Pos_ReadDirect<s16, false>(); }
+template <>
+float PosScale(float val)
+{ return val; }
-void LOADERDECL Pos_ReadDirect_Float3()
+template <typename T, int N>
+void LOADERDECL Pos_ReadDirect()
{
- // No need to use floating point here.
- ((u32 *)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
- ((u32 *)VertexManager::s_pCurBufferPointer)[1] = DataReadU32();
- ((u32 *)VertexManager::s_pCurBufferPointer)[2] = DataReadU32();
- LOG_VTX();
- VertexManager::s_pCurBufferPointer += 12;
-}
+ static_assert(N <= 3, "N > 3 is not sane!");
+
+ for (int i = 0; i < 3; ++i)
+ DataWrite(i<N ? PosScale(DataRead<T>()) : 0.f);
-void LOADERDECL Pos_ReadDirect_Float2()
-{
- // No need to use floating point here.
- ((u32 *)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
- ((u32 *)VertexManager::s_pCurBufferPointer)[1] = DataReadU32();
- ((u32 *)VertexManager::s_pCurBufferPointer)[2] = 0;
LOG_VTX();
- VertexManager::s_pCurBufferPointer += 12;
}
-
-template<class T, bool three,int MaxSize>
-inline void Pos_ReadIndex_Byte(int Index)
+template <typename I, typename T, int N>
+void LOADERDECL Pos_ReadIndex()
{
- if(Index < MaxSize)
- {
- const u8* pData = cached_arraybases[ARRAY_POSITION] + ((u32)Index * arraystrides[ARRAY_POSITION]);
- ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(T)(pData[0])) * posScale;
- ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(T)(pData[1])) * posScale;
- if (three)
- ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(T)(pData[2])) * posScale;
- else
- ((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f;
- LOG_VTX();
- VertexManager::s_pCurBufferPointer += 12;
- }
-}
+ static_assert(!std::numeric_limits<I>::is_signed, "Only unsigned I is sane!");
+ static_assert(N <= 3, "N > 3 is not sane!");
-template<class T, bool three,int MaxSize>
-inline void Pos_ReadIndex_Short(int Index)
-{
- if(Index < MaxSize)
+ auto const index = DataRead<I>();
+ if (index < std::numeric_limits<I>::max())
{
- const u16* pData = (const u16 *)(cached_arraybases[ARRAY_POSITION] + ((u32)Index * arraystrides[ARRAY_POSITION]));
- ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(T)Common::swap16(pData[0])) * posScale;
- ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(T)Common::swap16(pData[1])) * posScale;
- if (three)
- ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(T)Common::swap16(pData[2])) * posScale;
- else
- ((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f;
- LOG_VTX();
- VertexManager::s_pCurBufferPointer += 12;
- }
-}
+ auto const data = reinterpret_cast<const T*>(cached_arraybases[ARRAY_POSITION] + (index * arraystrides[ARRAY_POSITION]));
+
+ for (int i = 0; i < 3; ++i)
+ DataWrite(i<N ? PosScale(Common::FromBigEndian(data[i])) : 0.f);
-template<bool three,int MaxSize>
-void Pos_ReadIndex_Float(int Index)
-{
- if(Index < MaxSize)
- {
- const u32* pData = (const u32 *)(cached_arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]));
- ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
- ((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]);
- if (three)
- ((u32*)VertexManager::s_pCurBufferPointer)[2] = Common::swap32(pData[2]);
- else
- ((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f;
LOG_VTX();
- VertexManager::s_pCurBufferPointer += 12;
}
}
@@ -173,87 +116,22 @@ void Pos_ReadIndex_Float(int Index)
static const __m128i kMaskSwap32_3 = _mm_set_epi32(0xFFFFFFFFL, 0x08090A0BL, 0x04050607L, 0x00010203L);
static const __m128i kMaskSwap32_2 = _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x04050607L, 0x00010203L);
-template<bool three,int MaxSize>
-void Pos_ReadIndex_Float_SSSE3(int Index)
+template <typename I, bool three>
+void LOADERDECL Pos_ReadIndex_Float_SSSE3()
{
- if(Index < MaxSize)
+ auto const index = DataRead<I>();
+ if (index < std::numeric_limits<I>::max())
{
- const u32* pData = (const u32 *)(cached_arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]));
+ const u32* pData = (const u32 *)(cached_arraybases[ARRAY_POSITION] + (index * arraystrides[ARRAY_POSITION]));
GC_ALIGNED128(const __m128i a = _mm_loadu_si128((__m128i*)pData));
GC_ALIGNED128(__m128i b = _mm_shuffle_epi8(a, three ? kMaskSwap32_3 : kMaskSwap32_2));
_mm_storeu_si128((__m128i*)VertexManager::s_pCurBufferPointer, b);
+ VertexManager::s_pCurBufferPointer += sizeof(float) * 3;
LOG_VTX();
- VertexManager::s_pCurBufferPointer += 12;
}
}
#endif
-// Explicitly instantiate these functions to decrease the possibility of
-// symbol binding problems when (only) calling them from JIT compiled code.
-template void Pos_ReadDirect<u8, true>();
-template void Pos_ReadDirect<s8, true>();
-template void Pos_ReadDirect<u16, true>();
-template void Pos_ReadDirect<s16, true>();
-template void Pos_ReadDirect<u8, false>();
-template void Pos_ReadDirect<s8, false>();
-template void Pos_ReadDirect<u16, false>();
-template void Pos_ReadDirect<s16, false>();
-template void Pos_ReadIndex_Byte<u8, true, 255>(int Index);
-template void Pos_ReadIndex_Byte<s8, true, 255>(int Index);
-template void Pos_ReadIndex_Short<u16, true, 255>(int Index);
-template void Pos_ReadIndex_Short<s16, true, 255>(int Index);
-template void Pos_ReadIndex_Float<true, 255>(int Index);
-template void Pos_ReadIndex_Byte<u8, false, 255>(int Index);
-template void Pos_ReadIndex_Byte<s8, false, 255>(int Index);
-template void Pos_ReadIndex_Short<u16, false, 255>(int Index);
-template void Pos_ReadIndex_Short<s16, false, 255>(int Index);
-template void Pos_ReadIndex_Float<false, 255>(int Index);
-template void Pos_ReadIndex_Byte<u8, true, 65535>(int Index);
-template void Pos_ReadIndex_Byte<s8, true, 65535>(int Index);
-template void Pos_ReadIndex_Short<u16, true, 65535>(int Index);
-template void Pos_ReadIndex_Short<s16, true, 65535>(int Index);
-template void Pos_ReadIndex_Float<true, 65535>(int Index);
-template void Pos_ReadIndex_Byte<u8, false, 65535>(int Index);
-template void Pos_ReadIndex_Byte<s8, false, 65535>(int Index);
-template void Pos_ReadIndex_Short<u16, false, 65535>(int Index);
-template void Pos_ReadIndex_Short<s16, false, 65535>(int Index);
-template void Pos_ReadIndex_Float<false, 65535>(int Index);
-
-// ==============================================================================
-// Index 8
-// ==============================================================================
-void LOADERDECL Pos_ReadIndex8_UByte3() {Pos_ReadIndex_Byte<u8, true, 255> (DataReadU8());}
-void LOADERDECL Pos_ReadIndex8_Byte3() {Pos_ReadIndex_Byte<s8, true, 255> (DataReadU8());}
-void LOADERDECL Pos_ReadIndex8_UShort3() {Pos_ReadIndex_Short<u16, true, 255> (DataReadU8());}
-void LOADERDECL Pos_ReadIndex8_Short3() {Pos_ReadIndex_Short<s16, true, 255> (DataReadU8());}
-void LOADERDECL Pos_ReadIndex8_Float3() {Pos_ReadIndex_Float<true, 255> (DataReadU8());}
-void LOADERDECL Pos_ReadIndex8_UByte2() {Pos_ReadIndex_Byte<u8, false, 255>(DataReadU8());}
-void LOADERDECL Pos_ReadIndex8_Byte2() {Pos_ReadIndex_Byte<s8, false, 255>(DataReadU8());}
-void LOADERDECL Pos_ReadIndex8_UShort2() {Pos_ReadIndex_Short<u16, false, 255>(DataReadU8());}
-void LOADERDECL Pos_ReadIndex8_Short2() {Pos_ReadIndex_Short<s16, false, 255>(DataReadU8());}
-void LOADERDECL Pos_ReadIndex8_Float2() {Pos_ReadIndex_Float<false, 255> (DataReadU8());}
-
-// ==============================================================================
-// Index 16
-// ==============================================================================
-void LOADERDECL Pos_ReadIndex16_UByte3() {Pos_ReadIndex_Byte<u8, true, 65535> (DataReadU16());}
-void LOADERDECL Pos_ReadIndex16_Byte3() {Pos_ReadIndex_Byte<s8, true, 65535> (DataReadU16());}
-void LOADERDECL Pos_ReadIndex16_UShort3() {Pos_ReadIndex_Short<u16, true, 65535> (DataReadU16());}
-void LOADERDECL Pos_ReadIndex16_Short3() {Pos_ReadIndex_Short<s16, true, 65535> (DataReadU16());}
-void LOADERDECL Pos_ReadIndex16_Float3() {Pos_ReadIndex_Float<true, 65535> (DataReadU16());}
-void LOADERDECL Pos_ReadIndex16_UByte2() {Pos_ReadIndex_Byte<u8, false, 65535>(DataReadU16());}
-void LOADERDECL Pos_ReadIndex16_Byte2() {Pos_ReadIndex_Byte<s8, false, 65535>(DataReadU16());}
-void LOADERDECL Pos_ReadIndex16_UShort2() {Pos_ReadIndex_Short<u16, false, 65535>(DataReadU16());}
-void LOADERDECL Pos_ReadIndex16_Short2() {Pos_ReadIndex_Short<s16, false, 65535>(DataReadU16());}
-void LOADERDECL Pos_ReadIndex16_Float2() {Pos_ReadIndex_Float<false, 65535> (DataReadU16());}
-
-#if _M_SSE >= 0x301
-void LOADERDECL Pos_ReadIndex8_Float3_SSSE3() {Pos_ReadIndex_Float_SSSE3<true, 255> (DataReadU8());}
-void LOADERDECL Pos_ReadIndex8_Float2_SSSE3() {Pos_ReadIndex_Float_SSSE3<false, 255> (DataReadU8());}
-void LOADERDECL Pos_ReadIndex16_Float3_SSSE3() {Pos_ReadIndex_Float_SSSE3<true, 65535> (DataReadU16());}
-void LOADERDECL Pos_ReadIndex16_Float2_SSSE3() {Pos_ReadIndex_Float_SSSE3<false, 65535> (DataReadU16());}
-#endif
-
static TPipelineFunction tableReadPosition[4][8][2] = {
{
{NULL, NULL,},
@@ -263,56 +141,40 @@ static TPipelineFunction tableReadPosition[4][8][2] = {
{NULL, NULL,},
},
{
- {Pos_ReadDirect_UByte2, Pos_ReadDirect_UByte3,},
- {Pos_ReadDirect_Byte2, Pos_ReadDirect_Byte3,},
- {Pos_ReadDirect_UShort2, Pos_ReadDirect_UShort3,},
- {Pos_ReadDirect_Short2, Pos_ReadDirect_Short3,},
- {Pos_ReadDirect_Float2, Pos_ReadDirect_Float3,},
+ {Pos_ReadDirect<u8, 2>, Pos_ReadDirect<u8, 3>,},
+ {Pos_ReadDirect<s8, 2>, Pos_ReadDirect<s8, 3>,},
+ {Pos_ReadDirect<u16, 2>, Pos_ReadDirect<u16, 3>,},
+ {Pos_ReadDirect<s16, 2>, Pos_ReadDirect<s16, 3>,},
+ {Pos_ReadDirect<float, 2>, Pos_ReadDirect<float, 3>,},
},
{
- {Pos_ReadIndex8_UByte2, Pos_ReadIndex8_UByte3,},
- {Pos_ReadIndex8_Byte2, Pos_ReadIndex8_Byte3,},
- {Pos_ReadIndex8_UShort2, Pos_ReadIndex8_UShort3,},
- {Pos_ReadIndex8_Short2, Pos_ReadIndex8_Short3,},
- {Pos_ReadIndex8_Float2, Pos_ReadIndex8_Float3,},
+ {Pos_ReadIndex<u8, u8, 2>, Pos_ReadIndex<u8, u8, 3>,},
+ {Pos_ReadIndex<u8, s8, 2>, Pos_ReadIndex<u8, s8, 3>,},
+ {Pos_ReadIndex<u8, u16, 2>, Pos_ReadIndex<u8, u16, 3>,},
+ {Pos_ReadIndex<u8, s16, 2>, Pos_ReadIndex<u8, s16, 3>,},
+ {Pos_ReadIndex<u8, float, 2>, Pos_ReadIndex<u8, float, 3>,},
},
{
- {Pos_ReadIndex16_UByte2, Pos_ReadIndex16_UByte3,},
- {Pos_ReadIndex16_Byte2, Pos_ReadIndex16_Byte3,},
- {Pos_ReadIndex16_UShort2, Pos_ReadIndex16_UShort3,},
- {Pos_ReadIndex16_Short2, Pos_ReadIndex16_Short3,},
- {Pos_ReadIndex16_Float2, Pos_ReadIndex16_Float3,},
+ {Pos_ReadIndex<u16, u8, 2>, Pos_ReadIndex<u16, u8, 3>,},
+ {Pos_ReadIndex<u16, s8, 2>, Pos_ReadIndex<u16, s8, 3>,},
+ {Pos_ReadIndex<u16, u16, 2>, Pos_ReadIndex<u16, u16, 3>,},
+ {Pos_ReadIndex<u16, s16, 2>, Pos_ReadIndex<u16, s16, 3>,},
+ {Pos_ReadIndex<u16, float, 2>, Pos_ReadIndex<u16, float, 3>,},
},
};
static int tableReadPositionVertexSize[4][8][2] = {
{
- {0, 0,},
- {0, 0,},
- {0, 0,},
- {0, 0,},
- {0, 0,},
+ {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,},
},
{
- {2, 3,},
- {2, 3,},
- {4, 6,},
- {4, 6,},
- {8, 12,},
+ {2, 3,}, {2, 3,}, {4, 6,}, {4, 6,}, {8, 12,},
},
{
- {1, 1,},
- {1, 1,},
- {1, 1,},
- {1, 1,},
- {1, 1,},
+ {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,},
},
{
- {2, 2,},
- {2, 2,},
- {2, 2,},
- {2, 2,},
- {2, 2,},
+ {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,},
},
};
@@ -322,10 +184,10 @@ void VertexLoader_Position::Init(void) {
#if _M_SSE >= 0x301
if (cpu_info.bSSSE3) {
- tableReadPosition[2][4][0] = Pos_ReadIndex8_Float2_SSSE3;
- tableReadPosition[2][4][1] = Pos_ReadIndex8_Float3_SSSE3;
- tableReadPosition[3][4][0] = Pos_ReadIndex16_Float2_SSSE3;
- tableReadPosition[3][4][1] = Pos_ReadIndex16_Float3_SSSE3;
+ tableReadPosition[2][4][0] = Pos_ReadIndex_Float_SSSE3<u8, false>;
+ tableReadPosition[2][4][1] = Pos_ReadIndex_Float_SSSE3<u8, true>;
+ tableReadPosition[3][4][0] = Pos_ReadIndex_Float_SSSE3<u16, false>;
+ tableReadPosition[3][4][1] = Pos_ReadIndex_Float_SSSE3<u16, true>;
}
#endif
diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Position.h b/Source/Core/VideoCommon/Src/VertexLoader_Position.h
index db8d8a38b5..c659e05487 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader_Position.h
+++ b/Source/Core/VideoCommon/Src/VertexLoader_Position.h
@@ -21,14 +21,14 @@
class VertexLoader_Position {
public:
- // Init
- static void Init(void);
+ // Init
+ static void Init(void);
- // GetSize
- static unsigned int GetSize(unsigned int _type, unsigned int _format, unsigned int _elements);
+ // GetSize
+ static unsigned int GetSize(unsigned int _type, unsigned int _format, unsigned int _elements);
- // GetFunction
- static TPipelineFunction GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements);
+ // GetFunction
+ static TPipelineFunction GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements);
};
#endif
diff --git a/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp b/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp
index ba3bb73f43..f914226a63 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp
+++ b/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp
@@ -28,290 +28,79 @@
#include <tmmintrin.h>
#endif
-#define LOG_TEX1() // PRIM_LOG("tex: %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0]);
-#define LOG_TEX2() // PRIM_LOG("tex: %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0], ((float*)VertexManager::s_pCurBufferPointer)[1]);
+template <int N>
+void LOG_TEX();
-extern int tcIndex;
-extern float tcScale[8];
-
-void LOADERDECL TexCoord_Read_Dummy()
+template <>
+__forceinline void LOG_TEX<1>()
{
- tcIndex++;
+ // warning: mapping buffer should be disabled to use this
+ // PRIM_LOG("tex: %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-1]);
}
-void LOADERDECL TexCoord_ReadDirect_UByte1()
+template <>
+__forceinline void LOG_TEX<2>()
{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadDirect_UByte2()
-{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU8() * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
+ // warning: mapping buffer should be disabled to use this
+ // PRIM_LOG("tex: %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-2], ((float*)VertexManager::s_pCurBufferPointer)[-1]);
}
-void LOADERDECL TexCoord_ReadDirect_Byte1()
-{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadDirect_Byte2()
-{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)DataReadU8() * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
-}
+extern int tcIndex;
+extern float tcScale[8];
-void LOADERDECL TexCoord_ReadDirect_UShort1()
-{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadDirect_UShort2()
+void LOADERDECL TexCoord_Read_Dummy()
{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU16() * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
tcIndex++;
}
-void LOADERDECL TexCoord_ReadDirect_Short1()
-{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadDirect_Short2()
+template <typename T>
+float TCScale(T val)
{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)DataReadU16() * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
+ return val * tcScale[tcIndex];
}
-void LOADERDECL TexCoord_ReadDirect_Float1()
-{
- ((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadDirect_Float2()
-{
- ((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
- ((u32*)VertexManager::s_pCurBufferPointer)[1] = DataReadU32();
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
-}
+template <>
+float TCScale(float val)
+{ return val; }
-// ==================================================================================
-void LOADERDECL TexCoord_ReadIndex8_UByte1()
+template <typename T, int N>
+void LOADERDECL TexCoord_ReadDirect()
{
- u8 Index = DataReadU8();
- const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(*pData) * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadIndex8_UByte2()
-{
- u8 Index = DataReadU8();
- const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)(pData[0]) * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u8)(pData[1]) * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
-}
+ for (int i = 0; i != N; ++i)
+ DataWrite(TCScale(DataRead<T>()));
-void LOADERDECL TexCoord_ReadIndex8_Byte1()
-{
- u8 Index = DataReadU8();
- const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
+ LOG_TEX<N>();
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(*pData) * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadIndex8_Byte2()
-{
- u8 Index = DataReadU8();
- const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(pData[0]) * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)(pData[1]) * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
+ ++tcIndex;
}
-void LOADERDECL TexCoord_ReadIndex8_UShort1()
-{
- u8 Index = DataReadU8();
- const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(*pData) * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadIndex8_UShort2()
+template <typename I, typename T, int N>
+void LOADERDECL TexCoord_ReadIndex()
{
- u8 Index = DataReadU8();
- const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(pData[0]) * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u16)Common::swap16(pData[1]) * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
-}
+ static_assert(!std::numeric_limits<I>::is_signed, "Only unsigned I is sane!");
+
+ auto const index = DataRead<I>();
+ auto const data = reinterpret_cast<const T*>(cached_arraybases[ARRAY_TEXCOORD0 + tcIndex]
+ + (index * arraystrides[ARRAY_TEXCOORD0 + tcIndex]));
-void LOADERDECL TexCoord_ReadIndex8_Short1()
-{
- u8 Index = DataReadU8();
- const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(pData[0]) * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadIndex8_Short2()
-{
- u8 Index = DataReadU8();
- const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(pData[0]) * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)Common::swap16(pData[1]) * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
-}
+ for (int i = 0; i != N; ++i)
+ DataWrite(TCScale(Common::FromBigEndian(data[i])));
-void LOADERDECL TexCoord_ReadIndex8_Float1()
-{
- u16 Index = DataReadU8();
- const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadIndex8_Float2()
-{
- u16 Index = DataReadU8();
- const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
- ((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]);
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
-}
-
-// ==================================================================================
-void LOADERDECL TexCoord_ReadIndex16_UByte1()
-{
- u16 Index = DataReadU16();
- const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)(pData[0]) * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadIndex16_UByte2()
-{
- u16 Index = DataReadU16();
- const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)(pData[0]) * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u8)(pData[1]) * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
-}
-
-void LOADERDECL TexCoord_ReadIndex16_Byte1()
-{
- u16 Index = DataReadU16();
- const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(pData[0]) * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadIndex16_Byte2()
-{
- u16 Index = DataReadU16();
- const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(pData[0]) * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)(pData[1]) * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
-}
-
-void LOADERDECL TexCoord_ReadIndex16_UShort1()
-{
- u16 Index = DataReadU16();
- const u16* pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(pData[0]) * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-void LOADERDECL TexCoord_ReadIndex16_UShort2()
-{
- u16 Index = DataReadU16();
- const u16* pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(pData[0]) * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u16)Common::swap16(pData[1]) * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
-}
-
-void LOADERDECL TexCoord_ReadIndex16_Short1()
-{
- u16 Index = DataReadU16();
- const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(*pData) * tcScale[tcIndex];
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-
-void LOADERDECL TexCoord_ReadIndex16_Short2()
-{
- // Heavy in ZWW
- u16 Index = DataReadU16();
- const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(pData[0]) * tcScale[tcIndex];
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)Common::swap16(pData[1]) * tcScale[tcIndex];
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
+ LOG_TEX<N>();
+ ++tcIndex;
}
#if _M_SSE >= 0x401
static const __m128i kMaskSwap16_2 = _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x02030001L);
-void LOADERDECL TexCoord_ReadIndex16_Short2_SSE4()
+template <typename I>
+void LOADERDECL TexCoord_ReadIndex_Short2_SSE4()
{
+ static_assert(!std::numeric_limits<I>::is_signed, "Only unsigned I is sane!");
+
// Heavy in ZWW
- u16 Index = DataReadU16();
- const s32 *pData = (const s32*)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
+ auto const index = DataRead<I>();
+ const s32 *pData = (const s32*)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
const __m128i a = _mm_cvtsi32_si128(*pData);
const __m128i b = _mm_shuffle_epi8(a, kMaskSwap16_2);
const __m128i c = _mm_cvtepi16_epi32(b);
@@ -319,47 +108,27 @@ void LOADERDECL TexCoord_ReadIndex16_Short2_SSE4()
const __m128 e = _mm_load1_ps(&tcScale[tcIndex]);
const __m128 f = _mm_mul_ps(d, e);
_mm_storeu_ps((float*)VertexManager::s_pCurBufferPointer, f);
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
+ VertexManager::s_pCurBufferPointer += sizeof(float) * 2;
+ LOG_TEX<2>();
tcIndex++;
}
#endif
-void LOADERDECL TexCoord_ReadIndex16_Float1()
-{
- u16 Index = DataReadU16();
- const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
- LOG_TEX1();
- VertexManager::s_pCurBufferPointer += 4;
- tcIndex++;
-}
-
-void LOADERDECL TexCoord_ReadIndex16_Float2()
-{
- u16 Index = DataReadU16();
- const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
- ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
- ((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]);
- LOG_TEX2();
- VertexManager::s_pCurBufferPointer += 8;
- tcIndex++;
-}
-
#if _M_SSE >= 0x301
static const __m128i kMaskSwap32 = _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x04050607L, 0x00010203L);
-void LOADERDECL TexCoord_ReadIndex16_Float2_SSSE3()
+template <typename I>
+void LOADERDECL TexCoord_ReadIndex_Float2_SSSE3()
{
- u16 Index = DataReadU16();
- const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
+ static_assert(!std::numeric_limits<I>::is_signed, "Only unsigned I is sane!");
+
+ auto const index = DataRead<I>();
+ const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
GC_ALIGNED128(const __m128i a = _mm_loadl_epi64((__m128i*)pData));
GC_ALIGNED128(const __m128i b = _mm_shuffle_epi8(a, kMaskSwap32));
- u8* p = VertexManager::s_pCurBufferPointer;
- _mm_storel_epi64((__m128i*)p, b);
- LOG_TEX2();
- p += 8;
- VertexManager::s_pCurBufferPointer = p;
+ _mm_storel_epi64((__m128i*)VertexManager::s_pCurBufferPointer, b);
+ VertexManager::s_pCurBufferPointer += sizeof(float) * 2;
+ LOG_TEX<2>();
tcIndex++;
}
#endif
@@ -373,56 +142,40 @@ static TPipelineFunction tableReadTexCoord[4][8][2] = {
{NULL, NULL,},
},
{
- {TexCoord_ReadDirect_UByte1, TexCoord_ReadDirect_UByte2,},
- {TexCoord_ReadDirect_Byte1, TexCoord_ReadDirect_Byte2,},
- {TexCoord_ReadDirect_UShort1, TexCoord_ReadDirect_UShort2,},
- {TexCoord_ReadDirect_Short1, TexCoord_ReadDirect_Short2,},
- {TexCoord_ReadDirect_Float1, TexCoord_ReadDirect_Float2,},
+ {TexCoord_ReadDirect<u8, 1>, TexCoord_ReadDirect<u8, 2>,},
+ {TexCoord_ReadDirect<s8, 1>, TexCoord_ReadDirect<s8, 2>,},
+ {TexCoord_ReadDirect<u16, 1>, TexCoord_ReadDirect<u16, 2>,},
+ {TexCoord_ReadDirect<s16, 1>, TexCoord_ReadDirect<s16, 2>,},
+ {TexCoord_ReadDirect<float, 1>, TexCoord_ReadDirect<float, 2>,},
},
{
- {TexCoord_ReadIndex8_UByte1, TexCoord_ReadIndex8_UByte2,},
- {TexCoord_ReadIndex8_Byte1, TexCoord_ReadIndex8_Byte2,},
- {TexCoord_ReadIndex8_UShort1, TexCoord_ReadIndex8_UShort2,},
- {TexCoord_ReadIndex8_Short1, TexCoord_ReadIndex8_Short2,},
- {TexCoord_ReadIndex8_Float1, TexCoord_ReadIndex8_Float2,},
+ {TexCoord_ReadIndex<u8, u8, 1>, TexCoord_ReadIndex<u8, u8, 2>,},
+ {TexCoord_ReadIndex<u8, s8, 1>, TexCoord_ReadIndex<u8, s8, 2>,},
+ {TexCoord_ReadIndex<u8, u16, 1>, TexCoord_ReadIndex<u8, u16, 2>,},
+ {TexCoord_ReadIndex<u8, s16, 1>, TexCoord_ReadIndex<u8, s16, 2>,},
+ {TexCoord_ReadIndex<u8, float, 1>, TexCoord_ReadIndex<u8, float, 2>,},
},
{
- {TexCoord_ReadIndex16_UByte1, TexCoord_ReadIndex16_UByte2,},
- {TexCoord_ReadIndex16_Byte1, TexCoord_ReadIndex16_Byte2,},
- {TexCoord_ReadIndex16_UShort1, TexCoord_ReadIndex16_UShort2,},
- {TexCoord_ReadIndex16_Short1, TexCoord_ReadIndex16_Short2,},
- {TexCoord_ReadIndex16_Float1, TexCoord_ReadIndex16_Float2,},
+ {TexCoord_ReadIndex<u16, u8, 1>, TexCoord_ReadIndex<u16, u8, 2>,},
+ {TexCoord_ReadIndex<u16, s8, 1>, TexCoord_ReadIndex<u16, s8, 2>,},
+ {TexCoord_ReadIndex<u16, u16, 1>, TexCoord_ReadIndex<u16, u16, 2>,},
+ {TexCoord_ReadIndex<u16, s16, 1>, TexCoord_ReadIndex<u16, s16, 2>,},
+ {TexCoord_ReadIndex<u16, float, 1>, TexCoord_ReadIndex<u16, float, 2>,},
},
};
static int tableReadTexCoordVertexSize[4][8][2] = {
{
- {0, 0,},
- {0, 0,},
- {0, 0,},
- {0, 0,},
- {0, 0,},
+ {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,},
},
{
- {1, 2,},
- {1, 2,},
- {2, 4,},
- {2, 4,},
- {4, 8,},
+ {1, 2,}, {1, 2,}, {2, 4,}, {2, 4,}, {4, 8,},
},
{
- {1, 1,},
- {1, 1,},
- {1, 1,},
- {1, 1,},
- {1, 1,},
+ {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,},
},
{
- {2, 2,},
- {2, 2,},
- {2, 2,},
- {2, 2,},
- {2, 2,},
+ {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,},
},
};
@@ -430,16 +183,20 @@ void VertexLoader_TextCoord::Init(void) {
#if _M_SSE >= 0x301
- if (cpu_info.bSSSE3) {
- tableReadTexCoord[3][4][1] = TexCoord_ReadIndex16_Float2_SSSE3;
+ if (cpu_info.bSSSE3)
+ {
+ tableReadTexCoord[2][4][1] = TexCoord_ReadIndex_Float2_SSSE3<u8>;
+ tableReadTexCoord[3][4][1] = TexCoord_ReadIndex_Float2_SSSE3<u16>;
}
#endif
#if _M_SSE >= 0x401
- if (cpu_info.bSSE4_1) {
- tableReadTexCoord[3][3][1] = TexCoord_ReadIndex16_Short2_SSE4;
+ if (cpu_info.bSSE4_1)
+ {
+ tableReadTexCoord[2][3][1] = TexCoord_ReadIndex_Short2_SSE4<u8>;
+ tableReadTexCoord[3][3][1] = TexCoord_ReadIndex_Short2_SSE4<u16>;
}
#endif
diff --git a/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.h b/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.h
index f7d5ee7ee7..8e9175d904 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.h
+++ b/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.h
@@ -24,18 +24,18 @@ class VertexLoader_TextCoord
{
public:
- // Init
- static void Init(void);
+ // Init
+ static void Init(void);
- // GetSize
- static unsigned int GetSize(unsigned int _type, unsigned int _format, unsigned int _elements);
+ // GetSize
+ static unsigned int GetSize(unsigned int _type, unsigned int _format, unsigned int _elements);
- // GetFunction
- static TPipelineFunction GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements);
+ // GetFunction
+ static TPipelineFunction GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements);
- // GetDummyFunction
+ // GetDummyFunction
// It is important to synchronize tcIndex.
- static TPipelineFunction GetDummyFunction();
+ static TPipelineFunction GetDummyFunction();
};
#endif
diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp
index cd5a01c6b3..87856b5aeb 100644
--- a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp
+++ b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp
@@ -12,171 +12,122 @@
#include "BPStructs.h"
#include "VertexManagerBase.h"
+#include "MainBase.h"
#include "VideoConfig.h"
VertexManager *g_vertex_manager;
u8 *VertexManager::s_pCurBufferPointer;
u8 *VertexManager::s_pBaseBufferPointer;
-
-u8 *VertexManager::LocalVBuffer;
-u16 *VertexManager::TIBuffer;
-u16 *VertexManager::LIBuffer;
-u16 *VertexManager::PIBuffer;
-
-bool VertexManager::Flushed;
+u8 *VertexManager::s_pEndBufferPointer;
VertexManager::VertexManager()
{
- Flushed = false;
+ LocalVBuffer.resize(MAXVBUFFERSIZE);
+ s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0];
+ s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
- LocalVBuffer = new u8[MAXVBUFFERSIZE];
- s_pCurBufferPointer = s_pBaseBufferPointer = LocalVBuffer;
+ TIBuffer.resize(MAXIBUFFERSIZE);
+ LIBuffer.resize(MAXIBUFFERSIZE);
+ PIBuffer.resize(MAXIBUFFERSIZE);
- TIBuffer = new u16[MAXIBUFFERSIZE];
- LIBuffer = new u16[MAXIBUFFERSIZE];
- PIBuffer = new u16[MAXIBUFFERSIZE];
-
- IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
+ ResetBuffer();
}
+VertexManager::~VertexManager()
+{}
+
void VertexManager::ResetBuffer()
{
- s_pCurBufferPointer = LocalVBuffer;
+ s_pCurBufferPointer = s_pBaseBufferPointer;
+ IndexGenerator::Start(GetTriangleIndexBuffer(), GetLineIndexBuffer(), GetPointIndexBuffer());
}
-VertexManager::~VertexManager()
+u32 VertexManager::GetRemainingSize()
{
- delete[] LocalVBuffer;
-
- delete[] TIBuffer;
- delete[] LIBuffer;
- delete[] PIBuffer;
-
- // TODO: necessary??
- ResetBuffer();
+ return (u32)(s_pEndBufferPointer - s_pCurBufferPointer);
}
-void VertexManager::AddIndices(int primitive, int numVertices)
-{
- //switch (primitive)
- //{
- //case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVertices); break;
- //case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVertices); break;
- //case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVertices); break;
- //case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVertices); break;
- //case GX_DRAW_LINES: IndexGenerator::AddLineList(numVertices); break;
- //case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVertices); break;
- //case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVertices); break;
- //}
-
- static void (*const primitive_table[])(int) =
+void VertexManager::PrepareForAdditionalData(int primitive, u32 count, u32 stride)
+{
+ u32 const needed_vertex_bytes = count * stride;
+
+ if (count > IndexGenerator::GetRemainingIndices() || count > GetRemainingIndices(primitive) || needed_vertex_bytes > GetRemainingSize())
{
- IndexGenerator::AddQuads,
- NULL,
- IndexGenerator::AddList,
- IndexGenerator::AddStrip,
- IndexGenerator::AddFan,
- IndexGenerator::AddLineList,
- IndexGenerator::AddLineStrip,
- IndexGenerator::AddPoints,
- };
-
- primitive_table[primitive](numVertices);
+ Flush();
+
+ if(count > IndexGenerator::GetRemainingIndices())
+ ERROR_LOG(VIDEO, "Too less index values. Use 32bit or reset them on flush.");
+ if (count > GetRemainingIndices(primitive))
+ ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all indices! "
+ "Increase MAXIBUFFERSIZE or we need primitive breaking afterall.");
+ if (needed_vertex_bytes > GetRemainingSize())
+ ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all vertices! "
+ "Increase MAXVBUFFERSIZE or we need primitive breaking afterall.");
+ }
}
-int VertexManager::GetRemainingSize()
+bool VertexManager::IsFlushed() const
{
- return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer);
+ return s_pBaseBufferPointer == s_pCurBufferPointer;
}
-int VertexManager::GetRemainingVertices(int primitive)
+u32 VertexManager::GetRemainingIndices(int primitive)
{
switch (primitive)
{
case GX_DRAW_QUADS:
+ return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4;
case GX_DRAW_TRIANGLES:
+ return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen());
case GX_DRAW_TRIANGLE_STRIP:
+ return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2;
case GX_DRAW_TRIANGLE_FAN:
- return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3;
- break;
+ return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2;
case GX_DRAW_LINES:
+ return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen());
case GX_DRAW_LINE_STRIP:
- return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2;
- break;
+ return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1;
case GX_DRAW_POINTS:
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen());
- break;
default:
return 0;
- break;
}
}
-void VertexManager::AddVertices(int primitive, int numVertices)
+void VertexManager::AddVertices(int primitive, u32 numVertices)
{
if (numVertices <= 0)
return;
- switch (primitive)
- {
- case GX_DRAW_QUADS:
- case GX_DRAW_TRIANGLES:
- case GX_DRAW_TRIANGLE_STRIP:
- case GX_DRAW_TRIANGLE_FAN:
- if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * numVertices)
- Flush();
- break;
-
- case GX_DRAW_LINES:
- case GX_DRAW_LINE_STRIP:
- if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * numVertices)
- Flush();
- break;
-
- case GX_DRAW_POINTS:
- if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < numVertices)
- Flush();
- break;
-
- default:
- return;
- break;
- }
-
- if (Flushed)
- {
- IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
- Flushed = false;
- }
-
ADDSTAT(stats.thisFrame.numPrims, numVertices);
INCSTAT(stats.thisFrame.numPrimitiveJoins);
- AddIndices(primitive, numVertices);
+
+ IndexGenerator::AddIndices(primitive, numVertices);
}
void VertexManager::Flush()
{
+ if (g_vertex_manager->IsFlushed())
+ return;
+
// loading a state will invalidate BP, so check for it
g_video_backend->CheckInvalidState();
-
+
+ VideoFifo_CheckEFBAccess();
+
g_vertex_manager->vFlush();
+
+ g_vertex_manager->ResetBuffer();
}
// TODO: need to merge more stuff into VideoCommon to use this
#if (0)
void VertexManager::Flush()
{
- if (LocalVBuffer == s_pCurBufferPointer || Flushed)
- return;
-
- Flushed = true;
-
- VideoFifo_CheckEFBAccess();
-
#if defined(_DEBUG) || defined(DEBUGFAST)
PRIM_LOG("frame%d:\n texgen=%d, numchan=%d, dualtex=%d, ztex=%d, cole=%d, alpe=%d, ze=%d", g_ActiveConfig.iSaveTargetId, xfregs.numTexGens,
xfregs.nNumChans, (int)xfregs.bEnableDualTexTransform, bpmem.ztex2.op,
@@ -249,21 +200,23 @@ void VertexManager::Flush()
// finally bind
if (false == PixelShaderCache::SetShader(false, g_nativeVertexFmt->m_components))
- goto shader_fail;
+ return;
if (false == VertexShaderCache::SetShader(g_nativeVertexFmt->m_components))
- goto shader_fail;
+ return;
const int stride = g_nativeVertexFmt->GetVertexStride();
//if (g_nativeVertexFmt)
g_nativeVertexFmt->SetupVertexPointers();
+ g_renderer->ResumePixelPerf(false);
g_vertex_manager->Draw(stride, false);
+ g_renderer->PausePixelPerf(false);
// run through vertex groups again to set alpha
if (false == g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate)
{
if (false == PixelShaderCache::SetShader(true, g_nativeVertexFmt->m_components))
- goto shader_fail;
+ return;
g_vertex_manager->Draw(stride, true);
}
@@ -277,10 +230,12 @@ void VertexManager::Flush()
// save the shaders
char strfile[255];
sprintf(strfile, "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
- std::ofstream fps(strfile);
+ std::ofstream fps;
+ OpenFStream(fps, strfile, std::ios_base::out);
fps << ps->strprog.c_str();
sprintf(strfile, "%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
- std::ofstream fvs(strfile);
+ std::ofstream fvs;
+ OpenFStream(fvs, strfile, std::ios_base::out);
fvs << vs->strprog.c_str();
}
@@ -297,9 +252,6 @@ void VertexManager::Flush()
}
#endif
++g_Config.iSaveTargetId;
-
-shader_fail:
- ResetBuffer();
}
#endif
@@ -310,12 +262,16 @@ void VertexManager::DoState(PointerWrap& p)
void VertexManager::DoStateShared(PointerWrap& p)
{
- p.DoPointer(s_pCurBufferPointer, LocalVBuffer);
- p.DoArray(LocalVBuffer, MAXVBUFFERSIZE);
- p.DoArray(TIBuffer, MAXIBUFFERSIZE);
- p.DoArray(LIBuffer, MAXIBUFFERSIZE);
- p.DoArray(PIBuffer, MAXIBUFFERSIZE);
-
- if (p.GetMode() == PointerWrap::MODE_READ)
- Flushed = false;
+ // It seems we half-assume to be flushed here
+ // We update s_pCurBufferPointer yet don't worry about IndexGenerator's outdated pointers
+ // and maybe other things are overlooked
+
+ p.Do(LocalVBuffer);
+ p.Do(TIBuffer);
+ p.Do(LIBuffer);
+ p.Do(PIBuffer);
+
+ s_pBaseBufferPointer = &LocalVBuffer[0];
+ s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
+ p.DoPointer(s_pCurBufferPointer, s_pBaseBufferPointer);
}
diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.h b/Source/Core/VideoCommon/Src/VertexManagerBase.h
index f3a4aa72e3..fafde8de44 100644
--- a/Source/Core/VideoCommon/Src/VertexManagerBase.h
+++ b/Source/Core/VideoCommon/Src/VertexManagerBase.h
@@ -2,72 +2,70 @@
#ifndef _VERTEXMANAGERBASE_H
#define _VERTEXMANAGERBASE_H
+#include "Common.h"
+#include <vector>
+
class NativeVertexFormat;
class PointerWrap;
class VertexManager
{
+private:
+ static const u32 SMALLEST_POSSIBLE_VERTEX = sizeof(float)*3; // 3 pos
+ static const u32 LARGEST_POSSIBLE_VERTEX = sizeof(float)*45 + sizeof(u32)*2; // 3 pos, 3*3 normal, 2*u32 color, 8*4 tex, 1 posMat
+
+ static const u32 MAX_PRIMITIVES_PER_COMMAND = (u16)-1;
+
public:
-
- enum
- {
- // values from OGL backend
- //MAXVBUFFERSIZE = 0x1FFFF,
- //MAXIBUFFERSIZE = 0xFFFF,
-
- // values from DX9 backend
- //MAXVBUFFERSIZE = 0x50000,
- //MAXIBUFFERSIZE = 0xFFFF,
-
- // values from DX11 backend
- MAXVBUFFERSIZE = 0x50000,
- MAXIBUFFERSIZE = 0xFFFF,
- };
+ static const u32 MAXVBUFFERSIZE = ROUND_UP_POW2 (MAX_PRIMITIVES_PER_COMMAND * LARGEST_POSSIBLE_VERTEX);
+
+ // We may convert triangle-fans to triangle-lists, almost 3x as many indices.
+ static const u32 MAXIBUFFERSIZE = ROUND_UP_POW2 (MAX_PRIMITIVES_PER_COMMAND * 3);
VertexManager();
- virtual ~VertexManager(); // needs to be virtual for DX11's dtor
+ // needs to be virtual for DX11's dtor
+ virtual ~VertexManager();
- static void AddVertices(int _primitive, int _numVertices);
+ static void AddVertices(int _primitive, u32 _numVertices);
- // TODO: protected?
static u8 *s_pCurBufferPointer;
static u8 *s_pBaseBufferPointer;
+ static u8 *s_pEndBufferPointer;
- static int GetRemainingSize();
- static int GetRemainingVertices(int primitive);
+ static u32 GetRemainingSize();
+ static void PrepareForAdditionalData(int primitive, u32 count, u32 stride);
+ static u32 GetRemainingIndices(int primitive);
static void Flush();
virtual ::NativeVertexFormat* CreateNativeVertexFormat() = 0;
- static u16* GetTriangleIndexBuffer() { return TIBuffer; }
- static u16* GetLineIndexBuffer() { return LIBuffer; }
- static u16* GetPointIndexBuffer() { return PIBuffer; }
- static u8* GetVertexBuffer() { return LocalVBuffer; }
-
static void DoState(PointerWrap& p);
virtual void CreateDeviceObjects(){};
virtual void DestroyDeviceObjects(){};
+
protected:
- // TODO: make private after Flush() is merged
- static void ResetBuffer();
-
- static u8 *LocalVBuffer;
- static u16 *TIBuffer;
- static u16 *LIBuffer;
- static u16 *PIBuffer;
-
- static bool Flushed;
+ u16* GetTriangleIndexBuffer() { return &TIBuffer[0]; }
+ u16* GetLineIndexBuffer() { return &LIBuffer[0]; }
+ u16* GetPointIndexBuffer() { return &PIBuffer[0]; }
+ u8* GetVertexBuffer() { return &s_pBaseBufferPointer[0]; }
virtual void vDoState(PointerWrap& p) { DoStateShared(p); }
void DoStateShared(PointerWrap& p);
private:
- static void AddIndices(int primitive, int numVertices);
+ bool IsFlushed() const;
+
+ void ResetBuffer();
+
//virtual void Draw(u32 stride, bool alphapass) = 0;
// temp
virtual void vFlush() = 0;
-
+
+ std::vector<u8> LocalVBuffer;
+ std::vector<u16> TIBuffer;
+ std::vector<u16> LIBuffer;
+ std::vector<u16> PIBuffer;
};
extern VertexManager *g_vertex_manager;
diff --git a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp
index cad117c2c8..2c0f5676ed 100644
--- a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp
+++ b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp
@@ -114,7 +114,8 @@ void ValidateVertexShaderIDs(API_TYPE api, VERTEXSHADERUIDSAFE old_id, const std
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%svsuid_mismatch_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << msg;
file << "\n\nOld shader code:\n" << old_code;
file << "\n\nNew shader code:\n" << new_code;
@@ -130,46 +131,51 @@ static char text[16384];
#define WRITE p+=sprintf
-char* GenerateVSOutputStruct(char* p, u32 components, API_TYPE api_type)
+char* GenerateVSOutputStruct(char* p, u32 components, API_TYPE ApiType)
{
+ // GLSL makes this ugly
+ // TODO: Make pretty
WRITE(p, "struct VS_OUTPUT {\n");
- WRITE(p, " float4 pos : POSITION;\n");
- WRITE(p, " float4 colors_0 : COLOR0;\n");
- WRITE(p, " float4 colors_1 : COLOR1;\n");
+ WRITE(p, " float4 pos %s POSITION;\n", ApiType == API_OPENGL ? ";//" : ":");
+ WRITE(p, " float4 colors_0 %s COLOR0;\n", ApiType == API_OPENGL ? ";//" : ":");
+ WRITE(p, " float4 colors_1 %s COLOR1;\n", ApiType == API_OPENGL ? ";//" : ":");
if (xfregs.numTexGen.numTexGens < 7) {
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
- WRITE(p, " float3 tex%d : TEXCOORD%d;\n", i, i);
- WRITE(p, " float4 clipPos : TEXCOORD%d;\n", xfregs.numTexGen.numTexGens);
+ WRITE(p, " float3 tex%d %s TEXCOORD%d;\n", i, ApiType == API_OPENGL ? ";//" : ":", i);
+ WRITE(p, " float4 clipPos %s TEXCOORD%d;\n", ApiType == API_OPENGL ? ";//" : ":", xfregs.numTexGen.numTexGens);
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
- WRITE(p, " float4 Normal : TEXCOORD%d;\n", xfregs.numTexGen.numTexGens + 1);
+ WRITE(p, " float4 Normal %s TEXCOORD%d;\n", ApiType == API_OPENGL ? ";//" : ":", xfregs.numTexGen.numTexGens + 1);
} else {
// clip position is in w of first 4 texcoords
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
{
for (int i = 0; i < 8; ++i)
- WRITE(p, " float4 tex%d : TEXCOORD%d;\n", i, i);
+ WRITE(p, " float4 tex%d %s TEXCOORD%d;\n", i, ApiType == API_OPENGL? ";//" : ":", i);
}
else
{
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
- WRITE(p, " float%d tex%d : TEXCOORD%d;\n", i < 4 ? 4 : 3 , i, i);
+ WRITE(p, " float%d tex%d %s TEXCOORD%d;\n", i < 4 ? 4 : 3 , i, ApiType == API_OPENGL ? ";//" : ":", i);
}
- }
+ }
WRITE(p, "};\n");
return p;
}
-const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
+extern const char* WriteRegister(API_TYPE ApiType, const char *prefix, const u32 num);
+extern const char *WriteLocation(API_TYPE ApiType);
+
+const char *GenerateVertexShaderCode(u32 components, API_TYPE ApiType)
{
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
text[sizeof(text) - 1] = 0x7C; // canary
_assert_(bpmem.genMode.numtexgens == xfregs.numTexGen.numTexGens);
_assert_(bpmem.genMode.numcolchans == xfregs.numChan.numColorChans);
-
- bool is_d3d = (api_type & API_D3D9 || api_type == API_D3D11);
+
+ bool is_d3d = (ApiType & API_D3D9 || ApiType == API_D3D11);
u32 lightMask = 0;
if (xfregs.numChan.numColorChans > 0)
lightMask |= xfregs.color[0].GetFullLightMask() | xfregs.alpha[0].GetFullLightMask();
@@ -178,91 +184,133 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
char *p = text;
WRITE(p, "//Vertex Shader: comp:%x, \n", components);
- WRITE(p, "typedef struct { float4 T0, T1, T2; float4 N0, N1, N2; } s_" I_POSNORMALMATRIX";\n"
- "typedef struct { float4 t; } FLT4;\n"
- "typedef struct { FLT4 T[24]; } s_" I_TEXMATRICES";\n"
- "typedef struct { FLT4 T[64]; } s_" I_TRANSFORMMATRICES";\n"
- "typedef struct { FLT4 T[32]; } s_" I_NORMALMATRICES";\n"
- "typedef struct { FLT4 T[64]; } s_" I_POSTTRANSFORMMATRICES";\n"
- "typedef struct { float4 col; float4 cosatt; float4 distatt; float4 pos; float4 dir; } Light;\n"
- "typedef struct { Light lights[8]; } s_" I_LIGHTS";\n"
- "typedef struct { float4 C0, C1, C2, C3; } s_" I_MATERIALS";\n"
- "typedef struct { float4 T0, T1, T2, T3; } s_" I_PROJECTION";\n"
- );
-
- p = GenerateVSOutputStruct(p, components, api_type);
// uniforms
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ WRITE(p, "layout(std140) uniform VSBlock {\n");
- WRITE(p, "uniform s_" I_TRANSFORMMATRICES" " I_TRANSFORMMATRICES" : register(c%d);\n", C_TRANSFORMMATRICES);
- WRITE(p, "uniform s_" I_TEXMATRICES" " I_TEXMATRICES" : register(c%d);\n", C_TEXMATRICES); // also using tex matrices
- WRITE(p, "uniform s_" I_NORMALMATRICES" " I_NORMALMATRICES" : register(c%d);\n", C_NORMALMATRICES);
- WRITE(p, "uniform s_" I_POSNORMALMATRIX" " I_POSNORMALMATRIX" : register(c%d);\n", C_POSNORMALMATRIX);
- WRITE(p, "uniform s_" I_POSTTRANSFORMMATRICES" " I_POSTTRANSFORMMATRICES" : register(c%d);\n", C_POSTTRANSFORMMATRICES);
- WRITE(p, "uniform s_" I_LIGHTS" " I_LIGHTS" : register(c%d);\n", C_LIGHTS);
- WRITE(p, "uniform s_" I_MATERIALS" " I_MATERIALS" : register(c%d);\n", C_MATERIALS);
- WRITE(p, "uniform s_" I_PROJECTION" " I_PROJECTION" : register(c%d);\n", C_PROJECTION);
- WRITE(p, "uniform float4 " I_DEPTHPARAMS" : register(c%d);\n", C_DEPTHPARAMS);
-
- WRITE(p, "VS_OUTPUT main(\n");
-
- // inputs
- if (components & VB_HAS_NRM0)
- WRITE(p, " float3 rawnorm0 : NORMAL0,\n");
- if (components & VB_HAS_NRM1) {
- if (is_d3d)
- WRITE(p, " float3 rawnorm1 : NORMAL1,\n");
- else
- WRITE(p, " float3 rawnorm1 : ATTR%d,\n", SHADER_NORM1_ATTRIB);
- }
- if (components & VB_HAS_NRM2) {
- if (is_d3d)
- WRITE(p, " float3 rawnorm2 : NORMAL2,\n");
- else
- WRITE(p, " float3 rawnorm2 : ATTR%d,\n", SHADER_NORM2_ATTRIB);
- }
- if (components & VB_HAS_COL0)
- WRITE(p, " float4 color0 : COLOR0,\n");
- if (components & VB_HAS_COL1)
- WRITE(p, " float4 color1 : COLOR1,\n");
- for (int i = 0; i < 8; ++i) {
- u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
- if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
- WRITE(p, " float%d tex%d : TEXCOORD%d,\n", hastexmtx ? 3 : 2, i, i);
- }
- if (components & VB_HAS_POSMTXIDX) {
- if (is_d3d)
+ WRITE(p, "%sfloat4 " I_POSNORMALMATRIX"[6] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_POSNORMALMATRIX));
+ WRITE(p, "%sfloat4 " I_PROJECTION"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_PROJECTION));
+ WRITE(p, "%sfloat4 " I_MATERIALS"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_MATERIALS));
+ WRITE(p, "%sfloat4 " I_LIGHTS"[40] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_LIGHTS));
+ WRITE(p, "%sfloat4 " I_TEXMATRICES"[24] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_TEXMATRICES)); // also using tex matrices
+ WRITE(p, "%sfloat4 " I_TRANSFORMMATRICES"[64] %s;\n", WriteLocation(ApiType),WriteRegister(ApiType, "c", C_TRANSFORMMATRICES));
+ WRITE(p, "%sfloat4 " I_NORMALMATRICES"[32] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_NORMALMATRICES));
+ WRITE(p, "%sfloat4 " I_POSTTRANSFORMMATRICES"[64] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_POSTTRANSFORMMATRICES));
+ WRITE(p, "%sfloat4 " I_DEPTHPARAMS" %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_DEPTHPARAMS));
+
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ WRITE(p, "};\n");
+
+ p = GenerateVSOutputStruct(p, components, ApiType);
+
+ if(ApiType == API_OPENGL)
+ {
+ WRITE(p, "ATTRIN float4 rawpos; // ATTR%d,\n", SHADER_POSITION_ATTRIB);
+ if (components & VB_HAS_POSMTXIDX)
+ WRITE(p, "ATTRIN int posmtx; // ATTR%d,\n", SHADER_POSMTX_ATTRIB);
+ if (components & VB_HAS_NRM0)
+ WRITE(p, "ATTRIN float3 rawnorm0; // ATTR%d,\n", SHADER_NORM0_ATTRIB);
+ if (components & VB_HAS_NRM1)
+ WRITE(p, "ATTRIN float3 rawnorm1; // ATTR%d,\n", SHADER_NORM1_ATTRIB);
+ if (components & VB_HAS_NRM2)
+ WRITE(p, "ATTRIN float3 rawnorm2; // ATTR%d,\n", SHADER_NORM2_ATTRIB);
+
+ if (components & VB_HAS_COL0)
+ WRITE(p, "ATTRIN float4 color0; // ATTR%d,\n", SHADER_COLOR0_ATTRIB);
+ if (components & VB_HAS_COL1)
+ WRITE(p, "ATTRIN float4 color1; // ATTR%d,\n", SHADER_COLOR1_ATTRIB);
+
+ for (int i = 0; i < 8; ++i) {
+ u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
+ if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
+ WRITE(p, "ATTRIN float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i, SHADER_TEXTURE0_ATTRIB + i);
+ }
+
+ // Let's set up attributes
+ if (xfregs.numTexGen.numTexGens < 7)
{
- WRITE(p, " float4 blend_indices : BLENDINDICES,\n");
+ for (int i = 0; i < 8; ++i)
+ WRITE(p, "VARYOUT float3 uv%d_2;\n", i);
+ WRITE(p, "VARYOUT float4 clipPos_2;\n");
+ if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
+ WRITE(p, "VARYOUT float4 Normal_2;\n");
}
else
- WRITE(p, " float fposmtx : ATTR%d,\n", SHADER_POSMTX_ATTRIB);
+ {
+ // wpos is in w of first 4 texcoords
+ if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
+ {
+ for (int i = 0; i < 8; ++i)
+ WRITE(p, "VARYOUT float4 uv%d_2;\n", i);
+ }
+ else
+ {
+ for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
+ WRITE(p, "VARYOUT float%d uv%d_2;\n", i < 4 ? 4 : 3 , i);
+ }
+ }
+ WRITE(p, "VARYOUT float4 colors_02;\n");
+ WRITE(p, "VARYOUT float4 colors_12;\n");
+
+ WRITE(p, "void main()\n{\n");
+ }
+ else
+ {
+ WRITE(p, "VS_OUTPUT main(\n");
+
+ // inputs
+ if (components & VB_HAS_NRM0)
+ WRITE(p, " float3 rawnorm0 : NORMAL0,\n");
+ if (components & VB_HAS_NRM1) {
+ if (is_d3d)
+ WRITE(p, " float3 rawnorm1 : NORMAL1,\n");
+ else
+ WRITE(p, " float3 rawnorm1 : ATTR%d,\n", SHADER_NORM1_ATTRIB);
+ }
+ if (components & VB_HAS_NRM2) {
+ if (is_d3d)
+ WRITE(p, " float3 rawnorm2 : NORMAL2,\n");
+ else
+ WRITE(p, " float3 rawnorm2 : ATTR%d,\n", SHADER_NORM2_ATTRIB);
+ }
+ if (components & VB_HAS_COL0)
+ WRITE(p, " float4 color0 : COLOR0,\n");
+ if (components & VB_HAS_COL1)
+ WRITE(p, " float4 color1 : COLOR1,\n");
+ for (int i = 0; i < 8; ++i) {
+ u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
+ if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
+ WRITE(p, " float%d tex%d : TEXCOORD%d,\n", hastexmtx ? 3 : 2, i, i);
+ }
+ if (components & VB_HAS_POSMTXIDX) {
+ if (is_d3d)
+ WRITE(p, " float4 blend_indices : BLENDINDICES,\n");
+ else
+ WRITE(p, " float fposmtx : ATTR%d,\n", SHADER_POSMTX_ATTRIB);
+ }
+ WRITE(p, " float4 rawpos : POSITION) {\n");
}
- WRITE(p, " float4 rawpos : POSITION) {\n");
WRITE(p, "VS_OUTPUT o;\n");
// transforms
if (components & VB_HAS_POSMTXIDX)
{
- if (api_type & API_D3D9)
+ if (ApiType & API_D3D9)
{
WRITE(p, "int4 indices = D3DCOLORtoUBYTE4(blend_indices);\n");
WRITE(p, "int posmtx = indices.x;\n");
}
- else if (api_type == API_D3D11)
+ else if (ApiType == API_D3D11)
{
WRITE(p, "int posmtx = blend_indices.x * 255.0f;\n");
}
- else
- {
- WRITE(p, "int posmtx = fposmtx;\n");
- }
- WRITE(p, "float4 pos = float4(dot(" I_TRANSFORMMATRICES".T[posmtx].t, rawpos), dot(" I_TRANSFORMMATRICES".T[posmtx+1].t, rawpos), dot(" I_TRANSFORMMATRICES".T[posmtx+2].t, rawpos), 1);\n");
+ WRITE(p, "float4 pos = float4(dot(" I_TRANSFORMMATRICES"[posmtx], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+1], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+2], rawpos), 1);\n");
if (components & VB_HAS_NRMALL) {
WRITE(p, "int normidx = posmtx >= 32 ? (posmtx-32) : posmtx;\n");
- WRITE(p, "float3 N0 = " I_NORMALMATRICES".T[normidx].t.xyz, N1 = " I_NORMALMATRICES".T[normidx+1].t.xyz, N2 = " I_NORMALMATRICES".T[normidx+2].t.xyz;\n");
+ WRITE(p, "float3 N0 = " I_NORMALMATRICES"[normidx].xyz, N1 = " I_NORMALMATRICES"[normidx+1].xyz, N2 = " I_NORMALMATRICES"[normidx+2].xyz;\n");
}
if (components & VB_HAS_NRM0)
@@ -274,27 +322,25 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
}
else
{
- WRITE(p, "float4 pos = float4(dot(" I_POSNORMALMATRIX".T0, rawpos), dot(" I_POSNORMALMATRIX".T1, rawpos), dot(" I_POSNORMALMATRIX".T2, rawpos), 1.0f);\n");
+ WRITE(p, "float4 pos = float4(dot(" I_POSNORMALMATRIX"[0], rawpos), dot(" I_POSNORMALMATRIX"[1], rawpos), dot(" I_POSNORMALMATRIX"[2], rawpos), 1.0f);\n");
if (components & VB_HAS_NRM0)
- WRITE(p, "float3 _norm0 = normalize(float3(dot(" I_POSNORMALMATRIX".N0.xyz, rawnorm0), dot(" I_POSNORMALMATRIX".N1.xyz, rawnorm0), dot(" I_POSNORMALMATRIX".N2.xyz, rawnorm0)));\n");
+ WRITE(p, "float3 _norm0 = normalize(float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm0), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm0), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm0)));\n");
if (components & VB_HAS_NRM1)
- WRITE(p, "float3 _norm1 = float3(dot(" I_POSNORMALMATRIX".N0.xyz, rawnorm1), dot(" I_POSNORMALMATRIX".N1.xyz, rawnorm1), dot(" I_POSNORMALMATRIX".N2.xyz, rawnorm1));\n");
+ WRITE(p, "float3 _norm1 = float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm1), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm1), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm1));\n");
if (components & VB_HAS_NRM2)
- WRITE(p, "float3 _norm2 = float3(dot(" I_POSNORMALMATRIX".N0.xyz, rawnorm2), dot(" I_POSNORMALMATRIX".N1.xyz, rawnorm2), dot(" I_POSNORMALMATRIX".N2.xyz, rawnorm2));\n");
+ WRITE(p, "float3 _norm2 = float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm2), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm2), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm2));\n");
}
if (!(components & VB_HAS_NRM0))
WRITE(p, "float3 _norm0 = float3(0.0f, 0.0f, 0.0f);\n");
-
-
- WRITE(p, "o.pos = float4(dot(" I_PROJECTION".T0, pos), dot(" I_PROJECTION".T1, pos), dot(" I_PROJECTION".T2, pos), dot(" I_PROJECTION".T3, pos));\n");
+ WRITE(p, "o.pos = float4(dot(" I_PROJECTION"[0], pos), dot(" I_PROJECTION"[1], pos), dot(" I_PROJECTION"[2], pos), dot(" I_PROJECTION"[3], pos));\n");
WRITE(p, "float4 mat, lacc;\n"
"float3 ldir, h;\n"
"float dist, dist2, attn;\n");
- if(xfregs.numChan.numColorChans == 0)
+ if (xfregs.numChan.numColorChans == 0)
{
if (components & VB_HAS_COL0)
WRITE(p, "o.colors_0 = color0;\n");
@@ -305,7 +351,7 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
// TODO: This probably isn't necessary if pixel lighting is enabled.
p = GenerateLightingShader(p, components, I_MATERIALS, I_LIGHTS, "color", "o.colors_");
- if(xfregs.numChan.numColorChans < 2)
+ if (xfregs.numChan.numColorChans < 2)
{
if (components & VB_HAS_COL1)
WRITE(p, "o.colors_1 = color1;\n");
@@ -367,7 +413,7 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
if (components & (VB_HAS_NRM1|VB_HAS_NRM2)) {
// transform the light dir into tangent space
- WRITE(p, "ldir = normalize(" I_LIGHTS".lights[%d].pos.xyz - pos.xyz);\n", texinfo.embosslightshift);
+ WRITE(p, "ldir = normalize(" I_LIGHTS"[%d + 3].xyz - pos.xyz);\n", texinfo.embosslightshift);
WRITE(p, "o.tex%d.xyz = o.tex%d.xyz + float3(dot(ldir, _norm1), dot(ldir, _norm2), 0.0f);\n", i, texinfo.embosssourceshift);
}
else
@@ -387,18 +433,20 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
break;
case XF_TEXGEN_REGULAR:
default:
- if (components & (VB_HAS_TEXMTXIDX0<<i)) {
+ if (components & (VB_HAS_TEXMTXIDX0<<i))
+ {
+ WRITE(p, "int tmp = int(tex%d.z);\n", i);
if (texinfo.projection == XF_TEXPROJ_STQ)
- WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z].t), dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z+1].t), dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z+2].t));\n", i, i, i, i);
+ WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES"[tmp]), dot(coord, " I_TRANSFORMMATRICES"[tmp+1]), dot(coord, " I_TRANSFORMMATRICES"[tmp+2]));\n", i);
else {
- WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z].t), dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z+1].t), 1);\n", i, i, i);
+ WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES"[tmp]), dot(coord, " I_TRANSFORMMATRICES"[tmp+1]), 1);\n", i);
}
}
else {
if (texinfo.projection == XF_TEXPROJ_STQ)
- WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES".T[%d].t), dot(coord, " I_TEXMATRICES".T[%d].t), dot(coord, " I_TEXMATRICES".T[%d].t));\n", i, 3*i, 3*i+1, 3*i+2);
+ WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]));\n", i, 3*i, 3*i+1, 3*i+2);
else
- WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES".T[%d].t), dot(coord, " I_TEXMATRICES".T[%d].t), 1);\n", i, 3*i, 3*i+1);
+ WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]), 1);\n", i, 3*i, 3*i+1);
}
break;
}
@@ -407,9 +455,9 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
const PostMtxInfo& postInfo = xfregs.postMtxInfo[i];
int postidx = postInfo.index;
- WRITE(p, "float4 P0 = " I_POSTTRANSFORMMATRICES".T[%d].t;\n"
- "float4 P1 = " I_POSTTRANSFORMMATRICES".T[%d].t;\n"
- "float4 P2 = " I_POSTTRANSFORMMATRICES".T[%d].t;\n",
+ WRITE(p, "float4 P0 = " I_POSTTRANSFORMMATRICES"[%d];\n"
+ "float4 P1 = " I_POSTTRANSFORMMATRICES"[%d];\n"
+ "float4 P2 = " I_POSTTRANSFORMMATRICES"[%d];\n",
postidx&0x3f, (postidx+1)&0x3f, (postidx+2)&0x3f);
if (texGenSpecialCase) {
@@ -455,9 +503,9 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
WRITE(p, "o.tex7 = pos.xyzz;\n");
else
WRITE(p, "o.tex7.w = pos.z;\n");
- }
+ }
if (components & VB_HAS_COL0)
- WRITE(p, "o.colors_0 = color0;\n");
+ WRITE(p, "o.colors_0 = color0;\n");
if (components & VB_HAS_COL1)
WRITE(p, "o.colors_1 = color1;\n");
@@ -465,44 +513,77 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
//write the true depth value, if the game uses depth textures pixel shaders will override with the correct values
//if not early z culling will improve speed
- // TODO: Can probably be dropped?
if (is_d3d)
{
WRITE(p, "o.pos.z = " I_DEPTHPARAMS".x * o.pos.w + o.pos.z * " I_DEPTHPARAMS".y;\n");
}
else
{
- // this results in a scale from -1..0 to -1..1 after perspective
- // divide
- WRITE(p, "o.pos.z = o.pos.w + o.pos.z * 2.0f;\n");
-
- // Sonic Unleashed puts its final rendering at the near or
- // far plane of the viewing frustrum(actually box, they use
- // orthogonal projection for that), and we end up putting it
- // just beyond, and the rendering gets clipped away. (The
- // primitive gets dropped)
- WRITE(p, "o.pos.z = o.pos.z * 1048575.0f/1048576.0f;\n");
-
- // the next steps of the OGL pipeline are:
- // (x_c,y_c,z_c,w_c) = o.pos //switch to OGL spec terminology
- // clipping to -w_c <= (x_c,y_c,z_c) <= w_c
- // (x_d,y_d,z_d) = (x_c,y_c,z_c)/w_c//perspective divide
- // z_w = (f-n)/2*z_d + (n+f)/2
- // z_w now contains the value to go to the 0..1 depth buffer
-
- //trying to get the correct semantic while not using glDepthRange
- //seems to get rather complicated
+ // this results in a scale from -1..0 to -1..1 after perspective
+ // divide
+ WRITE(p, "o.pos.z = o.pos.w + o.pos.z * 2.0f;\n");
+
+ // Sonic Unleashed puts its final rendering at the near or
+ // far plane of the viewing frustrum(actually box, they use
+ // orthogonal projection for that), and we end up putting it
+ // just beyond, and the rendering gets clipped away. (The
+ // primitive gets dropped)
+ WRITE(p, "o.pos.z = o.pos.z * 1048575.0f/1048576.0f;\n");
+
+ // the next steps of the OGL pipeline are:
+ // (x_c,y_c,z_c,w_c) = o.pos //switch to OGL spec terminology
+ // clipping to -w_c <= (x_c,y_c,z_c) <= w_c
+ // (x_d,y_d,z_d) = (x_c,y_c,z_c)/w_c//perspective divide
+ // z_w = (f-n)/2*z_d + (n+f)/2
+ // z_w now contains the value to go to the 0..1 depth buffer
+
+ //trying to get the correct semantic while not using glDepthRange
+ //seems to get rather complicated
}
- if (api_type & API_D3D9)
+ if (ApiType & API_D3D9)
{
// D3D9 is addressing pixel centers instead of pixel boundaries in clip space.
// Thus we need to offset the final position by half a pixel
WRITE(p, "o.pos = o.pos + float4(" I_DEPTHPARAMS".z, " I_DEPTHPARAMS".w, 0.f, 0.f);\n");
}
- WRITE(p, "return o;\n}\n");
+ if(ApiType == API_OPENGL)
+ {
+ // Bit ugly here
+ // TODO: Make pretty
+ // Will look better when we bind uniforms in GLSL 1.3
+ // clipPos/w needs to be done in pixel shader, not here
+ if (xfregs.numTexGen.numTexGens < 7) {
+ for (unsigned int i = 0; i < 8; ++i)
+ if(i < xfregs.numTexGen.numTexGens)
+ WRITE(p, " uv%d_2.xyz = o.tex%d;\n", i, i);
+ else
+ WRITE(p, " uv%d_2.xyz = float3(0.0f, 0.0f, 0.0f);\n", i);
+ WRITE(p, " clipPos_2 = o.clipPos;\n");
+ if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
+ WRITE(p, " Normal_2 = o.Normal;\n");
+ } else {
+ // clip position is in w of first 4 texcoords
+ if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
+ {
+ for (int i = 0; i < 8; ++i)
+ WRITE(p, " uv%d_2 = o.tex%d;\n", i, i);
+ }
+ else
+ {
+ for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
+ WRITE(p, " uv%d_2%s = o.tex%d;\n", i, i < 4 ? ".xyzw" : ".xyz" , i);
+ }
+ }
+ WRITE(p, "colors_02 = o.colors_0;\n");
+ WRITE(p, "colors_12 = o.colors_1;\n");
+ WRITE(p, "gl_Position = o.pos;\n");
+ WRITE(p, "}\n");
+ }
+ else
+ WRITE(p, "return o;\n}\n");
if (text[sizeof(text) - 1] != 0x7C)
PanicAlert("VertexShader generator - buffer too small, canary has been eaten!");
diff --git a/Source/Core/VideoCommon/Src/VertexShaderGen.h b/Source/Core/VideoCommon/Src/VertexShaderGen.h
index cb253a9b6c..4d7ab68e11 100644
--- a/Source/Core/VideoCommon/Src/VertexShaderGen.h
+++ b/Source/Core/VideoCommon/Src/VertexShaderGen.h
@@ -21,9 +21,24 @@
#include "XFMemory.h"
#include "VideoCommon.h"
-#define SHADER_POSMTX_ATTRIB 1
-#define SHADER_NORM1_ATTRIB 6
-#define SHADER_NORM2_ATTRIB 7
+// TODO should be reordered
+#define SHADER_POSITION_ATTRIB 0
+#define SHADER_POSMTX_ATTRIB 1
+#define SHADER_NORM0_ATTRIB 2
+#define SHADER_NORM1_ATTRIB 3
+#define SHADER_NORM2_ATTRIB 4
+#define SHADER_COLOR0_ATTRIB 5
+#define SHADER_COLOR1_ATTRIB 6
+
+#define SHADER_TEXTURE0_ATTRIB 8
+#define SHADER_TEXTURE1_ATTRIB 9
+#define SHADER_TEXTURE2_ATTRIB 10
+#define SHADER_TEXTURE3_ATTRIB 11
+#define SHADER_TEXTURE4_ATTRIB 12
+#define SHADER_TEXTURE5_ATTRIB 13
+#define SHADER_TEXTURE6_ATTRIB 14
+#define SHADER_TEXTURE7_ATTRIB 15
+
// shader variables
@@ -46,8 +61,17 @@
#define C_NORMALMATRICES (C_TRANSFORMMATRICES + 64)
#define C_POSTTRANSFORMMATRICES (C_NORMALMATRICES + 32)
#define C_DEPTHPARAMS (C_POSTTRANSFORMMATRICES + 64)
-#define C_VENVCONST_END (C_DEPTHPARAMS + 4)
-
+#define C_VENVCONST_END (C_DEPTHPARAMS + 1)
+const s_svar VSVar_Loc[] = { {I_POSNORMALMATRIX, C_POSNORMALMATRIX, 6 },
+ {I_PROJECTION , C_PROJECTION, 4 },
+ {I_MATERIALS, C_MATERIALS, 4 },
+ {I_LIGHTS, C_LIGHTS, 40 },
+ {I_TEXMATRICES, C_TEXMATRICES, 24 },
+ {I_TRANSFORMMATRICES , C_TRANSFORMMATRICES, 64 },
+ {I_NORMALMATRICES , C_NORMALMATRICES, 32 },
+ {I_POSTTRANSFORMMATRICES, C_POSTTRANSFORMMATRICES, 64 },
+ {I_DEPTHPARAMS, C_DEPTHPARAMS, 1 },
+ };
template<bool safe>
class _VERTEXSHADERUID
{
diff --git a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp
index 1dce567b0d..a5e84ee69b 100644
--- a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp
+++ b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp
@@ -102,7 +102,7 @@ float PHackValue(std::string sValue)
c[i] = (cStr[i] == ',') ? '.' : *(cStr+i);
if (c[i] == '.')
fp = true;
- }
+ }
cStr = c;
sTof.str(cStr);
sTof >> f;
@@ -119,22 +119,22 @@ void UpdateProjectionHack(int iPhackvalue[], std::string sPhackvalue[])
float fhacksign1 = 1.0, fhacksign2 = 1.0;
bool bProjHack3 = false;
const char *sTemp[2];
-
+
if (iPhackvalue[0] == 1)
{
NOTICE_LOG(VIDEO, "\t\t--- Ortographic Projection Hack ON ---");
-
+
fhacksign1 *= (iPhackvalue[1] == 1) ? -1.0f : fhacksign1;
sTemp[0] = (iPhackvalue[1] == 1) ? " * (-1)" : "";
fhacksign2 *= (iPhackvalue[2] == 1) ? -1.0f : fhacksign2;
sTemp[1] = (iPhackvalue[2] == 1) ? " * (-1)" : "";
-
+
fhackvalue1 = PHackValue(sPhackvalue[0]);
NOTICE_LOG(VIDEO, "- zNear Correction = (%f + zNear)%s", fhackvalue1, sTemp[0]);
fhackvalue2 = PHackValue(sPhackvalue[1]);
NOTICE_LOG(VIDEO, "- zFar Correction = (%f + zFar)%s", fhackvalue2, sTemp[1]);
-
+
sTemp[0] = "DISABLED";
bProjHack3 = (iPhackvalue[3] == 1) ? true : bProjHack3;
if (bProjHack3)
@@ -171,22 +171,22 @@ void VertexShaderManager::Dirty()
{
nTransformMatricesChanged[0] = 0;
nTransformMatricesChanged[1] = 256;
-
+
nNormalMatricesChanged[0] = 0;
nNormalMatricesChanged[1] = 96;
-
+
nPostTransformMatricesChanged[0] = 0;
nPostTransformMatricesChanged[1] = 256;
-
+
nLightsChanged[0] = 0;
nLightsChanged[1] = 0x80;
-
+
bPosNormalMatrixChanged = true;
bTexMatricesChanged[0] = true;
bTexMatricesChanged[1] = true;
-
+
bProjectionChanged = true;
-
+
nMaterialsChanged = 15;
}
@@ -194,6 +194,8 @@ void VertexShaderManager::Dirty()
// TODO: A cleaner way to control the matricies without making a mess in the parameters field
void VertexShaderManager::SetConstants()
{
+ if (g_ActiveConfig.backend_info.APIType == API_OPENGL && !g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ Dirty();
if (nTransformMatricesChanged[0] >= 0)
{
int startn = nTransformMatricesChanged[0] / 4;
@@ -356,7 +358,7 @@ void VertexShaderManager::SetConstants()
switch(xfregs.projection.type)
{
case GX_PERSPECTIVE:
-
+
g_fProjectionMatrix[0] = rawProjection[0] * g_ActiveConfig.fAspectRatioHackW;
g_fProjectionMatrix[1] = 0.0f;
g_fProjectionMatrix[2] = rawProjection[1];
@@ -372,7 +374,7 @@ void VertexShaderManager::SetConstants()
g_fProjectionMatrix[10] = rawProjection[4];
g_fProjectionMatrix[11] = rawProjection[5];
-
+
g_fProjectionMatrix[12] = 0.0f;
g_fProjectionMatrix[13] = 0.0f;
// donkopunchstania: GC GPU rounds differently?
@@ -397,9 +399,9 @@ void VertexShaderManager::SetConstants()
SETSTAT_FT(stats.gproj_14, g_fProjectionMatrix[14]);
SETSTAT_FT(stats.gproj_15, g_fProjectionMatrix[15]);
break;
-
+
case GX_ORTHOGRAPHIC:
-
+
g_fProjectionMatrix[0] = rawProjection[0];
g_fProjectionMatrix[1] = 0.0f;
g_fProjectionMatrix[2] = 0.0f;
@@ -424,10 +426,10 @@ void VertexShaderManager::SetConstants()
this hack was added...setting g_fProjectionMatrix[14] to -1 might make the hack more stable, needs more testing.
Only works for OGL and DX9...this is not helping DX11
*/
-
+
g_fProjectionMatrix[14] = 0.0f;
g_fProjectionMatrix[15] = (g_ProjHack3 && rawProjection[0] == 2.0f ? 0.0f : 1.0f); //causes either the efb copy or bloom layer not to show if proj hack enabled
-
+
SETSTAT_FT(stats.g2proj_0, g_fProjectionMatrix[0]);
SETSTAT_FT(stats.g2proj_1, g_fProjectionMatrix[1]);
SETSTAT_FT(stats.g2proj_2, g_fProjectionMatrix[2]);
@@ -451,7 +453,7 @@ void VertexShaderManager::SetConstants()
SETSTAT_FT(stats.proj_4, rawProjection[4]);
SETSTAT_FT(stats.proj_5, rawProjection[5]);
break;
-
+
default:
ERROR_LOG(VIDEO, "unknown projection type: %d", xfregs.projection.type);
}
diff --git a/Source/Core/VideoCommon/Src/VertexShaderManager.h b/Source/Core/VideoCommon/Src/VertexShaderManager.h
index 86f77ee3da..a0c89f1e60 100644
--- a/Source/Core/VideoCommon/Src/VertexShaderManager.h
+++ b/Source/Core/VideoCommon/Src/VertexShaderManager.h
@@ -43,7 +43,7 @@ public:
static void Dirty();
static void Shutdown();
static void DoState(PointerWrap &p);
-;
+
// constant management
static void SetConstants();
diff --git a/Source/Core/VideoCommon/Src/VideoCommon.h b/Source/Core/VideoCommon/Src/VideoCommon.h
index 1eeed20b82..bf83235591 100644
--- a/Source/Core/VideoCommon/Src/VideoCommon.h
+++ b/Source/Core/VideoCommon/Src/VideoCommon.h
@@ -90,8 +90,8 @@ struct TargetRectangle : public MathUtil::Rectangle<int>
#define PRIM_LOG(...) DEBUG_LOG(VIDEO, ##__VA_ARGS__)
#endif
-
-// #define LOG_VTX() DEBUG_LOG(VIDEO, "vtx: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0], ((float*)VertexManager::s_pCurBufferPointer)[1], ((float*)VertexManager::s_pCurBufferPointer)[2]);
+// warning: mapping buffer should be disabled to use this
+// #define LOG_VTX() DEBUG_LOG(VIDEO, "vtx: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-3], ((float*)VertexManager::s_pCurBufferPointer)[-2], ((float*)VertexManager::s_pCurBufferPointer)[-1]);
#define LOG_VTX()
@@ -102,8 +102,7 @@ typedef enum
API_D3D9_SM20 = 4,
API_D3D9 = 6,
API_D3D11 = 8,
- API_GLSL = 16,
- API_NONE = 32
+ API_NONE = 16
} API_TYPE;
inline u32 RGBA8ToRGBA6ToRGBA8(u32 src)
@@ -149,5 +148,11 @@ inline unsigned int GetPow2(unsigned int val)
++ret;
return ret;
}
+struct s_svar
+{
+ const char *name;
+ const unsigned int reg;
+ const unsigned int size;
+};
#endif // _VIDEOCOMMON_H
diff --git a/Source/Core/VideoCommon/Src/VideoConfig.cpp b/Source/Core/VideoCommon/Src/VideoConfig.cpp
index a76514a10c..60677ceeeb 100644
--- a/Source/Core/VideoCommon/Src/VideoConfig.cpp
+++ b/Source/Core/VideoCommon/Src/VideoConfig.cpp
@@ -22,6 +22,7 @@
#include "VideoConfig.h"
#include "VideoCommon.h"
#include "FileUtil.h"
+#include "Core.h"
VideoConfig g_Config;
VideoConfig g_ActiveConfig;
@@ -51,7 +52,7 @@ void VideoConfig::Load(const char *ini_file)
std::string temp;
IniFile iniFile;
iniFile.Load(ini_file);
-
+
iniFile.Get("Hardware", "VSync", &bVSync, 0); // Hardware
iniFile.Get("Settings", "wideScreenHack", &bWidescreenHack, false);
iniFile.Get("Settings", "AspectRatio", &iAspectRatio, (int)ASPECT_AUTO);
@@ -76,17 +77,18 @@ void VideoConfig::Load(const char *ini_file)
iniFile.Get("Settings", "AnaglyphStereoSeparation", &iAnaglyphStereoSeparation, 200);
iniFile.Get("Settings", "AnaglyphFocalAngle", &iAnaglyphFocalAngle, 0);
iniFile.Get("Settings", "EnablePixelLighting", &bEnablePixelLighting, 0);
-
+ iniFile.Get("Settings", "HackedBufferUpload", &bHackedBufferUpload, 0);
+
iniFile.Get("Settings", "MSAA", &iMultisampleMode, 0);
iniFile.Get("Settings", "EFBScale", &iEFBScale, 2); // native
-
+
iniFile.Get("Settings", "DstAlphaPass", &bDstAlphaPass, false);
-
+
iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0);
iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0);
iniFile.Get("Settings", "WireFrame", &bWireFrame, 0);
iniFile.Get("Settings", "DisableFog", &bDisableFog, 0);
-
+
iniFile.Get("Settings", "EnableOpenCL", &bEnableOpenCL, false);
iniFile.Get("Settings", "OMPDecoder", &bOMPDecoder, false);
@@ -96,7 +98,7 @@ void VideoConfig::Load(const char *ini_file)
iniFile.Get("Enhancements", "MaxAnisotropy", &iMaxAnisotropy, 0); // NOTE - this is x in (1 << x)
iniFile.Get("Enhancements", "PostProcessingShader", &sPostProcessingShader, "");
iniFile.Get("Enhancements", "Enable3dVision", &b3DVision, false);
-
+
iniFile.Get("Hacks", "EFBAccessEnable", &bEFBAccessEnable, true);
iniFile.Get("Hacks", "DlistCachingEnable", &bDlistCachingEnable,false);
iniFile.Get("Hacks", "EFBCopyEnable", &bEFBCopyEnable, true);
@@ -134,6 +136,7 @@ void VideoConfig::GameIniLoad(const char *ini_file)
iniFile.GetIfExists("Video_Settings", "AnaglyphStereoSeparation", &iAnaglyphStereoSeparation);
iniFile.GetIfExists("Video_Settings", "AnaglyphFocalAngle", &iAnaglyphFocalAngle);
iniFile.GetIfExists("Video_Settings", "EnablePixelLighting", &bEnablePixelLighting);
+ iniFile.GetIfExists("Video_Settings", "HackedBufferUpload", &bHackedBufferUpload);
iniFile.GetIfExists("Video_Settings", "MSAA", &iMultisampleMode);
iniFile.GetIfExists("Video_Settings", "EFBScale", &iEFBScale); // integral
iniFile.GetIfExists("Video_Settings", "DstAlphaPass", &bDstAlphaPass);
@@ -172,6 +175,7 @@ void VideoConfig::VerifyValidity()
if (!backend_info.bSupports3DVision) b3DVision = false;
if (!backend_info.bSupportsFormatReinterpretation) bEFBEmulateFormatChanges = false;
if (!backend_info.bSupportsPixelLighting) bEnablePixelLighting = false;
+ if (backend_info.APIType != API_OPENGL) backend_info.bSupportsGLSLUBO = false;
}
void VideoConfig::Save(const char *ini_file)
@@ -202,7 +206,7 @@ void VideoConfig::Save(const char *ini_file)
iniFile.Set("Settings", "AnaglyphStereoSeparation", iAnaglyphStereoSeparation);
iniFile.Set("Settings", "AnaglyphFocalAngle", iAnaglyphFocalAngle);
iniFile.Set("Settings", "EnablePixelLighting", bEnablePixelLighting);
-
+ iniFile.Set("Settings", "HackedBufferUpload", bHackedBufferUpload);
iniFile.Set("Settings", "ShowEFBCopyRegions", bShowEFBCopyRegions);
iniFile.Set("Settings", "MSAA", iMultisampleMode);
@@ -215,14 +219,14 @@ void VideoConfig::Save(const char *ini_file)
iniFile.Set("Settings", "EnableOpenCL", bEnableOpenCL);
iniFile.Set("Settings", "OMPDecoder", bOMPDecoder);
-
+
iniFile.Set("Settings", "EnableShaderDebugging", bEnableShaderDebugging);
iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering);
iniFile.Set("Enhancements", "MaxAnisotropy", iMaxAnisotropy);
iniFile.Set("Enhancements", "PostProcessingShader", sPostProcessingShader);
iniFile.Set("Enhancements", "Enable3dVision", b3DVision);
-
+
iniFile.Set("Hacks", "EFBAccessEnable", bEFBAccessEnable);
iniFile.Set("Hacks", "DlistCachingEnable", bDlistCachingEnable);
iniFile.Set("Hacks", "EFBCopyEnable", bEFBCopyEnable);
@@ -233,7 +237,7 @@ void VideoConfig::Save(const char *ini_file)
iniFile.Set("Hacks", "EFBEmulateFormatChanges", bEFBEmulateFormatChanges);
iniFile.Set("Hardware", "Adapter", iAdapter);
-
+
iniFile.Save(ini_file);
}
@@ -289,3 +293,8 @@ void VideoConfig::GameIniSave(const char* default_ini, const char* game_ini)
iniFile.Save(game_ini);
}
+
+bool VideoConfig::IsVSync()
+{
+ return Core::isTabPressed ? false : bVSync;
+}
diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h
index 183fcf784c..442e95f9bf 100644
--- a/Source/Core/VideoCommon/Src/VideoConfig.h
+++ b/Source/Core/VideoCommon/Src/VideoConfig.h
@@ -37,17 +37,6 @@
#define CONF_SAVETARGETS 8
#define CONF_SAVESHADERS 16
-enum MultisampleMode {
- MULTISAMPLE_OFF,
- MULTISAMPLE_2X,
- MULTISAMPLE_4X,
- MULTISAMPLE_8X,
- MULTISAMPLE_CSAA_8X,
- MULTISAMPLE_CSAA_8XQ,
- MULTISAMPLE_CSAA_16X,
- MULTISAMPLE_CSAA_16XQ,
-};
-
enum AspectMode {
ASPECT_AUTO = 0,
ASPECT_FORCE_16_9 = 1,
@@ -67,6 +56,7 @@ struct VideoConfig
void Save(const char *ini_file);
void GameIniSave(const char* default_ini, const char* game_ini);
void UpdateProjectionHack();
+ bool IsVSync();
// General
bool bVSync;
@@ -98,12 +88,12 @@ struct VideoConfig
bool bTexFmtOverlayCenter;
bool bShowEFBCopyRegions;
bool bLogFPSToFile;
-
+
// Render
bool bWireFrame;
bool bDstAlphaPass;
bool bDisableFog;
-
+
// Utility
bool bDumpTextures;
bool bHiresTextures;
@@ -115,7 +105,7 @@ struct VideoConfig
int iAnaglyphStereoSeparation;
int iAnaglyphFocalAngle;
bool b3DVision;
-
+
// Hacks
bool bEFBAccessEnable;
bool bDlistCachingEnable;
@@ -133,6 +123,7 @@ struct VideoConfig
bool bZTPSpeedHack; // The Legend of Zelda: Twilight Princess
bool bUseBBox;
bool bEnablePixelLighting;
+ bool bHackedBufferUpload;
int iLog; // CONF_ bits
int iSaveTargetId; // TODO: Should be dropped
@@ -162,13 +153,15 @@ struct VideoConfig
bool bSupportsDualSourceBlend; // only supported by D3D11 and OpenGL
bool bSupportsFormatReinterpretation;
bool bSupportsPixelLighting;
+
+ bool bSupportsGLSLUBO; // needed by pixelShaderGen, so must stay in videoCommon
} backend_info;
- // Utility
- bool RealXFBEnabled() const { return bUseXFB && bUseRealXFB; }
- bool VirtualXFBEnabled() const { return bUseXFB && !bUseRealXFB; }
- bool EFBCopiesToTextureEnabled() const { return bEFBCopyEnable && bCopyEFBToTexture; }
- bool EFBCopiesToRamEnabled() const { return bEFBCopyEnable && !bCopyEFBToTexture; }
+ // Utility
+ bool RealXFBEnabled() const { return bUseXFB && bUseRealXFB; }
+ bool VirtualXFBEnabled() const { return bUseXFB && !bUseRealXFB; }
+ bool EFBCopiesToTextureEnabled() const { return bEFBCopyEnable && bCopyEFBToTexture; }
+ bool EFBCopiesToRamEnabled() const { return bEFBCopyEnable && !bCopyEFBToTexture; }
};
extern VideoConfig g_Config;
diff --git a/Source/Core/VideoCommon/Src/VideoState.cpp b/Source/Core/VideoCommon/Src/VideoState.cpp
index ad5384cda9..0d99d0378f 100644
--- a/Source/Core/VideoCommon/Src/VideoState.cpp
+++ b/Source/Core/VideoCommon/Src/VideoState.cpp
@@ -30,33 +30,33 @@
static void DoState(PointerWrap &p)
{
- // BP Memory
- p.Do(bpmem);
+ // BP Memory
+ p.Do(bpmem);
p.DoMarker("BP Memory");
// CP Memory
- p.DoArray(arraybases, 16);
- p.DoArray(arraystrides, 16);
- p.Do(MatrixIndexA);
- p.Do(MatrixIndexB);
- p.Do(g_VtxDesc.Hex);
+ p.DoArray(arraybases, 16);
+ p.DoArray(arraystrides, 16);
+ p.Do(MatrixIndexA);
+ p.Do(MatrixIndexB);
+ p.Do(g_VtxDesc.Hex);
p.DoArray(g_VtxAttr, 8);
p.DoMarker("CP Memory");
- // XF Memory
- p.Do(xfregs);
- p.DoArray(xfmem, XFMEM_SIZE);
+ // XF Memory
+ p.Do(xfregs);
+ p.DoArray(xfmem, XFMEM_SIZE);
p.DoMarker("XF Memory");
// Texture decoder
- p.DoArray(texMem, TMEM_SIZE);
+ p.DoArray(texMem, TMEM_SIZE);
p.DoMarker("texMem");
- // FIFO
- Fifo_DoState(p);
+ // FIFO
+ Fifo_DoState(p);
p.DoMarker("Fifo");
- CommandProcessor::DoState(p);
+ CommandProcessor::DoState(p);
p.DoMarker("CommandProcessor");
PixelEngine::DoState(p);
@@ -77,7 +77,7 @@ static void DoState(PointerWrap &p)
void VideoCommon_DoState(PointerWrap &p)
{
- DoState(p);
+ DoState(p);
}
void VideoCommon_RunLoop(bool enable)
diff --git a/Source/Core/VideoCommon/Src/XFMemory.h b/Source/Core/VideoCommon/Src/XFMemory.h
index fc199b8c32..2ef3e41eb5 100644
--- a/Source/Core/VideoCommon/Src/XFMemory.h
+++ b/Source/Core/VideoCommon/Src/XFMemory.h
@@ -110,70 +110,70 @@
union LitChannel
{
- struct
- {
- u32 matsource : 1;
- u32 enablelighting : 1;
- u32 lightMask0_3 : 4;
- u32 ambsource : 1;
- u32 diffusefunc : 2; // LIGHTDIF_X
- u32 attnfunc : 2; // LIGHTATTN_X
- u32 lightMask4_7 : 4;
- };
- struct
- {
- u32 hex : 15;
- u32 unused : 17;
- };
- struct
- {
- u32 dummy0 : 7;
- u32 lightparams : 4;
- u32 dummy1 : 21;
- };
- unsigned int GetFullLightMask() const
- {
- return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
- }
+ struct
+ {
+ u32 matsource : 1;
+ u32 enablelighting : 1;
+ u32 lightMask0_3 : 4;
+ u32 ambsource : 1;
+ u32 diffusefunc : 2; // LIGHTDIF_X
+ u32 attnfunc : 2; // LIGHTATTN_X
+ u32 lightMask4_7 : 4;
+ };
+ struct
+ {
+ u32 hex : 15;
+ u32 unused : 17;
+ };
+ struct
+ {
+ u32 dummy0 : 7;
+ u32 lightparams : 4;
+ u32 dummy1 : 21;
+ };
+ unsigned int GetFullLightMask() const
+ {
+ return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
+ }
};
union INVTXSPEC
{
- struct
- {
- u32 numcolors : 2;
- u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals
- u32 numtextures : 4;
- u32 unused : 24;
- };
- u32 hex;
+ struct
+ {
+ u32 numcolors : 2;
+ u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals
+ u32 numtextures : 4;
+ u32 unused : 24;
+ };
+ u32 hex;
};
union TexMtxInfo
{
- struct
- {
- u32 unknown : 1;
- u32 projection : 1; // XF_TEXPROJ_X
- u32 inputform : 2; // XF_TEXINPUT_X
- u32 texgentype : 3; // XF_TEXGEN_X
- u32 sourcerow : 5; // XF_SRCGEOM_X
- u32 embosssourceshift : 3; // what generated texcoord to use
- u32 embosslightshift : 3; // light index that is used
- };
- u32 hex;
+ struct
+ {
+ u32 unknown : 1;
+ u32 projection : 1; // XF_TEXPROJ_X
+ u32 inputform : 2; // XF_TEXINPUT_X
+ u32 texgentype : 3; // XF_TEXGEN_X
+ u32 sourcerow : 5; // XF_SRCGEOM_X
+ u32 embosssourceshift : 3; // what generated texcoord to use
+ u32 embosslightshift : 3; // light index that is used
+ };
+ u32 hex;
};
union PostMtxInfo
{
- struct
- {
- u32 index : 6; // base row of dual transform matrix
- u32 unused : 2;
- u32 normalize : 1; // normalize before send operation
- };
- u32 hex;
+ struct
+ {
+ u32 index : 6; // base row of dual transform matrix
+ u32 unused : 2;
+ u32 normalize : 1; // normalize before send operation
+ };
+ u32 hex;
};
union NumColorChannel
@@ -207,25 +207,25 @@ union DualTexInfo
struct Light
{
- u32 useless[3];
- u32 color; //rgba
- float a0; //attenuation
- float a1;
- float a2;
- float k0; //k stuff
- float k1;
- float k2;
- union
- {
- struct {
+ u32 useless[3];
+ u32 color; //rgba
+ float a0; //attenuation
+ float a1;
+ float a2;
+ float k0; //k stuff
+ float k1;
+ float k2;
+ union
+ {
+ struct {
float dpos[3];
- float ddir[3]; // specular lights only
- };
- struct {
- float sdir[3];
- float shalfangle[3]; // specular lights only
- };
- };
+ float ddir[3]; // specular lights only
+ };
+ struct {
+ float sdir[3];
+ float shalfangle[3]; // specular lights only
+ };
+ };
};
struct Viewport
@@ -246,35 +246,35 @@ struct Projection
struct XFRegisters
{
- u32 error; // 0x1000
- u32 diag; // 0x1001
- u32 state0; // 0x1002
- u32 state1; // 0x1003
- u32 xfClock; // 0x1004
- u32 clipDisable; // 0x1005
- u32 perf0; // 0x1006
- u32 perf1; // 0x1007
- INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input
- NumColorChannel numChan; // 0x1009
- u32 ambColor[2]; // 0x100a, 0x100b
- u32 matColor[2]; // 0x100c, 0x100d
- LitChannel color[2]; // 0x100e, 0x100f
- LitChannel alpha[2]; // 0x1010, 0x1011
- DualTexInfo dualTexTrans; // 0x1012
- u32 unk3; // 0x1013
- u32 unk4; // 0x1014
- u32 unk5; // 0x1015
- u32 unk6; // 0x1016
- u32 unk7; // 0x1017
- u32 MatrixIndexA; // 0x1018
- u32 MatrixIndexB; // 0x1019
- Viewport viewport; // 0x101a - 0x101f
- Projection projection; // 0x1020 - 0x1026
- u32 unk8[24]; // 0x1027 - 0x103e
- NumTexGen numTexGen; // 0x103f
- TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
- u32 unk9[8]; // 0x1048 - 0x104f
- PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
+ u32 error; // 0x1000
+ u32 diag; // 0x1001
+ u32 state0; // 0x1002
+ u32 state1; // 0x1003
+ u32 xfClock; // 0x1004
+ u32 clipDisable; // 0x1005
+ u32 perf0; // 0x1006
+ u32 perf1; // 0x1007
+ INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input
+ NumColorChannel numChan; // 0x1009
+ u32 ambColor[2]; // 0x100a, 0x100b
+ u32 matColor[2]; // 0x100c, 0x100d
+ LitChannel color[2]; // 0x100e, 0x100f
+ LitChannel alpha[2]; // 0x1010, 0x1011
+ DualTexInfo dualTexTrans; // 0x1012
+ u32 unk3; // 0x1013
+ u32 unk4; // 0x1014
+ u32 unk5; // 0x1015
+ u32 unk6; // 0x1016
+ u32 unk7; // 0x1017
+ u32 MatrixIndexA; // 0x1018
+ u32 MatrixIndexB; // 0x1019
+ Viewport viewport; // 0x101a - 0x101f
+ Projection projection; // 0x1020 - 0x1026
+ u32 unk8[24]; // 0x1027 - 0x103e
+ NumTexGen numTexGen; // 0x103f
+ TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
+ u32 unk9[8]; // 0x1048 - 0x104f
+ PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
};
diff --git a/Source/Core/VideoCommon/Src/XFStructs.cpp b/Source/Core/VideoCommon/Src/XFStructs.cpp
index 9f395bfecf..df9624b6f0 100644
--- a/Source/Core/VideoCommon/Src/XFStructs.cpp
+++ b/Source/Core/VideoCommon/Src/XFStructs.cpp
@@ -36,37 +36,37 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData)
u32 address = baseAddress;
u32 dataIndex = 0;
- while (transferSize > 0 && address < 0x1058)
- {
- u32 newValue = pData[dataIndex];
+ while (transferSize > 0 && address < 0x1058)
+ {
+ u32 newValue = pData[dataIndex];
u32 nextAddress = address + 1;
- switch (address)
- {
- case XFMEM_ERROR:
- case XFMEM_DIAG:
- case XFMEM_STATE0: // internal state 0
- case XFMEM_STATE1: // internal state 1
- case XFMEM_CLOCK:
+ switch (address)
+ {
+ case XFMEM_ERROR:
+ case XFMEM_DIAG:
+ case XFMEM_STATE0: // internal state 0
+ case XFMEM_STATE1: // internal state 1
+ case XFMEM_CLOCK:
case XFMEM_SETGPMETRIC:
nextAddress = 0x1007;
- break;
+ break;
- case XFMEM_CLIPDISABLE:
+ case XFMEM_CLIPDISABLE:
//if (data & 1) {} // disable clipping detection
//if (data & 2) {} // disable trivial rejection
//if (data & 4) {} // disable cpoly clipping acceleration
- break;
+ break;
- case XFMEM_VTXSPECS: //__GXXfVtxSpecs, wrote 0004
- break;
+ case XFMEM_VTXSPECS: //__GXXfVtxSpecs, wrote 0004
+ break;
- case XFMEM_SETNUMCHAN:
+ case XFMEM_SETNUMCHAN:
if (xfregs.numChan.numColorChans != (newValue & 3))
- VertexManager::Flush();
- break;
+ VertexManager::Flush();
+ break;
- case XFMEM_SETCHAN0_AMBCOLOR: // Channel Ambient Color
+ case XFMEM_SETCHAN0_AMBCOLOR: // Channel Ambient Color
case XFMEM_SETCHAN1_AMBCOLOR:
{
u8 chan = address - XFMEM_SETCHAN0_AMBCOLOR;
@@ -75,11 +75,11 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData)
VertexManager::Flush();
VertexShaderManager::SetMaterialColorChanged(chan);
PixelShaderManager::SetMaterialColorChanged(chan);
- }
+ }
break;
}
- case XFMEM_SETCHAN0_MATCOLOR: // Channel Material Color
+ case XFMEM_SETCHAN0_MATCOLOR: // Channel Material Color
case XFMEM_SETCHAN1_MATCOLOR:
{
u8 chan = address - XFMEM_SETCHAN0_MATCOLOR;
@@ -92,28 +92,28 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData)
break;
}
- case XFMEM_SETCHAN0_COLOR: // Channel Color
+ case XFMEM_SETCHAN0_COLOR: // Channel Color
case XFMEM_SETCHAN1_COLOR:
case XFMEM_SETCHAN0_ALPHA: // Channel Alpha
- case XFMEM_SETCHAN1_ALPHA:
+ case XFMEM_SETCHAN1_ALPHA:
if (((u32*)&xfregs)[address - 0x1000] != (newValue & 0x7fff))
- VertexManager::Flush();
+ VertexManager::Flush();
break;
- case XFMEM_DUALTEX:
+ case XFMEM_DUALTEX:
if (xfregs.dualTexTrans.enabled != (newValue & 1))
- VertexManager::Flush();
- break;
+ VertexManager::Flush();
+ break;
- case XFMEM_SETMATRIXINDA:
- //_assert_msg_(GX_XF, 0, "XF matrixindex0");
+ case XFMEM_SETMATRIXINDA:
+ //_assert_msg_(GX_XF, 0, "XF matrixindex0");
VertexShaderManager::SetTexMatrixChangedA(newValue);
- break;
- case XFMEM_SETMATRIXINDB:
- //_assert_msg_(GX_XF, 0, "XF matrixindex1");
- VertexShaderManager::SetTexMatrixChangedB(newValue);
- break;
+ break;
+ case XFMEM_SETMATRIXINDB:
+ //_assert_msg_(GX_XF, 0, "XF matrixindex1");
+ VertexShaderManager::SetTexMatrixChangedB(newValue);
+ break;
case XFMEM_SETVIEWPORT:
case XFMEM_SETVIEWPORT+1:
@@ -135,16 +135,16 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData)
case XFMEM_SETPROJECTION+4:
case XFMEM_SETPROJECTION+5:
case XFMEM_SETPROJECTION+6:
- VertexManager::Flush();
+ VertexManager::Flush();
VertexShaderManager::SetProjectionChanged();
nextAddress = XFMEM_SETPROJECTION + 7;
break;
- case XFMEM_SETNUMTEXGENS: // GXSetNumTexGens
+ case XFMEM_SETNUMTEXGENS: // GXSetNumTexGens
if (xfregs.numTexGen.numTexGens != (newValue & 15))
VertexManager::Flush();
- break;
+ break;
case XFMEM_SETTEXMTXINFO:
case XFMEM_SETTEXMTXINFO+1:
@@ -178,47 +178,47 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData)
// Maybe these are for Normals?
case 0x1048: //xfregs.texcoords[0].nrmmtxinfo.hex = data; break; ??
- case 0x1049:
- case 0x104a:
- case 0x104b:
- case 0x104c:
- case 0x104d:
- case 0x104e:
- case 0x104f:
+ case 0x1049:
+ case 0x104a:
+ case 0x104b:
+ case 0x104c:
+ case 0x104d:
+ case 0x104e:
+ case 0x104f:
DEBUG_LOG(VIDEO, "Possible Normal Mtx XF reg?: %x=%x\n", address, newValue);
break;
case 0x1013:
- case 0x1014:
- case 0x1015:
- case 0x1016:
- case 0x1017:
+ case 0x1014:
+ case 0x1015:
+ case 0x1016:
+ case 0x1017:
- default:
- WARN_LOG(VIDEO, "Unknown XF Reg: %x=%x\n", address, newValue);
- break;
- }
+ default:
+ WARN_LOG(VIDEO, "Unknown XF Reg: %x=%x\n", address, newValue);
+ break;
+ }
int transferred = nextAddress - address;
address = nextAddress;
transferSize -= transferred;
dataIndex += transferred;
- }
+ }
}
void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
{
- // do not allow writes past registers
- if (baseAddress + transferSize > 0x1058)
- {
- INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
+ // do not allow writes past registers
+ if (baseAddress + transferSize > 0x1058)
+ {
+ INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
- if (baseAddress >= 0x1058)
- transferSize = 0;
- else
- transferSize = 0x1058 - baseAddress;
- }
+ if (baseAddress >= 0x1058)
+ transferSize = 0;
+ else
+ transferSize = 0x1058 - baseAddress;
+ }
// write to XF mem
if (baseAddress < 0x1000 && transferSize > 0)
@@ -247,11 +247,11 @@ void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
}
// write to XF regs
- if (transferSize > 0)
+ if (transferSize > 0)
{
XFRegWritten(transferSize, baseAddress, pData);
memcpy_gc((u32*)(&xfregs) + (baseAddress - 0x1000), pData, transferSize * 4);
- }
+ }
}
// TODO - verify that it is correct. Seems to work, though.
diff --git a/Source/Core/VideoCommon/Src/memcpy_amd.cpp b/Source/Core/VideoCommon/Src/memcpy_amd.cpp
index 4bc3012e81..bd393560d4 100644
--- a/Source/Core/VideoCommon/Src/memcpy_amd.cpp
+++ b/Source/Core/VideoCommon/Src/memcpy_amd.cpp
@@ -465,8 +465,8 @@ End:
void * memcpy_amd(void *dest, const void *src, size_t n)
{
-memcpy(dest, src, n);
-return dest;
+ memcpy(dest, src, n);
+ return dest;
}
diff --git a/Source/Core/VideoCommon/Src/DLCache.cpp b/Source/Core/VideoCommon/Src/x64DLCache.cpp
index c828ea3a03..3e03271993 100644
--- a/Source/Core/VideoCommon/Src/DLCache.cpp
+++ b/Source/Core/VideoCommon/Src/x64DLCache.cpp
@@ -35,7 +35,7 @@
#include "VertexLoaderManager.h"
#include "VertexManagerBase.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "DLCache.h"
#include "VideoConfig.h"
@@ -111,17 +111,17 @@ struct CachedDisplayList
u32 num_cp_reg;
u32 num_bp_reg;
u32 num_index_xf;
- u32 num_draw_call;
+ u32 num_draw_call;
u32 pass;
u32 check;
- int frame_count;
+ int frame_count;
u32 BufferCount;
void InsertRegion(ReferencedDataRegion* NewRegion)
{
if(LastRegion)
{
- LastRegion->NextRegion = NewRegion;
+ LastRegion->NextRegion = NewRegion;
}
LastRegion = NewRegion;
if(!Regions)
@@ -174,7 +174,7 @@ struct CachedDisplayList
Current = Current->NextRegion;
}
return true;
- }
+ }
ReferencedDataRegion* FindOverlapingRegion(u8* RegionStart, u32 Regionsize)
{
@@ -182,7 +182,7 @@ struct CachedDisplayList
while(Current)
{
if(!Current->IntersectsMemoryRange(RegionStart, Regionsize))
- return Current;
+ return Current;
Current = Current->NextRegion;
}
return Current;
@@ -330,7 +330,7 @@ u32 AnalyzeAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
u32 addr = DataReadU32();
u32 count = DataReadU32();
ExecuteDisplayList(addr, count);
- }
+ }
break;
case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
DEBUG_LOG(VIDEO, "GX 0x44: %08x", cmd_byte);
@@ -392,7 +392,7 @@ u32 AnalyzeAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
dl->num_draw_call = num_draw_call;
dl->num_index_xf = num_index_xf;
dl->num_xf_reg = num_xf_reg;
- // reset to the old pointer
+ // reset to the old pointer
g_pVideoData = old_pVideoData;
return result;
}
@@ -458,7 +458,7 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
NewRegion->MustClean = true;
NewRegion->size = transfer_size * 4;
NewRegion->start_address = (u8*) new u8[NewRegion->size+15+12]; // alignment and guaranteed space
- NewRegion->hash = 0;
+ NewRegion->hash = 0;
dl->InsertRegion(NewRegion);
u32 *data_buffer = (u32*)(u8*)(((size_t)NewRegion->start_address+0xf)&~0xf);
DataReadU32xFuncs[transfer_size-1](data_buffer);
@@ -539,7 +539,6 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
if (cmd_byte & 0x80)
{
// load vertices (use computed vertex size from FifoCommandRunnable above)
-
u16 numVertices = DataReadU16();
if(numVertices > 0)
{
@@ -550,8 +549,7 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7)
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
numVertices);
- u8* EndAddress = VertexManager::s_pCurBufferPointer;
- u32 Vdatasize = (u32)(EndAddress - StartAddress);
+ u32 Vdatasize = (u32)(VertexManager::s_pCurBufferPointer - StartAddress);
if (Vdatasize > 0)
{
// Compile
@@ -559,7 +557,7 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
NewRegion->MustClean = true;
NewRegion->size = Vdatasize;
NewRegion->start_address = (u8*)new u8[Vdatasize];
- NewRegion->hash = 0;
+ NewRegion->hash = 0;
dl->InsertRegion(NewRegion);
memcpy(NewRegion->start_address, StartAddress, Vdatasize);
emitter.ABI_CallFunctionCCCP((void *)&VertexLoaderManager::RunCompiledVertices, cmd_byte & GX_VAT_MASK, (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, numVertices, NewRegion->start_address);
@@ -578,7 +576,6 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
}
}
}
-
}
else
{
@@ -627,7 +624,7 @@ void Clear()
}
dl_map.clear();
// Reset the cache pointers.
- emitter.SetCodePtr(dlcode_cache);
+ emitter.SetCodePtr(dlcode_cache);
}
void ProgressiveCleanup()
@@ -685,14 +682,14 @@ bool HandleDisplayList(u32 address, u32 size)
{
vhash = DLCache::CreateVMapId(Parentiter->second.VATUsed);
iter = Parentiter->second.dl_map.find(vhash);
- childexist = iter != Parentiter->second.dl_map.end();
+ childexist = iter != Parentiter->second.dl_map.end();
}
if (Parentiter != DLCache::dl_map.end() && childexist)
{
DLCache::CachedDisplayList &dl = iter->second;
if (dl.uncachable)
{
- return false;
+ return false;
}
switch (dl.pass)
@@ -701,7 +698,7 @@ bool HandleDisplayList(u32 address, u32 size)
// First, check that the hash is the same as the last time.
if (dl.dl_hash != GetHash64(Memory::GetPointer(address), size, 0))
{
- dl.uncachable = true;
+ dl.uncachable = true;
return false;
}
DLCache::CompileAndRunDisplayList(address, size, &dl);
@@ -718,7 +715,7 @@ bool HandleDisplayList(u32 address, u32 size)
if (DlistChanged)
{
dl.uncachable = true;
- dl.ClearRegions();
+ dl.ClearRegions();
return false;
}
dl.frame_count= frameCount;
@@ -765,10 +762,9 @@ bool HandleDisplayList(u32 address, u32 size)
vdl.VATUsed = dlvatused;
vdl.count = 1;
DLCache::dl_map[dl_id] = vdl;
-
}
+
return true;
-
}
void IncrementCheckContextId()
diff --git a/Source/Core/VideoCommon/Src/TextureDecoder.cpp b/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp
index 30df817902..f5612f34a4 100644
--- a/Source/Core/VideoCommon/Src/TextureDecoder.cpp
+++ b/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp
@@ -517,7 +517,7 @@ inline void decodebytesARGB8_4ToRgba(u32 *dst, const u16 *src, const u16 * src2)
{
#if 0
for (int x = 0; x < 4; x++) {
- dst[x] = ((src[x] & 0xFF) << 24) | ((src[x] & 0xFF00)>>8) | (src2[x] << 8);
+ dst[x] = ((src[x] & 0xFF) << 24) | ((src[x] & 0xFF00)>>8) | (src2[x] << 8);
}
#else
dst[0] = ((src[0] & 0xFF) << 24) | ((src[0] & 0xFF00)>>8) | (src2[0] << 8);
@@ -556,7 +556,7 @@ void decodeDXTBlock(u32 *dst, const DXTBlock *src, int pitch)
{
int blue3 = ((blue2 - blue1) >> 1) - ((blue2 - blue1) >> 3);
int green3 = ((green2 - green1) >> 1) - ((green2 - green1) >> 3);
- int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3);
+ int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3);
colors[2] = makecol(red1 + red3, green1 + green3, blue1 + blue3, 255);
colors[3] = makecol(red2 - red3, green2 - green3, blue2 - blue3, 255);
}
@@ -1119,20 +1119,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
_mm_storeu_si128( (__m128i*)( dst+(y + iy+1) * width + x + 4 ), o4 );
}
}
-#if 0
- // Reference C implementation:
- for (int y = 0; y < height; y += 8)
- for (int x = 0; x < width; x += 8)
- for (int iy = 0; iy < 8; iy++, src += 4)
- for (int ix = 0; ix < 4; ix++)
- {
- int val = src[ix];
- u8 i1 = Convert4To8(val >> 4);
- u8 i2 = Convert4To8(val & 0xF);
- memset(dst+(y + iy) * width + x + ix * 2 , i1,4);
- memset(dst+(y + iy) * width + x + ix * 2 + 1 , i2,4);
- }
-#endif
}
break;
case GX_TF_I8: // speed critical
@@ -1248,26 +1234,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
}
}
-#if 0
- // Reference C implementation
- for (int y = 0; y < height; y += 4)
- for (int x = 0; x < width; x += 8)
- for (int iy = 0; iy < 4; ++iy, src += 8)
- {
- u32 * newdst = dst + (y + iy)*width+x;
- const u8 * newsrc = src;
- u8 srcval;
-
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = newsrc[0]; newdst[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- }
-#endif
}
break;
case GX_TF_C8:
@@ -1380,20 +1346,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
_mm_storeu_si128( (__m128i*)(dst + (y + iy) * width + x), r1 );
}
}
-#if 0
- // Reference C implementation:
- for (int y = 0; y < height; y += 4)
- for (int x = 0; x < width; x += 4)
- for (int iy = 0; iy < 4; iy++, src += 8)
- {
- u32 *ptr = dst + (y + iy) * width + x;
- u16 *s = (u16 *)src;
- ptr[0] = decodeIA8Swapped(s[0]);
- ptr[1] = decodeIA8Swapped(s[1]);
- ptr[2] = decodeIA8Swapped(s[2]);
- ptr[3] = decodeIA8Swapped(s[3]);
- }
-#endif
}
break;
case GX_TF_C14X2:
@@ -1493,18 +1445,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
__m128i *ptr = (__m128i *)(dst + (y + iy) * width + x);
_mm_storeu_si128(ptr, abgr888x4);
}
-#if 0
- // Reference C implementation.
- for (int y = 0; y < height; y += 4)
- for (int x = 0; x < width; x += 4)
- for (int iy = 0; iy < 4; iy++, src += 8)
- {
- u32 *ptr = dst + (y + iy) * width + x;
- u16 *s = (u16 *)src;
- for(int j = 0; j < 4; j++)
- *ptr++ = decode565RGBA(Common::swap16(*s++));
- }
-#endif
}
break;
case GX_TF_RGB5A3:
@@ -1718,13 +1658,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
}
}
}
-#if 0
- // Reference C implementation:
- for (int y = 0; y < height; y += 4)
- for (int x = 0; x < width; x += 4)
- for (int iy = 0; iy < 4; iy++, src += 8)
- decodebytesRGB5A3rgba(dst+(y+iy)*width+x, (u16*)src);
-#endif
}
break;
case GX_TF_RGBA8: // speed critical
@@ -1860,16 +1793,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
_mm_storeu_si128(dst128, rgba11);
}
}
-#if 0
- // Reference C implementation.
- for (int y = 0; y < height; y += 4)
- for (int x = 0; x < width; x += 4)
- {
- for (int iy = 0; iy < 4; iy++)
- decodebytesARGB8_4ToRgba(dst + (y+iy)*width + x, (u16*)src + 4 * iy, (u16*)src + 4 * iy + 16);
- src += 64;
- }
-#endif
}
break;
case GX_TF_CMPR: // speed critical
@@ -2104,22 +2027,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
}
}
}
-#if 0
- for (int y = 0; y < height; y += 8)
- {
- for (int x = 0; x < width; x += 8)
- {
- decodeDXTBlockRGBA((u32*)dst + y * width + x, (DXTBlock*)src, width);
- src += sizeof(DXTBlock);
- decodeDXTBlockRGBA((u32*)dst + y * width + x + 4, (DXTBlock*)src, width);
- src += sizeof(DXTBlock);
- decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x, (DXTBlock*)src, width);
- src += sizeof(DXTBlock);
- decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src, width);
- src += sizeof(DXTBlock);
- }
- }
-#endif
break;
}
}
@@ -2233,7 +2140,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
u32 base = (tBlk * widthBlks + sBlk) * blockWidth * blockHeight;
u16 blkS = s & (blockWidth - 1);
u16 blkT = t & (blockHeight - 1);
- u32 blkOff = blkT * blockWidth + blkS;
+ u32 blkOff = blkT * blockWidth + blkS;
*/
switch (texformat)
@@ -2247,9 +2154,9 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
u16 blkS = s & 7;
u16 blkT = t & 7;
u32 blkOff = (blkT << 3) + blkS;
-
+
int rs = (blkOff & 1)?0:4;
- u32 offset = base + (blkOff >> 1);
+ u32 offset = base + (blkOff >> 1);
u8 val = (*(src + offset) >> rs) & 0xF;
u16 *tlut = (u16*)(texMem + tlutaddr);
@@ -2259,7 +2166,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
case 0:
*((u32*)dst) = decodeIA8Swapped(tlut[val]);
break;
- case 1:
+ case 1:
*((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
break;
case 2:
@@ -2277,9 +2184,9 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
u16 blkS = s & 7;
u16 blkT = t & 7;
u32 blkOff = (blkT << 3) + blkS;
-
+
int rs = (blkOff & 1)?0:4;
- u32 offset = base + (blkOff >> 1);
+ u32 offset = base + (blkOff >> 1);
u8 val = (*(src + offset) >> rs) & 0xF;
val = Convert4To8(val);
@@ -2298,7 +2205,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
u16 blkS = s & 7;
u16 blkT = t & 3;
u32 blkOff = (blkT << 3) + blkS;
-
+
u8 val = *(src + base + blkOff);
dst[0] = val;
dst[1] = val;
@@ -2315,7 +2222,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
u16 blkS = s & 7;
u16 blkT = t & 3;
u32 blkOff = (blkT << 3) + blkS;
-
+
u8 val = *(src + base + blkOff);
u16 *tlut = (u16*)(texMem + tlutaddr);
@@ -2324,7 +2231,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
case 0:
*((u32*)dst) = decodeIA8Swapped(tlut[val]);
break;
- case 1:
+ case 1:
*((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
break;
case 2:
@@ -2342,7 +2249,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
u16 blkS = s & 7;
u16 blkT = t & 3;
u32 blkOff = (blkT << 3) + blkS;
-
+
u8 val = *(src + base + blkOff);
const u8 a = Convert4To8(val>>4);
const u8 l = Convert4To8(val&0xF);
@@ -2361,7 +2268,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
u16 blkS = s & 3;
u16 blkT = t & 3;
u32 blkOff = (blkT << 2) + blkS;
-
+
u32 offset = (base + blkOff) << 1;
const u16* valAddr = (u16*)(src + offset);
@@ -2377,7 +2284,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
u16 blkS = s & 3;
u16 blkT = t & 3;
u32 blkOff = (blkT << 2) + blkS;
-
+
u32 offset = (base + blkOff) << 1;
const u16* valAddr = (u16*)(src + offset);
@@ -2389,7 +2296,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
case 0:
*((u32*)dst) = decodeIA8Swapped(tlut[val]);
break;
- case 1:
+ case 1:
*((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
break;
case 2:
@@ -2407,7 +2314,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
u16 blkS = s & 3;
u16 blkT = t & 3;
u32 blkOff = (blkT << 2) + blkS;
-
+
u32 offset = (base + blkOff) << 1;
const u16* valAddr = (u16*)(src + offset);
@@ -2465,7 +2372,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
u32 offset = (base + blkOff) << 3;
const DXTBlock* dxtBlock = (const DXTBlock*)(src + offset);
-
+
u16 c1 = Common::swap16(dxtBlock->color1);
u16 c2 = Common::swap16(dxtBlock->color2);
int blue1 = Convert5To8(c1 & 0x1F);
@@ -2484,7 +2391,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
colorSel |= c1 > c2?0:4;
u32 color = 0;
-
+
switch (colorSel)
{
case 0:
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj
index bf9122e6b5..f785cb5c84 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj
@@ -111,8 +111,8 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <OpenMPSupport>false</OpenMPSupport>
- </ClCompile>
+ <OpenMPSupport>false</OpenMPSupport>
+ </ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
@@ -143,7 +143,7 @@
<ClCompile>
<AdditionalIncludeDirectories>..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OpenMPSupport>false</OpenMPSupport>
- </ClCompile>
+ </ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -182,7 +182,6 @@
<ClCompile Include="Src\CommandProcessor.cpp" />
<ClCompile Include="Src\CPMemory.cpp" />
<ClCompile Include="Src\Debugger.cpp" />
- <ClCompile Include="Src\DLCache.cpp" />
<ClCompile Include="Src\EmuWindow.cpp" />
<ClCompile Include="Src\Fifo.cpp" />
<ClCompile Include="Src\FPSCounter.cpp" />
@@ -197,6 +196,7 @@
<ClCompile Include="Src\OpcodeDecoding.cpp" />
<ClCompile Include="Src\OpenCL.cpp" />
<ClCompile Include="Src\OpenCL\OCLTextureDecoder.cpp" />
+ <ClCompile Include="Src\PerfQueryBase.cpp" />
<ClCompile Include="Src\PixelEngine.cpp" />
<ClCompile Include="Src\PixelShaderGen.cpp" />
<ClCompile Include="Src\PixelShaderManager.cpp" />
@@ -204,7 +204,6 @@
<ClCompile Include="Src\Statistics.cpp" />
<ClCompile Include="Src\TextureCacheBase.cpp" />
<ClCompile Include="Src\TextureConversionShader.cpp" />
- <ClCompile Include="Src\TextureDecoder.cpp" />
<ClCompile Include="Src\VertexLoader.cpp" />
<ClCompile Include="Src\VertexLoaderManager.cpp" />
<ClCompile Include="Src\VertexLoader_Color.cpp" />
@@ -216,6 +215,8 @@
<ClCompile Include="Src\VertexShaderManager.cpp" />
<ClCompile Include="Src\VideoConfig.cpp" />
<ClCompile Include="Src\VideoState.cpp" />
+ <ClCompile Include="Src\x64DLCache.cpp" />
+ <ClCompile Include="Src\x64TextureDecoder.cpp" />
<ClCompile Include="Src\XFMemory.cpp" />
<ClCompile Include="Src\XFStructs.cpp" />
</ItemGroup>
@@ -244,6 +245,7 @@
<ClInclude Include="Src\OpcodeDecoding.h" />
<ClInclude Include="Src\OpenCL.h" />
<ClInclude Include="Src\OpenCL\OCLTextureDecoder.h" />
+ <ClInclude Include="Src\PerfQueryBase.h" />
<ClInclude Include="Src\PixelEngine.h" />
<ClInclude Include="Src\PixelShaderGen.h" />
<ClInclude Include="Src\PixelShaderManager.h" />
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
index e7019f17ed..330b23d370 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
@@ -5,9 +5,6 @@
<ClCompile Include="Src\memcpy_amd.cpp" />
<ClCompile Include="Src\PixelEngine.cpp" />
<ClCompile Include="Src\VideoConfig.cpp" />
- <ClCompile Include="Src\DLCache.cpp">
- <Filter>Vertex Loading</Filter>
- </ClCompile>
<ClCompile Include="Src\VertexLoader.cpp">
<Filter>Vertex Loading</Filter>
</ClCompile>
@@ -92,9 +89,6 @@
<ClCompile Include="Src\OpcodeDecoding.cpp">
<Filter>Decoding</Filter>
</ClCompile>
- <ClCompile Include="Src\TextureDecoder.cpp">
- <Filter>Decoding</Filter>
- </ClCompile>
<ClCompile Include="Src\Debugger.cpp">
<Filter>Base</Filter>
</ClCompile>
@@ -107,6 +101,9 @@
<ClCompile Include="Src\MainBase.cpp">
<Filter>Base</Filter>
</ClCompile>
+ <ClCompile Include="Src\PerfQueryBase.cpp">
+ <Filter>Base</Filter>
+ </ClCompile>
<ClCompile Include="Src\RenderBase.cpp">
<Filter>Base</Filter>
</ClCompile>
@@ -122,6 +119,12 @@
<ClCompile Include="Src\FPSCounter.cpp">
<Filter>Util</Filter>
</ClCompile>
+ <ClCompile Include="Src\x64TextureDecoder.cpp">
+ <Filter>Decoding</Filter>
+ </ClCompile>
+ <ClCompile Include="Src\x64DLCache.cpp">
+ <Filter>Vertex Loading</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Src\CommandProcessor.h" />
@@ -237,6 +240,9 @@
<ClInclude Include="Src\MainBase.h">
<Filter>Base</Filter>
</ClInclude>
+ <ClInclude Include="Src\PerfQueryBase.h">
+ <Filter>Base</Filter>
+ </ClInclude>
<ClInclude Include="Src\RenderBase.h">
<Filter>Base</Filter>
</ClInclude>
@@ -285,4 +291,4 @@
<UniqueIdentifier>{e2a527a2-ccc8-4ab8-a93e-dd2628c0f3b6}</UniqueIdentifier>
</Filter>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/Source/DSPTool/Src/DSPTool.cpp b/Source/DSPTool/Src/DSPTool.cpp
index 9628e36895..891729079a 100644
--- a/Source/DSPTool/Src/DSPTool.cpp
+++ b/Source/DSPTool/Src/DSPTool.cpp
@@ -25,6 +25,7 @@
u8 DSPHost_ReadHostMemory(u32 addr) { return 0; }
void DSPHost_WriteHostMemory(u8 value, u32 addr) {}
bool DSPHost_OnThread() { return false; }
+bool DSPHost_Wii() { return false; }
u32 DSPHost_CodeLoaded(const u8 *ptr, int size) {return 0x1337c0de;}
void DSPHost_InterruptRequest() {}
void DSPHost_UpdateDebugger() {}
diff --git a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj
index 52d1c37aed..aab9345ef7 100644
--- a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj
+++ b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj
@@ -199,6 +199,7 @@
<ClCompile Include="Src\LineGeometryShader.cpp" />
<ClCompile Include="Src\main.cpp" />
<ClCompile Include="Src\NativeVertexFormat.cpp" />
+ <ClCompile Include="Src\PerfQuery.cpp" />
<ClCompile Include="Src\PixelShaderCache.cpp" />
<ClCompile Include="Src\PointGeometryShader.cpp" />
<ClCompile Include="Src\PSTextureEncoder.cpp" />
@@ -228,6 +229,7 @@
<ClInclude Include="Src\Globals.h" />
<ClInclude Include="Src\LineGeometryShader.h" />
<ClInclude Include="Src\main.h" />
+ <ClInclude Include="Src\PerfQuery.h" />
<ClInclude Include="Src\PixelShaderCache.h" />
<ClInclude Include="Src\PointGeometryShader.h" />
<ClInclude Include="Src\PSTextureEncoder.h" />
diff --git a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters
index 6492e887ca..4b8efac92b 100644
--- a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters
+++ b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters
@@ -57,6 +57,9 @@
<ClCompile Include="Src\PointGeometryShader.cpp">
<Filter>Render</Filter>
</ClCompile>
+ <ClCompile Include="Src\PerfQuery.cpp">
+ <Filter>Render</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Src\Globals.h" />
@@ -117,6 +120,9 @@
<ClInclude Include="Src\PointGeometryShader.h">
<Filter>Render</Filter>
</ClInclude>
+ <ClInclude Include="Src\PerfQuery.h">
+ <Filter>Render</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="D3D">
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp
index 1dcc6dd193..873f3a47fd 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp
@@ -520,7 +520,7 @@ void EndFrame()
void Present()
{
// TODO: Is 1 the correct value for vsyncing?
- swapchain->Present((UINT)g_ActiveConfig.bVSync, 0);
+ swapchain->Present((UINT)g_ActiveConfig.IsVSync(), 0);
}
} // namespace D3D
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp
index 41e5423990..c688228945 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp
@@ -64,7 +64,8 @@ bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob)
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << code;
file.close();
@@ -121,7 +122,8 @@ bool CompileGeometryShader(const char* code, unsigned int len, D3DBlob** blob,
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sbad_gs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << code;
file.close();
@@ -180,7 +182,8 @@ bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob,
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << code;
file.close();
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp
index cb94884eb7..199f063d40 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp
@@ -208,6 +208,8 @@ void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
void XFBSource::CopyEFB(float Gamma)
{
+ g_renderer->ResetAPIState(); // reset any game specific settings
+
// Copy EFB data to XFB and restore render target again
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight);
@@ -222,6 +224,8 @@ void XFBSource::CopyEFB(float Gamma)
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(),
FramebufferManager::GetEFBDepthTexture()->GetDSV());
+
+ g_renderer->RestoreAPIState();
}
} // namespace DX11 \ No newline at end of file
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp
new file mode 100644
index 0000000000..b859d50ec6
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp
@@ -0,0 +1,150 @@
+#include "RenderBase.h"
+
+#include "D3DBase.h"
+#include "PerfQuery.h"
+
+namespace DX11 {
+
+PerfQuery::PerfQuery()
+ : m_query_read_pos()
+ , m_query_count()
+{
+ for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
+ {
+ D3D11_QUERY_DESC qdesc = CD3D11_QUERY_DESC(D3D11_QUERY_OCCLUSION, 0);
+ D3D::device->CreateQuery(&qdesc, &m_query_buffer[i].query);
+ }
+ ResetQuery();
+}
+
+PerfQuery::~PerfQuery()
+{
+ for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
+ {
+ // TODO: EndQuery?
+ m_query_buffer[i].query->Release();
+ }
+}
+
+void PerfQuery::EnableQuery(PerfQueryGroup type)
+{
+ // Is this sane?
+ if (m_query_count > ARRAYSIZE(m_query_buffer) / 2)
+ WeakFlush();
+
+ if (ARRAYSIZE(m_query_buffer) == m_query_count)
+ {
+ // TODO
+ FlushOne();
+ ERROR_LOG(VIDEO, "flushed query buffer early!");
+ }
+
+ // start query
+ if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
+ {
+ auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ARRAYSIZE(m_query_buffer)];
+
+ D3D::context->Begin(entry.query);
+ entry.query_type = type;
+
+ ++m_query_count;
+ }
+}
+
+void PerfQuery::DisableQuery(PerfQueryGroup type)
+{
+ // stop query
+ if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
+ {
+ auto& entry = m_query_buffer[(m_query_read_pos + m_query_count + ARRAYSIZE(m_query_buffer)-1) % ARRAYSIZE(m_query_buffer)];
+ D3D::context->End(entry.query);
+ }
+}
+
+void PerfQuery::ResetQuery()
+{
+ m_query_count = 0;
+ std::fill_n(m_results, ARRAYSIZE(m_results), 0);
+}
+
+u32 PerfQuery::GetQueryResult(PerfQueryType type)
+{
+ u32 result = 0;
+
+ if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC)
+ {
+ result = m_results[PQG_ZCOMP_ZCOMPLOC];
+ }
+ else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT)
+ {
+ result = m_results[PQG_ZCOMP];
+ }
+ else if (type == PQ_BLEND_INPUT)
+ {
+ result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC];
+ }
+ else if (type == PQ_EFB_COPY_CLOCKS)
+ {
+ result = m_results[PQG_EFB_COPY_CLOCKS];
+ }
+
+ return result / 4;
+}
+
+void PerfQuery::FlushOne()
+{
+ auto& entry = m_query_buffer[m_query_read_pos];
+
+ UINT64 result = 0;
+ HRESULT hr = S_FALSE;
+ while (hr != S_OK)
+ {
+ // TODO: Might cause us to be stuck in an infinite loop!
+ hr = D3D::context->GetData(entry.query, &result, sizeof(result), 0);
+ }
+
+ // NOTE: Reported pixel metrics should be referenced to native resolution
+ m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight();
+
+ m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer);
+ --m_query_count;
+}
+
+// TODO: could selectively flush things, but I don't think that will do much
+void PerfQuery::FlushResults()
+{
+ while (!IsFlushed())
+ FlushOne();
+}
+
+void PerfQuery::WeakFlush()
+{
+ while (!IsFlushed())
+ {
+ auto& entry = m_query_buffer[m_query_read_pos];
+
+ UINT64 result = 0;
+ HRESULT hr = D3D::context->GetData(entry.query, &result, sizeof(result), D3D11_ASYNC_GETDATA_DONOTFLUSH);
+
+ if (hr == S_OK)
+ {
+ // NOTE: Reported pixel metrics should be referenced to native resolution
+ m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight();
+
+ m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer);
+ --m_query_count;
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+bool PerfQuery::IsFlushed() const
+{
+ return 0 == m_query_count;
+}
+
+
+} // namespace
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h
new file mode 100644
index 0000000000..b3709d1013
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h
@@ -0,0 +1,46 @@
+#ifndef _PERFQUERY_H_
+#define _PERFQUERY_H_
+
+#include "PerfQueryBase.h"
+
+namespace DX11 {
+
+class PerfQuery : public PerfQueryBase
+{
+public:
+ PerfQuery();
+ ~PerfQuery();
+
+ void EnableQuery(PerfQueryGroup type);
+ void DisableQuery(PerfQueryGroup type);
+ void ResetQuery();
+ u32 GetQueryResult(PerfQueryType type);
+ void FlushResults();
+ bool IsFlushed() const;
+
+private:
+ struct ActiveQuery
+ {
+ ID3D11Query* query;
+ PerfQueryGroup query_type;
+ };
+
+ void WeakFlush();
+
+ // Only use when non-empty
+ void FlushOne();
+
+ // when testing in SMS: 64 was too small, 128 was ok
+ static const int PERF_QUERY_BUFFER_SIZE = 512;
+
+ ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE];
+ int m_query_read_pos;
+
+ // TODO: sloppy
+ volatile int m_query_count;
+ volatile u32 m_results[PQG_NUM_MEMBERS];
+};
+
+} // namespace
+
+#endif // _PERFQUERY_H_
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
index a6cb52c40f..2dcfcd041c 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
@@ -65,6 +65,7 @@ ID3D11RasterizerState* resetraststate = NULL;
static ID3D11Texture2D* s_screenshot_texture = NULL;
+
// GX pipeline state
struct
{
@@ -761,11 +762,11 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle
return SUCCEEDED(hr);
}
-void formatBufferDump(const char *in, char *out, int w, int h, int p)
+void formatBufferDump(const u8* in, u8* out, int w, int h, int p)
{
for (int y = 0; y < h; ++y)
{
- const u8 *line = (u8*)(in + (h - y - 1) * p);
+ auto line = (in + (h - y - 1) * p);
for (int x = 0; x < w; ++x)
{
out[0] = line[2];
@@ -782,8 +783,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
{
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- AVIDump::AddFrame(frame_data);
+ if (g_ActiveConfig.bDumpFrames && !frame_data.empty())
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -794,8 +795,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- AVIDump::AddFrame(frame_data);
+ if (g_ActiveConfig.bDumpFrames && !frame_data.empty())
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -934,16 +935,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map);
- if (!frame_data || w != s_recordWidth || h != s_recordHeight)
+ if (frame_data.empty() || w != s_recordWidth || h != s_recordHeight)
{
- delete[] frame_data;
- frame_data = new char[3 * s_recordWidth * s_recordHeight];
+ frame_data.resize(3 * s_recordWidth * s_recordHeight);
w = s_recordWidth;
h = s_recordHeight;
}
- char* source_ptr = (char*)map.pData + GetTargetRectangle().left*4 + GetTargetRectangle().top*map.RowPitch;
- formatBufferDump(source_ptr, frame_data, s_recordWidth, s_recordHeight, map.RowPitch);
- AVIDump::AddFrame(frame_data);
+ auto source_ptr = (const u8*)map.pData + GetTargetRectangle().left*4 + GetTargetRectangle().top*map.RowPitch;
+ formatBufferDump(source_ptr, &frame_data[0], s_recordWidth, s_recordHeight, map.RowPitch);
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
D3D::context->Unmap(s_screenshot_texture, 0);
}
bLastFrameDumped = true;
@@ -952,7 +952,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
{
if (bLastFrameDumped && bAVIDumping)
{
- SAFE_DELETE_ARRAY(frame_data);
+ std::vector<u8>().swap(frame_data);
w = h = 0;
AVIDump::Stop();
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp
index ab8ed68654..da8c98e19e 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp
@@ -39,41 +39,41 @@ namespace DX11
{
// TODO: Find sensible values for these two
-const UINT IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * 16 * sizeof(u16);
-const UINT VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE * 16;
-const UINT MAXVBUFFER_COUNT = 2;
+const UINT IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * sizeof(u16) * 8;
+const UINT VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE;
+const UINT MAX_VBUFFER_COUNT = 2;
void VertexManager::CreateDeviceObjects()
{
D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(IBUFFER_SIZE,
D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
- m_vertexDrawOffset = 0;
- m_triangleDrawIndex = 0;
- m_lineDrawIndex = 0;
- m_pointDrawIndex = 0;
- m_indexBuffers = new PID3D11Buffer[MAXVBUFFER_COUNT];
- m_vertexBuffers = new PID3D11Buffer[MAXVBUFFER_COUNT];
- for (m_activeIndexBuffer = 0; m_activeIndexBuffer < MAXVBUFFER_COUNT; m_activeIndexBuffer++)
+ m_vertex_draw_offset = 0;
+ m_triangle_draw_index = 0;
+ m_line_draw_index = 0;
+ m_point_draw_index = 0;
+ m_index_buffers = new PID3D11Buffer[MAX_VBUFFER_COUNT];
+ m_vertex_buffers = new PID3D11Buffer[MAX_VBUFFER_COUNT];
+ for (m_current_index_buffer = 0; m_current_index_buffer < MAX_VBUFFER_COUNT; m_current_index_buffer++)
{
- m_indexBuffers[m_activeIndexBuffer] = NULL;
- CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_indexBuffers[m_activeIndexBuffer])),
+ m_index_buffers[m_current_index_buffer] = NULL;
+ CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_index_buffers[m_current_index_buffer])),
"Failed to create index buffer.");
- D3D::SetDebugObjectName((ID3D11DeviceChild*)m_indexBuffers[m_activeIndexBuffer], "index buffer of VertexManager");
+ D3D::SetDebugObjectName((ID3D11DeviceChild*)m_index_buffers[m_current_index_buffer], "index buffer of VertexManager");
}
bufdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufdesc.ByteWidth = VBUFFER_SIZE;
- for (m_activeVertexBuffer = 0; m_activeVertexBuffer < MAXVBUFFER_COUNT; m_activeVertexBuffer++)
+ for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
{
- m_vertexBuffers[m_activeVertexBuffer] = NULL;
- CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_vertexBuffers[m_activeVertexBuffer])),
+ m_vertex_buffers[m_current_vertex_buffer] = NULL;
+ CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_vertex_buffers[m_current_vertex_buffer])),
"Failed to create vertex buffer.");
- D3D::SetDebugObjectName((ID3D11DeviceChild*)m_vertexBuffers[m_activeVertexBuffer], "Vertex buffer of VertexManager");
+ D3D::SetDebugObjectName((ID3D11DeviceChild*)m_vertex_buffers[m_current_vertex_buffer], "Vertex buffer of VertexManager");
}
- m_activeVertexBuffer = 0;
- m_activeIndexBuffer = 0;
- m_indexBufferCursor = IBUFFER_SIZE;
- m_vertexBufferCursor = VBUFFER_SIZE;
+ m_current_vertex_buffer = 0;
+ m_current_index_buffer = 0;
+ m_index_buffer_cursor = IBUFFER_SIZE;
+ m_vertex_buffer_cursor = VBUFFER_SIZE;
m_lineShader.Init();
m_pointShader.Init();
}
@@ -82,10 +82,10 @@ void VertexManager::DestroyDeviceObjects()
{
m_pointShader.Shutdown();
m_lineShader.Shutdown();
- for (m_activeVertexBuffer = 0; m_activeVertexBuffer < MAXVBUFFER_COUNT; m_activeVertexBuffer++)
+ for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
{
- SAFE_RELEASE(m_vertexBuffers[m_activeVertexBuffer]);
- SAFE_RELEASE(m_indexBuffers[m_activeVertexBuffer]);
+ SAFE_RELEASE(m_vertex_buffers[m_current_vertex_buffer]);
+ SAFE_RELEASE(m_index_buffers[m_current_vertex_buffer]);
}
}
@@ -100,47 +100,47 @@ VertexManager::~VertexManager()
DestroyDeviceObjects();
}
-void VertexManager::LoadBuffers()
+void VertexManager::PrepareDrawBuffers()
{
D3D11_MAPPED_SUBRESOURCE map;
- UINT vSize = UINT(s_pCurBufferPointer - LocalVBuffer);
+ UINT vSize = UINT(s_pCurBufferPointer - s_pBaseBufferPointer);
D3D11_MAP MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
- if (m_vertexBufferCursor + vSize >= VBUFFER_SIZE)
+ if (m_vertex_buffer_cursor + vSize >= VBUFFER_SIZE)
{
// Wrap around
- m_activeVertexBuffer = (m_activeVertexBuffer + 1) % MAXVBUFFER_COUNT;
- m_vertexBufferCursor = 0;
+ m_current_vertex_buffer = (m_current_vertex_buffer + 1) % MAX_VBUFFER_COUNT;
+ m_vertex_buffer_cursor = 0;
MapType = D3D11_MAP_WRITE_DISCARD;
}
- D3D::context->Map(m_vertexBuffers[m_activeVertexBuffer], 0, MapType, 0, &map);
+ D3D::context->Map(m_vertex_buffers[m_current_vertex_buffer], 0, MapType, 0, &map);
- memcpy((u8*)map.pData + m_vertexBufferCursor, LocalVBuffer, vSize);
- D3D::context->Unmap(m_vertexBuffers[m_activeVertexBuffer], 0);
- m_vertexDrawOffset = m_vertexBufferCursor;
- m_vertexBufferCursor += vSize;
+ memcpy((u8*)map.pData + m_vertex_buffer_cursor, s_pBaseBufferPointer, vSize);
+ D3D::context->Unmap(m_vertex_buffers[m_current_vertex_buffer], 0);
+ m_vertex_draw_offset = m_vertex_buffer_cursor;
+ m_vertex_buffer_cursor += vSize;
UINT iCount = IndexGenerator::GetTriangleindexLen() +
IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
- if (m_indexBufferCursor + iCount >= (IBUFFER_SIZE / sizeof(u16)))
+ if (m_index_buffer_cursor + iCount >= (IBUFFER_SIZE / sizeof(u16)))
{
// Wrap around
- m_activeIndexBuffer = (m_activeIndexBuffer + 1) % MAXVBUFFER_COUNT;
- m_indexBufferCursor = 0;
+ m_current_index_buffer = (m_current_index_buffer + 1) % MAX_VBUFFER_COUNT;
+ m_index_buffer_cursor = 0;
MapType = D3D11_MAP_WRITE_DISCARD;
}
- D3D::context->Map(m_indexBuffers[m_activeIndexBuffer], 0, MapType, 0, &map);
-
- m_triangleDrawIndex = m_indexBufferCursor;
- m_lineDrawIndex = m_triangleDrawIndex + IndexGenerator::GetTriangleindexLen();
- m_pointDrawIndex = m_lineDrawIndex + IndexGenerator::GetLineindexLen();
- memcpy((u16*)map.pData + m_triangleDrawIndex, TIBuffer, sizeof(u16) * IndexGenerator::GetTriangleindexLen());
- memcpy((u16*)map.pData + m_lineDrawIndex, LIBuffer, sizeof(u16) * IndexGenerator::GetLineindexLen());
- memcpy((u16*)map.pData + m_pointDrawIndex, PIBuffer, sizeof(u16) * IndexGenerator::GetPointindexLen());
- D3D::context->Unmap(m_indexBuffers[m_activeIndexBuffer], 0);
- m_indexBufferCursor += iCount;
+ D3D::context->Map(m_index_buffers[m_current_index_buffer], 0, MapType, 0, &map);
+
+ m_triangle_draw_index = m_index_buffer_cursor;
+ m_line_draw_index = m_triangle_draw_index + IndexGenerator::GetTriangleindexLen();
+ m_point_draw_index = m_line_draw_index + IndexGenerator::GetLineindexLen();
+ memcpy((u16*)map.pData + m_triangle_draw_index, GetTriangleIndexBuffer(), sizeof(u16) * IndexGenerator::GetTriangleindexLen());
+ memcpy((u16*)map.pData + m_line_draw_index, GetLineIndexBuffer(), sizeof(u16) * IndexGenerator::GetLineindexLen());
+ memcpy((u16*)map.pData + m_point_draw_index, GetPointIndexBuffer(), sizeof(u16) * IndexGenerator::GetPointindexLen());
+ D3D::context->Unmap(m_index_buffers[m_current_index_buffer], 0);
+ m_index_buffer_cursor += iCount;
}
static const float LINE_PT_TEX_OFFSETS[8] = {
@@ -149,13 +149,13 @@ static const float LINE_PT_TEX_OFFSETS[8] = {
void VertexManager::Draw(UINT stride)
{
- D3D::context->IASetVertexBuffers(0, 1, &m_vertexBuffers[m_activeVertexBuffer], &stride, &m_vertexDrawOffset);
- D3D::context->IASetIndexBuffer(m_indexBuffers[m_activeIndexBuffer], DXGI_FORMAT_R16_UINT, 0);
+ D3D::context->IASetVertexBuffers(0, 1, &m_vertex_buffers[m_current_vertex_buffer], &stride, &m_vertex_draw_offset);
+ D3D::context->IASetIndexBuffer(m_index_buffers[m_current_index_buffer], DXGI_FORMAT_R16_UINT, 0);
if (IndexGenerator::GetNumTriangles() > 0)
{
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
- D3D::context->DrawIndexed(IndexGenerator::GetTriangleindexLen(), m_triangleDrawIndex, 0);
+ D3D::context->DrawIndexed(IndexGenerator::GetTriangleindexLen(), m_triangle_draw_index, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
// Disable culling for lines and points
@@ -177,7 +177,7 @@ void VertexManager::Draw(UINT stride)
texOffset, vpWidth, vpHeight, texOffsetEnable))
{
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
- D3D::context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_lineDrawIndex, 0);
+ D3D::context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_line_draw_index, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
D3D::context->GSSetShader(NULL, NULL, 0);
@@ -199,7 +199,7 @@ void VertexManager::Draw(UINT stride)
texOffset, vpWidth, vpHeight, texOffsetEnable))
{
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
- D3D::context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_pointDrawIndex, 0);
+ D3D::context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_point_draw_index, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
D3D::context->GSSetShader(NULL, NULL, 0);
@@ -211,11 +211,6 @@ void VertexManager::Draw(UINT stride)
void VertexManager::vFlush()
{
- if (LocalVBuffer == s_pCurBufferPointer) return;
- if (Flushed) return;
- Flushed=true;
- VideoFifo_CheckEFBAccess();
-
u32 usedtextures = 0;
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i)
if (bpmem.tevorders[i / 2].getEnable(i & 1))
@@ -263,26 +258,25 @@ void VertexManager::vFlush()
g_nativeVertexFmt->m_components))
{
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
- goto shader_fail;
+ return;
}
if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components))
{
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
- goto shader_fail;
+ return;
}
- LoadBuffers();
+ PrepareDrawBuffers();
unsigned int stride = g_nativeVertexFmt->GetVertexStride();
g_nativeVertexFmt->SetupVertexPointers();
g_renderer->ApplyState(useDstAlpha);
-
+
+ g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
Draw(stride);
+ g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
g_renderer->RestoreState();
-
-shader_fail:
- ResetBuffer();
}
} // namespace
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h
index 9e6b7f2dca..b5d0d21757 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h
+++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h
@@ -37,22 +37,22 @@ public:
private:
- void LoadBuffers();
- void Draw(UINT stride);
+ void PrepareDrawBuffers();
+ void Draw(u32 stride);
// temp
void vFlush();
- UINT m_indexBufferCursor;
- UINT m_vertexBufferCursor;
- UINT m_vertexDrawOffset;
- UINT m_triangleDrawIndex;
- UINT m_lineDrawIndex;
- UINT m_pointDrawIndex;
- UINT m_activeVertexBuffer;
- UINT m_activeIndexBuffer;
+ u32 m_vertex_buffer_cursor;
+ u32 m_vertex_draw_offset;
+ u32 m_index_buffer_cursor;
+ u32 m_current_vertex_buffer;
+ u32 m_current_index_buffer;
+ u32 m_triangle_draw_index;
+ u32 m_line_draw_index;
+ u32 m_point_draw_index;
typedef ID3D11Buffer* PID3D11Buffer;
- PID3D11Buffer* m_indexBuffers;
- PID3D11Buffer* m_vertexBuffers;
+ PID3D11Buffer* m_index_buffers;
+ PID3D11Buffer* m_vertex_buffers;
LineGeometryShader m_lineShader;
PointGeometryShader m_pointShader;
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp
index d727ce1ebf..6fdc815554 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp
@@ -162,7 +162,7 @@ void VertexShaderCache::Init()
for (k = 0;k < 64;k++) vs_constant_offset_table[C_TRANSFORMMATRICES+k] = 312+4*k;
for (k = 0;k < 32;k++) vs_constant_offset_table[C_NORMALMATRICES+k] = 568+4*k;
for (k = 0;k < 64;k++) vs_constant_offset_table[C_POSTTRANSFORMMATRICES+k] = 696+4*k;
- for (k = 0;k < 4;k++) vs_constant_offset_table[C_DEPTHPARAMS+k] = 952+4*k;
+ vs_constant_offset_table[C_DEPTHPARAMS] = 952;
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str());
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VideoBackend.h b/Source/Plugins/Plugin_VideoDX11/Src/VideoBackend.h
index 4c6de67ab1..a76935da72 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/VideoBackend.h
+++ b/Source/Plugins/Plugin_VideoDX11/Src/VideoBackend.h
@@ -15,6 +15,7 @@ class VideoBackend : public VideoBackendHardware
std::string GetName();
void Video_Prepare();
+ void Video_Cleanup();
void ShowConfig(void* parent);
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp
index b7dd9101d3..17bbdcf33c 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp
@@ -42,6 +42,7 @@
#include "D3DUtil.h"
#include "D3DBase.h"
+#include "PerfQuery.h"
#include "PixelShaderCache.h"
#include "TextureCache.h"
#include "VertexManager.h"
@@ -102,15 +103,13 @@ void InitBackendInfo()
if (FAILED(hr))
PanicAlert("Failed to create IDXGIFactory object");
- char tmpstr[512] = {};
- DXGI_ADAPTER_DESC desc;
// adapters
g_Config.backend_info.Adapters.clear();
g_Config.backend_info.AAModes.clear();
while (factory->EnumAdapters((UINT)g_Config.backend_info.Adapters.size(), &ad) != DXGI_ERROR_NOT_FOUND)
{
+ DXGI_ADAPTER_DESC desc;
ad->GetDesc(&desc);
- WideCharToMultiByte(/*CP_UTF8*/CP_ACP, 0, desc.Description, -1, tmpstr, 512, 0, false);
// TODO: These don't get updated on adapter change, yet
if (g_Config.backend_info.Adapters.size() == g_Config.iAdapter)
@@ -127,7 +126,7 @@ void InitBackendInfo()
}
}
- g_Config.backend_info.Adapters.push_back(tmpstr);
+ g_Config.backend_info.Adapters.push_back(UTF16ToUTF8(desc.Description));
ad->Release();
}
@@ -185,6 +184,7 @@ void VideoBackend::Video_Prepare()
g_renderer = new Renderer;
g_texture_cache = new TextureCache;
g_vertex_manager = new VertexManager;
+ g_perf_query = new PerfQuery;
VertexShaderCache::Init();
PixelShaderCache::Init();
D3D::InitUtils();
@@ -208,6 +208,7 @@ void VideoBackend::Shutdown()
{
s_BackendInitialized = false;
+ // TODO: should be in Video_Cleanup
if (g_renderer)
{
s_efbAccessRequested = FALSE;
@@ -227,6 +228,7 @@ void VideoBackend::Shutdown()
D3D::ShutdownUtils();
PixelShaderCache::Shutdown();
VertexShaderCache::Shutdown();
+ delete g_perf_query;
delete g_vertex_manager;
delete g_texture_cache;
delete g_renderer;
@@ -235,4 +237,7 @@ void VideoBackend::Shutdown()
}
}
+void VideoBackend::Video_Cleanup() {
+}
+
}
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp
index ff3f68a6cd..b3d241fe14 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp
@@ -66,6 +66,7 @@ static int numAdapters;
static int cur_adapter;
// Value caches for state filtering
+const int MaxStreamSources = 16;
const int MaxTextureStages = 9;
const int MaxRenderStates = 210 + 46;
const int MaxTextureTypes = 33;
@@ -83,10 +84,23 @@ static DWORD m_SamplerStates[MaxSamplerSize][MaxSamplerTypes];
static bool m_SamplerStatesSet[MaxSamplerSize][MaxSamplerTypes];
static bool m_SamplerStatesChanged[MaxSamplerSize][MaxSamplerTypes];
-LPDIRECT3DBASETEXTURE9 m_Textures[16];
-LPDIRECT3DVERTEXDECLARATION9 m_VtxDecl;
-LPDIRECT3DPIXELSHADER9 m_PixelShader;
-LPDIRECT3DVERTEXSHADER9 m_VertexShader;
+static LPDIRECT3DBASETEXTURE9 m_Textures[16];
+static LPDIRECT3DVERTEXDECLARATION9 m_VtxDecl;
+static bool m_VtxDeclChanged;
+static LPDIRECT3DPIXELSHADER9 m_PixelShader;
+static bool m_PixelShaderChanged;
+static LPDIRECT3DVERTEXSHADER9 m_VertexShader;
+static bool m_VertexShaderChanged;
+struct StreamSourceDescriptor
+{
+ LPDIRECT3DVERTEXBUFFER9 pStreamData;
+ UINT OffsetInBytes;
+ UINT Stride;
+};
+static StreamSourceDescriptor m_stream_sources[MaxStreamSources];
+static bool m_stream_sources_Changed[MaxStreamSources];
+static LPDIRECT3DINDEXBUFFER9 m_index_buffer;
+static bool m_index_buffer_Changed;
// Z buffer formats to be used for EFB depth surface
D3DFORMAT DepthFormats[] = {
@@ -170,9 +184,9 @@ void EnableAlphaToCoverage()
{
// Each vendor has their own specific little hack.
if (GetCurAdapter().ident.VendorId == VENDOR_ATI)
- D3D::SetRenderState(D3DRS_POINTSIZE, (D3DFORMAT)MAKEFOURCC('A', '2', 'M', '1'));
+ SetRenderState(D3DRS_POINTSIZE, (D3DFORMAT)MAKEFOURCC('A', '2', 'M', '1'));
else
- D3D::SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
+ SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
}
void InitPP(int adapter, int f, int aa_mode, D3DPRESENT_PARAMETERS *pp)
@@ -209,20 +223,20 @@ void InitPP(int adapter, int f, int aa_mode, D3DPRESENT_PARAMETERS *pp)
yres = pp->BackBufferHeight = client.bottom - client.top;
}
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
- pp->PresentationInterval = g_Config.bVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
+ pp->PresentationInterval = g_Config.IsVSync() ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
pp->Windowed = !g_Config.b3DVision;
}
void Enumerate()
{
- numAdapters = D3D::D3D->GetAdapterCount();
+ numAdapters = D3D->GetAdapterCount();
for (int i = 0; i < std::min(MAX_ADAPTERS, numAdapters); i++)
{
Adapter &a = adapters[i];
a.aa_levels.clear();
a.resolutions.clear();
- D3D::D3D->GetAdapterIdentifier(i, 0, &a.ident);
+ D3D->GetAdapterIdentifier(i, 0, &a.ident);
bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA;
// Add SuperSamples modes
@@ -233,17 +247,17 @@ void Enumerate()
//disable them will they are not implemnted
/*
DWORD qlevels = 0;
- if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
+ if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("2x MSAA", D3DMULTISAMPLE_2_SAMPLES, 0));
- if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
+ if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("4x MSAA", D3DMULTISAMPLE_4_SAMPLES, 0));
- if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
+ if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("8x MSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
@@ -251,7 +265,7 @@ void Enumerate()
if (isNvidia)
{
// CSAA support
- if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
+ if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES, &qlevels))
{
if (qlevels > 2)
@@ -262,7 +276,7 @@ void Enumerate()
a.aa_levels.push_back(AALevel("8xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
}
}
- if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
+ if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
{
if (qlevels > 2)
@@ -296,11 +310,11 @@ void Enumerate()
{
strcpy(a.aa_levels[0].name, "(Not supported on this device)");
}
- int numModes = D3D::D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
+ int numModes = D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
for (int m = 0; m < numModes; m++)
{
D3DDISPLAYMODE mode;
- D3D::D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
+ D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
int found = -1;
for (int x = 0; x < (int)a.resolutions.size(); x++)
@@ -440,8 +454,8 @@ HRESULT Create(int adapter, HWND wnd, int _resolution, int aa_mode, bool auto_de
dev->GetRenderTarget(0, &back_buffer);
if (dev->GetDepthStencilSurface(&back_buffer_z) == D3DERR_NOTFOUND)
back_buffer_z = NULL;
- D3D::SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE );
- D3D::SetRenderState(D3DRS_FILLMODE, g_Config.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
+ SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE );
+ SetRenderState(D3DRS_FILLMODE, g_Config.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
memset(m_Textures, 0, sizeof(m_Textures));
memset(m_TextureStageStatesSet, 0, sizeof(m_TextureStageStatesSet));
memset(m_RenderStatesSet, 0, sizeof(m_RenderStatesSet));
@@ -452,6 +466,15 @@ HRESULT Create(int adapter, HWND wnd, int _resolution, int aa_mode, bool auto_de
m_VtxDecl = NULL;
m_PixelShader = NULL;
m_VertexShader = NULL;
+ m_index_buffer = NULL;
+ memset(m_stream_sources, 0, sizeof(m_stream_sources));
+ m_index_buffer = NULL;
+
+ m_VtxDeclChanged = false;
+ m_PixelShaderChanged = false;
+ m_VertexShaderChanged = false;
+ memset(m_stream_sources_Changed, 0 , sizeof(m_stream_sources_Changed));
+ m_index_buffer_Changed = false;
// Device state would normally be set here
return S_OK;
}
@@ -516,7 +539,7 @@ bool CheckDepthStencilSupport(D3DFORMAT target_format, D3DFORMAT depth_format)
D3DFORMAT GetSupportedDepthTextureFormat()
{
for (int i = 0; i < sizeof(DepthFormats)/sizeof(D3DFORMAT); ++i)
- if (D3D::CheckTextureSupport(D3DUSAGE_DEPTHSTENCIL, DepthFormats[i]))
+ if (CheckTextureSupport(D3DUSAGE_DEPTHSTENCIL, DepthFormats[i]))
return DepthFormats[i];
return D3DFMT_UNKNOWN;
@@ -525,7 +548,7 @@ D3DFORMAT GetSupportedDepthTextureFormat()
D3DFORMAT GetSupportedDepthSurfaceFormat(D3DFORMAT target_format)
{
for (int i = 0; i < sizeof(DepthFormats)/sizeof(D3DFORMAT); ++i)
- if (D3D::CheckDepthStencilSupport(target_format, DepthFormats[i]))
+ if (CheckDepthStencilSupport(target_format, DepthFormats[i]))
return DepthFormats[i];
return D3DFMT_UNKNOWN;
@@ -533,13 +556,13 @@ D3DFORMAT GetSupportedDepthSurfaceFormat(D3DFORMAT target_format)
const char *VertexShaderVersionString()
{
- int version = ((D3D::caps.VertexShaderVersion >> 8) & 0xFF);
+ int version = ((caps.VertexShaderVersion >> 8) & 0xFF);
return vsVersions[std::min(4, version)];
}
const char *PixelShaderVersionString()
{
- int version = ((D3D::caps.PixelShaderVersion >> 8) & 0xFF);
+ int version = ((caps.PixelShaderVersion >> 8) & 0xFF);
return psVersions[std::min(4, version)];
}
@@ -653,14 +676,14 @@ void ApplyCachedState()
for (int type = 0; type < MaxSamplerTypes; type++)
{
if(m_SamplerStatesSet[sampler][type])
- D3D::dev->SetSamplerState(sampler, (D3DSAMPLERSTATETYPE)type, m_SamplerStates[sampler][type]);
+ dev->SetSamplerState(sampler, (D3DSAMPLERSTATETYPE)type, m_SamplerStates[sampler][type]);
}
}
for (int rs = 0; rs < MaxRenderStates; rs++)
{
if (m_RenderStatesSet[rs])
- D3D::dev->SetRenderState((D3DRENDERSTATETYPE)rs, m_RenderStates[rs]);
+ dev->SetRenderState((D3DRENDERSTATETYPE)rs, m_RenderStates[rs]);
}
// We don't bother restoring these so let's just wipe the state copy
@@ -671,6 +694,13 @@ void ApplyCachedState()
m_VtxDecl = NULL;
m_PixelShader = NULL;
m_VertexShader = NULL;
+ memset(m_stream_sources, 0, sizeof(m_stream_sources));
+ m_index_buffer = NULL;
+ m_VtxDeclChanged = false;
+ m_PixelShaderChanged = false;
+ m_VertexShaderChanged = false;
+ memset(m_stream_sources_Changed, 0 , sizeof(m_stream_sources_Changed));
+ m_index_buffer_Changed = false;
}
void SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture)
@@ -678,7 +708,7 @@ void SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture)
if (m_Textures[Stage] != pTexture)
{
m_Textures[Stage] = pTexture;
- D3D::dev->SetTexture(Stage, pTexture);
+ dev->SetTexture(Stage, pTexture);
}
}
@@ -686,7 +716,7 @@ void RefreshRenderState(D3DRENDERSTATETYPE State)
{
if(m_RenderStatesSet[State] && m_RenderStatesChanged[State])
{
- D3D::dev->SetRenderState(State, m_RenderStates[State]);
+ dev->SetRenderState(State, m_RenderStates[State]);
m_RenderStatesChanged[State] = false;
}
}
@@ -698,7 +728,7 @@ void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value)
m_RenderStates[State] = Value;
m_RenderStatesSet[State] = true;
m_RenderStatesChanged[State] = false;
- D3D::dev->SetRenderState(State, Value);
+ dev->SetRenderState(State, Value);
}
}
@@ -707,7 +737,7 @@ void ChangeRenderState(D3DRENDERSTATETYPE State, DWORD Value)
if (m_RenderStates[State] != Value || !m_RenderStatesSet[State])
{
m_RenderStatesChanged[State] = m_RenderStatesSet[State];
- D3D::dev->SetRenderState(State, Value);
+ dev->SetRenderState(State, Value);
}
else
{
@@ -722,7 +752,7 @@ void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Valu
m_TextureStageStates[Stage][Type] = Value;
m_TextureStageStatesSet[Stage][Type]=true;
m_TextureStageStatesChanged[Stage][Type]=false;
- D3D::dev->SetTextureStageState(Stage, Type, Value);
+ dev->SetTextureStageState(Stage, Type, Value);
}
}
@@ -730,7 +760,7 @@ void RefreshTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type)
{
if(m_TextureStageStatesSet[Stage][Type] && m_TextureStageStatesChanged[Stage][Type])
{
- D3D::dev->SetTextureStageState(Stage, Type, m_TextureStageStates[Stage][Type]);
+ dev->SetTextureStageState(Stage, Type, m_TextureStageStates[Stage][Type]);
m_TextureStageStatesChanged[Stage][Type] = false;
}
}
@@ -740,7 +770,7 @@ void ChangeTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD V
if (m_TextureStageStates[Stage][Type] != Value || !m_TextureStageStatesSet[Stage][Type])
{
m_TextureStageStatesChanged[Stage][Type] = m_TextureStageStatesSet[Stage][Type];
- D3D::dev->SetTextureStageState(Stage, Type, Value);
+ dev->SetTextureStageState(Stage, Type, Value);
}
else
{
@@ -755,7 +785,7 @@ void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
m_SamplerStates[Sampler][Type] = Value;
m_SamplerStatesSet[Sampler][Type] = true;
m_SamplerStatesChanged[Sampler][Type] = false;
- D3D::dev->SetSamplerState(Sampler, Type, Value);
+ dev->SetSamplerState(Sampler, Type, Value);
}
}
@@ -763,7 +793,7 @@ void RefreshSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type)
{
if(m_SamplerStatesSet[Sampler][Type] && m_SamplerStatesChanged[Sampler][Type])
{
- D3D::dev->SetSamplerState(Sampler, Type, m_SamplerStates[Sampler][Type]);
+ dev->SetSamplerState(Sampler, Type, m_SamplerStates[Sampler][Type]);
m_SamplerStatesChanged[Sampler][Type] = false;
}
}
@@ -773,7 +803,7 @@ void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
if (m_SamplerStates[Sampler][Type] != Value || !m_SamplerStatesSet[Sampler][Type])
{
m_SamplerStatesChanged[Sampler][Type] = m_SamplerStatesSet[Sampler][Type];
- D3D::dev->SetSamplerState(Sampler, Type, Value);
+ dev->SetSamplerState(Sampler, Type, Value);
}
else
{
@@ -783,67 +813,155 @@ void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
void RefreshVertexDeclaration()
{
- if (m_VtxDecl)
+ if (m_VtxDeclChanged)
{
- D3D::dev->SetVertexDeclaration(m_VtxDecl);
+ dev->SetVertexDeclaration(m_VtxDecl);
+ m_VtxDeclChanged = false;
}
}
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl)
{
- if (!decl) {
- m_VtxDecl = NULL;
- return;
- }
if (decl != m_VtxDecl)
{
- D3D::dev->SetVertexDeclaration(decl);
+ dev->SetVertexDeclaration(decl);
m_VtxDecl = decl;
+ m_VtxDeclChanged = false;
+ }
+}
+
+void ChangeVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl)
+{
+ if (decl != m_VtxDecl) {
+ dev->SetVertexDeclaration(decl);
+ m_VtxDeclChanged = true;
+ }
+}
+
+void ChangeVertexShader(LPDIRECT3DVERTEXSHADER9 shader)
+{
+ if (shader != m_VertexShader)
+ {
+ dev->SetVertexShader(shader);
+ m_VertexShaderChanged = true;
}
}
void RefreshVertexShader()
{
- if (m_VertexShader)
+ if (m_VertexShaderChanged)
{
- D3D::dev->SetVertexShader(m_VertexShader);
+ dev->SetVertexShader(m_VertexShader);
+ m_VertexShaderChanged = false;
}
}
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader)
{
- if (!shader) {
- m_VertexShader = NULL;
- return;
- }
if (shader != m_VertexShader)
{
- D3D::dev->SetVertexShader(shader);
+ dev->SetVertexShader(shader);
m_VertexShader = shader;
+ m_VertexShaderChanged = false;
}
}
void RefreshPixelShader()
{
- if (m_PixelShader)
+ if (m_PixelShaderChanged)
{
- D3D::dev->SetPixelShader(m_PixelShader);
+ dev->SetPixelShader(m_PixelShader);
+ m_PixelShaderChanged = false;
}
}
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader)
{
- if (!shader) {
- m_PixelShader = NULL;
- return;
- }
if (shader != m_PixelShader)
{
- D3D::dev->SetPixelShader(shader);
+ dev->SetPixelShader(shader);
m_PixelShader = shader;
+ m_PixelShaderChanged = false;
+ }
+}
+
+void ChangePixelShader(LPDIRECT3DPIXELSHADER9 shader)
+{
+ if (shader != m_PixelShader)
+ {
+ dev->SetPixelShader(shader);
+ m_PixelShaderChanged = true;
+ }
+}
+
+void SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
+{
+ if (m_stream_sources[StreamNumber].OffsetInBytes != OffsetInBytes
+ || m_stream_sources[StreamNumber].pStreamData != pStreamData
+ || m_stream_sources[StreamNumber].Stride != Stride)
+ {
+ m_stream_sources[StreamNumber].OffsetInBytes = OffsetInBytes;
+ m_stream_sources[StreamNumber].pStreamData = pStreamData;
+ m_stream_sources[StreamNumber].Stride = Stride;
+ dev->SetStreamSource(StreamNumber, pStreamData, OffsetInBytes, Stride);
+ m_stream_sources_Changed[StreamNumber] = false;
+ }
+}
+
+void ChangeStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
+{
+ if (m_stream_sources[StreamNumber].OffsetInBytes != OffsetInBytes
+ || m_stream_sources[StreamNumber].pStreamData != pStreamData
+ || m_stream_sources[StreamNumber].Stride != Stride)
+ {
+ dev->SetStreamSource(StreamNumber, pStreamData, OffsetInBytes, Stride);
+ m_stream_sources_Changed[StreamNumber] = true;
+ }
+
+}
+
+void RefreshStreamSource(UINT StreamNumber)
+{
+ if (m_PixelShaderChanged)
+ {
+ dev->SetStreamSource(
+ StreamNumber,
+ m_stream_sources[StreamNumber].pStreamData,
+ m_stream_sources[StreamNumber].OffsetInBytes,
+ m_stream_sources[StreamNumber].Stride);
+ m_stream_sources_Changed[StreamNumber] = false;
}
}
+void SetIndices(LPDIRECT3DINDEXBUFFER9 pIndexData)
+{
+ if(pIndexData != m_index_buffer)
+ {
+ m_index_buffer = pIndexData;
+ dev->SetIndices(pIndexData);
+ m_index_buffer_Changed = false;
+ }
+}
+
+void ChangeIndices(LPDIRECT3DINDEXBUFFER9 pIndexData)
+{
+ if(pIndexData != m_index_buffer)
+ {
+ dev->SetIndices(pIndexData);
+ m_index_buffer_Changed = true;
+ }
+}
+
+void RefreshIndices()
+{
+ if (m_index_buffer_Changed)
+ {
+ dev->SetIndices(m_index_buffer);
+ m_index_buffer_Changed = false;
+ }
+}
+
+
} // namespace
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h
index d1e7eeaa91..7be482a55f 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h
+++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h
@@ -100,12 +100,23 @@ void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
void RefreshVertexDeclaration();
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl);
+void ChangeVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl);
void RefreshVertexShader();
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader);
+void ChangeVertexShader(LPDIRECT3DVERTEXSHADER9 shader);
void RefreshPixelShader();
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader);
+void ChangePixelShader(LPDIRECT3DPIXELSHADER9 shader);
+
+void SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride);
+void ChangeStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride);
+void RefreshStreamSource(UINT StreamNumber);
+
+void SetIndices(LPDIRECT3DINDEXBUFFER9 pIndexData);
+void ChangeIndices(LPDIRECT3DINDEXBUFFER9 pIndexData);
+void RefreshIndices();
void ApplyCachedState();
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp
index 9c17c3df8c..c7c4cf266a 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp
@@ -50,7 +50,8 @@ bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecode
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << code;
file.close();
@@ -105,7 +106,8 @@ bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodel
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << code;
file.close();
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp
index 9510ad444c..d24720e6f9 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp
@@ -198,6 +198,8 @@ const int TS[6][2] =
void RestoreShaders()
{
D3D::SetTexture(0, 0);
+ D3D::RefreshStreamSource(0);
+ D3D::RefreshIndices();
D3D::RefreshVertexDeclaration();
D3D::RefreshPixelShader();
D3D::RefreshVertexShader();
@@ -217,9 +219,9 @@ void CD3DFont::SetRenderStates()
{
D3D::SetTexture(0, m_pTexture);
- dev->SetPixelShader(0);
- dev->SetVertexShader(0);
-
+ D3D::ChangePixelShader(0);
+ D3D::ChangeVertexShader(0);
+ D3D::ChangeVertexDeclaration(0);
dev->SetFVF(D3DFVF_FONT2DVERTEX);
for (int i = 0; i < 6; i++)
@@ -236,7 +238,7 @@ int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, flo
return 0;
SetRenderStates();
- dev->SetStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
+ D3D::ChangeStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
float vpWidth = 1;
float vpHeight = 1;
@@ -389,9 +391,10 @@ void drawShadedTexQuad(IDirect3DTexture9 *texture,
{ 1.0f - dw,-1.0f + dh, 0.0f,1.0f, u2, v2, sw, sh, g},
{ 1.0f - dw, 1.0f + dh, 0.0f,1.0f, u2, v1, sw, sh, g}
};
- dev->SetVertexShader(Vshader);
- dev->SetPixelShader(PShader);
+ D3D::ChangeVertexShader(Vshader);
+ D3D::ChangePixelShader(PShader);
D3D::SetTexture(0, texture);
+ D3D::ChangeVertexDeclaration(0);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE1(2));
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
@@ -424,9 +427,10 @@ void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
{ rDest->right - dw , rDest->top + dh, 1.0f,1.0f, u2, v2, sw, sh, g},
{ rDest->right - dw , rDest->bottom + dh, 1.0f,1.0f, u2, v1, sw, sh, g}
};
- dev->SetVertexShader(Vshader);
- dev->SetPixelShader(PShader);
+ D3D::ChangeVertexShader(Vshader);
+ D3D::ChangePixelShader(PShader);
D3D::SetTexture(0, texture);
+ D3D::ChangeVertexDeclaration(0);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE1(2));
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
@@ -442,8 +446,9 @@ void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2)
{ x1, y1, 0.f, 1.f, Color },
{ x2, y1, 0.f, 1.f, Color },
};
- dev->SetVertexShader(VertexShaderCache::GetClearVertexShader());
- dev->SetPixelShader(PixelShaderCache::GetClearProgram());
+ D3D::ChangeVertexShader(VertexShaderCache::GetClearVertexShader());
+ D3D::ChangePixelShader(PixelShaderCache::GetClearProgram());
+ D3D::ChangeVertexDeclaration(0);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(CQVertex));
RestoreShaders();
@@ -457,8 +462,9 @@ void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVer
{ 1.0f, -1.0f, z, 1.0f, Color},
{-1.0f, -1.0f, z, 1.0f, Color}
};
- dev->SetVertexShader(Vshader);
- dev->SetPixelShader(PShader);
+ D3D::ChangeVertexShader(Vshader);
+ D3D::ChangePixelShader(PShader);
+ D3D::ChangeVertexDeclaration(0);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp
index 1903bce989..5dfcc51c66 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp
@@ -187,6 +187,8 @@ void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, c
void XFBSource::CopyEFB(float Gamma)
{
+ g_renderer->ResetAPIState(); // reset any game specific settings
+
// Copy EFB data to XFB and restore render target again
LPDIRECT3DSURFACE9 Rendersurf = NULL;
texture->GetSurfaceLevel(0, &Rendersurf);
@@ -229,6 +231,8 @@ void XFBSource::CopyEFB(float Gamma)
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
Rendersurf->Release();
+
+ g_renderer->RestoreAPIState();
}
} // namespace DX9
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp b/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp
index bfaf21ec7e..d68228273c 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp
@@ -19,7 +19,7 @@
#include "D3DBase.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "MemoryUtil.h"
#include "VertexShaderGen.h"
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp
index 0657309801..7a175fd443 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp
@@ -67,6 +67,7 @@ static int s_fps = 0;
static u32 s_blendMode;
static u32 s_LastAA;
static bool IS_AMD;
+static float m_fMaxPointSize;
static char *st;
@@ -187,6 +188,9 @@ Renderer::Renderer()
D3D::BeginFrame();
D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, true);
D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width,s_backbuffer_height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL );
+ D3D::SetRenderState(D3DRS_POINTSCALEENABLE,false);
+ m_fMaxPointSize = D3D::GetCaps().MaxPointSize;
+
}
Renderer::~Renderer()
@@ -216,11 +220,11 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
}
-void formatBufferDump(const char *in, char *out, int w, int h, int p)
+void formatBufferDump(const u8* in, u8* out, int w, int h, int p)
{
for (int y = 0; y < h; y++)
{
- const char *line = in + (h - y - 1) * p;
+ auto line = in + (h - y - 1) * p;
for (int x = 0; x < w; x++)
{
memcpy(out, line, 3);
@@ -725,8 +729,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
{
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- AVIDump::AddFrame(frame_data);
+ if (g_ActiveConfig.bDumpFrames && !frame_data.empty())
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -737,8 +741,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- AVIDump::AddFrame(frame_data);
+ if (g_ActiveConfig.bDumpFrames && !frame_data.empty())
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -935,15 +939,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
D3DLOCKED_RECT rect;
if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, GetTargetRectangle().AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY)))
{
- if (!frame_data || w != s_recordWidth || h != s_recordHeight)
+ if (frame_data.empty() || w != s_recordWidth || h != s_recordHeight)
{
- delete[] frame_data;
- frame_data = new char[3 * s_recordWidth * s_recordHeight];
+ frame_data.resize(3 * s_recordWidth * s_recordHeight);
w = s_recordWidth;
h = s_recordHeight;
}
- formatBufferDump((const char*)rect.pBits, frame_data, s_recordWidth, s_recordHeight, rect.Pitch);
- AVIDump::AddFrame(frame_data);
+ formatBufferDump((const u8*)rect.pBits, &frame_data[0], s_recordWidth, s_recordHeight, rect.Pitch);
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
ScreenShootMEMSurface->UnlockRect();
}
}
@@ -953,12 +956,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
{
if (bLastFrameDumped && bAVIDumping)
{
- if (frame_data)
- {
- delete[] frame_data;
- frame_data = 0;
- w = h = 0;
- }
+ std::vector<u8>().swap(frame_data);
+ w = h = 0;
AVIDump::Stop();
bAVIDumping = false;
OSD::AddMessage("Stop dumping frames to AVI", 2000);
@@ -1285,7 +1284,15 @@ void Renderer::SetLineWidth()
// We can't change line width in D3D unless we use ID3DXLine
float fratio = xfregs.viewport.wd != 0 ? Renderer::EFBToScaledXf(1.f) : 1.0f;
float psize = bpmem.lineptwidth.linesize * fratio / 6.0f;
+ //little hack to compensate scalling problems in dx9 must be taken out when scalling is fixed.
+ psize *= 2.0f;
+ if (psize > m_fMaxPointSize)
+ {
+ psize = m_fMaxPointSize;
+ }
D3D::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize));
+ D3D::SetRenderState(D3DRS_POINTSIZE_MIN, *((DWORD*)&psize));
+ D3D::SetRenderState(D3DRS_POINTSIZE_MAX, *((DWORD*)&psize));
}
void Renderer::SetSamplerState(int stage, int texindex)
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp
index f105d0f774..0e7d82cf7a 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp
@@ -82,6 +82,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
const float *colmat)
{
+ g_renderer->ResetAPIState(); // reset any game specific settings
+
const LPDIRECT3DTEXTURE9 read_texture = (srcFormat == PIXELFMT_Z24) ?
FramebufferManager::GetEFBDepthTexture() :
FramebufferManager::GetEFBColorTexture();
@@ -179,6 +181,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
D3D::SetTexture(0, NULL);
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
+
+ g_renderer->RestoreAPIState();
}
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height,
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp
index 661cf36e76..543a1b9ddc 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp
@@ -42,9 +42,9 @@ extern NativeVertexFormat *g_nativeVertexFmt;
namespace DX9
{
//This are the initially requeted size for the buffers expresed in elements
-const u32 IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * 16;
-const u32 VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE * 16;
-const u32 MAXVBUFFER_COUNT = 2;
+const u32 IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * sizeof(u16) * 8;
+const u32 VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE;
+const u32 MAX_VBUFFER_COUNT = 2;
inline void DumpBadShaders()
{
@@ -67,88 +67,88 @@ inline void DumpBadShaders()
void VertexManager::CreateDeviceObjects()
{
- NumVBuffers = 0;
- VBuffers = NULL;
- IBuffers = NULL;
+ m_buffers_count = 0;
+ m_vertex_buffers = NULL;
+ m_index_buffers = NULL;
D3DCAPS9 DeviceCaps = D3D::GetCaps();
u32 devicevMaxBufferSize = DeviceCaps.MaxPrimitiveCount * 3 * DeviceCaps.MaxStreamStride;
//Calculate Device Dependant size
- CurrentVBufferSize = (VBUFFER_SIZE > devicevMaxBufferSize) ? devicevMaxBufferSize : VBUFFER_SIZE;
- CurrentIBufferSize = (IBUFFER_SIZE > DeviceCaps.MaxVertexIndex) ? DeviceCaps.MaxVertexIndex : IBUFFER_SIZE;
+ m_vertex_buffer_size = (VBUFFER_SIZE > devicevMaxBufferSize) ? devicevMaxBufferSize : VBUFFER_SIZE;
+ m_index_buffer_size = (IBUFFER_SIZE > DeviceCaps.MaxVertexIndex) ? DeviceCaps.MaxVertexIndex : IBUFFER_SIZE;
//if device caps are not enough for Vbuffer fall back to vertex arrays
- if (CurrentIBufferSize < MAXIBUFFERSIZE || CurrentVBufferSize < MAXVBUFFERSIZE) return;
+ if (m_index_buffer_size < MAXIBUFFERSIZE || m_vertex_buffer_size < MAXVBUFFERSIZE) return;
- VBuffers = new LPDIRECT3DVERTEXBUFFER9[MAXVBUFFER_COUNT];
- IBuffers = new LPDIRECT3DINDEXBUFFER9[MAXVBUFFER_COUNT];
+ m_vertex_buffers = new LPDIRECT3DVERTEXBUFFER9[MAX_VBUFFER_COUNT];
+ m_index_buffers = new LPDIRECT3DINDEXBUFFER9[MAX_VBUFFER_COUNT];
bool Fail = false;
- for (CurrentVBuffer = 0; CurrentVBuffer < MAXVBUFFER_COUNT; CurrentVBuffer++)
+ for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
{
- VBuffers[CurrentVBuffer] = NULL;
- IBuffers[CurrentVBuffer] = NULL;
+ m_vertex_buffers[m_current_vertex_buffer] = NULL;
+ m_index_buffers[m_current_vertex_buffer] = NULL;
}
- for (CurrentVBuffer = 0; CurrentVBuffer < MAXVBUFFER_COUNT; CurrentVBuffer++)
+ for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
{
- if(FAILED( D3D::dev->CreateVertexBuffer( CurrentVBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &VBuffers[CurrentVBuffer], NULL ) ) )
+ if(FAILED( D3D::dev->CreateVertexBuffer( m_vertex_buffer_size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_vertex_buffers[m_current_vertex_buffer], NULL ) ) )
{
Fail = true;
break;
}
- if( FAILED( D3D::dev->CreateIndexBuffer( CurrentIBufferSize * sizeof(u16), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &IBuffers[CurrentVBuffer], NULL ) ) )
+ if( FAILED( D3D::dev->CreateIndexBuffer( m_index_buffer_size * sizeof(u16), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_index_buffers[m_current_vertex_buffer], NULL ) ) )
{
Fail = true;
return;
}
}
- NumVBuffers = CurrentVBuffer;
- CurrentVBuffer = 0;
- CurrentIBuffer = 0;
- CurrentIBufferIndex = CurrentIBufferSize;
- CurrentVBufferIndex = CurrentVBufferSize;
-
+ m_buffers_count = m_current_vertex_buffer;
+ m_current_vertex_buffer = 0;
+ m_current_index_buffer = 0;
+ m_index_buffer_cursor = m_index_buffer_size;
+ m_vertex_buffer_cursor = m_vertex_buffer_size;
+ m_current_stride = 0;
if (Fail)
{
- NumVBuffers--;
- if (NumVBuffers < 2)
+ m_buffers_count--;
+ if (m_buffers_count < 2)
{
//Error creating Vertex buffers. clean and fall to Vertex arrays
- NumVBuffers = MAXVBUFFER_COUNT;
+ m_buffers_count = MAX_VBUFFER_COUNT;
DestroyDeviceObjects();
}
}
}
void VertexManager::DestroyDeviceObjects()
{
- D3D::dev->SetStreamSource( 0, NULL, 0, 0);
- D3D::dev->SetIndices(NULL);
- for (int i = 0; i < MAXVBUFFER_COUNT; i++)
+ D3D::SetStreamSource( 0, NULL, 0, 0);
+ D3D::SetIndices(NULL);
+ for (int i = 0; i < MAX_VBUFFER_COUNT; i++)
{
- if(VBuffers)
+ if(m_vertex_buffers)
{
- if (VBuffers[i])
+ if (m_vertex_buffers[i])
{
- VBuffers[i]->Release();
- VBuffers[i] = NULL;
+ m_vertex_buffers[i]->Release();
+ m_vertex_buffers[i] = NULL;
}
}
- if (IBuffers[i])
+ if (m_index_buffers[i])
{
- IBuffers[i]->Release();
- IBuffers[i] = NULL;
+ m_index_buffers[i]->Release();
+ m_index_buffers[i] = NULL;
}
}
- if(VBuffers)
- delete [] VBuffers;
- if(IBuffers)
- delete [] IBuffers;
- VBuffers = NULL;
- IBuffers = NULL;
+ if(m_vertex_buffers)
+ delete [] m_vertex_buffers;
+ if(m_index_buffers)
+ delete [] m_index_buffers;
+ m_vertex_buffers = NULL;
+ m_index_buffers = NULL;
}
-void VertexManager::PrepareVBuffers(int stride)
+void VertexManager::PrepareDrawBuffers(u32 stride)
{
- if (!NumVBuffers)
+ if (!m_buffers_count)
{
return;
}
@@ -158,145 +158,160 @@ void VertexManager::PrepareVBuffers(int stride)
int TdataSize = IndexGenerator::GetTriangleindexLen();
int LDataSize = IndexGenerator::GetLineindexLen();
int PDataSize = IndexGenerator::GetPointindexLen();
- int IndexDataSize = TdataSize + LDataSize + PDataSize;
+ int IndexDataSize = TdataSize + LDataSize;
DWORD LockMode = D3DLOCK_NOOVERWRITE;
-
- if (CurrentVBufferIndex > CurrentVBufferSize - datasize)
+ m_vertex_buffer_cursor--;
+ m_vertex_buffer_cursor = m_vertex_buffer_cursor - (m_vertex_buffer_cursor % stride) + stride;
+ if (m_vertex_buffer_cursor > m_vertex_buffer_size - datasize)
{
LockMode = D3DLOCK_DISCARD;
- CurrentVBufferIndex = 0;
- CurrentVBuffer = (CurrentVBuffer + 1) % NumVBuffers;
- }
-
- if(FAILED(VBuffers[CurrentVBuffer]->Lock(CurrentVBufferIndex, datasize,(VOID**)(&pVertices), LockMode)))
+ m_vertex_buffer_cursor = 0;
+ m_current_vertex_buffer = (m_current_vertex_buffer + 1) % m_buffers_count;
+ }
+ if(FAILED(m_vertex_buffers[m_current_vertex_buffer]->Lock(m_vertex_buffer_cursor, datasize,(VOID**)(&pVertices), LockMode)))
{
DestroyDeviceObjects();
return;
}
- memcpy(pVertices, LocalVBuffer, datasize);
- VBuffers[CurrentVBuffer]->Unlock();
+ memcpy(pVertices, s_pBaseBufferPointer, datasize);
+ m_vertex_buffers[m_current_vertex_buffer]->Unlock();
LockMode = D3DLOCK_NOOVERWRITE;
-
- if (CurrentIBufferIndex > CurrentIBufferSize - IndexDataSize)
+ if (m_index_buffer_cursor > m_index_buffer_size - IndexDataSize)
{
LockMode = D3DLOCK_DISCARD;
- CurrentIBufferIndex = 0;
- CurrentIBuffer = (CurrentIBuffer + 1) % NumVBuffers;
- }
+ m_index_buffer_cursor = 0;
+ m_current_index_buffer = (m_current_index_buffer + 1) % m_buffers_count;
+ }
- if(FAILED(IBuffers[CurrentIBuffer]->Lock(CurrentIBufferIndex * sizeof(u16), IndexDataSize * sizeof(u16), (VOID**)(&pIndices), LockMode )))
+ if(FAILED(m_index_buffers[m_current_index_buffer]->Lock(m_index_buffer_cursor * sizeof(u16), IndexDataSize * sizeof(u16), (VOID**)(&pIndices), LockMode )))
{
DestroyDeviceObjects();
return;
}
if(TdataSize)
{
- memcpy(pIndices, TIBuffer, TdataSize * sizeof(u16));
+ memcpy(pIndices, GetTriangleIndexBuffer(), TdataSize * sizeof(u16));
pIndices += TdataSize;
}
if(LDataSize)
{
- memcpy(pIndices, LIBuffer, LDataSize * sizeof(u16));
+ memcpy(pIndices, GetLineIndexBuffer(), LDataSize * sizeof(u16));
pIndices += LDataSize;
}
- if(PDataSize)
- {
- memcpy(pIndices, PIBuffer, PDataSize * sizeof(u16));
+ m_index_buffers[m_current_index_buffer]->Unlock();
+ if(m_current_stride != stride || m_vertex_buffer_cursor == 0)
+ {
+ m_current_stride = stride;
+ D3D::SetStreamSource( 0, m_vertex_buffers[m_current_vertex_buffer], 0, stride);
}
- IBuffers[CurrentIBuffer]->Unlock();
- D3D::dev->SetStreamSource( 0, VBuffers[CurrentVBuffer], CurrentVBufferIndex, stride);
- if(CurrentIBufferIndex == 0)
+ if (m_index_buffer_cursor == 0)
{
- D3D::dev->SetIndices(IBuffers[CurrentIBuffer]);
+ D3D::SetIndices(m_index_buffers[m_current_index_buffer]);
}
+
}
-void VertexManager::DrawVB(int stride)
+void VertexManager::DrawVertexBuffer(int stride)
{
- if (IndexGenerator::GetNumTriangles() > 0)
+ int triangles = IndexGenerator::GetNumTriangles();
+ int lines = IndexGenerator::GetNumLines();
+ int points = IndexGenerator::GetNumPoints();
+ int numverts = IndexGenerator::GetNumVerts();
+ int StartIndex = m_index_buffer_cursor;
+ int basevertex = m_vertex_buffer_cursor / stride;
+ if (triangles > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitive(
- D3DPT_TRIANGLELIST,
- 0,
+ D3DPT_TRIANGLELIST,
+ basevertex,
0,
- IndexGenerator::GetNumVerts(),
- CurrentIBufferIndex,
- IndexGenerator::GetNumTriangles())))
+ numverts,
+ StartIndex,
+ triangles)))
{
DumpBadShaders();
}
+ StartIndex += IndexGenerator::GetTriangleindexLen();
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
- if (IndexGenerator::GetNumLines() > 0)
+ if (lines > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitive(
D3DPT_LINELIST,
- 0,
+ basevertex,
0,
- IndexGenerator::GetNumVerts(),
- CurrentIBufferIndex + IndexGenerator::GetTriangleindexLen(),
+ numverts,
+ StartIndex,
IndexGenerator::GetNumLines())))
{
DumpBadShaders();
}
+ StartIndex += IndexGenerator::GetLineindexLen();
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
- if (IndexGenerator::GetNumPoints() > 0)
+ if (points > 0)
{
- if (FAILED(D3D::dev->DrawIndexedPrimitive(
- D3DPT_POINTLIST,
- 0,
- 0,
- IndexGenerator::GetNumVerts(),
- CurrentIBufferIndex + IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen(),
- IndexGenerator::GetNumPoints())))
+ //DrawIndexedPrimitive does not support point list so we have to draw the points one by one
+ for (int i = 0; i < points; i++)
{
- DumpBadShaders();
+ if (FAILED(D3D::dev->DrawPrimitive(
+ D3DPT_POINTLIST,
+ basevertex + GetPointIndexBuffer()[i],
+ 1)))
+ {
+ DumpBadShaders();
+ }
+ INCSTAT(stats.thisFrame.numDrawCalls);
}
- INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+
+
}
}
-void VertexManager::DrawVA(int stride)
-{
- if (IndexGenerator::GetNumTriangles() > 0)
+void VertexManager::DrawVertexArray(int stride)
+{
+ int triangles = IndexGenerator::GetNumTriangles();
+ int lines = IndexGenerator::GetNumLines();
+ int points = IndexGenerator::GetNumPoints();
+ int numverts = IndexGenerator::GetNumVerts();
+ if (triangles > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_TRIANGLELIST,
- 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumTriangles(),
- TIBuffer,
+ 0, numverts, triangles,
+ GetTriangleIndexBuffer(),
D3DFMT_INDEX16,
- LocalVBuffer,
+ s_pBaseBufferPointer,
stride)))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
- if (IndexGenerator::GetNumLines() > 0)
+ if (lines > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_LINELIST,
- 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumLines(),
- LIBuffer,
+ 0, numverts, lines,
+ GetLineIndexBuffer(),
D3DFMT_INDEX16,
- LocalVBuffer,
+ s_pBaseBufferPointer,
stride)))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
- if (IndexGenerator::GetNumPoints() > 0)
+ if (points > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_POINTLIST,
- 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumPoints(),
- PIBuffer,
+ 0, numverts, points,
+ GetPointIndexBuffer(),
D3DFMT_INDEX16,
- LocalVBuffer,
+ s_pBaseBufferPointer,
stride)))
{
DumpBadShaders();
@@ -307,11 +322,6 @@ void VertexManager::DrawVA(int stride)
void VertexManager::vFlush()
{
- if (LocalVBuffer == s_pCurBufferPointer) return;
- if (Flushed) return;
- Flushed = true;
- VideoFifo_CheckEFBAccess();
-
u32 usedtextures = 0;
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i)
if (bpmem.tevorders[i / 2].getEnable(i & 1))
@@ -350,7 +360,7 @@ void VertexManager::vFlush()
// set global constants
VertexShaderManager::SetConstants();
PixelShaderManager::SetConstants();
- int stride = g_nativeVertexFmt->GetVertexStride();
+ u32 stride = g_nativeVertexFmt->GetVertexStride();
if (!PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components))
{
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
@@ -362,9 +372,16 @@ void VertexManager::vFlush()
goto shader_fail;
}
- PrepareVBuffers(stride);
+ PrepareDrawBuffers(stride);
g_nativeVertexFmt->SetupVertexPointers();
- if(NumVBuffers){ DrawVB(stride);} else { DrawVA(stride);}
+ if(m_buffers_count)
+ {
+ DrawVertexBuffer(stride);
+ }
+ else
+ {
+ DrawVertexArray(stride);
+ }
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
@@ -377,18 +394,24 @@ void VertexManager::vFlush()
}
// update alpha only
g_renderer->ApplyState(true);
- if(NumVBuffers){ DrawVB(stride);} else { DrawVA(stride);}
+ if(m_buffers_count)
+ {
+ DrawVertexBuffer(stride);
+ }
+ else
+ {
+ DrawVertexArray(stride);
+ }
g_renderer->RestoreState();
}
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
shader_fail:
- if(NumVBuffers)
+ if(m_buffers_count)
{
- CurrentIBufferIndex += IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
- CurrentVBufferIndex += IndexGenerator::GetNumVerts() * stride;
+ m_index_buffer_cursor += IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
+ m_vertex_buffer_cursor += IndexGenerator::GetNumVerts() * stride;
}
- ResetBuffer();
}
}
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.h b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.h
index aa4e9ed57b..2a165aa9af 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.h
+++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.h
@@ -34,18 +34,19 @@ public:
void CreateDeviceObjects();
void DestroyDeviceObjects();
private:
- u32 CurrentVBufferIndex;
- u32 CurrentVBufferSize;
- u32 CurrentIBufferIndex;
- u32 CurrentIBufferSize;
- u32 NumVBuffers;
- u32 CurrentVBuffer;
- u32 CurrentIBuffer;
- LPDIRECT3DVERTEXBUFFER9 *VBuffers;
- LPDIRECT3DINDEXBUFFER9 *IBuffers;
- void PrepareVBuffers(int stride);
- void DrawVB(int stride);
- void DrawVA(int stride);
+ u32 m_vertex_buffer_cursor;
+ u32 m_vertex_buffer_size;
+ u32 m_index_buffer_cursor;
+ u32 m_index_buffer_size;
+ u32 m_buffers_count;
+ u32 m_current_vertex_buffer;
+ u32 m_current_stride;
+ u32 m_current_index_buffer;
+ LPDIRECT3DVERTEXBUFFER9 *m_vertex_buffers;
+ LPDIRECT3DINDEXBUFFER9 *m_index_buffers;
+ void PrepareDrawBuffers(u32 stride);
+ void DrawVertexBuffer(int stride);
+ void DrawVertexArray(int stride);
// temp
void vFlush();
};
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VideoBackend.h b/Source/Plugins/Plugin_VideoDX9/Src/VideoBackend.h
index 77cbd14dae..5b7c54d326 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/VideoBackend.h
+++ b/Source/Plugins/Plugin_VideoDX9/Src/VideoBackend.h
@@ -13,8 +13,10 @@ class VideoBackend : public VideoBackendHardware
void Shutdown();
std::string GetName();
+ std::string GetDisplayName();
void Video_Prepare();
+ void Video_Cleanup();
void ShowConfig(void* parent);
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp
index 3c00e1d619..4b4fc6608e 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp
@@ -57,6 +57,7 @@
#include "ConfigManager.h"
#include "VideoBackend.h"
+#include "PerfQueryBase.h"
namespace DX9
{
@@ -86,6 +87,11 @@ std::string VideoBackend::GetName()
return "Direct3D9";
}
+std::string VideoBackend::GetDisplayName()
+{
+ return "Direct3D9 (deprecated)";
+}
+
void InitBackendInfo()
{
DX9::D3D::Init();
@@ -97,8 +103,6 @@ void InitBackendInfo()
g_Config.backend_info.bSupports3DVision = true;
g_Config.backend_info.bSupportsDualSourceBlend = false;
g_Config.backend_info.bSupportsFormatReinterpretation = true;
-
-
g_Config.backend_info.bSupportsPixelLighting = C_PLIGHTS + 40 <= maxConstants && C_PMATERIALS + 4 <= maxConstants;
// adapters
@@ -172,6 +176,7 @@ void VideoBackend::Video_Prepare()
g_vertex_manager = new VertexManager;
g_renderer = new Renderer;
g_texture_cache = new TextureCache;
+ g_perf_query = new PerfQueryBase;
// VideoCommon
BPInit();
Fifo_Init();
@@ -191,6 +196,7 @@ void VideoBackend::Shutdown()
{
s_BackendInitialized = false;
+ // TODO: should be in Video_Cleanup
if (g_renderer)
{
s_efbAccessRequested = FALSE;
@@ -209,6 +215,7 @@ void VideoBackend::Shutdown()
// internal interfaces
PixelShaderCache::Shutdown();
VertexShaderCache::Shutdown();
+ delete g_perf_query;
delete g_texture_cache;
delete g_renderer;
delete g_vertex_manager;
@@ -218,4 +225,7 @@ void VideoBackend::Shutdown()
D3D::Shutdown();
}
+void VideoBackend::Video_Cleanup() {
+}
+
}
diff --git a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt
index 43b127f5ef..3d4e225932 100644
--- a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt
+++ b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt
@@ -2,10 +2,14 @@ set(SRCS Src/FramebufferManager.cpp
Src/GLUtil.cpp
Src/main.cpp
Src/NativeVertexFormat.cpp
+ Src/PerfQuery.cpp
Src/PixelShaderCache.cpp
Src/PostProcessing.cpp
+ Src/ProgramShaderCache.cpp
Src/RasterFont.cpp
Src/Render.cpp
+ Src/SamplerCache.cpp
+ Src/StreamBuffer.cpp
Src/TextureCache.cpp
Src/TextureConverter.cpp
Src/VertexShaderCache.cpp
@@ -33,12 +37,6 @@ if(wxWidgets_FOUND)
set(LIBS ${LIBS} ${wxWidgets_LIBRARIES})
endif(wxWidgets_FOUND)
-if(WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- set(LIBS ${LIBS} Cg CgGL)
-elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- list(APPEND LIBS "${CMAKE_SOURCE_DIR}/Externals/Cg/Cg.framework")
-endif()
-
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(LIBS ${LIBS} clrun)
endif()
diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj
index d74bc2edb5..403aac2c30 100644
--- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj
+++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj
@@ -121,8 +121,8 @@
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -133,8 +133,8 @@
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -147,8 +147,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -161,8 +161,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -175,8 +175,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -189,8 +189,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -200,10 +200,14 @@
<ClCompile Include="Src\GLUtil.cpp" />
<ClCompile Include="Src\main.cpp" />
<ClCompile Include="Src\NativeVertexFormat.cpp" />
+ <ClCompile Include="Src\PerfQuery.cpp" />
<ClCompile Include="Src\PixelShaderCache.cpp" />
<ClCompile Include="Src\PostProcessing.cpp" />
+ <ClCompile Include="Src\ProgramShaderCache.cpp" />
<ClCompile Include="Src\RasterFont.cpp" />
<ClCompile Include="Src\Render.cpp" />
+ <ClCompile Include="Src\SamplerCache.cpp" />
+ <ClCompile Include="Src\StreamBuffer.cpp" />
<ClCompile Include="Src\stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
@@ -222,15 +226,17 @@
<ClInclude Include="Src\Globals.h" />
<ClInclude Include="Src\GLUtil.h" />
<ClInclude Include="Src\main.h" />
- <ClInclude Include="Src\PixelShaderCache.h" />
+ <ClInclude Include="Src\PerfQuery.h" />
<ClInclude Include="Src\PostProcessing.h" />
+ <ClInclude Include="Src\ProgramShaderCache.h" />
<ClInclude Include="Src\RasterFont.h" />
<ClInclude Include="Src\Render.h" />
+ <ClInclude Include="Src\SamplerCache.h" />
+ <ClInclude Include="Src\StreamBuffer.h" />
<ClInclude Include="Src\stdafx.h" />
<ClInclude Include="Src\TextureCache.h" />
<ClInclude Include="Src\TextureConverter.h" />
<ClInclude Include="Src\VertexManager.h" />
- <ClInclude Include="Src\VertexShaderCache.h" />
<ClInclude Include="Src\VideoBackend.h" />
</ItemGroup>
<ItemGroup>
diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters
index cd170691da..a8b79d85ad 100644
--- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters
+++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters
@@ -27,15 +27,24 @@
<ClCompile Include="Src\PostProcessing.cpp">
<Filter>Render</Filter>
</ClCompile>
+ <ClCompile Include="Src\ProgramShaderCache.cpp">
+ <Filter>Render</Filter>
+ </ClCompile>
<ClCompile Include="Src\Render.cpp">
<Filter>Render</Filter>
</ClCompile>
+ <ClCompile Include="Src\StreamBuffer.cpp">
+ <Filter>Render</Filter>
+ </ClCompile>
<ClCompile Include="Src\TextureCache.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="Src\VertexShaderCache.cpp">
<Filter>Render</Filter>
</ClCompile>
+ <ClCompile Include="Src\PerfQuery.cpp">
+ <Filter>Render</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Src\Globals.h" />
@@ -57,10 +66,10 @@
<ClInclude Include="Src\FramebufferManager.h">
<Filter>Render</Filter>
</ClInclude>
- <ClInclude Include="Src\PixelShaderCache.h">
+ <ClInclude Include="Src\PostProcessing.h">
<Filter>Render</Filter>
</ClInclude>
- <ClInclude Include="Src\PostProcessing.h">
+ <ClInclude Include="Src\ProgramShaderCache.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="Src\Render.h">
@@ -69,7 +78,7 @@
<ClInclude Include="Src\TextureCache.h">
<Filter>Render</Filter>
</ClInclude>
- <ClInclude Include="Src\VertexShaderCache.h">
+ <ClInclude Include="Src\PerfQuery.h">
<Filter>Render</Filter>
</ClInclude>
</ItemGroup>
@@ -90,4 +99,4 @@
<UniqueIdentifier>{aaa16061-dca9-4155-be44-f77538e839fc}</UniqueIdentifier>
</Filter>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp
index 0e37c3adb6..27a88bf68a 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp
@@ -17,6 +17,7 @@
#include "Globals.h"
#include "FramebufferManager.h"
+#include "VertexShaderGen.h"
#include "TextureConverter.h"
#include "Render.h"
@@ -25,8 +26,6 @@
namespace OGL
{
-extern bool s_bHaveFramebufferBlit; // comes from Render.cpp. ugly.
-
int FramebufferManager::m_targetWidth;
int FramebufferManager::m_targetHeight;
int FramebufferManager::m_msaaSamples;
@@ -41,7 +40,7 @@ GLuint FramebufferManager::m_resolvedFramebuffer;
GLuint FramebufferManager::m_resolvedColorTexture;
GLuint FramebufferManager::m_resolvedDepthTexture;
-GLuint FramebufferManager::m_xfbFramebuffer; // Only used in MSAA mode
+GLuint FramebufferManager::m_xfbFramebuffer;
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
{
@@ -52,7 +51,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
m_resolvedColorTexture = 0;
m_resolvedDepthTexture = 0;
m_xfbFramebuffer = 0;
-
+
m_targetWidth = targetWidth;
m_targetHeight = targetHeight;
@@ -72,7 +71,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
// Create EFB target.
- glGenFramebuffersEXT(1, &m_efbFramebuffer);
+ glGenFramebuffers(1, &m_efbFramebuffer);
if (m_msaaSamples <= 1)
{
@@ -83,20 +82,20 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
m_efbColor = glObj[0];
m_efbDepth = glObj[1];
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbColor);
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_RECTANGLE, m_efbColor);
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbDepth);
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_RECTANGLE, m_efbDepth);
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+ glBindTexture(GL_TEXTURE_RECTANGLE, 0);
// Bind target textures to the EFB framebuffer.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, m_efbColor, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_RECTANGLE, m_efbDepth, 0);
GL_REPORT_FBO_ERROR();
}
@@ -109,67 +108,67 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
// Create EFB target renderbuffers.
GLuint glObj[2];
- glGenRenderbuffersEXT(2, glObj);
+ glGenRenderbuffers(2, glObj);
m_efbColor = glObj[0];
m_efbDepth = glObj[1];
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor);
+ glBindRenderbuffer(GL_RENDERBUFFER, m_efbColor);
if (m_msaaCoverageSamples)
- glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
+ glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
else
- glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth);
+ glBindRenderbuffer(GL_RENDERBUFFER, m_efbDepth);
if (m_msaaCoverageSamples)
- glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
+ glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
else
- glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
// Bind target renderbuffers to EFB framebuffer.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_efbColor);
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_efbDepth);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_efbColor);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_efbDepth);
GL_REPORT_FBO_ERROR();
// Create resolved targets for transferring multisampled EFB to texture.
- glGenFramebuffersEXT(1, &m_resolvedFramebuffer);
+ glGenFramebuffers(1, &m_resolvedFramebuffer);
glGenTextures(2, glObj);
m_resolvedColorTexture = glObj[0];
m_resolvedDepthTexture = glObj[1];
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture);
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_RECTANGLE, m_resolvedColorTexture);
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture);
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_RECTANGLE, m_resolvedDepthTexture);
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+ glBindTexture(GL_TEXTURE_RECTANGLE, 0);
// Bind resolved textures to resolved framebuffer.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, m_resolvedColorTexture, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_RECTANGLE, m_resolvedDepthTexture, 0);
GL_REPORT_FBO_ERROR();
// Return to EFB framebuffer.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
}
// Create XFB framebuffer; targets will be created elsewhere.
- glGenFramebuffersEXT(1, &m_xfbFramebuffer);
-
+ glGenFramebuffers(1, &m_xfbFramebuffer);
+
// EFB framebuffer is currently bound, make sure to clear its alpha value to 1.f
glViewport(0, 0, m_targetWidth, m_targetHeight);
glScissor(0, 0, m_targetWidth, m_targetHeight);
@@ -180,7 +179,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
FramebufferManager::~FramebufferManager()
{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLuint glObj[3];
@@ -189,7 +188,7 @@ FramebufferManager::~FramebufferManager()
glObj[0] = m_efbFramebuffer;
glObj[1] = m_resolvedFramebuffer;
glObj[2] = m_xfbFramebuffer;
- glDeleteFramebuffersEXT(3, glObj);
+ glDeleteFramebuffers(3, glObj);
m_efbFramebuffer = 0;
m_xfbFramebuffer = 0;
@@ -204,7 +203,7 @@ FramebufferManager::~FramebufferManager()
if (m_msaaSamples <= 1)
glDeleteTextures(2, glObj);
else
- glDeleteRenderbuffersEXT(2, glObj);
+ glDeleteRenderbuffers(2, glObj);
m_efbColor = 0;
m_efbDepth = 0;
}
@@ -224,16 +223,16 @@ GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
// Resolve.
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
- glBlitFramebufferEXT(
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer);
+ glBlitFramebuffer(
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
GL_COLOR_BUFFER_BIT, GL_NEAREST
);
// Return to EFB.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
return m_resolvedColorTexture;
}
@@ -254,16 +253,16 @@ GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc)
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
// Resolve.
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
- glBlitFramebufferEXT(
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer);
+ glBlitFramebuffer(
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
GL_DEPTH_BUFFER_BIT, GL_NEAREST
);
// Return to EFB.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
return m_resolvedDepthTexture;
}
@@ -284,7 +283,7 @@ void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, c
void FramebufferManager::SetFramebuffer(GLuint fb)
{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb != 0 ? fb : GetEFBFramebuffer());
+ glBindFramebuffer(GL_FRAMEBUFFER, fb != 0 ? fb : GetEFBFramebuffer());
}
// Apply AA if enabled
@@ -298,106 +297,60 @@ GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_r
return GetEFBDepthTexture(source_rect);
}
+XFBSource::~XFBSource()
+{
+ glDeleteRenderbuffers(1, &renderbuf);
+}
+
+
void XFBSource::Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const
{
// Texture map xfbSource->texture onto the main buffer
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
-
- glBegin(GL_QUADS);
- glTexCoord2f(sourcerc.left, sourcerc.bottom);
- glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0);
- glVertex2f(drawrc.left, drawrc.bottom);
-
- glTexCoord2f(sourcerc.left, sourcerc.top);
- glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1);
- glVertex2f(drawrc.left, drawrc.top);
-
- glTexCoord2f(sourcerc.right, sourcerc.top);
- glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1);
- glVertex2f(drawrc.right, drawrc.top);
-
- glTexCoord2f(sourcerc.right, sourcerc.bottom);
- glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0);
- glVertex2f(drawrc.right, drawrc.bottom);
- glEnd();
+ glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuf);
+ glBlitFramebuffer(sourcerc.left, sourcerc.bottom, sourcerc.right, sourcerc.top,
+ drawrc.left, drawrc.bottom, drawrc.right, drawrc.top,
+ GL_COLOR_BUFFER_BIT, GL_LINEAR);
GL_REPORT_ERRORD();
}
void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
{
- TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, texture);
+ TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, renderbuf);
}
void XFBSource::CopyEFB(float Gamma)
{
// Copy EFB data to XFB and restore render target again
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetEFBFramebuffer());
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer());
-#if 0
- if (m_msaaSamples <= 1)
-#else
- if (!s_bHaveFramebufferBlit)
-#endif
- {
- // Just copy the EFB directly.
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
- glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, texWidth, texHeight, 0);
+ // Bind texture.
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuf);
+ GL_REPORT_FBO_ERROR();
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- }
- else
- {
- // OpenGL cannot copy directly from a multisampled framebuffer, so use
- // EXT_framebuffer_blit.
-
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, FramebufferManager::GetXFBFramebuffer());
-
- // Bind texture.
- glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texture, 0);
- GL_REPORT_FBO_ERROR();
-
- glBlitFramebufferEXT(
- 0, 0, texWidth, texHeight,
- 0, 0, texWidth, texHeight,
- GL_COLOR_BUFFER_BIT, GL_NEAREST
- );
+ glBlitFramebuffer(
+ 0, 0, texWidth, texHeight,
+ 0, 0, texWidth, texHeight,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST
+ );
- // Unbind texture.
- glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
+ // Return to EFB.
+ FramebufferManager::SetFramebuffer(0);
- // Return to EFB.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
- }
}
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
{
- GLuint texture;
-
- glGenTextures(1, &texture);
+ GLuint renderbuf;
-#if 0// XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible.
- if (m_msaaSamples > 1)
-#else
- if (s_bHaveFramebufferBlit)
-#endif
- {
- // In MSAA mode, allocate the texture image here. In non-MSAA mode,
- // the image will be allocated by glCopyTexImage2D (later).
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, target_width, target_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- }
+ glGenRenderbuffers(1, &renderbuf);
+
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuf);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, target_width, target_height);
- return new XFBSource(texture);
+ return new XFBSource(renderbuf);
}
void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc)
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.h b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.h
index ffe3399705..2a7b20defd 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.h
@@ -57,15 +57,15 @@ namespace OGL {
struct XFBSource : public XFBSourceBase
{
- XFBSource(GLuint tex) : texture(tex) {}
- ~XFBSource() { glDeleteTextures(1, &texture); }
+ XFBSource(GLuint rbuf) : renderbuf(rbuf) {}
+ ~XFBSource();
void CopyEFB(float Gamma);
void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
void Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const;
- const GLuint texture;
+ const GLuint renderbuf;
};
class FramebufferManager : public FramebufferManagerBase
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
index 29a1b6a662..4f71fb4a7d 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
@@ -51,10 +51,10 @@ void VideoBackend::UpdateFPSDisplay(const char *text)
}
void InitInterface()
{
- #if defined(USE_EGL) && USE_EGL
+ #ifdef ANDROID
+ GLInterface = new cInterfaceBase;
+ #elif defined(USE_EGL) && USE_EGL
GLInterface = new cInterfaceEGL;
- #elif defined(USE_WX) && USE_WX
- GLInterface = new cInterfaceWX;
#elif defined(__APPLE__)
GLInterface = new cInterfaceAGL;
#elif defined(_WIN32)
@@ -70,14 +70,14 @@ GLuint OpenGL_CompileProgram ( const char* vertexShader, const char* fragmentSha
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
GLuint programID = glCreateProgram();
- GLint Result = GL_FALSE;
- char stringBuffer[1024];
- GLsizei stringBufferUsage = 0;
// compile vertex shader
glShaderSource(vertexShaderID, 1, &vertexShader, NULL);
glCompileShader(vertexShaderID);
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL)
+ GLint Result = GL_FALSE;
+ char stringBuffer[1024];
+ GLsizei stringBufferUsage = 0;
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderInfoLog(vertexShaderID, 1024, &stringBufferUsage, stringBuffer);
if(Result && stringBufferUsage) {
@@ -157,32 +157,26 @@ void OpenGL_ReportARBProgramError()
bool OpenGL_ReportFBOError(const char *function, const char *file, int line)
{
#ifndef USE_GLES
- unsigned int fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- if (fbo_status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ unsigned int fbo_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (fbo_status != GL_FRAMEBUFFER_COMPLETE)
{
- const char *error = "-";
+ const char *error = "unknown error";
switch (fbo_status)
{
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- error = "INCOMPLETE_ATTACHMENT_EXT";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- error = "INCOMPLETE_MISSING_ATTACHMENT_EXT";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- error = "INCOMPLETE_DIMENSIONS_EXT";
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ error = "INCOMPLETE_ATTACHMENT";
break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- error = "INCOMPLETE_FORMATS_EXT";
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ error = "INCOMPLETE_MISSING_ATTACHMENT";
break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- error = "INCOMPLETE_DRAW_BUFFER_EXT";
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+ error = "INCOMPLETE_DRAW_BUFFER";
break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- error = "INCOMPLETE_READ_BUFFER_EXT";
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+ error = "INCOMPLETE_READ_BUFFER";
break;
- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- error = "UNSUPPORTED_EXT";
+ case GL_FRAMEBUFFER_UNSUPPORTED:
+ error = "UNSUPPORTED";
break;
}
ERROR_LOG(VIDEO, "%s:%d: (%s) OpenGL FBO error - %s\n",
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h
index 09d38bb731..7ebe9b3b23 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h
@@ -63,26 +63,22 @@ bool OpenGL_ReportFBOError(const char *function, const char *file, int line);
#define GL_REPORT_FBO_ERROR() OpenGL_ReportFBOError(__FUNCTION__, __FILE__, __LINE__)
#define GL_REPORT_PROGRAM_ERROR() OpenGL_ReportARBProgramError()
#else
-#define GL_REPORT_ERROR() GL_NO_ERROR
+__forceinline GLenum GL_REPORT_ERROR() { return GL_NO_ERROR; }
#define GL_REPORT_ERRORD() (void)GL_NO_ERROR
#define GL_REPORT_FBO_ERROR() (void)true
#define GL_REPORT_PROGRAM_ERROR() (void)0
#endif
-#if defined __APPLE__ || defined __linux__ || defined _WIN32
-#include <Cg/cg.h>
-#include <Cg/cgGL.h>
-#define HAVE_CG 1
-extern CGcontext g_cgcontext;
-extern CGprofile g_cgvProf, g_cgfProf;
+// this should be removed in future, but as long as glsl is unstable, we should really read this messages
+#if defined(_DEBUG) || defined(DEBUGFAST)
+#define DEBUG_GLSL 1
+#else
+#define DEBUG_GLSL 0
#endif
-// XXX: Dual-source blending in OpenGL does not work correctly yet. To make it
-// work, we may need to use glBindFragDataLocation. To use that, we need to
-// use GLSL shaders across the whole pipeline. Yikes!
-//#define USE_DUAL_SOURCE_BLEND
-
-// TODO: should be removed if we use glsl a lot
-#define DEBUG_GLSL
+// Isn't defined if we aren't using GLEW 1.6
+#ifndef GL_ONE_MINUS_SRC1_ALPHA
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#endif
#endif // _GLINIT_H_
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp
index ae20649433..acfdb7ee2e 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp
@@ -17,56 +17,18 @@
#include "GLUtil.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "MemoryUtil.h"
+#include "ProgramShaderCache.h"
#include "VertexShaderGen.h"
#include "CPMemory.h"
#include "NativeVertexFormat.h"
#include "VertexManager.h"
-#define COMPILED_CODE_SIZE 4096
-
-// TODO: this guy is never initialized
-u32 s_prevcomponents; // previous state set
-/*
-#ifdef _WIN32
-#ifdef _M_IX86
-#define USE_JIT
-#endif
-#endif
-*/
-// Note the use of CallCdeclFunction3I etc.
-// This is a horrible hack that is necessary because in 64-bit mode, Opengl32.dll is based way, way above the 32-bit
-// address space that is within reach of a CALL, and just doing &fn gives us these high uncallable addresses. So we
-// want to grab the function pointers from the import table instead.
-
-// This problem does not apply to glew functions, only core opengl32 functions.
-
// Here's some global state. We only use this to keep track of what we've sent to the OpenGL state
// machine.
-#ifdef USE_JIT
-DECLARE_IMPORT(glNormalPointer);
-DECLARE_IMPORT(glVertexPointer);
-DECLARE_IMPORT(glColorPointer);
-DECLARE_IMPORT(glTexCoordPointer);
-#endif
-
-class GLVertexFormat : public NativeVertexFormat
-{
- u8 *m_compiledCode;
- PortableVertexDeclaration vtx_decl;
-
-public:
- GLVertexFormat();
- ~GLVertexFormat();
-
- virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
- virtual void SetupVertexPointers();
- virtual void EnableComponents(u32 components);
-};
-
namespace OGL
{
@@ -75,23 +37,14 @@ NativeVertexFormat* VertexManager::CreateNativeVertexFormat()
return new GLVertexFormat();
}
-}
-
GLVertexFormat::GLVertexFormat()
{
-#ifdef USE_JIT
- m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false);
- if (m_compiledCode)
- memset(m_compiledCode, 0, COMPILED_CODE_SIZE);
-#endif
+
}
GLVertexFormat::~GLVertexFormat()
{
-#ifdef USE_JIT
- FreeMemoryPages(m_compiledCode, COMPILED_CODE_SIZE);
- m_compiledCode = 0;
-#endif
+ glDeleteVertexArrays(1, &VAO);
}
inline GLuint VarToGL(VarType t)
@@ -104,183 +57,56 @@ inline GLuint VarToGL(VarType t)
void GLVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
{
- s_prevcomponents = 0;
-
- vertex_stride = _vtx_decl.stride;
- using namespace Gen;
+ this->vtx_decl = _vtx_decl;
+ vertex_stride = vtx_decl.stride;
// We will not allow vertex components causing uneven strides.
- if (_vtx_decl.stride & 3)
- PanicAlert("Uneven vertex stride: %i", _vtx_decl.stride);
-
-#ifdef USE_JIT
- Gen::XEmitter emit(m_compiledCode);
- // Alright, we have our vertex declaration. Compile some crazy code to set it quickly using GL.
- emit.ABI_EmitPrologue(6);
+ if (vertex_stride & 3)
+ PanicAlert("Uneven vertex stride: %i", vertex_stride);
- emit.CallCdeclFunction4_I(glVertexPointer, 3, GL_FLOAT, _vtx_decl.stride, 0);
-
- if (_vtx_decl.num_normals >= 1)
- {
- emit.CallCdeclFunction3_I(glNormalPointer, VarToGL(_vtx_decl.normal_gl_type), _vtx_decl.stride, _vtx_decl.normal_offset[0]);
- if (_vtx_decl.num_normals == 3) {
- emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM1_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[1]);
- emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM2_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[2]);
- }
- }
-
- for (int i = 0; i < 2; i++)
- {
- if (_vtx_decl.color_offset[i] != -1)
- {
- if (i == 0)
- emit.CallCdeclFunction4_I(glColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]);
- else
- emit.CallCdeclFunction4((void *)glSecondaryColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]);
- }
- }
-
- for (int i = 0; i < 8; i++)
- {
- if (_vtx_decl.texcoord_offset[i] != -1)
- {
- int id = GL_TEXTURE0 + i;
-#ifdef _M_X64
-#ifdef _MSC_VER
- emit.MOV(32, R(RCX), Imm32(id));
-#else
- emit.MOV(32, R(RDI), Imm32(id));
-#endif
-#else
- emit.ABI_AlignStack(1 * 4);
- emit.PUSH(32, Imm32(id));
-#endif
- emit.CALL((void *)glClientActiveTexture);
-#ifndef _M_X64
-#ifdef _WIN32
- // don't inc stack on windows, stdcall
-#else
- emit.ABI_RestoreStack(1 * 4);
-#endif
-#endif
- emit.CallCdeclFunction4_I(
- glTexCoordPointer, _vtx_decl.texcoord_size[i], VarToGL(_vtx_decl.texcoord_gl_type[i]),
- _vtx_decl.stride, _vtx_decl.texcoord_offset[i]);
- }
- }
-
- if (_vtx_decl.posmtx_offset != -1)
- emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, _vtx_decl.stride, _vtx_decl.posmtx_offset);
-
- emit.ABI_EmitEpilogue(6);
-
- if (emit.GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE)
- Crash();
-
-#endif
- this->vtx_decl = _vtx_decl;
-}
+ VertexManager *vm = (OGL::VertexManager*)g_vertex_manager;
+
+ glGenVertexArrays(1, &VAO);
+ glBindVertexArray(VAO);
+
+ // the element buffer is bound directly to the vao, so we must it set for every vao
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vm->m_index_buffers);
+ glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers);
-void GLVertexFormat::SetupVertexPointers() {
- // Cast a pointer to compiled code to a pointer to a function taking no parameters, through a (void *) cast first to
- // get around type checking errors, and call it.
-#ifdef USE_JIT
- ((void (*)())(void*)m_compiledCode)();
-#else
- glVertexPointer(3, GL_FLOAT, vtx_decl.stride, VertexManager::s_pBaseBufferPointer);
- if (vtx_decl.num_normals >= 1) {
- glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[0]));
- if (vtx_decl.num_normals == 3) {
- glVertexAttribPointer(SHADER_NORM1_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[1]));
- glVertexAttribPointer(SHADER_NORM2_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[2]));
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 3, GL_FLOAT, GL_FALSE, vtx_decl.stride, (u8*)NULL);
+
+ for (int i = 0; i < 3; i++) {
+ if (vtx_decl.num_normals > i) {
+ glEnableVertexAttribArray(SHADER_NORM0_ATTRIB+i);
+ glVertexAttribPointer(SHADER_NORM0_ATTRIB+i, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (u8*)NULL + vtx_decl.normal_offset[i]);
}
}
for (int i = 0; i < 2; i++) {
if (vtx_decl.color_offset[i] != -1) {
- if (i == 0)
- glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
- else {
- glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
- }
+ glEnableVertexAttribArray(SHADER_COLOR0_ATTRIB+i);
+ glVertexAttribPointer(SHADER_COLOR0_ATTRIB+i, 4, GL_UNSIGNED_BYTE, GL_TRUE, vtx_decl.stride, (u8*)NULL + vtx_decl.color_offset[i]);
}
}
for (int i = 0; i < 8; i++) {
if (vtx_decl.texcoord_offset[i] != -1) {
- int id = GL_TEXTURE0 + i;
- glClientActiveTexture(id);
- glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]),
- vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.texcoord_offset[i]));
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB+i);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB+i, vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]),
+ GL_FALSE, vtx_decl.stride, (u8*)NULL + vtx_decl.texcoord_offset[i]);
}
}
if (vtx_decl.posmtx_offset != -1) {
- glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.posmtx_offset));
+ glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB);
+ glVertexAttribIPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, vtx_decl.stride, (u8*)NULL + vtx_decl.posmtx_offset);
}
-#endif
-}
-
-void GLVertexFormat::EnableComponents(u32 components)
-{
- if (s_prevcomponents != components)
- {
- VertexManager::Flush();
- // matrices
- if ((components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX))
- {
- if (components & VB_HAS_POSMTXIDX)
- glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB);
- else
- glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB);
- }
-
- // normals
- if ((components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0))
- {
- if (components & VB_HAS_NRM0)
- glEnableClientState(GL_NORMAL_ARRAY);
- else
- glDisableClientState(GL_NORMAL_ARRAY);
- }
- if ((components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1))
- {
- if (components & VB_HAS_NRM1) {
- glEnableVertexAttribArray(SHADER_NORM1_ATTRIB);
- glEnableVertexAttribArray(SHADER_NORM2_ATTRIB);
- }
- else {
- glDisableVertexAttribArray(SHADER_NORM1_ATTRIB);
- glDisableVertexAttribArray(SHADER_NORM2_ATTRIB);
- }
- }
-
- // color
- for (int i = 0; i < 2; ++i)
- {
- if ((components & (VB_HAS_COL0 << i)) != (s_prevcomponents & (VB_HAS_COL0 << i)))
- {
- if (components & (VB_HAS_COL0 << i))
- glEnableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
- else
- glDisableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
- }
- }
+ vm->m_last_vao = VAO;
+}
- // tex
- for (int i = 0; i < 8; ++i)
- {
- if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i)))
- {
- glClientActiveTexture(GL_TEXTURE0 + i);
- if (components & (VB_HAS_UV0 << i))
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- else
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- }
- }
+void GLVertexFormat::SetupVertexPointers() {
+}
- s_prevcomponents = components;
- }
}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp
new file mode 100644
index 0000000000..db47217655
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp
@@ -0,0 +1,133 @@
+#include "RenderBase.h"
+#include "GLUtil.h"
+#include "PerfQuery.h"
+
+namespace OGL
+{
+
+PerfQuery::PerfQuery()
+ : m_query_read_pos()
+ , m_query_count()
+{
+ for (u32 i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
+ glGenQueries(1, &m_query_buffer[i].query_id);
+
+ ResetQuery();
+}
+
+PerfQuery::~PerfQuery()
+{
+ for (u32 i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
+ glDeleteQueries(1, &m_query_buffer[i].query_id);
+}
+
+void PerfQuery::EnableQuery(PerfQueryGroup type)
+{
+ // Is this sane?
+ if (m_query_count > ARRAYSIZE(m_query_buffer) / 2)
+ WeakFlush();
+
+ if (ARRAYSIZE(m_query_buffer) == m_query_count)
+ {
+ FlushOne();
+ //ERROR_LOG(VIDEO, "flushed query buffer early!");
+ }
+
+ // start query
+ if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
+ {
+ auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ARRAYSIZE(m_query_buffer)];
+
+ glBeginQuery(GL_SAMPLES_PASSED, entry.query_id);
+ entry.query_type = type;
+
+ ++m_query_count;
+ }
+}
+
+void PerfQuery::DisableQuery(PerfQueryGroup type)
+{
+ // stop query
+ if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
+ {
+ glEndQuery(GL_SAMPLES_PASSED);
+ }
+}
+
+bool PerfQuery::IsFlushed() const
+{
+ return 0 == m_query_count;
+}
+
+void PerfQuery::FlushOne()
+{
+ auto& entry = m_query_buffer[m_query_read_pos];
+
+ GLuint result = 0;
+ glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT, &result);
+
+ // NOTE: Reported pixel metrics should be referenced to native resolution
+ m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight();
+
+ m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer);
+ --m_query_count;
+}
+
+// TODO: could selectively flush things, but I don't think that will do much
+void PerfQuery::FlushResults()
+{
+ while (!IsFlushed())
+ FlushOne();
+}
+
+void PerfQuery::WeakFlush()
+{
+ while (!IsFlushed())
+ {
+ auto& entry = m_query_buffer[m_query_read_pos];
+
+ GLuint result = GL_FALSE;
+ glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT_AVAILABLE, &result);
+
+ if (GL_TRUE == result)
+ {
+ FlushOne();
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+void PerfQuery::ResetQuery()
+{
+ m_query_count = 0;
+ std::fill_n(m_results, ARRAYSIZE(m_results), 0);
+}
+
+u32 PerfQuery::GetQueryResult(PerfQueryType type)
+{
+ u32 result = 0;
+
+ if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC)
+ {
+ result = m_results[PQG_ZCOMP_ZCOMPLOC];
+ }
+ else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT)
+ {
+ result = m_results[PQG_ZCOMP];
+ }
+ else if (type == PQ_BLEND_INPUT)
+ {
+ result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC];
+ }
+ else if (type == PQ_EFB_COPY_CLOCKS)
+ {
+ result = m_results[PQG_EFB_COPY_CLOCKS];
+ }
+
+ return result / 4;
+}
+
+} // namespace
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h
new file mode 100644
index 0000000000..b96fe7a4a0
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h
@@ -0,0 +1,46 @@
+#ifndef _PERFQUERY_H_
+#define _PERFQUERY_H_
+
+#include "PerfQueryBase.h"
+
+namespace OGL {
+
+class PerfQuery : public PerfQueryBase
+{
+public:
+ PerfQuery();
+ ~PerfQuery();
+
+ void EnableQuery(PerfQueryGroup type);
+ void DisableQuery(PerfQueryGroup type);
+ void ResetQuery();
+ u32 GetQueryResult(PerfQueryType type);
+ void FlushResults();
+ bool IsFlushed() const;
+
+private:
+ struct ActiveQuery
+ {
+ GLuint query_id;
+ PerfQueryGroup query_type;
+ };
+
+ // when testing in SMS: 64 was too small, 128 was ok
+ static const u32 PERF_QUERY_BUFFER_SIZE = 512;
+
+ void WeakFlush();
+ // Only use when non-empty
+ void FlushOne();
+
+ // This contains gl query objects with unretrieved results.
+ ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE];
+ u32 m_query_read_pos;
+
+ // TODO: sloppy
+ volatile u32 m_query_count;
+ volatile u32 m_results[PQG_NUM_MEMBERS];
+};
+
+} // namespace
+
+#endif // _PERFQUERY_H_
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp
index 61e41008b3..1d3865851a 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp
@@ -27,346 +27,88 @@
#include "Common.h"
#include "Render.h"
#include "VertexShaderGen.h"
-#include "PixelShaderCache.h"
+#include "ProgramShaderCache.h"
#include "PixelShaderManager.h"
+#include "OnScreenDisplay.h"
+#include "StringUtil.h"
#include "FileUtil.h"
#include "Debugger.h"
namespace OGL
{
-static int s_nMaxPixelInstructions;
-static GLuint s_ColorMatrixProgram = 0;
-static GLuint s_DepthMatrixProgram = 0;
-PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
-PIXELSHADERUID PixelShaderCache::s_curuid;
-bool PixelShaderCache::s_displayCompileAlert;
-GLuint PixelShaderCache::CurrentShader;
-bool PixelShaderCache::ShaderEnabled;
-
-PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry = NULL;
-PIXELSHADERUID PixelShaderCache::last_uid;
-
-GLuint PixelShaderCache::GetDepthMatrixProgram()
-{
- return s_DepthMatrixProgram;
-}
-
-GLuint PixelShaderCache::GetColorMatrixProgram()
+void SetPSConstant4fvByName(const char * name, unsigned int offset, const float *f, const unsigned int count = 1)
{
- return s_ColorMatrixProgram;
-}
-
-void PixelShaderCache::Init()
-{
- glEnable(GL_FRAGMENT_PROGRAM_ARB);
- ShaderEnabled = true;
- CurrentShader = 0;
- last_entry = NULL;
- GL_REPORT_ERRORD();
-
- s_displayCompileAlert = true;
-
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions);
-
- if(s_nMaxPixelInstructions == 0) // Some combination of drivers and hardware returns zero for some reason.
- s_nMaxPixelInstructions = 4096;
- if (strstr((const char*)glGetString(GL_VENDOR), "Humper") != NULL) s_nMaxPixelInstructions = 4096;
-#if CG_VERSION_NUM == 2100
- if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
+ ProgramShaderCache::PCacheEntry tmp = ProgramShaderCache::GetShaderProgram();
+ for (int a = 0; a < NUM_UNIFORMS; ++a)
{
- s_nMaxPixelInstructions = 4096;
- }
-#endif
-
- int maxinst, maxattribs;
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&maxinst);
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, (GLint *)&maxattribs);
- INFO_LOG(VIDEO, "pixel max_alu=%d, max_inst=%d, max_attrib=%d", s_nMaxPixelInstructions, maxinst, maxattribs);
-
- char pmatrixprog[2048];
- sprintf(pmatrixprog, "!!ARBfp1.0"
- "TEMP R0;\n"
- "TEMP R1;\n"
- "PARAM K0 = { 0.5, 0.5, 0.5, 0.5};\n"
- "TEX R0, fragment.texcoord[0], texture[0], RECT;\n"
- "MUL R0, R0, program.env[%d];\n"
- "ADD R0, R0, K0;\n"
- "FLR R0, R0;\n"
- "MUL R0, R0, program.env[%d];\n"
- "DP4 R1.x, R0, program.env[%d];\n"
- "DP4 R1.y, R0, program.env[%d];\n"
- "DP4 R1.z, R0, program.env[%d];\n"
- "DP4 R1.w, R0, program.env[%d];\n"
- "ADD result.color, R1, program.env[%d];\n"
- "END\n",C_COLORMATRIX+5,C_COLORMATRIX+6, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+2, C_COLORMATRIX+3, C_COLORMATRIX+4);
- glGenProgramsARB(1, &s_ColorMatrixProgram);
- SetCurrentShader(s_ColorMatrixProgram);
- glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);
-
- GLenum err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR) {
- ERROR_LOG(VIDEO, "Failed to create color matrix fragment program");
- glDeleteProgramsARB(1, &s_ColorMatrixProgram);
- s_ColorMatrixProgram = 0;
- }
-
- sprintf(pmatrixprog, "!!ARBfp1.0\n"
- "TEMP R0;\n"
- "TEMP R1;\n"
- "TEMP R2;\n"
- //16777215/16777216*256, 1/255, 256, 0
- "PARAM K0 = { 255.99998474121, 0.003921568627451, 256.0, 0.0};\n"
- "PARAM K1 = { 15.0, 0.066666666666, 0.0, 0.0};\n"
- //sample the depth value
- "TEX R2, fragment.texcoord[0], texture[0], RECT;\n"
-
- //scale from [0*16777216..1*16777216] to
- //[0*16777215..1*16777215], multiply by 256
- "MUL R0, R2.x, K0.x;\n" // *16777215/16777216*256
-
- //It is easy to get bad results due to low precision
- //here, for example converting like this:
- //MUL R0,R0,{ 65536, 256, 1, 16777216 }
- //FRC R0,R0
- //gives {?, 128/255, 254/255, ?} for depth value 254/255
- //on some gpus
-
- "FLR R0.x,R0;\n" //bits 31..24
-
- "SUB R0.yzw,R0,R0.x;\n" //subtract bits 31..24 from rest
- "MUL R0.yzw,R0,K0.z;\n" // *256
- "FLR R0.y,R0;\n" //bits 23..16
-
- "SUB R0.zw,R0,R0.y;\n" //subtract bits 23..16 from rest
- "MUL R0.zw,R0,K0.z;\n" // *256
- "FLR R0.z,R0;\n" //bits 15..8
-
- "MOV R0.w,R0.x;\n" //duplicate bit 31..24
-
- "MUL R0,R0,K0.y;\n" // /255
-
- "MUL R0.w,R0,K1.x;\n" // *15
- "FLR R0.w,R0;\n" //bits 31..28
- "MUL R0.w,R0,K1.y;\n" // /15
-
- "DP4 R1.x, R0, program.env[%d];\n"
- "DP4 R1.y, R0, program.env[%d];\n"
- "DP4 R1.z, R0, program.env[%d];\n"
- "DP4 R1.w, R0, program.env[%d];\n"
- "ADD result.color, R1, program.env[%d];\n"
- "END\n", C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+2, C_COLORMATRIX+3, C_COLORMATRIX+4);
- glGenProgramsARB(1, &s_DepthMatrixProgram);
- SetCurrentShader(s_DepthMatrixProgram);
- glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);
-
- err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR) {
- ERROR_LOG(VIDEO, "Failed to create depth matrix fragment program");
- glDeleteProgramsARB(1, &s_DepthMatrixProgram);
- s_DepthMatrixProgram = 0;
- }
-
-}
-
-void PixelShaderCache::Shutdown()
-{
- glDeleteProgramsARB(1, &s_ColorMatrixProgram);
- s_ColorMatrixProgram = 0;
- glDeleteProgramsARB(1, &s_DepthMatrixProgram);
- s_DepthMatrixProgram = 0;
- PSCache::iterator iter = PixelShaders.begin();
- for (; iter != PixelShaders.end(); iter++)
- iter->second.Destroy();
- PixelShaders.clear();
-}
-
-FRAGMENTSHADER* PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
-{
- PIXELSHADERUID uid;
- GetPixelShaderId(&uid, dstAlphaMode, components);
-
- // Check if the shader is already set
- if (last_entry)
- {
- if (uid == last_uid)
+ if (!strcmp(name, UniformNames[a]))
{
- GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
- ValidatePixelShaderIDs(API_OPENGL, last_entry->safe_uid, last_entry->shader.strprog, dstAlphaMode, components);
- return &last_entry->shader;
+ if (tmp.shader.UniformLocations[a] == -1)
+ return;
+ else
+ {
+ glUniform4fv(tmp.shader.UniformLocations[a] + offset, count, f);
+ return;
+ }
}
}
-
- last_uid = uid;
-
- PSCache::iterator iter = PixelShaders.find(uid);
- if (iter != PixelShaders.end())
- {
- PSCacheEntry &entry = iter->second;
- last_entry = &entry;
-
- GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
- ValidatePixelShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, dstAlphaMode, components);
- return &last_entry->shader;
- }
-
- // Make an entry in the table
- PSCacheEntry& newentry = PixelShaders[uid];
- last_entry = &newentry;
- const char *code = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components);
-
- if (g_ActiveConfig.bEnableShaderDebugging && code)
- {
- GetSafePixelShaderId(&newentry.safe_uid, dstAlphaMode, components);
- newentry.shader.strprog = code;
- }
-
-#if defined(_DEBUG) || defined(DEBUGFAST)
- if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
- static int counter = 0;
- char szTemp[MAX_PATH];
- sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
-
- SaveData(szTemp, code);
- }
-#endif
-
- if (!code || !CompilePixelShader(newentry.shader, code)) {
- GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
- return NULL;
- }
-
- INCSTAT(stats.numPixelShadersCreated);
- SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
- GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
- return &last_entry->shader;
}
-bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
+// Renderer functions
+void Renderer::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{
- GLenum err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR)
- {
- ERROR_LOG(VIDEO, "glError %08x before PS!", err);
- }
-
-#if defined HAVE_CG && HAVE_CG
- char stropt[128];
- sprintf(stropt, "MaxLocalParams=224,NumInstructionSlots=%d", s_nMaxPixelInstructions);
- const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
- CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
+ float const f[4] = {f1, f2, f3, f4};
- // handle errors
- if (!cgIsProgram(tempprog))
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- cgDestroyProgram(tempprog);
-
- static int num_failures = 0;
- char szTemp[MAX_PATH];
- sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
- file << pstrprogram;
- file.close();
-
- PanicAlert("Failed to compile pixel shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%d):\n%s",
- szTemp,
- g_cgfProf,
- cgGetLastListing(g_cgcontext));
-
- return false;
+ ProgramShaderCache::SetMultiPSConstant4fv(const_number, f, 1);
+ return;
}
-
- // handle warnings
- if (cgGetError() != CG_NO_ERROR)
+ for (unsigned int a = 0; a < 10; ++a)
{
- WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext));
- WARN_LOG(VIDEO, "%s", pstrprogram);
+ if (const_number >= PSVar_Loc[a].reg && const_number < (PSVar_Loc[a].reg + PSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - PSVar_Loc[a].reg;
+ SetPSConstant4fvByName(PSVar_Loc[a].name, offset, f);
+ return;
+ }
}
+}
- // This looks evil - we modify the program through the const char * we got from cgGetProgramString!
- // It SHOULD not have any nasty side effects though - but you never know...
- char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
- char *plocal = strstr(pcompiledprog, "program.local");
- while (plocal != NULL)
+void Renderer::SetPSConstant4fv(unsigned int const_number, const float *f)
+{
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- const char *penv = " program.env";
- memcpy(plocal, penv, 13);
- plocal = strstr(plocal+13, "program.local");
+ ProgramShaderCache::SetMultiPSConstant4fv(const_number, f, 1);
+ return;
}
-
- glGenProgramsARB(1, &ps.glprogid);
- SetCurrentShader(ps.glprogid);
- glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
-
- err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR)
+ for (unsigned int a = 0; a < 10; ++a)
{
- GLint error_pos, native_limit;
- glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native_limit);
- // Error occur
- if (error_pos != -1) {
- const char *program_error = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
- char line[256];
- strncpy(line, (const char *)pcompiledprog + error_pos, 255);
- line[255] = 0;
- ERROR_LOG(VIDEO, "Error at %i: %s", error_pos, program_error);
- ERROR_LOG(VIDEO, "Line dump: \n%s", line);
- } else if (native_limit != -1) {
- ERROR_LOG(VIDEO, "Hit limit? %i", native_limit);
- // TODO
+ if (const_number >= PSVar_Loc[a].reg && const_number < (PSVar_Loc[a].reg + PSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - PSVar_Loc[a].reg;
+ SetPSConstant4fvByName(PSVar_Loc[a].name, offset, f);
+ return;
}
- ERROR_LOG(VIDEO, "%s", pstrprogram);
- ERROR_LOG(VIDEO, "%s", pcompiledprog);
}
-
- cgDestroyProgram(tempprog);
-#endif
-
- return true;
}
-//Disable Fragment programs and reset the selected Program
-void PixelShaderCache::DisableShader()
-{
- if(ShaderEnabled)
- {
- glDisable(GL_FRAGMENT_PROGRAM_ARB);
- ShaderEnabled = false;
- }
-}
-
-//bind a program if is diferent from the binded oone
-void PixelShaderCache::SetCurrentShader(GLuint Shader)
+void Renderer::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{
- if(!ShaderEnabled)
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- glEnable(GL_FRAGMENT_PROGRAM_ARB);
- ShaderEnabled = true;
+ ProgramShaderCache::SetMultiPSConstant4fv(const_number, f, count);
+ return;
}
- if(CurrentShader != Shader)
+ for (unsigned int a = 0; a < 10; ++a)
{
- if(Shader != 0)
- CurrentShader = Shader;
- glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, CurrentShader);
+ if (const_number >= PSVar_Loc[a].reg && const_number < (PSVar_Loc[a].reg + PSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - PSVar_Loc[a].reg;
+ SetPSConstant4fvByName(PSVar_Loc[a].name, offset, f, count);
+ return;
+ }
}
}
-
-void Renderer::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
-{
- float f[4] = { f1, f2, f3, f4 };
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
-}
-
-void Renderer::SetPSConstant4fv(unsigned int const_number, const float *f)
-{
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
-}
-
-void Renderer::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
-{
- for (unsigned int i = 0; i < count; i++,f+=4)
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number + i, f);
-}
-
} // namespace OGL
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h
deleted file mode 100644
index f528eeb35b..0000000000
--- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (C) 2003 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#ifndef _PIXELSHADERCACHE_H_
-#define _PIXELSHADERCACHE_H_
-
-#include <map>
-#include <string>
-
-#include "BPMemory.h"
-#include "PixelShaderGen.h"
-
-namespace OGL
-{
-
-struct FRAGMENTSHADER
-{
- FRAGMENTSHADER() : glprogid(0) { }
- void Destroy()
- {
- if (glprogid)
- {
- glDeleteProgramsARB(1, &glprogid);
- glprogid = 0;
- }
- }
- GLuint glprogid; // opengl program id
- std::string strprog;
-};
-
-class PixelShaderCache
-{
- struct PSCacheEntry
- {
- FRAGMENTSHADER shader;
- PSCacheEntry() {}
- ~PSCacheEntry() {}
- void Destroy()
- {
- shader.Destroy();
- }
- PIXELSHADERUIDSAFE safe_uid;
- };
-
- typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
-
- static PSCache PixelShaders;
-
- static PIXELSHADERUID s_curuid; // the current pixel shader uid (progressively changed as memory is written)
-
- static bool s_displayCompileAlert;
-
- static GLuint CurrentShader;
- static PSCacheEntry* last_entry;
- static PIXELSHADERUID last_uid;
-
- static bool ShaderEnabled;
-
-public:
- static void Init();
- static void Shutdown();
-
- static FRAGMENTSHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 components);
- static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram);
-
- static GLuint GetColorMatrixProgram();
-
- static GLuint GetDepthMatrixProgram();
-
- static void SetCurrentShader(GLuint Shader);
-
- static void DisableShader();
-};
-
-} // namespace OGL
-
-#endif // _PIXELSHADERCACHE_H_
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp
index 7442e5d294..9a3e0b9bed 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp
@@ -20,7 +20,8 @@
#include "VideoConfig.h"
#include "GLUtil.h"
#include "PostProcessing.h"
-#include "PixelShaderCache.h"
+#include "ProgramShaderCache.h"
+#include "FramebufferManager.h"
namespace OGL
{
@@ -29,16 +30,72 @@ namespace PostProcessing
{
static std::string s_currentShader;
-static FRAGMENTSHADER s_shader;
+static SHADER s_shader;
+static bool s_enable;
+
+static u32 s_width;
+static u32 s_height;
+static GLuint s_fbo;
+static GLuint s_texture;
+static GLuint s_vao;
+static GLuint s_vbo;
+
+static GLuint s_uniform_resolution;
+
+static char s_vertex_shader[] =
+ "in vec2 rawpos;\n"
+ "in vec2 tex0;\n"
+ "out vec2 uv0;\n"
+ "void main(void) {\n"
+ " gl_Position = vec4(rawpos,0,1);\n"
+ " uv0 = tex0;\n"
+ "}\n";
void Init()
{
s_currentShader = "";
+ s_enable = 0;
+ s_width = 0;
+ s_height = 0;
+
+ glGenFramebuffers(1, &s_fbo);
+ glGenTextures(1, &s_texture);
+ glBindTexture(GL_TEXTURE_2D, s_texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); // disable mipmaps
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glBindFramebuffer(GL_FRAMEBUFFER, s_fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, s_texture, 0);
+ FramebufferManager::SetFramebuffer(0);
+
+ glGenBuffers(1, &s_vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, s_vbo);
+ GLfloat vertices[] = {
+ -1.f, -1.f, 0.f, 0.f,
+ -1.f, 1.f, 0.f, 1.f,
+ 1.f, -1.f, 1.f, 0.f,
+ 1.f, 1.f, 1.f, 1.f
+ };
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+ glGenVertexArrays(1, &s_vao);
+ glBindVertexArray( s_vao );
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, NULL);
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
}
void Shutdown()
{
s_shader.Destroy();
+
+ glDeleteFramebuffers(1, &s_vbo);
+ glDeleteTextures(1, &s_texture);
+
+ glDeleteBuffers(1, &s_vbo);
+ glDeleteVertexArrays(1, &s_vao);
}
void ReloadShader()
@@ -46,45 +103,83 @@ void ReloadShader()
s_currentShader = "";
}
-bool ApplyShader()
+void BindTargetFramebuffer ()
{
- if (s_currentShader != File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt")
- {
- // Set immediately to prevent endless recompiles on failure.
- if (!g_ActiveConfig.sPostProcessingShader.empty())
- s_currentShader = File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt";
- else
- s_currentShader.clear();
-
- s_shader.Destroy();
-
- if (!s_currentShader.empty())
- {
- std::string code;
- if (File::ReadFileToString(true, s_currentShader.c_str(), code))
- {
- if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str()))
- {
- ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
- }
- }
- else
- {
- ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
- }
- }
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, s_enable ? s_fbo : 0);
+}
+
+void BlitToScreen()
+{
+ if(!s_enable) return;
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ glViewport(0, 0, s_width, s_height);
+
+ glBindVertexArray(s_vao);
+ s_shader.Bind();
+
+ glUniform4f(s_uniform_resolution, (float)s_width, (float)s_height, 1.0f/(float)s_width, 1.0f/(float)s_height);
+
+ glActiveTexture(GL_TEXTURE0+9);
+ glBindTexture(GL_TEXTURE_2D, s_texture);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+/* glBindFramebuffer(GL_READ_FRAMEBUFFER, s_fbo);
+
+ glBlitFramebuffer(rc.left, rc.bottom, rc.right, rc.top,
+ rc.left, rc.bottom, rc.right, rc.top,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);*/
+}
+
+void Update ( u32 width, u32 height )
+{
+ ApplyShader();
+
+ if(s_enable && (width != s_width || height != s_height)) {
+ s_width = width;
+ s_height = height;
+
+ // alloc texture for framebuffer
+ glActiveTexture(GL_TEXTURE0+9);
+ glBindTexture(GL_TEXTURE_2D, s_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
+}
- if (s_shader.glprogid != 0)
- {
- PixelShaderCache::SetCurrentShader(s_shader.glprogid);
- return true;
+void ApplyShader()
+{
+ // shader didn't changed
+ if (s_currentShader == g_ActiveConfig.sPostProcessingShader) return;
+ s_currentShader = g_ActiveConfig.sPostProcessingShader;
+ s_enable = false;
+ s_shader.Destroy();
+
+ // shader disabled
+ if (g_ActiveConfig.sPostProcessingShader == "") return;
+
+ // so need to compile shader
+
+ // loading shader code
+ std::string code;
+ std::string path = File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt";
+ if(!File::ReadFileToString(true, path.c_str(), code)) {
+ ERROR_LOG(VIDEO, "post-processing shader not found: %s", path.c_str());
+ return;
}
- else
- {
- PixelShaderCache::DisableShader();
- return false;
+
+ // and compile it
+ if (!ProgramShaderCache::CompileShader(s_shader, s_vertex_shader, code.c_str())) {
+ ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
+ return;
}
+
+ // read uniform locations
+ s_uniform_resolution = glGetUniformLocation(s_shader.glprogid, "resolution");
+
+ // successful
+ s_enable = true;
}
} // namespace
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.h b/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.h
index 5d667e2b0a..10a30d9e27 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.h
@@ -30,9 +30,13 @@ namespace PostProcessing
void Init();
void Shutdown();
+void BindTargetFramebuffer();
+void BlitToScreen();
+void Update(u32 width, u32 height);
+
void ReloadShader();
-// Returns false if no shader was applied.
-bool ApplyShader();
+
+void ApplyShader();
} // namespace
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp
new file mode 100644
index 0000000000..4c516853d7
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp
@@ -0,0 +1,553 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "ProgramShaderCache.h"
+#include "MathUtil.h"
+#include "StreamBuffer.h"
+#include "Debugger.h"
+#include "Statistics.h"
+#include "ImageWrite.h"
+#include "Render.h"
+
+namespace OGL
+{
+
+static const u32 UBO_LENGTH = 32*1024*1024;
+
+GLintptr ProgramShaderCache::s_vs_data_size;
+GLintptr ProgramShaderCache::s_ps_data_size;
+GLintptr ProgramShaderCache::s_vs_data_offset;
+u8 *ProgramShaderCache::s_ubo_buffer;
+u32 ProgramShaderCache::s_ubo_buffer_size;
+bool ProgramShaderCache::s_ubo_dirty;
+
+static StreamBuffer *s_buffer;
+
+LinearDiskCache<SHADERUID, u8> g_program_disk_cache;
+static GLuint CurrentProgram = 0;
+ProgramShaderCache::PCache ProgramShaderCache::pshaders;
+ProgramShaderCache::PCacheEntry* ProgramShaderCache::last_entry;
+SHADERUID ProgramShaderCache::last_uid;
+
+static char s_glsl_header[1024] = "";
+
+const char *UniformNames[NUM_UNIFORMS] =
+{
+ // PIXEL SHADER UNIFORMS
+ I_COLORS,
+ I_KCOLORS,
+ I_ALPHA,
+ I_TEXDIMS,
+ I_ZBIAS ,
+ I_INDTEXSCALE ,
+ I_INDTEXMTX,
+ I_FOG,
+ I_PLIGHTS,
+ I_PMATERIALS,
+ // VERTEX SHADER UNIFORMS
+ I_POSNORMALMATRIX,
+ I_PROJECTION ,
+ I_MATERIALS,
+ I_LIGHTS,
+ I_TEXMATRICES,
+ I_TRANSFORMMATRICES ,
+ I_NORMALMATRICES ,
+ I_POSTTRANSFORMMATRICES,
+ I_DEPTHPARAMS,
+};
+
+void SHADER::SetProgramVariables()
+{
+ // glsl shader must be bind to set samplers
+ Bind();
+
+ // Bind UBO
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ {
+ GLint PSBlock_id = glGetUniformBlockIndex(glprogid, "PSBlock");
+ GLint VSBlock_id = glGetUniformBlockIndex(glprogid, "VSBlock");
+
+ if(PSBlock_id != -1)
+ glUniformBlockBinding(glprogid, PSBlock_id, 1);
+ if(VSBlock_id != -1)
+ glUniformBlockBinding(glprogid, VSBlock_id, 2);
+ }
+
+ // We cache our uniform locations for now
+ // Once we move up to a newer version of GLSL, ~1.30
+ // We can remove this
+
+ // (Sonicadvance): For some reason this fails on my hardware
+ //glGetUniformIndices(glprogid, NUM_UNIFORMS, UniformNames, UniformLocations);
+ // Got to do it this crappy way.
+ UniformLocations[0] = glGetUniformLocation(glprogid, UniformNames[0]);
+ if (!g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ for (int a = 1; a < NUM_UNIFORMS; ++a)
+ UniformLocations[a] = glGetUniformLocation(glprogid, UniformNames[a]);
+
+ // Bind Texture Sampler
+ for (int a = 0; a <= 9; ++a)
+ {
+ char name[8];
+ snprintf(name, 8, "samp%d", a);
+
+ // Still need to get sampler locations since we aren't binding them statically in the shaders
+ int loc = glGetUniformLocation(glprogid, name);
+ if (loc != -1)
+ glUniform1i(loc, a);
+ }
+
+}
+
+void SHADER::SetProgramBindings()
+{
+ if (g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
+ {
+ // So we do support extended blending
+ // So we need to set a few more things here.
+ // Bind our out locations
+ glBindFragDataLocationIndexed(glprogid, 0, 0, "ocol0");
+ glBindFragDataLocationIndexed(glprogid, 0, 1, "ocol1");
+ }
+ else
+ glBindFragDataLocation(glprogid, 0, "ocol0");
+
+ // Need to set some attribute locations
+ glBindAttribLocation(glprogid, SHADER_POSITION_ATTRIB, "rawpos");
+
+ glBindAttribLocation(glprogid, SHADER_POSMTX_ATTRIB, "fposmtx");
+
+ glBindAttribLocation(glprogid, SHADER_COLOR0_ATTRIB, "color0");
+ glBindAttribLocation(glprogid, SHADER_COLOR1_ATTRIB, "color1");
+
+ glBindAttribLocation(glprogid, SHADER_NORM0_ATTRIB, "rawnorm0");
+ glBindAttribLocation(glprogid, SHADER_NORM1_ATTRIB, "rawnorm1");
+ glBindAttribLocation(glprogid, SHADER_NORM2_ATTRIB, "rawnorm2");
+
+ for(int i=0; i<8; i++) {
+ char attrib_name[8];
+ snprintf(attrib_name, 8, "tex%d", i);
+ glBindAttribLocation(glprogid, SHADER_TEXTURE0_ATTRIB+i, attrib_name);
+ }
+}
+
+void SHADER::Bind()
+{
+ if(CurrentProgram != glprogid)
+ {
+ glUseProgram(glprogid);
+ CurrentProgram = glprogid;
+ }
+}
+
+
+void ProgramShaderCache::SetMultiPSConstant4fv(unsigned int offset, const float *f, unsigned int count)
+{
+ s_ubo_dirty = true;
+ memcpy(s_ubo_buffer+(offset*4*sizeof(float)), f, count*4*sizeof(float));
+}
+
+void ProgramShaderCache::SetMultiVSConstant4fv(unsigned int offset, const float *f, unsigned int count)
+{
+ s_ubo_dirty = true;
+ memcpy(s_ubo_buffer+(offset*4*sizeof(float))+s_vs_data_offset, f, count*4*sizeof(float));
+}
+
+void ProgramShaderCache::UploadConstants()
+{
+ if(s_ubo_dirty) {
+ s_buffer->Alloc(s_ubo_buffer_size);
+ size_t offset = s_buffer->Upload(s_ubo_buffer, s_ubo_buffer_size);
+ glBindBufferRange(GL_UNIFORM_BUFFER, 1, s_buffer->getBuffer(), offset, s_ps_data_size);
+ glBindBufferRange(GL_UNIFORM_BUFFER, 2, s_buffer->getBuffer(), offset + s_vs_data_offset, s_vs_data_size);
+ s_ubo_dirty = false;
+ }
+}
+
+GLuint ProgramShaderCache::GetCurrentProgram(void)
+{
+ return CurrentProgram;
+}
+
+SHADER* ProgramShaderCache::SetShader ( DSTALPHA_MODE dstAlphaMode, u32 components )
+{
+ SHADERUID uid;
+ GetShaderId(&uid, dstAlphaMode, components);
+
+ // Check if the shader is already set
+ if (last_entry)
+ {
+ if (uid == last_uid)
+ {
+ GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
+ ValidateShaderIDs(last_entry, dstAlphaMode, components);
+ last_entry->shader.Bind();
+ return &last_entry->shader;
+ }
+ }
+
+ last_uid = uid;
+
+ // Check if shader is already in cache
+ PCache::iterator iter = pshaders.find(uid);
+ if (iter != pshaders.end())
+ {
+ PCacheEntry *entry = &iter->second;
+ last_entry = entry;
+
+ GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
+ ValidateShaderIDs(entry, dstAlphaMode, components);
+ last_entry->shader.Bind();
+ return &last_entry->shader;
+ }
+
+ // Make an entry in the table
+ PCacheEntry& newentry = pshaders[uid];
+ last_entry = &newentry;
+ newentry.in_cache = 0;
+
+ const char *vcode = GenerateVertexShaderCode(components, API_OPENGL);
+ const char *pcode = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components);
+
+ if (g_ActiveConfig.bEnableShaderDebugging)
+ {
+ GetSafeShaderId(&newentry.safe_uid, dstAlphaMode, components);
+ newentry.shader.strvprog = vcode;
+ newentry.shader.strpprog = pcode;
+ }
+
+#if defined(_DEBUG) || defined(DEBUGFAST)
+ if (g_ActiveConfig.iLog & CONF_SAVESHADERS) {
+ static int counter = 0;
+ char szTemp[MAX_PATH];
+ sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
+ SaveData(szTemp, vcode);
+ sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
+ SaveData(szTemp, pcode);
+ }
+#endif
+
+ if (!CompileShader(newentry.shader, vcode, pcode)) {
+ GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
+ return NULL;
+ }
+
+ INCSTAT(stats.numPixelShadersCreated);
+ SETSTAT(stats.numPixelShadersAlive, pshaders.size());
+ GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
+
+ last_entry->shader.Bind();
+ return &last_entry->shader;
+}
+
+bool ProgramShaderCache::CompileShader ( SHADER& shader, const char* vcode, const char* pcode )
+{
+ GLuint vsid = CompileSingleShader(GL_VERTEX_SHADER, vcode);
+ GLuint psid = CompileSingleShader(GL_FRAGMENT_SHADER, pcode);
+
+ if(!vsid || !psid)
+ {
+ glDeleteShader(vsid);
+ glDeleteShader(psid);
+ return false;
+ }
+
+ GLuint pid = shader.glprogid = glCreateProgram();;
+
+ glAttachShader(pid, vsid);
+ glAttachShader(pid, psid);
+
+ if (g_ogl_config.bSupportsGLSLCache)
+ glProgramParameteri(pid, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
+
+ shader.SetProgramBindings();
+
+ glLinkProgram(pid);
+
+ // original shaders aren't needed any more
+ glDeleteShader(vsid);
+ glDeleteShader(psid);
+
+ GLint linkStatus;
+ glGetProgramiv(pid, GL_LINK_STATUS, &linkStatus);
+ GLsizei length = 0;
+ glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &length);
+ if (linkStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
+ {
+ GLsizei charsWritten;
+ GLchar* infoLog = new GLchar[length];
+ glGetProgramInfoLog(pid, length, &charsWritten, infoLog);
+ ERROR_LOG(VIDEO, "Program info log:\n%s", infoLog);
+ char szTemp[MAX_PATH];
+ sprintf(szTemp, "%sp_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), pid);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
+ file << infoLog << s_glsl_header << vcode << s_glsl_header << pcode;
+ file.close();
+ delete [] infoLog;
+ }
+ if (linkStatus != GL_TRUE)
+ {
+ // Compile failed
+ ERROR_LOG(VIDEO, "Program linking failed; see info log");
+
+ // Don't try to use this shader
+ glDeleteProgram(pid);
+ return false;
+ }
+
+ shader.SetProgramVariables();
+
+ return true;
+}
+
+GLuint ProgramShaderCache::CompileSingleShader (GLuint type, const char* code )
+{
+ GLuint result = glCreateShader(type);
+
+ const char *src[] = {s_glsl_header, code};
+
+ glShaderSource(result, 2, src, NULL);
+ glCompileShader(result);
+ GLint compileStatus;
+ glGetShaderiv(result, GL_COMPILE_STATUS, &compileStatus);
+ GLsizei length = 0;
+ glGetShaderiv(result, GL_INFO_LOG_LENGTH, &length);
+ if (compileStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
+ {
+ GLsizei charsWritten;
+ GLchar* infoLog = new GLchar[length];
+ glGetShaderInfoLog(result, length, &charsWritten, infoLog);
+ ERROR_LOG(VIDEO, "PS Shader info log:\n%s", infoLog);
+ char szTemp[MAX_PATH];
+ sprintf(szTemp, "%sps_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), result);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
+ file << infoLog << s_glsl_header << code;
+ file.close();
+ delete[] infoLog;
+ }
+ if (compileStatus != GL_TRUE)
+ {
+ // Compile failed
+ ERROR_LOG(VIDEO, "Shader compilation failed; see info log");
+
+ // Don't try to use this shader
+ glDeleteShader(result);
+ return 0;
+ }
+ (void)GL_REPORT_ERROR();
+ return result;
+}
+
+
+
+void ProgramShaderCache::GetShaderId ( SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 components )
+{
+ GetPixelShaderId(&uid->puid, dstAlphaMode, components);
+ GetVertexShaderId(&uid->vuid, components);
+}
+
+void ProgramShaderCache::GetSafeShaderId ( SHADERUIDSAFE* uid, DSTALPHA_MODE dstAlphaMode, u32 components )
+{
+ GetSafePixelShaderId(&uid->puid, dstAlphaMode, components);
+ GetSafeVertexShaderId(&uid->vuid, components);
+}
+
+void ProgramShaderCache::ValidateShaderIDs ( PCacheEntry *entry, DSTALPHA_MODE dstAlphaMode, u32 components )
+{
+ ValidateVertexShaderIDs(API_OPENGL, entry->safe_uid.vuid, entry->shader.strvprog, components);
+ ValidatePixelShaderIDs(API_OPENGL, entry->safe_uid.puid, entry->shader.strpprog, dstAlphaMode, components);
+}
+
+
+
+ProgramShaderCache::PCacheEntry ProgramShaderCache::GetShaderProgram(void)
+{
+ return *last_entry;
+}
+
+void ProgramShaderCache::Init(void)
+{
+ // We have to get the UBO alignment here because
+ // if we generate a buffer that isn't aligned
+ // then the UBO will fail.
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ {
+ GLint Align;
+ glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &Align);
+
+ s_ps_data_size = C_PENVCONST_END * sizeof(float) * 4;
+ s_vs_data_size = C_VENVCONST_END * sizeof(float) * 4;
+ s_vs_data_offset = ROUND_UP(s_ps_data_size, Align);
+ s_ubo_buffer_size = ROUND_UP(s_ps_data_size, Align) + ROUND_UP(s_vs_data_size, Align);
+
+ // We multiply by *4*4 because we need to get down to basic machine units.
+ // So multiply by four to get how many floats we have from vec4s
+ // Then once more to get bytes
+ s_buffer = new StreamBuffer(GL_UNIFORM_BUFFER, UBO_LENGTH);
+
+ s_ubo_buffer = new u8[s_ubo_buffer_size];
+ memset(s_ubo_buffer, 0, s_ubo_buffer_size);
+ s_ubo_dirty = true;
+ }
+
+ // Read our shader cache, only if supported
+ if (g_ogl_config.bSupportsGLSLCache)
+ {
+ GLint Supported;
+ glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &Supported);
+ if(!Supported)
+ {
+ ERROR_LOG(VIDEO, "GL_ARB_get_program_binary is supported, but no binary format is known. So disable shader cache.");
+ g_ogl_config.bSupportsGLSLCache = false;
+ }
+ else
+ {
+ if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
+ File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str());
+
+ char cache_filename[MAX_PATH];
+ sprintf(cache_filename, "%sogl-%s-shaders.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
+ SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
+
+ ProgramShaderCacheInserter inserter;
+ g_program_disk_cache.OpenAndRead(cache_filename, inserter);
+ }
+ SETSTAT(stats.numPixelShadersAlive, pshaders.size());
+ }
+
+ CreateHeader();
+
+ CurrentProgram = 0;
+ last_entry = NULL;
+}
+
+void ProgramShaderCache::Shutdown(void)
+{
+ // store all shaders in cache on disk
+ if (g_ogl_config.bSupportsGLSLCache)
+ {
+ PCache::iterator iter = pshaders.begin();
+ for (; iter != pshaders.end(); ++iter)
+ {
+ if(iter->second.in_cache) continue;
+
+ GLint binary_size;
+ glGetProgramiv(iter->second.shader.glprogid, GL_PROGRAM_BINARY_LENGTH, &binary_size);
+ if(!binary_size) continue;
+
+ u8 *data = new u8[binary_size+sizeof(GLenum)];
+ u8 *binary = data + sizeof(GLenum);
+ GLenum *prog_format = (GLenum*)data;
+ glGetProgramBinary(iter->second.shader.glprogid, binary_size, NULL, prog_format, binary);
+
+ g_program_disk_cache.Append(iter->first, data, binary_size+sizeof(GLenum));
+ delete [] data;
+ }
+
+ g_program_disk_cache.Sync();
+ g_program_disk_cache.Close();
+ }
+
+ glUseProgram(0);
+
+ PCache::iterator iter = pshaders.begin();
+ for (; iter != pshaders.end(); ++iter)
+ iter->second.Destroy();
+ pshaders.clear();
+
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ {
+ delete s_buffer;
+ s_buffer = 0;
+ delete [] s_ubo_buffer;
+ s_ubo_buffer = 0;
+ }
+}
+
+void ProgramShaderCache::CreateHeader ( void )
+{
+#ifdef _WIN32
+ // Intel Windows driver has a issue:
+ // their glsl doesn't know about the ubo extension, so we can't load it.
+ // but as version 140, ubo is in core and don't have to be loaded in glsl.
+ // as sandy do ogl3.1, glsl 140 is supported, so force it in this way.
+ // TODO: remove this again when the issue is fixed:
+ // see http://communities.intel.com/thread/36084
+ bool glsl140_hack = strcmp(g_ogl_config.gl_vendor, "Intel") == 0;
+#elif __APPLE__
+ // as apple doesn't support glsl130 at all, we also have to use glsl140
+ bool glsl140_hack = true;
+#else
+ bool glsl140_hack = false;
+#endif
+
+ snprintf(s_glsl_header, sizeof(s_glsl_header),
+ "#version %s\n"
+ "%s\n" // tex_rect
+ "%s\n" // ubo
+
+ "\n"// A few required defines and ones that will make our lives a lot easier
+ "#define ATTRIN in\n"
+ "#define ATTROUT out\n"
+ "#define VARYIN centroid in\n"
+ "#define VARYOUT centroid out\n"
+
+ // Silly differences
+ "#define float2 vec2\n"
+ "#define float3 vec3\n"
+ "#define float4 vec4\n"
+
+ // hlsl to glsl function translation
+ "#define frac(x) fract(x)\n"
+ "#define saturate(x) clamp(x, 0.0f, 1.0f)\n"
+ "#define lerp(x, y, z) mix(x, y, z)\n"
+
+
+ , glsl140_hack ? "140" : "130"
+ , glsl140_hack ? "#define texture2DRect texture" : "#extension GL_ARB_texture_rectangle : enable"
+ , g_ActiveConfig.backend_info.bSupportsGLSLUBO && !glsl140_hack ? "#extension GL_ARB_uniform_buffer_object : enable" : "// ubo disabled"
+ );
+}
+
+
+void ProgramShaderCache::ProgramShaderCacheInserter::Read ( const SHADERUID& key, const u8* value, u32 value_size )
+{
+ const u8 *binary = value+sizeof(GLenum);
+ GLenum *prog_format = (GLenum*)value;
+ GLint binary_size = value_size-sizeof(GLenum);
+
+ PCacheEntry entry;
+ entry.in_cache = 1;
+ entry.shader.glprogid = glCreateProgram();
+ glProgramBinary(entry.shader.glprogid, *prog_format, binary, binary_size);
+
+ GLint success;
+ glGetProgramiv(entry.shader.glprogid, GL_LINK_STATUS, &success);
+
+ if (success)
+ {
+ pshaders[key] = entry;
+ entry.shader.SetProgramVariables();
+ }
+ else
+ glDeleteProgram(entry.shader.glprogid);
+}
+
+
+} // namespace OGL
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h
new file mode 100644
index 0000000000..c4b03c2973
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h
@@ -0,0 +1,137 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef PROGRAM_SHADER_CACHE_H_
+#define PROGRAM_SHADER_CACHE_H_
+
+#include "GLUtil.h"
+
+#include "PixelShaderGen.h"
+#include "VertexShaderGen.h"
+
+#include "LinearDiskCache.h"
+#include "ConfigManager.h"
+
+namespace OGL
+{
+
+template<bool safe>
+class _SHADERUID
+{
+public:
+ _VERTEXSHADERUID<safe> vuid;
+ _PIXELSHADERUID<safe> puid;
+
+ _SHADERUID() {}
+
+ _SHADERUID(const _SHADERUID& r) : vuid(r.vuid), puid(r.puid) {}
+
+ bool operator <(const _SHADERUID& r) const
+ {
+ if(puid < r.puid) return true;
+ if(r.puid < puid) return false;
+ if(vuid < r.vuid) return true;
+ return false;
+ }
+
+ bool operator ==(const _SHADERUID& r) const
+ {
+ return puid == r.puid && vuid == r.vuid;
+ }
+};
+typedef _SHADERUID<false> SHADERUID;
+typedef _SHADERUID<true> SHADERUIDSAFE;
+
+
+const int NUM_UNIFORMS = 19;
+extern const char *UniformNames[NUM_UNIFORMS];
+
+struct SHADER
+{
+ SHADER() : glprogid(0) { }
+ void Destroy()
+ {
+ glDeleteProgram(glprogid);
+ glprogid = 0;
+ }
+ GLuint glprogid; // opengl program id
+
+ std::string strvprog, strpprog;
+ GLint UniformLocations[NUM_UNIFORMS];
+
+ void SetProgramVariables();
+ void SetProgramBindings();
+ void Bind();
+};
+
+class ProgramShaderCache
+{
+public:
+
+ struct PCacheEntry
+ {
+ SHADER shader;
+ SHADERUIDSAFE safe_uid;
+ bool in_cache;
+
+ void Destroy()
+ {
+ shader.Destroy();
+ }
+ };
+
+ static PCacheEntry GetShaderProgram(void);
+ static GLuint GetCurrentProgram(void);
+ static SHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 components);
+ static void GetShaderId(SHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 components);
+ static void GetSafeShaderId(SHADERUIDSAFE *uid, DSTALPHA_MODE dstAlphaMode, u32 components);
+ static void ValidateShaderIDs(PCacheEntry *entry, DSTALPHA_MODE dstAlphaMode, u32 components);
+
+ static bool CompileShader(SHADER &shader, const char* vcode, const char* pcode);
+ static GLuint CompileSingleShader(GLuint type, const char *code);
+
+ static void SetMultiPSConstant4fv(unsigned int offset, const float *f, unsigned int count);
+ static void SetMultiVSConstant4fv(unsigned int offset, const float *f, unsigned int count);
+ static void UploadConstants();
+
+ static void Init(void);
+ static void Shutdown(void);
+ static void CreateHeader(void);
+
+private:
+ class ProgramShaderCacheInserter : public LinearDiskCacheReader<SHADERUID, u8>
+ {
+ public:
+ void Read(const SHADERUID &key, const u8 *value, u32 value_size);
+ };
+
+ typedef std::map<SHADERUID, PCacheEntry> PCache;
+
+ static PCache pshaders;
+ static PCacheEntry* last_entry;
+ static SHADERUID last_uid;
+
+ static GLintptr s_vs_data_size;
+ static GLintptr s_ps_data_size;
+ static GLintptr s_vs_data_offset;
+ static u8 *s_ubo_buffer;
+ static u32 s_ubo_buffer_size;
+ static bool s_ubo_dirty;
+};
+
+} // namespace OGL
+#endif
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp b/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp
index da53fae6d5..0ba2a5b1ae 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp
@@ -17,12 +17,18 @@
#include "GLUtil.h"
-#include <string.h>
-
#include "RasterFont.h"
+#include "ProgramShaderCache.h"
// globals
-const GLubyte rasters[][13] = {
+namespace OGL {
+
+static const u32 char_width = 8;
+static const u32 char_height = 13;
+static const u32 char_offset = 32;
+static const u32 char_count = 95;
+
+const u8 rasters[char_count][char_height] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
@@ -120,104 +126,159 @@ const GLubyte rasters[][13] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
};
+static const char *s_vertexShaderSrc =
+ "uniform vec2 charSize;\n"
+ "in vec2 rawpos;\n"
+ "in vec2 tex0;\n"
+ "out vec2 uv0;\n"
+ "void main(void) {\n"
+ " gl_Position = vec4(rawpos,0,1);\n"
+ " uv0 = tex0 * charSize;\n"
+ "}\n";
+
+static const char *s_fragmentShaderSrc =
+ "uniform sampler2D samp8;\n"
+ "uniform vec4 color;\n"
+ "in vec2 uv0;\n"
+ "out vec4 ocol0;\n"
+ "void main(void) {\n"
+ " ocol0 = texture(samp8,uv0) * color;\n"
+ "}\n";
+
+static SHADER s_shader;
+
RasterFont::RasterFont()
{
- // set GL modes
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- // create the raster font
- fontOffset = glGenLists(128);
- for (int i = 32; i < 127; i++) {
- glNewList(i + fontOffset, GL_COMPILE);
- glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
- glEndList();
+ // generate the texture
+ glGenTextures(1, &texture);
+ glActiveTexture(GL_TEXTURE0+8);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ u32* texture_data = new u32[char_width*char_count*char_height];
+ for(u32 y=0; y<char_height; y++) {
+ for(u32 c=0; c<char_count; c++) {
+ for(u32 x=0; x<char_width; x++) {
+ bool pixel = rasters[c][y] & (1<<(char_width-x-1));
+ texture_data[char_width*char_count*y+char_width*c+x] = pixel ? -1 : 0;
+ }
+ }
}
-
- temp_buffer = new char[TEMP_BUFFER_SIZE];
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, char_width*char_count, char_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
+ delete [] texture_data;
+
+ // generate shader
+ ProgramShaderCache::CompileShader(s_shader, s_vertexShaderSrc, s_fragmentShaderSrc);
+
+ // bound uniforms
+ glUniform2f(glGetUniformLocation(s_shader.glprogid,"charSize"), 1.0f / GLfloat(char_count), 1.0f);
+ uniform_color_id = glGetUniformLocation(s_shader.glprogid,"color");
+ glUniform4f(uniform_color_id, 1.0f, 1.0f, 1.0f, 1.0f);
+ cached_color = -1;
+
+ // generate VBO & VAO
+ glGenBuffers(1, &VBO);
+ glGenVertexArrays(1, &VAO);
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ glBindVertexArray(VAO);
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, NULL);
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
}
RasterFont::~RasterFont()
{
- glDeleteLists(fontOffset, 128);
- delete [] temp_buffer;
+ glDeleteTextures(1, &texture);
+ glDeleteBuffers(1, &VBO);
+ glDeleteVertexArrays(1, &VAO);
+ s_shader.Destroy();
}
-void RasterFont::printString(const char *s, double x, double y, double z)
+void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight, u32 color)
{
- int length = (int)strlen(s);
- if (!length)
- return;
- if (length >= TEMP_BUFFER_SIZE)
- length = TEMP_BUFFER_SIZE - 1;
-
- // Sanitize string to avoid GL errors.
- char *s2 = temp_buffer;
- memcpy(s2, s, length);
- s2[length] = 0;
- for (int i = 0; i < length; i++) {
- if (s2[i] < 32 || s2[i] > 126)
- s2[i] = '!';
- }
-
- // go to the right spot
- glRasterPos3d(x, y, z);
- GL_REPORT_ERRORD();
-
- glPushAttrib (GL_LIST_BIT);
- glListBase(fontOffset);
- glCallLists((GLsizei)strlen(s2), GL_UNSIGNED_BYTE, (GLubyte *) s2);
- GL_REPORT_ERRORD();
- glPopAttrib();
- GL_REPORT_ERRORD();
-}
-
-void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z)
-{
- int length = (int)strlen(s);
- int x = (int)(screen_width/2.0 - (length/2.0)*char_width);
- printString(s, x, y, z);
-}
-
-void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight)
-{
- double x = start_x;
- double y = start_y;
- char temp[1024];
- char *t = temp;
- while (*text)
- {
- if (*text == '\n')
- {
- *t = 0;
- printString(temp, x, y, z);
- y -= char_height * 2.0f / bbHeight;
+ size_t length = strlen(text);
+ GLfloat *vertices = new GLfloat[length*6*4];
+
+ int usage = 0;
+ GLfloat delta_x = GLfloat(2*char_width)/GLfloat(bbWidth);
+ GLfloat delta_y = GLfloat(2*char_height)/GLfloat(bbHeight);
+ GLfloat border_x = 2.0/GLfloat(bbWidth);
+ GLfloat border_y = 4.0/GLfloat(bbHeight);
+
+ GLfloat x = GLfloat(start_x);
+ GLfloat y = GLfloat(start_y);
+
+ for(size_t i=0; i<length; i++) {
+ u8 c = text[i];
+
+ if(c == '\n') {
x = start_x;
- t = temp;
- }
- else if (*text == '\r')
- {
- t = temp;
+ y -= delta_y + border_y;
+ continue;
}
- else if (*text == '\t')
- {
- //todo: add tabs every something like 4*char_width
- *t = 0;
- int cpos = (int)strlen(temp);
- int newpos = (cpos + 4) & (~3);
- printString(temp, x, y, z);
- x = start_x + (char_width*newpos) * 2.0f / bbWidth;
- t = temp;
- *t++ = ' ';
+
+ // do not print spaces, they can be skipped easyly
+ if(c == ' ') {
+ x += delta_x + border_x;
+ continue;
}
- else
- *t++ = *text;
-
- text++;
+
+ if(c < char_offset || c >= char_count+char_offset) continue;
+
+ vertices[usage++] = x;
+ vertices[usage++] = y;
+ vertices[usage++] = GLfloat(c-char_offset);
+ vertices[usage++] = 0.0f;
+
+ vertices[usage++] = x+delta_x;
+ vertices[usage++] = y;
+ vertices[usage++] = GLfloat(c-char_offset+1);
+ vertices[usage++] = 0.0f;
+
+ vertices[usage++] = x+delta_x;
+ vertices[usage++] = y+delta_y;
+ vertices[usage++] = GLfloat(c-char_offset+1);
+ vertices[usage++] = 1.0f;
+
+ vertices[usage++] = x;
+ vertices[usage++] = y;
+ vertices[usage++] = GLfloat(c-char_offset);
+ vertices[usage++] = 0.0f;
+
+ vertices[usage++] = x+delta_x;
+ vertices[usage++] = y+delta_y;
+ vertices[usage++] = GLfloat(c-char_offset+1);
+ vertices[usage++] = 1.0f;
+
+ vertices[usage++] = x;
+ vertices[usage++] = y+delta_y;
+ vertices[usage++] = GLfloat(c-char_offset);
+ vertices[usage++] = 1.0f;
+
+ x += delta_x + border_x;
+ }
+
+ if(!usage) {
+ delete [] vertices;
+ return;
}
+
+ glBindVertexArray(VAO);
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ glBufferData(GL_ARRAY_BUFFER, usage*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
+
+ delete [] vertices;
- // ????
- if (t != text)
- {
- *t = 0;
- printString(temp, x, y, z);
+ s_shader.Bind();
+
+ if(color != cached_color) {
+ glUniform4f(uniform_color_id, GLfloat((color>>16)&0xff)/255.f,GLfloat((color>>8)&0xff)/255.f,GLfloat((color>>0)&0xff)/255.f,GLfloat((color>>24)&0xff)/255.f);
+ cached_color = color;
}
+
+ glActiveTexture(GL_TEXTURE0+8);
+ glDrawArrays(GL_TRIANGLES, 0, usage/4);
+}
+
}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.h b/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.h
index 3ebc684dd0..3715a91213 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.h
@@ -18,25 +18,24 @@
#ifndef _RASTERFONT_H_
#define _RASTERFONT_H_
+namespace OGL {
+
class RasterFont {
public:
RasterFont();
~RasterFont(void);
static int debug;
-
- // some useful constants
- enum {char_width = 10};
- enum {char_height = 15};
-
- // and the happy helper functions
- void printString(const char *s, double x, double y, double z=0.0);
- void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
-
- void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
+
+ void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight, u32 color);
private:
- int fontOffset;
- char *temp_buffer;
- enum {TEMP_BUFFER_SIZE = 64 * 1024};
+
+ u32 VBO;
+ u32 VAO;
+ u32 texture;
+ u32 uniform_color_id;
+ u32 cached_color;
};
+}
+
#endif // _RASTERFONT_H_
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
index 3ff8b834ce..97015db667 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
@@ -24,6 +24,9 @@
#include <cstdio>
#include "GLUtil.h"
+#if defined(HAVE_WX) && HAVE_WX
+#include "WxUtils.h"
+#endif
#include "FileUtil.h"
@@ -43,9 +46,8 @@
#include "RasterFont.h"
#include "VertexShaderGen.h"
#include "DLCache.h"
-#include "PixelShaderCache.h"
#include "PixelShaderManager.h"
-#include "VertexShaderCache.h"
+#include "ProgramShaderCache.h"
#include "VertexShaderManager.h"
#include "VertexLoaderManager.h"
#include "VertexLoader.h"
@@ -63,6 +65,9 @@
#include "BPFunctions.h"
#include "FPSCounter.h"
#include "ConfigManager.h"
+#include "VertexManager.h"
+#include "SamplerCache.h"
+#include "StreamBuffer.h"
#include "main.h" // Local
#ifdef _WIN32
@@ -94,31 +99,41 @@ typedef struct
} ScrStrct;
#endif
-#if defined HAVE_CG && HAVE_CG
-CGcontext g_cgcontext;
-CGprofile g_cgvProf;
-CGprofile g_cgfProf;
-#endif
int OSDInternalW, OSDInternalH;
namespace OGL
{
+enum MultisampleMode {
+ MULTISAMPLE_OFF,
+ MULTISAMPLE_2X,
+ MULTISAMPLE_4X,
+ MULTISAMPLE_8X,
+ MULTISAMPLE_CSAA_8X,
+ MULTISAMPLE_CSAA_8XQ,
+ MULTISAMPLE_CSAA_16X,
+ MULTISAMPLE_CSAA_16XQ,
+ MULTISAMPLE_SSAA_4X,
+};
+
+
+VideoConfig g_ogl_config;
+
// Declarations and definitions
// ----------------------------
-int s_fps=0;
-
+static int s_fps = 0;
+static GLuint s_ShowEFBCopyRegions_VBO = 0;
+static GLuint s_ShowEFBCopyRegions_VAO = 0;
+static SHADER s_ShowEFBCopyRegions;
-RasterFont* s_pfont = NULL;
+static RasterFont* s_pfont = NULL;
// 1 for no MSAA. Use s_MSAASamples > 1 to check for MSAA.
static int s_MSAASamples = 1;
static int s_MSAACoverageSamples = 0;
static int s_LastMultisampleMode = 0;
-bool s_bHaveFramebufferBlit = false; // export to FramebufferManager.cpp
-static bool s_bHaveCoverageMSAA = false;
static u32 s_blendMode;
#if defined(HAVE_WX) && HAVE_WX
@@ -126,69 +141,82 @@ static std::thread scrshotThread;
#endif
// EFB cache related
-const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks.
-const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up
-const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE;
+static const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks.
+static const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up
+static const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE;
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
-
-#if defined HAVE_CG && HAVE_CG
-void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
-{
- DEBUG_LOG(VIDEO, "Cg error: %s", cgGetErrorString(err));
- const char* listing = cgGetLastListing(g_cgcontext);
- if (listing != NULL)
- DEBUG_LOG(VIDEO, " last listing: %s", listing);
-}
-#endif
-
int GetNumMSAASamples(int MSAAMode)
{
- // required for MSAA
- if (!s_bHaveFramebufferBlit)
- return 1;
-
+ int samples;
switch (MSAAMode)
{
case MULTISAMPLE_OFF:
- return 1;
+ samples = 1;
+ break;
case MULTISAMPLE_2X:
- return 2;
+ samples = 2;
+ break;
case MULTISAMPLE_4X:
case MULTISAMPLE_CSAA_8X:
case MULTISAMPLE_CSAA_16X:
- return 4;
+ case MULTISAMPLE_SSAA_4X:
+ samples = 4;
+ break;
case MULTISAMPLE_8X:
case MULTISAMPLE_CSAA_8XQ:
case MULTISAMPLE_CSAA_16XQ:
- return 8;
+ samples = 8;
+ break;
default:
- return 1;
+ samples = 1;
}
+
+ if(samples <= g_ogl_config.max_samples) return samples;
+
+ ERROR_LOG(VIDEO, "MSAA Bug: %d samples selected, but only %d supported by gpu.", samples, g_ogl_config.max_samples);
+ return g_ogl_config.max_samples;
}
int GetNumMSAACoverageSamples(int MSAAMode)
{
- if (!s_bHaveCoverageMSAA)
- return 0;
-
+ int samples;
switch (g_ActiveConfig.iMultisampleMode)
{
case MULTISAMPLE_CSAA_8X:
case MULTISAMPLE_CSAA_8XQ:
- return 8;
+ samples = 8;
+ break;
case MULTISAMPLE_CSAA_16X:
case MULTISAMPLE_CSAA_16XQ:
- return 16;
+ samples = 16;
+ break;
default:
- return 0;
+ samples = 0;
+ }
+ if(g_ogl_config.bSupportCoverageMSAA || samples == 0) return samples;
+
+ ERROR_LOG(VIDEO, "MSAA Bug: CSAA selected, but not supported by gpu.");
+ return 0;
+}
+
+void ApplySSAASettings() {
+ if(g_ActiveConfig.iMultisampleMode == MULTISAMPLE_SSAA_4X) {
+ if(g_ogl_config.bSupportSampleShading) {
+ glEnable(GL_SAMPLE_SHADING_ARB);
+ glMinSampleShadingARB(s_MSAASamples);
+ } else {
+ ERROR_LOG(VIDEO, "MSAA Bug: SSAA selected, but not supported by gpu.");
+ }
+ } else if(g_ogl_config.bSupportSampleShading) {
+ glDisable(GL_SAMPLE_SHADING_ARB);
}
}
@@ -199,39 +227,14 @@ Renderer::Renderer()
OSDInternalH = 0;
s_fps=0;
+ s_ShowEFBCopyRegions_VBO = 0;
s_blendMode = 0;
-
InitFPSCounter();
-#if defined HAVE_CG && HAVE_CG
- g_cgcontext = cgCreateContext();
- cgGetError();
- cgSetErrorHandler(HandleCgError, NULL);
-#endif
-
- // Look for required extensions.
- const char *ptoken = (const char*)glGetString(GL_EXTENSIONS);
- if (!ptoken)
- {
- PanicAlert("Your OpenGL Driver seems to be not working.\n"
- "Please make sure your drivers are up-to-date and\n"
- "that your video hardware is OpenGL 2.x compatible.");
- return; // TODO: fail
- }
-
- INFO_LOG(VIDEO, "Supported OpenGL Extensions:");
- INFO_LOG(VIDEO, "%s", ptoken); // write to the log file
- INFO_LOG(VIDEO, "\n");
-
- OSD::AddMessage(StringFromFormat("Video Info: %s, %s, %s",
- glGetString(GL_VENDOR),
- glGetString(GL_RENDERER),
- glGetString(GL_VERSION)).c_str(), 5000);
-
bool bSuccess = true;
GLint numvertexattribs = 0;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &numvertexattribs);
- if (numvertexattribs < 11)
+ if (numvertexattribs < 16)
{
ERROR_LOG(VIDEO, "GPU: OGL ERROR: Number of attributes %d not enough.\n"
"GPU: Does your video card support OpenGL 2.x?",
@@ -240,42 +243,113 @@ Renderer::Renderer()
}
// Init extension support.
+#ifdef __APPLE__
+ glewExperimental = 1;
+#endif
if (glewInit() != GLEW_OK)
{
ERROR_LOG(VIDEO, "glewInit() failed! Does your video card support OpenGL 2.x?");
return; // TODO: fail
}
- if (!GLEW_EXT_framebuffer_object)
+ if (!GLEW_EXT_secondary_color)
{
- ERROR_LOG(VIDEO, "GPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets.\n"
+ ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_EXT_secondary_color.\n"
"GPU: Does your video card support OpenGL 2.x?");
bSuccess = false;
}
- if (!GLEW_EXT_secondary_color)
+ if (!GLEW_ARB_framebuffer_object)
{
- ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_EXT_secondary_color.\n"
- "GPU: Does your video card support OpenGL 2.x?");
+ ERROR_LOG(VIDEO, "GPU: ERROR: Need GL_ARB_framebufer_object for multiple render targets.\n"
+ "GPU: Does your video card support OpenGL 3.0?");
bSuccess = false;
}
- s_bHaveFramebufferBlit = strstr(ptoken, "GL_EXT_framebuffer_blit") != NULL;
- s_bHaveCoverageMSAA = strstr(ptoken, "GL_NV_framebuffer_multisample_coverage") != NULL;
+ if (!GLEW_ARB_vertex_array_object)
+ {
+ ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_vertex_array_object.\n"
+ "GPU: Does your video card support OpenGL 3.0?");
+ bSuccess = false;
+ }
+
+ if (!GLEW_ARB_map_buffer_range)
+ {
+ ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_map_buffer_range.\n"
+ "GPU: Does your video card support OpenGL 3.0?");
+ bSuccess = false;
+ }
- s_LastMultisampleMode = g_ActiveConfig.iMultisampleMode;
- s_MSAASamples = GetNumMSAASamples(s_LastMultisampleMode);
- s_MSAACoverageSamples = GetNumMSAACoverageSamples(s_LastMultisampleMode);
+ if (!GLEW_ARB_sampler_objects && bSuccess)
+ {
+ ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_sampler_objects."
+ "GPU: Does your video card support OpenGL 3.2?"
+ "Please report this issue, then there will be a workaround");
+ bSuccess = false;
+ }
if (!bSuccess)
return; // TODO: fail
+
+ g_Config.backend_info.bSupportsDualSourceBlend = GLEW_ARB_blend_func_extended;
+ g_Config.backend_info.bSupportsGLSLUBO = GLEW_ARB_uniform_buffer_object;
+
+ g_ogl_config.bSupportsGLSLCache = GLEW_ARB_get_program_binary;
+ g_ogl_config.bSupportsGLPinnedMemory = GLEW_AMD_pinned_memory;
+ g_ogl_config.bSupportsGLSync = GLEW_ARB_sync;
+ g_ogl_config.bSupportsGLBaseVertex = GLEW_ARB_draw_elements_base_vertex;
+ g_ogl_config.bSupportCoverageMSAA = GLEW_NV_framebuffer_multisample_coverage;
+ g_ogl_config.bSupportSampleShading = GLEW_ARB_sample_shading;
+
+ g_ogl_config.gl_vendor = (const char*)glGetString(GL_VENDOR);
+ g_ogl_config.gl_renderer = (const char*)glGetString(GL_RENDERER);
+ g_ogl_config.gl_version = (const char*)glGetString(GL_VERSION);
+
+ glGetIntegerv(GL_MAX_SAMPLES, &g_ogl_config.max_samples);
+
+ if(g_Config.backend_info.bSupportsGLSLUBO && (
+ // hd3000 get corruption, hd4000 also and a big slowdown
+ !strcmp(g_ogl_config.gl_vendor, "Intel Open Source Technology Center") && (
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.0") ||
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.1") ||
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.2") ||
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.3") ||
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.1.0") ||
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.1.1") )
+ )) {
+ g_Config.backend_info.bSupportsGLSLUBO = false;
+ ERROR_LOG(VIDEO, "buggy driver detected. Disable UBO");
+ }
+
+ UpdateActiveConfig();
+ OSD::AddMessage(StringFromFormat("Video Info: %s, %s, %s",
+ g_ogl_config.gl_vendor,
+ g_ogl_config.gl_renderer,
+ g_ogl_config.gl_version).c_str(), 5000);
+
+ OSD::AddMessage(StringFromFormat("Missing Extensions: %s%s%s%s%s%s%s%s",
+ g_ActiveConfig.backend_info.bSupportsDualSourceBlend ? "" : "DualSourceBlend ",
+ g_ActiveConfig.backend_info.bSupportsGLSLUBO ? "" : "UniformBuffer ",
+ g_ogl_config.bSupportsGLPinnedMemory ? "" : "PinnedMemory ",
+ g_ogl_config.bSupportsGLSLCache ? "" : "ShaderCache ",
+ g_ogl_config.bSupportsGLBaseVertex ? "" : "BaseVertex ",
+ g_ogl_config.bSupportsGLSync ? "" : "Sync ",
+ g_ogl_config.bSupportCoverageMSAA ? "" : "CSAA ",
+ g_ogl_config.bSupportSampleShading ? "" : "SSAA "
+ ).c_str(), 5000);
+
+ s_LastMultisampleMode = g_ActiveConfig.iMultisampleMode;
+ s_MSAASamples = GetNumMSAASamples(s_LastMultisampleMode);
+ s_MSAACoverageSamples = GetNumMSAACoverageSamples(s_LastMultisampleMode);
+ ApplySSAASettings();
+
// Decide frambuffer size
s_backbuffer_width = (int)GLInterface->GetBackBufferWidth();
s_backbuffer_height = (int)GLInterface->GetBackBufferHeight();
// Handle VSync on/off
- int swapInterval = g_ActiveConfig.bVSync ? 1 : 0;
+ int swapInterval = g_ActiveConfig.IsVSync() ? 1 : 0;
GLInterface->SwapInterval(swapInterval);
// check the max texture width and height
@@ -288,9 +362,6 @@ Renderer::Renderer()
if (GL_REPORT_ERROR() != GL_NO_ERROR)
bSuccess = false;
- if (glDrawBuffers == NULL && !GLEW_ARB_draw_buffers)
- glDrawBuffers = glDrawBuffersARB;
-
if (!GLEW_ARB_texture_non_power_of_two)
WARN_LOG(VIDEO, "ARB_texture_non_power_of_two not supported.");
@@ -314,90 +385,17 @@ Renderer::Renderer()
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
s_MSAASamples, s_MSAACoverageSamples);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
-
if (GL_REPORT_ERROR() != GL_NO_ERROR)
bSuccess = false;
-
- s_pfont = new RasterFont();
-
-#if defined HAVE_CG && HAVE_CG
- // load the effect, find the best profiles (if any)
- if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE)
- {
- ERROR_LOG(VIDEO, "arbvp1 not supported");
- return; // TODO: fail
- }
-
- if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE)
- {
- ERROR_LOG(VIDEO, "arbfp1 not supported");
- return; // TODO: fail
- }
-
- g_cgvProf = cgGLGetLatestProfile(CG_GL_VERTEX);
- g_cgfProf = cgGLGetLatestProfile(CG_GL_FRAGMENT);
- if (strstr((const char*)glGetString(GL_VENDOR), "Humper") == NULL)
- {
-#if CG_VERSION_NUM == 2100
- // A bug was introduced in Cg2.1's handling of very large profile option values
- // so this will not work on ATI. ATI returns MAXINT = 2147483647 (0x7fffffff)
- // which is correct in OpenGL but Cg fails to handle it properly. As a result
- // -1 is used by Cg resulting (signedness incorrect) and compilation fails.
- if (strstr((const char*)glGetString(GL_VENDOR), "ATI") == NULL)
-#endif
- {
- cgGLSetOptimalOptions(g_cgvProf);
- cgGLSetOptimalOptions(g_cgfProf);
- }
- }
-#endif // HAVE_CG
-
- int nenvvertparams, nenvfragparams, naddrregisters[2];
- glGetProgramivARB(GL_VERTEX_PROGRAM_ARB,
- GL_MAX_PROGRAM_ENV_PARAMETERS_ARB,
- (GLint *)&nenvvertparams);
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
- GL_MAX_PROGRAM_ENV_PARAMETERS_ARB,
- (GLint *)&nenvfragparams);
- glGetProgramivARB(GL_VERTEX_PROGRAM_ARB,
- GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB,
- (GLint *)&naddrregisters[0]);
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
- GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB,
- (GLint *)&naddrregisters[1]);
- DEBUG_LOG(VIDEO, "Max program env parameters: vert=%d, frag=%d",
- nenvvertparams, nenvfragparams);
- DEBUG_LOG(VIDEO, "Max program address register parameters: vert=%d, frag=%d",
- naddrregisters[0], naddrregisters[1]);
-
- if (nenvvertparams < 238)
- ERROR_LOG(VIDEO, "Not enough vertex shader environment constants!!");
-
-#if defined HAVE_CG && HAVE_CG
- INFO_LOG(VIDEO, "Max buffer sizes: %d %d",
- cgGetProgramBufferMaxSize(g_cgvProf),
- cgGetProgramBufferMaxSize(g_cgfProf));
-#ifndef _DEBUG
- cgGLSetDebugMode(GL_FALSE);
-#endif
-#endif
-
+
glStencilFunc(GL_ALWAYS, 0, 0);
glBlendFunc(GL_ONE, GL_ONE);
glViewport(0, 0, GetTargetWidth(), GetTargetHeight()); // Reset The Current Viewport
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
- glDisable(GL_LIGHTING);
glDepthFunc(GL_LEQUAL);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
@@ -406,39 +404,14 @@ Renderer::Renderer()
glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, GetTargetWidth(), GetTargetHeight());
- glBlendColorEXT(0, 0, 0, 0.5f);
+ glBlendColor(0, 0, 0, 0.5f);
glClearDepth(1.0f);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- // legacy multitexturing: select texture channel only.
- glActiveTexture(GL_TEXTURE0);
- glClientActiveTexture(GL_TEXTURE0);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
UpdateActiveConfig();
-
- //return GL_REPORT_ERROR() == GL_NO_ERROR && bSuccess;
- return;
}
Renderer::~Renderer()
{
- g_Config.bRunning = false;
- UpdateActiveConfig();
- delete s_pfont;
- s_pfont = 0;
-
-#if defined HAVE_CG && HAVE_CG
- if (g_cgcontext)
- {
- cgDestroyContext(g_cgcontext);
- g_cgcontext = 0;
- }
-#endif
#if defined(HAVE_WX) && HAVE_WX
if (scrshotThread.joinable())
@@ -448,6 +421,49 @@ Renderer::~Renderer()
delete g_framebuffer_manager;
}
+void Renderer::Shutdown()
+{
+ g_Config.bRunning = false;
+ UpdateActiveConfig();
+
+ glDeleteBuffers(1, &s_ShowEFBCopyRegions_VBO);
+ glDeleteVertexArrays(1, &s_ShowEFBCopyRegions_VAO);
+ s_ShowEFBCopyRegions_VBO = 0;
+
+ delete s_pfont;
+ s_pfont = 0;
+ s_ShowEFBCopyRegions.Destroy();
+}
+
+void Renderer::Init()
+{
+ s_pfont = new RasterFont();
+
+ ProgramShaderCache::CompileShader(s_ShowEFBCopyRegions,
+ "in vec2 rawpos;\n"
+ "in vec3 color0;\n"
+ "out vec4 c;\n"
+ "void main(void) {\n"
+ " gl_Position = vec4(rawpos,0,1);\n"
+ " c = vec4(color0, 1.0);\n"
+ "}\n",
+ "in vec4 c;\n"
+ "out vec4 ocol0;\n"
+ "void main(void) {\n"
+ " ocol0 = c;\n"
+ "}\n");
+
+ // creating buffers
+ glGenBuffers(1, &s_ShowEFBCopyRegions_VBO);
+ glGenVertexArrays(1, &s_ShowEFBCopyRegions_VAO);
+ glBindBuffer(GL_ARRAY_BUFFER, s_ShowEFBCopyRegions_VBO);
+ glBindVertexArray( s_ShowEFBCopyRegions_VAO );
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*5, NULL);
+ glEnableVertexAttribArray(SHADER_COLOR0_ATTRIB);
+ glVertexAttribPointer(SHADER_COLOR0_ATTRIB, 3, GL_FLOAT, 0, sizeof(GLfloat)*5, (GLfloat*)NULL+2);
+}
+
// Create On-Screen-Messages
void Renderer::DrawDebugInfo()
{
@@ -469,16 +485,18 @@ void Renderer::DrawDebugInfo()
if (g_ActiveConfig.bShowEFBCopyRegions)
{
- // Store Line Size
- GLfloat lSize;
- glGetFloatv(GL_LINE_WIDTH, &lSize);
-
// Set Line Size
glLineWidth(3.0f);
- glBegin(GL_LINES);
+ // 2*Coords + 3*Color
+ glBindBuffer(GL_ARRAY_BUFFER, s_ShowEFBCopyRegions_VBO);
+ glBufferData(GL_ARRAY_BUFFER, stats.efb_regions.size() * sizeof(GLfloat) * (2+3)*2*6, NULL, GL_STREAM_DRAW);
+ GLfloat *Vertices = (GLfloat*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
// Draw EFB copy regions rectangles
+ int a = 0;
+ GLfloat color[3] = {0.0f, 1.0f, 1.0f};
+
for (std::vector<EFBRectangle>::const_iterator it = stats.efb_regions.begin();
it != stats.efb_regions.end(); ++it)
{
@@ -489,25 +507,97 @@ void Renderer::DrawDebugInfo()
GLfloat x2 = (GLfloat) -1.0f + ((GLfloat)it->right / halfWidth);
GLfloat y2 = (GLfloat) 1.0f - ((GLfloat)it->bottom / halfHeight);
- // Draw shadow of rect
- glColor3f(0.0f, 0.0f, 0.0f);
- glVertex2f(x, y - 0.01); glVertex2f(x2, y - 0.01);
- glVertex2f(x, y2 - 0.01); glVertex2f(x2, y2 - 0.01);
- glVertex2f(x + 0.005, y); glVertex2f(x + 0.005, y2);
- glVertex2f(x2 + 0.005, y); glVertex2f(x2 + 0.005, y2);
-
- // Draw rect
- glColor3f(0.0f, 1.0f, 1.0f);
- glVertex2f(x, y); glVertex2f(x2, y);
- glVertex2f(x, y2); glVertex2f(x2, y2);
- glVertex2f(x, y); glVertex2f(x, y2);
- glVertex2f(x2, y); glVertex2f(x2, y2);
+ Vertices[a++] = x;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+
+ Vertices[a++] = x;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+
+ Vertices[a++] = x;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ // TO DO: build something nicer here
+ GLfloat temp = color[0];
+ color[0] = color[1];
+ color[1] = color[2];
+ color[2] = temp;
}
-
- glEnd();
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+
+ s_ShowEFBCopyRegions.Bind();
+ glBindVertexArray( s_ShowEFBCopyRegions_VAO );
+ glDrawArrays(GL_LINES, 0, stats.efb_regions.size() * 2*6);
// Restore Line Size
- glLineWidth(lSize);
+ SetLineWidth();
// Clear stored regions
stats.efb_regions.clear();
@@ -532,20 +622,12 @@ void Renderer::RenderText(const char *text, int left, int top, u32 color)
const int nBackbufferWidth = (int)GLInterface->GetBackBufferWidth();
const int nBackbufferHeight = (int)GLInterface->GetBackBufferHeight();
- glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
- ((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
s_pfont->printMultilineText(text,
left * 2.0f / (float)nBackbufferWidth - 1,
1 - top * 2.0f / (float)nBackbufferHeight,
- 0, nBackbufferWidth, nBackbufferHeight);
+ 0, nBackbufferWidth, nBackbufferHeight, color);
GL_REPORT_ERRORD();
-
- glDisable(GL_BLEND);
}
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
@@ -671,7 +753,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
{
// Resolve our rectangle.
FramebufferManager::GetEFBDepthTexture(efbPixelRc);
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetResolvedFramebuffer());
}
u32* depthMap = new u32[targetPixelRcWidth * targetPixelRcHeight];
@@ -720,7 +802,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
{
// Resolve our rectangle.
FramebufferManager::GetEFBColorTexture(efbPixelRc);
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetResolvedFramebuffer());
}
u32* colorMap = new u32[targetPixelRcWidth * targetPixelRcHeight];
@@ -858,7 +940,11 @@ 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;
+ bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
+
+ bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && target_has_alpha;
+ bool useDualSource = useDstAlpha && g_ActiveConfig.backend_info.bSupportsDualSourceBlend;
+
const GLenum glSrcFactors[8] =
{
GL_ZERO,
@@ -884,11 +970,13 @@ void Renderer::SetBlendMode(bool forceUpdate)
// blend mode bit mask
// 0 - blend enable
+ // 1 - dst alpha enabled
// 2 - reverse subtract enable (else add)
// 3-5 - srcRGB function
// 6-8 - dstRGB function
- u32 newval = bpmem.blendmode.subtract << 2;
+ u32 newval = useDualSource << 1;
+ newval |= bpmem.blendmode.subtract << 2;
if (bpmem.blendmode.subtract)
newval |= 0x0049; // enable blending src 1 dst 1
@@ -901,33 +989,23 @@ void Renderer::SetBlendMode(bool forceUpdate)
u32 changes = forceUpdate ? 0xFFFFFFFF : newval ^ s_blendMode;
-#ifdef USE_DUAL_SOURCE_BLEND
- bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate
- && bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
- bool useDualSource = useDstAlpha && GLEW_ARB_blend_func_extended;
-#endif
-
if (changes & 1)
// blend enable change
(newval & 1) ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
if (changes & 4)
{
-#ifdef USE_DUAL_SOURCE_BLEND
// subtract enable change
GLenum equation = newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD;
GLenum equationAlpha = useDualSource ? GL_FUNC_ADD : equation;
+
glBlendEquationSeparate(equation, equationAlpha);
-#else
- glBlendEquation(newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD);
-#endif
}
- if (changes & 0x1F8)
+ if (changes & 0x1FA)
{
GLenum srcFactor = glSrcFactors[(newval >> 3) & 7];
GLenum dstFactor = glDestFactors[(newval >> 6) & 7];
-#ifdef USE_DUAL_SOURCE_BLEND
GLenum srcFactorAlpha = srcFactor;
GLenum dstFactorAlpha = dstFactor;
if (useDualSource)
@@ -945,31 +1023,31 @@ void Renderer::SetBlendMode(bool forceUpdate)
else if (dstFactor == GL_ONE_MINUS_SRC_ALPHA)
dstFactor = GL_ONE_MINUS_SRC1_ALPHA;
}
-
+
// blend RGB change
glBlendFuncSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha);
-#else
- glBlendFunc(srcFactor, dstFactor);
-#endif
}
s_blendMode = newval;
}
+void DumpFrame(const std::vector<u8>& data, int w, int h)
+{
+#if defined(HAVE_LIBAV) || defined(_WIN32)
+ if (g_ActiveConfig.bDumpFrames && !data.empty())
+ {
+ AVIDump::AddFrame(&data[0], w, h);
+ }
+#endif
+}
+
// This function has the final picture. We adjust the aspect ratio here.
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma)
{
static int w = 0, h = 0;
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- {
-#ifdef _WIN32
- AVIDump::AddFrame(frame_data);
-#elif defined HAVE_LIBAV
- AVIDump::AddFrame((u8*)frame_data, w, h);
-#endif
- }
+ DumpFrame(frame_data, w, h);
Core::Callback_VideoCopiedToXFB(false);
return;
}
@@ -979,20 +1057,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if (g_ActiveConfig.VirtualXFBEnabled() && (!xfbSourceList || xfbCount == 0))
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- {
-#ifdef _WIN32
- AVIDump::AddFrame(frame_data);
-#elif defined HAVE_LIBAV
- AVIDump::AddFrame((u8*)frame_data, w, h);
-#endif
- }
+ DumpFrame(frame_data, w, h);
Core::Callback_VideoCopiedToXFB(false);
return;
}
ResetAPIState();
+ PostProcessing::Update(s_backbuffer_width, s_backbuffer_height);
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
TargetRectangle flipped_trc = GetTargetRectangle();
@@ -1000,38 +1072,20 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
int tmp = flipped_trc.top;
flipped_trc.top = flipped_trc.bottom;
flipped_trc.bottom = tmp;
-
- // Textured triangles are necessary because of post-processing shaders
-
- // Disable all other stages
- for (int i = 1; i < 8; ++i)
- OGL::TextureCache::DisableStage(i);
-
- // Update GLViewPort
- glViewport(flipped_trc.left, flipped_trc.bottom, flipped_trc.GetWidth(), flipped_trc.GetHeight());
-
+
GL_REPORT_ERRORD();
// Copy the framebuffer to screen.
- // Texture map s_xfbTexture onto the main buffer
- glActiveTexture(GL_TEXTURE0);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- // Use linear filtering.
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
- // We must call ApplyShader here even if no post proc is selected - it takes
- // care of disabling it in that case. It returns false in case of no post processing.
- bool applyShader = PostProcessing::ApplyShader();
-
const XFBSourceBase* xfbSource = NULL;
if(g_ActiveConfig.bUseXFB)
{
+ // Render to the real/postprocessing buffer now.
+ PostProcessing::BindTargetFramebuffer();
+
// draw each xfb source
- // Render to the real buffer now.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the window backbuffer
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer());
for (u32 i = 0; i < xfbCount; ++i)
{
@@ -1041,10 +1095,10 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if (g_ActiveConfig.bUseRealXFB)
{
- drawRc.top = 1;
- drawRc.bottom = -1;
- drawRc.left = -1;
- drawRc.right = 1;
+ drawRc.top = flipped_trc.top;
+ drawRc.bottom = flipped_trc.bottom;
+ drawRc.left = flipped_trc.left;
+ drawRc.right = flipped_trc.right;
}
else
{
@@ -1052,12 +1106,12 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
int xfbHeight = xfbSource->srcHeight;
int xfbWidth = xfbSource->srcWidth;
int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbWidth * 2);
-
- drawRc.top = 1.0f - (2.0f * (hOffset) / (float)fbHeight);
- drawRc.bottom = 1.0f - (2.0f * (hOffset + xfbHeight) / (float)fbHeight);
- drawRc.left = -(xfbWidth / (float)fbWidth);
- drawRc.right = (xfbWidth / (float)fbWidth);
-
+
+ drawRc.top = flipped_trc.top - hOffset * flipped_trc.GetHeight() / fbHeight;
+ drawRc.bottom = flipped_trc.top - (hOffset + xfbHeight) * flipped_trc.GetHeight() / fbHeight;
+ drawRc.left = flipped_trc.left + (flipped_trc.GetWidth() - xfbWidth * flipped_trc.GetWidth() / fbWidth)/2;
+ drawRc.right = flipped_trc.left + (flipped_trc.GetWidth() + xfbWidth * flipped_trc.GetWidth() / fbWidth)/2;
+
// The following code disables auto stretch. Kept for reference.
// scale draw area for a 1 to 1 pixel mapping with the draw target
//float vScale = (float)fbHeight / (float)flipped_trc.GetHeight();
@@ -1077,62 +1131,30 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
sourceRc.bottom = xfbSource->sourceRc.bottom;
xfbSource->Draw(sourceRc, drawRc, 0, 0);
-
- // We must call ApplyShader here even if no post proc is selected.
- // It takes care of disabling it in that case. It returns false in
- // case of no post processing.
- if (applyShader)
- PixelShaderCache::DisableShader();
}
}
else
{
TargetRectangle targetRc = ConvertEFBRectangle(rc);
- GLuint read_texture = FramebufferManager::ResolveAndGetRenderTarget(rc);
- // Render to the real buffer now.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the window backbuffer
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
- if (applyShader)
- {
- glBegin(GL_QUADS);
- glTexCoord2f(targetRc.left, targetRc.bottom);
- glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0);
- glVertex2f(-1, -1);
-
- glTexCoord2f(targetRc.left, targetRc.top);
- glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1);
- glVertex2f(-1, 1);
-
- glTexCoord2f(targetRc.right, targetRc.top);
- glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1);
- glVertex2f( 1, 1);
-
- glTexCoord2f(targetRc.right, targetRc.bottom);
- glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0);
- glVertex2f( 1, -1);
- glEnd();
- PixelShaderCache::DisableShader();
- }
- else
- {
- glBegin(GL_QUADS);
- glTexCoord2f(targetRc.left, targetRc.bottom);
- glVertex2f(-1, -1);
-
- glTexCoord2f(targetRc.left, targetRc.top);
- glVertex2f(-1, 1);
-
- glTexCoord2f(targetRc.right, targetRc.top);
- glVertex2f( 1, 1);
-
- glTexCoord2f(targetRc.right, targetRc.bottom);
- glVertex2f( 1, -1);
- glEnd();
- }
+
+ // for msaa mode, we must resolve the efb content to non-msaa
+ FramebufferManager::ResolveAndGetRenderTarget(rc);
+
+ // Render to the real/postprocessing buffer now. (resolve have changed this in msaa mode)
+ PostProcessing::BindTargetFramebuffer();
+
+ // always the non-msaa fbo
+ GLuint fb = s_MSAASamples>1?FramebufferManager::GetResolvedFramebuffer():FramebufferManager::GetEFBFramebuffer();
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
+ glBlitFramebuffer(targetRc.left, targetRc.bottom, targetRc.right, targetRc.top,
+ flipped_trc.left, flipped_trc.bottom, flipped_trc.right, flipped_trc.top,
+ GL_COLOR_BUFFER_BIT, GL_LINEAR);
}
+
+ PostProcessing::BlitToScreen();
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- OGL::TextureCache::DisableStage(0);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
// Save screenshot
if (s_bScreenshot)
@@ -1149,16 +1171,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if (g_ActiveConfig.bDumpFrames)
{
std::lock_guard<std::mutex> lk(s_criticalScreenshot);
- if (!frame_data || w != flipped_trc.GetWidth() ||
+ if (frame_data.empty() || w != flipped_trc.GetWidth() ||
h != flipped_trc.GetHeight())
{
- if (frame_data) delete[] frame_data;
w = flipped_trc.GetWidth();
h = flipped_trc.GetHeight();
- frame_data = new char[3 * w * h];
+ frame_data.resize(3 * w * h);
}
glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glReadPixels(flipped_trc.left, flipped_trc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data);
+ glReadPixels(flipped_trc.left, flipped_trc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]);
if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0)
{
if (!bLastFrameDumped)
@@ -1179,12 +1200,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
}
if (bAVIDumping)
{
- #ifdef _WIN32
- AVIDump::AddFrame(frame_data);
- #else
- FlipImageData((u8*)frame_data, w, h);
- AVIDump::AddFrame((u8*)frame_data, w, h);
+ #ifndef _WIN32
+ FlipImageData(&frame_data[0], w, h);
#endif
+
+ AVIDump::AddFrame(&frame_data[0], w, h);
}
bLastFrameDumped = true;
@@ -1196,12 +1216,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
{
if (bLastFrameDumped && bAVIDumping)
{
- if (frame_data)
- {
- delete[] frame_data;
- frame_data = NULL;
- w = h = 0;
- }
+ std::vector<u8>().swap(frame_data);
+ w = h = 0;
AVIDump::Stop();
bAVIDumping = false;
OSD::AddMessage("Stop dumping frames", 2000);
@@ -1215,9 +1231,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
std::string movie_file_name;
w = GetTargetRectangle().GetWidth();
h = GetTargetRectangle().GetHeight();
- frame_data = new char[3 * w * h];
+ frame_data.resize(3 * w * h);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glReadPixels(GetTargetRectangle().left, GetTargetRectangle().bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data);
+ glReadPixels(GetTargetRectangle().left, GetTargetRectangle().bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]);
if (GL_REPORT_ERROR() == GL_NO_ERROR)
{
if (!bLastFrameDumped)
@@ -1228,21 +1244,17 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
OSD::AddMessage("Error opening framedump.raw for writing.", 2000);
else
{
- char msg [255];
- sprintf(msg, "Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h);
- OSD::AddMessage(msg, 2000);
+ OSD::AddMessage(StringFromFormat("Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h).c_str(), 2000);
}
}
if (pFrameDump)
{
- FlipImageData((u8*)frame_data, w, h);
- pFrameDump.WriteBytes(frame_data, w * 3 * h);
+ FlipImageData(&frame_data[0], w, h);
+ pFrameDump.WriteBytes(&frame_data[0], w * 3 * h);
pFrameDump.Flush();
}
bLastFrameDumped = true;
}
-
- delete[] frame_data;
}
else
{
@@ -1289,11 +1301,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
s_LastMultisampleMode = g_ActiveConfig.iMultisampleMode;
s_MSAASamples = GetNumMSAASamples(s_LastMultisampleMode);
s_MSAACoverageSamples = GetNumMSAACoverageSamples(s_LastMultisampleMode);
-
+ ApplySSAASettings();
+
delete g_framebuffer_manager;
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
s_MSAASamples, s_MSAACoverageSamples);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
}
}
@@ -1301,18 +1313,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
s_fps = UpdateFPSCounter();
// ---------------------------------------------------------------------
GL_REPORT_ERRORD();
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- DrawDebugText();
DrawDebugInfo();
+ DrawDebugText();
GL_REPORT_ERRORD();
- // Get the status of the Blend mode
- GLboolean blend_enabled = glIsEnabled(GL_BLEND);
- glDisable(GL_BLEND);
OSD::DrawMessages();
- if (blend_enabled)
- glEnable(GL_BLEND);
GL_REPORT_ERRORD();
// Copy the rendered frame to the real window
@@ -1329,6 +1339,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
GL_REPORT_ERRORD();
+ GLInterface->SwapInterval(g_ActiveConfig.IsVSync() ? 1 : 0);
+
// Clean out old stuff from caches. It's not worth it to clean out the shader caches.
DLCache::ProgressiveCleanup();
TextureCache::Cleanup();
@@ -1371,8 +1383,6 @@ void Renderer::ResetAPIState()
{
// Gets us to a reasonably sane state where it's possible to do things like
// image copies with textured quads, etc.
- VertexShaderCache::DisableShader();
- PixelShaderCache::DisableShader();
glDisable(GL_SCISSOR_TEST);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
@@ -1393,9 +1403,12 @@ void Renderer::RestoreAPIState()
VertexShaderManager::SetViewportChanged();
glPolygonMode(GL_FRONT_AND_BACK, g_ActiveConfig.bWireFrame ? GL_LINE : GL_FILL);
-
- VertexShaderCache::SetCurrentShader(0);
- PixelShaderCache::SetCurrentShader(0);
+
+ VertexManager *vm = (OGL::VertexManager*)g_vertex_manager;
+ glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers);
+ vm->m_last_vao = 0;
+
+ TextureCache::SetStage();
}
void Renderer::SetGenerationMode()
@@ -1433,6 +1446,7 @@ void Renderer::SetDepthMode()
else
{
// if the test is disabled write is disabled too
+ // TODO: When PE performance metrics are being emulated via occlusion queries, we should (probably?) enable depth test with depth function ALWAYS here
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
}
@@ -1492,7 +1506,11 @@ void Renderer::SetLineWidth()
void Renderer::SetSamplerState(int stage, int texindex)
{
- // TODO
+ auto const& tex = bpmem.tex[texindex];
+ auto const& tm0 = tex.texMode0[stage];
+ auto const& tm1 = tex.texMode1[stage];
+
+ g_sampler_cache->SetSamplerState((texindex * 4) + stage, tm0, tm1);
}
void Renderer::SetInterlacingMode()
@@ -1552,7 +1570,7 @@ void TakeScreenshot(ScrStrct* threadStruct)
// Save the screenshot and finally kill the wxImage object
// This is really expensive when saving to PNG, but not at all when using BMP
- threadStruct->img->SaveFile(wxString::FromAscii(threadStruct->filename.c_str()),
+ threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename),
wxBITMAP_TYPE_PNG);
threadStruct->img->Destroy();
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.h b/Source/Plugins/Plugin_VideoOGL/Src/Render.h
index 9cf1573b56..d5510753c2 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/Render.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.h
@@ -9,11 +9,30 @@ namespace OGL
void ClearEFBCache();
+// ogl-only config, so not in VideoConfig.h
+extern struct VideoConfig {
+ bool bSupportsGLSLCache;
+ bool bSupportsGLPinnedMemory;
+ bool bSupportsGLSync;
+ bool bSupportsGLBaseVertex;
+ bool bSupportCoverageMSAA;
+ bool bSupportSampleShading;
+
+ const char *gl_vendor;
+ const char *gl_renderer;
+ const char* gl_version;
+
+ s32 max_samples;
+} g_ogl_config;
+
class Renderer : public ::Renderer
{
public:
Renderer();
~Renderer();
+
+ static void Init();
+ static void Shutdown();
void SetColorMask();
void SetBlendMode(bool forceUpdate);
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.cpp
new file mode 100644
index 0000000000..b007f89796
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.cpp
@@ -0,0 +1,129 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "SamplerCache.h"
+
+namespace OGL
+{
+
+SamplerCache *g_sampler_cache;
+
+SamplerCache::SamplerCache()
+ : m_last_max_anisotropy()
+{}
+
+SamplerCache::~SamplerCache()
+{
+ Clear();
+}
+
+void SamplerCache::SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1)
+{
+ // TODO: can this go somewhere else?
+ if (m_last_max_anisotropy != g_ActiveConfig.iMaxAnisotropy)
+ {
+ m_last_max_anisotropy = g_ActiveConfig.iMaxAnisotropy;
+ Clear();
+ }
+
+ Params params(tm0, tm1);
+
+ // take equivalent forced linear when bForceFiltering
+ if (g_ActiveConfig.bForceFiltering)
+ {
+ params.tm0.min_filter |= 0x4;
+ params.tm0.mag_filter |= 0x1;
+ }
+
+ // TODO: Should keep a circular buffer for each stage of recently used samplers.
+
+ auto& active_sampler = m_active_samplers[stage];
+ if (active_sampler.first != params || !active_sampler.second.sampler_id)
+ {
+ // Active sampler does not match parameters (or is invalid), bind the proper one.
+ active_sampler.first = params;
+ active_sampler.second = GetEntry(params);
+ glBindSampler(stage, active_sampler.second.sampler_id);
+ }
+}
+
+auto SamplerCache::GetEntry(const Params& params) -> Value&
+{
+ auto& val = m_cache[params];
+ if (!val.sampler_id)
+ {
+ // Sampler not found in cache, create it.
+ glGenSamplers(1, &val.sampler_id);
+ SetParameters(val.sampler_id, params);
+
+ // TODO: Maybe kill old samplers if the cache gets huge. It doesn't seem to get huge though.
+ //ERROR_LOG(VIDEO, "Sampler cache size is now %ld.", m_cache.size());
+ }
+
+ return val;
+}
+
+void SamplerCache::SetParameters(GLuint sampler_id, const Params& params)
+{
+ static const GLint min_filters[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 wrap_settings[4] =
+ {
+ GL_CLAMP_TO_EDGE,
+ GL_REPEAT,
+ GL_MIRRORED_REPEAT,
+ GL_REPEAT,
+ };
+
+ auto& tm0 = params.tm0;
+ auto& tm1 = params.tm1;
+
+ glSamplerParameteri(sampler_id, GL_TEXTURE_MIN_FILTER, min_filters[tm0.min_filter % ARRAYSIZE(min_filters)]);
+ glSamplerParameteri(sampler_id, GL_TEXTURE_MAG_FILTER, tm0.mag_filter ? GL_LINEAR : GL_NEAREST);
+
+ glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_S, wrap_settings[tm0.wrap_s]);
+ glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_T, wrap_settings[tm0.wrap_t]);
+
+ glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, tm0.lod_bias / 32.f);
+
+ glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, tm1.min_lod / 16.f);
+ glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, tm1.max_lod / 16.f);
+
+ if (g_ActiveConfig.iMaxAnisotropy > 0)
+ glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy));
+}
+
+void SamplerCache::Clear()
+{
+ for (auto it = m_cache.begin(); it != m_cache.end(); ++it)
+ {
+ glDeleteSamplers(1, &it->second.sampler_id);
+ }
+ m_cache.clear();
+}
+
+}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.h b/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.h
new file mode 100644
index 0000000000..81180d2a7a
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.h
@@ -0,0 +1,80 @@
+
+#ifndef INCLUDE_SAMPLER_CACHE_H_
+#define INCLUDE_SAMPLER_CACHE_H_
+
+#include <map>
+
+#include "Render.h"
+#include "GLUtil.h"
+
+namespace OGL
+{
+
+class SamplerCache : NonCopyable
+{
+public:
+ SamplerCache();
+ ~SamplerCache();
+
+ void SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1);
+ void Clear();
+
+private:
+ struct Params
+ {
+ union
+ {
+ struct
+ {
+ TexMode0 tm0;
+ TexMode1 tm1;
+ };
+
+ u64 hex;
+ };
+
+ Params()
+ : hex()
+ {}
+
+ Params(const TexMode0& _tm0, const TexMode1& _tm1)
+ : tm0(_tm0)
+ , tm1(_tm1)
+ {
+ static_assert(sizeof(Params) == 8, "Assuming I can treat this as a 64bit int.");
+ }
+
+ bool operator<(const Params& other) const
+ {
+ return hex < other.hex;
+ }
+
+ bool operator!=(const Params& other) const
+ {
+ return hex != other.hex;
+ }
+ };
+
+ struct Value
+ {
+ Value()
+ : sampler_id()
+ {}
+
+ GLuint sampler_id;
+ };
+
+ void SetParameters(GLuint sampler_id, const Params& params);
+ Value& GetEntry(const Params& params);
+
+ std::map<Params, Value> m_cache;
+ std::pair<Params, Value> m_active_samplers[8];
+
+ int m_last_max_anisotropy;
+};
+
+extern SamplerCache *g_sampler_cache;
+
+}
+
+#endif
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp
new file mode 100644
index 0000000000..24b6b7d9b4
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp
@@ -0,0 +1,242 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Globals.h"
+#include "GLUtil.h"
+#include "StreamBuffer.h"
+#include "MemoryUtil.h"
+#include "Render.h"
+
+namespace OGL
+{
+
+static const u32 SYNC_POINTS = 16;
+static const u32 ALIGN_PINNED_MEMORY = 4096;
+
+StreamBuffer::StreamBuffer(u32 type, size_t size, StreamType uploadType)
+: m_uploadtype(uploadType), m_buffertype(type), m_size(size)
+{
+ glGenBuffers(1, &m_buffer);
+
+ bool nvidia = !strcmp(g_ogl_config.gl_vendor, "NVIDIA Corporation");
+
+ if(m_uploadtype & STREAM_DETECT)
+ {
+ if(!g_ogl_config.bSupportsGLBaseVertex && (m_uploadtype & BUFFERSUBDATA))
+ m_uploadtype = BUFFERSUBDATA;
+ else if(g_ogl_config.bSupportsGLSync && g_Config.bHackedBufferUpload && (m_uploadtype & MAP_AND_RISK))
+ m_uploadtype = MAP_AND_RISK;
+ else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && (m_uploadtype & PINNED_MEMORY))
+ m_uploadtype = PINNED_MEMORY;
+ else if(nvidia && (m_uploadtype & BUFFERSUBDATA))
+ m_uploadtype = BUFFERSUBDATA;
+ else if(g_ogl_config.bSupportsGLSync && (m_uploadtype & MAP_AND_SYNC))
+ m_uploadtype = MAP_AND_SYNC;
+ else
+ m_uploadtype = MAP_AND_ORPHAN;
+ }
+
+ Init();
+}
+
+StreamBuffer::~StreamBuffer()
+{
+ Shutdown();
+ glDeleteBuffers(1, &m_buffer);
+}
+
+#define SLOT(x) (x)*SYNC_POINTS/m_size
+
+void StreamBuffer::Alloc ( size_t size, u32 stride )
+{
+ size_t m_iterator_aligned = m_iterator;
+ if(m_iterator_aligned && stride) {
+ m_iterator_aligned--;
+ m_iterator_aligned = m_iterator_aligned - (m_iterator_aligned % stride) + stride;
+ }
+ size_t iter_end = m_iterator_aligned + size;
+
+ switch(m_uploadtype) {
+ case MAP_AND_ORPHAN:
+ if(iter_end >= m_size) {
+ glBufferData(m_buffertype, m_size, NULL, GL_STREAM_DRAW);
+ m_iterator_aligned = 0;
+ }
+ break;
+ case MAP_AND_SYNC:
+ case PINNED_MEMORY:
+
+ // insert waiting slots for used memory
+ for(u32 i=SLOT(m_used_iterator); i<SLOT(m_iterator); i++)
+ {
+ fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ }
+ m_used_iterator = m_iterator;
+
+ // wait for new slots to end of buffer
+ for(u32 i=SLOT(m_free_iterator)+1; i<=SLOT(iter_end) && i < SYNC_POINTS; i++)
+ {
+ glClientWaitSync(fences[i], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
+ glDeleteSync(fences[i]);
+ }
+ m_free_iterator = iter_end;
+
+ // if buffer is full
+ if(iter_end >= m_size) {
+
+ // insert waiting slots in unused space at the end of the buffer
+ for(u32 i=SLOT(m_used_iterator); i < SYNC_POINTS; i++)
+ fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+ // move to the start
+ m_used_iterator = m_iterator_aligned = m_iterator = 0; // offset 0 is always aligned
+ iter_end = size;
+
+ // wait for space at the start
+ for(u32 i=0; i<=SLOT(iter_end); i++)
+ {
+ glClientWaitSync(fences[i], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
+ glDeleteSync(fences[i]);
+ }
+ m_free_iterator = iter_end;
+ }
+
+ break;
+ case MAP_AND_RISK:
+ if(iter_end >= m_size) {
+ m_iterator_aligned = 0;
+ }
+ break;
+ case BUFFERSUBDATA:
+ m_iterator_aligned = 0;
+ break;
+ case STREAM_DETECT:
+ case DETECT_MASK: // Just to shutup warnings
+ break;
+ }
+ m_iterator = m_iterator_aligned;
+}
+
+size_t StreamBuffer::Upload ( u8* data, size_t size )
+{
+ switch(m_uploadtype) {
+ case MAP_AND_SYNC:
+ case MAP_AND_ORPHAN:
+ pointer = (u8*)glMapBufferRange(m_buffertype, m_iterator, size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
+ if(pointer) {
+ memcpy(pointer, data, size);
+ glUnmapBuffer(m_buffertype);
+ } else {
+ ERROR_LOG(VIDEO, "buffer mapping failed");
+ }
+ break;
+ case PINNED_MEMORY:
+ case MAP_AND_RISK:
+ if(pointer)
+ memcpy(pointer+m_iterator, data, size);
+ break;
+ case BUFFERSUBDATA:
+ glBufferSubData(m_buffertype, m_iterator, size, data);
+ break;
+ case STREAM_DETECT:
+ case DETECT_MASK: // Just to shutup warnings
+ break;
+ }
+ size_t ret = m_iterator;
+ m_iterator += size;
+ return ret;
+}
+
+void StreamBuffer::Init()
+{
+ m_iterator = 0;
+ m_used_iterator = 0;
+ m_free_iterator = 0;
+
+ switch(m_uploadtype) {
+ case MAP_AND_SYNC:
+ fences = new GLsync[SYNC_POINTS];
+ for(u32 i=0; i<SYNC_POINTS; i++)
+ fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+ case MAP_AND_ORPHAN:
+ case BUFFERSUBDATA:
+ glBindBuffer(m_buffertype, m_buffer);
+ glBufferData(m_buffertype, m_size, NULL, GL_STREAM_DRAW);
+ break;
+ case PINNED_MEMORY:
+ glGetError(); // errors before this allocation should be ignored
+ fences = new GLsync[SYNC_POINTS];
+ for(u32 i=0; i<SYNC_POINTS; i++)
+ fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+ pointer = (u8*)AllocateAlignedMemory(ROUND_UP(m_size,ALIGN_PINNED_MEMORY), ALIGN_PINNED_MEMORY );
+ glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_buffer);
+ glBufferData(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, ROUND_UP(m_size,ALIGN_PINNED_MEMORY), pointer, GL_STREAM_COPY);
+ glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
+ glBindBuffer(m_buffertype, m_buffer);
+
+ // on error, switch to another backend. some old catalyst seems to have broken pinned memory support
+ if(glGetError() != GL_NO_ERROR) {
+ ERROR_LOG(VIDEO, "pinned memory detected, but not working. Please report this: %s, %s, %s", g_ogl_config.gl_vendor, g_ogl_config.gl_renderer, g_ogl_config.gl_version);
+ Shutdown();
+ m_uploadtype = MAP_AND_SYNC;
+ Init();
+ }
+ break;
+ case MAP_AND_RISK:
+ glBindBuffer(m_buffertype, m_buffer);
+ glBufferData(m_buffertype, m_size, NULL, GL_STREAM_DRAW);
+ pointer = (u8*)glMapBuffer(m_buffertype, GL_WRITE_ONLY);
+ glUnmapBuffer(m_buffertype);
+ if(!pointer)
+ ERROR_LOG(VIDEO, "buffer allocation failed");
+
+ case STREAM_DETECT:
+ case DETECT_MASK: // Just to shutup warnings
+ break;
+ }
+}
+
+void StreamBuffer::Shutdown()
+{
+ switch(m_uploadtype) {
+ case MAP_AND_SYNC:
+ for(u32 i=0; i<SYNC_POINTS; i++)
+ glDeleteSync(fences[i]);
+ delete [] fences;
+ break;
+
+ case MAP_AND_RISK:
+ case MAP_AND_ORPHAN:
+ case BUFFERSUBDATA:
+ break;
+ case PINNED_MEMORY:
+ for(u32 i=0; i<SYNC_POINTS; i++)
+ glDeleteSync(fences[i]);
+ delete [] fences;
+ glBindBuffer(m_buffertype, 0);
+ glFinish(); // ogl pipeline must be flushed, else this buffer can be in use
+ FreeAlignedMemory(pointer);
+ break;
+ case STREAM_DETECT:
+ case DETECT_MASK: // Just to shutup warnings
+ break;
+ }
+}
+
+}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.h b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.h
new file mode 100644
index 0000000000..fa3fd539ea
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.h
@@ -0,0 +1,72 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+
+#ifndef STREAMBUFFER_H
+#define STREAMBUFFER_H
+
+#include "VideoCommon.h"
+#include "FramebufferManager.h"
+#include "GLUtil.h"
+
+// glew < 1.8 doesn't support pinned memory
+#ifndef GLEW_AMD_pinned_memory
+#define GLEW_AMD_pinned_memory glewIsSupported("GL_AMD_pinned_memory")
+#define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160
+#endif
+
+namespace OGL
+{
+enum StreamType {
+ DETECT_MASK = 0x1F,
+ STREAM_DETECT = (1 << 0),
+ MAP_AND_ORPHAN = (1 << 1),
+ MAP_AND_SYNC = (1 << 2),
+ MAP_AND_RISK = (1 << 3),
+ PINNED_MEMORY = (1 << 4),
+ BUFFERSUBDATA = (1 << 5)
+};
+
+class StreamBuffer {
+
+public:
+ StreamBuffer(u32 type, size_t size, StreamType uploadType = DETECT_MASK);
+ ~StreamBuffer();
+
+ void Alloc(size_t size, u32 stride = 0);
+ size_t Upload(u8 *data, size_t size);
+
+ u32 getBuffer() { return m_buffer; }
+
+private:
+ void Init();
+ void Shutdown();
+
+ StreamType m_uploadtype;
+ u32 m_buffer;
+ u32 m_buffertype;
+ size_t m_size;
+ u8 *pointer;
+ size_t m_iterator;
+ size_t m_used_iterator;
+ size_t m_free_iterator;
+ GLsync *fences;
+};
+
+}
+
+#endif // STREAMBUFFER_H
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp
index ee918ee6c0..b0bc682f29 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp
@@ -42,7 +42,7 @@
#include "HW/Memmap.h"
#include "ImageWrite.h"
#include "MemoryUtil.h"
-#include "PixelShaderCache.h"
+#include "ProgramShaderCache.h"
#include "PixelShaderManager.h"
#include "Render.h"
#include "Statistics.h"
@@ -56,6 +56,24 @@
namespace OGL
{
+static SHADER s_ColorMatrixProgram;
+static SHADER s_DepthMatrixProgram;
+static GLuint s_ColorMatrixUniform;
+static GLuint s_DepthMatrixUniform;
+static u32 s_ColorCbufid;
+static u32 s_DepthCbufid;
+
+static u32 s_Textures[8];
+static u32 s_ActiveTexture;
+static u32 s_NextStage;
+
+struct VBOCache {
+ GLuint vbo;
+ GLuint vao;
+ TargetRectangle targetSource;
+};
+static std::map<u64,VBOCache> s_VBO;
+
static u32 s_TempFramebuffer = 0;
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level)
@@ -63,8 +81,11 @@ bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width
int width = std::max(virtual_width >> level, 1);
int height = std::max(virtual_height >> level, 1);
std::vector<u32> data(width * height);
+ glActiveTexture(GL_TEXTURE0+9);
glBindTexture(textarget, tex);
glGetTexImage(textarget, level, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]);
+ glBindTexture(textarget, 0);
+ TextureCache::SetStage();
const GLenum err = GL_REPORT_ERROR();
if (GL_NO_ERROR != err)
@@ -80,6 +101,9 @@ TextureCache::TCacheEntry::~TCacheEntry()
{
if (texture)
{
+ for(int i=0; i<8; i++)
+ if(s_Textures[i] == texture)
+ s_Textures[i] = 0;
glDeleteTextures(1, &texture);
texture = 0;
}
@@ -93,14 +117,17 @@ TextureCache::TCacheEntry::TCacheEntry()
void TextureCache::TCacheEntry::Bind(unsigned int stage)
{
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, texture);
- GL_REPORT_ERRORD();
-
- // TODO: is this already done somewhere else?
- TexMode0 &tm0 = bpmem.tex[stage >> 2].texMode0[stage & 3];
- TexMode1 &tm1 = bpmem.tex[stage >> 2].texMode1[stage & 3];
- SetTextureParameters(tm0, tm1);
+ if (s_Textures[stage] != texture)
+ {
+ if (s_ActiveTexture != stage)
+ {
+ glActiveTexture(GL_TEXTURE0 + stage);
+ s_ActiveTexture = stage;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, texture);
+ s_Textures[stage] = texture;
+ }
}
bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
@@ -129,13 +156,13 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
PanicAlert("Invalid PC texture format %i", pcfmt);
case PC_TEX_FMT_BGRA32:
gl_format = GL_BGRA;
- gl_iformat = 4;
+ gl_iformat = GL_RGBA;
gl_type = GL_UNSIGNED_BYTE;
break;
case PC_TEX_FMT_RGBA32:
gl_format = GL_RGBA;
- gl_iformat = 4;
+ gl_iformat = GL_RGBA;
gl_type = GL_UNSIGNED_BYTE;
break;
@@ -177,7 +204,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
entry.gl_type = gl_type;
entry.pcfmt = pcfmt;
- entry.bHaveMipMaps = tex_levels != 1;
+ entry.m_tex_levels = tex_levels;
entry.Load(width, height, expanded_width, 0);
@@ -187,19 +214,33 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level)
{
- //glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, texture);
- //GL_REPORT_ERRORD();
+ if (s_ActiveTexture != s_NextStage)
+ {
+ glActiveTexture(GL_TEXTURE0 + s_NextStage);
+ s_ActiveTexture = s_NextStage;
+ }
+
+ if (s_Textures[s_NextStage] != texture)
+ {
+ glBindTexture(GL_TEXTURE_2D, texture);
+ s_Textures[s_NextStage] = texture;
+ }
+
+ // TODO: sloppy, just do this on creation?
+ if (level == 0)
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_tex_levels - 1);
+ }
if (pcfmt != PC_TEX_FMT_DXT1)
{
if (expanded_width != width)
- glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
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);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
else
{
@@ -214,31 +255,26 @@ TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(
unsigned int scaled_tex_w, unsigned int scaled_tex_h)
{
TCacheEntry *const entry = new TCacheEntry;
+ glActiveTexture(GL_TEXTURE0+9);
glBindTexture(GL_TEXTURE_2D, entry->texture);
GL_REPORT_ERRORD();
const GLenum
gl_format = GL_RGBA,
- gl_iformat = 4,
+ gl_iformat = GL_RGBA,
gl_type = GL_UNSIGNED_BYTE;
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ entry->m_tex_levels = 1;
glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, scaled_tex_w, scaled_tex_h, 0, gl_format, gl_type, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ SetStage();
+
GL_REPORT_ERRORD();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- if (GL_REPORT_ERROR() != GL_NO_ERROR)
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- GL_REPORT_ERRORD();
- }
-
return entry;
}
@@ -247,8 +283,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
const float *colmat)
{
- glBindTexture(GL_TEXTURE_2D, texture);
-
+ g_renderer->ResetAPIState(); // reset any game specific settings
+
// Make sure to resolve anything we need to read from.
const GLuint read_texture = (srcFormat == PIXELFMT_Z24) ?
FramebufferManager::ResolveAndGetDepthTarget(srcRect) :
@@ -259,38 +295,85 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture)
{
if (s_TempFramebuffer == 0)
- glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
+ glGenFramebuffers(1, (GLuint*)&s_TempFramebuffer);
FramebufferManager::SetFramebuffer(s_TempFramebuffer);
// Bind texture to temporary framebuffer
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
GL_REPORT_FBO_ERROR();
GL_REPORT_ERRORD();
-
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
- glActiveTexture(GL_TEXTURE0);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
+
+ glActiveTexture(GL_TEXTURE0+9);
+ glBindTexture(GL_TEXTURE_RECTANGLE, read_texture);
glViewport(0, 0, virtual_width, virtual_height);
- PixelShaderCache::SetCurrentShader((srcFormat == PIXELFMT_Z24) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram());
- PixelShaderManager::SetColorMatrix(colmat); // set transformation
+ if(srcFormat == PIXELFMT_Z24) {
+ s_DepthMatrixProgram.Bind();
+ if(s_DepthCbufid != cbufid)
+ glUniform4fv(s_DepthMatrixUniform, 5, colmat);
+ s_DepthCbufid = cbufid;
+ } else {
+ s_ColorMatrixProgram.Bind();
+ if(s_ColorCbufid != cbufid)
+ glUniform4fv(s_ColorMatrixUniform, 7, colmat);
+ s_ColorCbufid = cbufid;
+ }
GL_REPORT_ERRORD();
TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect);
-
- glBegin(GL_QUADS);
- glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.bottom); glVertex2f(-1, 1);
- glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.top ); glVertex2f(-1, -1);
- glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.top ); glVertex2f( 1, -1);
- glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.bottom); glVertex2f( 1, 1);
- glEnd();
+ GL_REPORT_ERRORD();
+
+ // should be unique enough, if not, vbo will "only" be uploaded to much
+ u64 targetSourceHash = u64(targetSource.left)<<48 | u64(targetSource.top)<<32 | u64(targetSource.right)<<16 | u64(targetSource.bottom);
+ std::map<u64, VBOCache>::iterator vbo_it = s_VBO.find(targetSourceHash);
+
+ if(vbo_it == s_VBO.end()) {
+ VBOCache item;
+ item.targetSource.bottom = -1;
+ item.targetSource.top = -1;
+ item.targetSource.left = -1;
+ item.targetSource.right = -1;
+ glGenBuffers(1, &item.vbo);
+ glGenVertexArrays(1, &item.vao);
+
+ glBindBuffer(GL_ARRAY_BUFFER, item.vbo);
+ glBindVertexArray(item.vao);
+
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL);
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
+
+ vbo_it = s_VBO.insert(std::pair<u64,VBOCache>(targetSourceHash, item)).first;
+ }
+ if(!(vbo_it->second.targetSource == targetSource)) {
+ GLfloat vertices[] = {
+ -1.f, 1.f,
+ (GLfloat)targetSource.left, (GLfloat)targetSource.bottom,
+ -1.f, -1.f,
+ (GLfloat)targetSource.left, (GLfloat)targetSource.top,
+ 1.f, -1.f,
+ (GLfloat)targetSource.right, (GLfloat)targetSource.top,
+ 1.f, 1.f,
+ (GLfloat)targetSource.right, (GLfloat)targetSource.bottom
+ };
+
+ glBindBuffer(GL_ARRAY_BUFFER, vbo_it->second.vbo);
+ glBufferData(GL_ARRAY_BUFFER, 4*4*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
+
+ vbo_it->second.targetSource = targetSource;
+ }
+
+ glBindVertexArray(vbo_it->second.vao);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
GL_REPORT_ERRORD();
// Unbind texture from temporary framebuffer
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
}
if (false == g_ActiveConfig.bCopyEFBToTexture)
@@ -318,7 +401,6 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
FramebufferManager::SetFramebuffer(0);
VertexShaderManager::SetViewportChanged();
- DisableStage(0);
GL_REPORT_ERRORD();
@@ -328,63 +410,97 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0);
}
+
+ g_renderer->RestoreAPIState();
}
-void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1)
+TextureCache::TextureCache()
{
- 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,
- };
- const GLint c_WrapSettings[4] =
- {
- GL_CLAMP_TO_EDGE,
- GL_REPEAT,
- GL_MIRRORED_REPEAT,
- GL_REPEAT,
- };
-
- 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));
+ const char *pColorMatrixProg =
+ "uniform sampler2DRect samp9;\n"
+ "uniform vec4 colmat[7];\n"
+ "in vec2 uv0;\n"
+ "out vec4 ocol0;\n"
+ "\n"
+ "void main(){\n"
+ " vec4 texcol = texture2DRect(samp9, uv0);\n"
+ " texcol = round(texcol * colmat[5]) * colmat[6];\n"
+ " ocol0 = texcol * mat4(colmat[0], colmat[1], colmat[2], colmat[3]) + colmat[4];\n"
+ "}\n";
+
+ const char *pDepthMatrixProg =
+ "uniform sampler2DRect samp9;\n"
+ "uniform vec4 colmat[5];\n"
+ "in vec2 uv0;\n"
+ "out vec4 ocol0;\n"
+ "\n"
+ "void main(){\n"
+ " vec4 texcol = texture2DRect(samp9, uv0);\n"
+ " vec4 EncodedDepth = fract((texcol.r * (16777215.0f/16777216.0f)) * vec4(1.0f,256.0f,256.0f*256.0f,1.0f));\n"
+ " texcol = round(EncodedDepth * (16777216.0f/16777215.0f) * vec4(255.0f,255.0f,255.0f,15.0f)) / vec4(255.0f,255.0f,255.0f,15.0f);\n"
+ " ocol0 = texcol * mat4(colmat[0], colmat[1], colmat[2], colmat[3]) + colmat[4];"
+ "}\n";
+
+
+ const char *VProgram =
+ "in vec2 rawpos;\n"
+ "in vec2 tex0;\n"
+ "out vec2 uv0;\n"
+ "void main()\n"
+ "{\n"
+ " uv0 = tex0;\n"
+ " gl_Position = vec4(rawpos,0,1);\n"
+ "}\n";
+
+ ProgramShaderCache::CompileShader(s_ColorMatrixProgram, VProgram, pColorMatrixProg);
+ ProgramShaderCache::CompileShader(s_DepthMatrixProgram, VProgram, pDepthMatrixProg);
+
+ s_ColorMatrixUniform = glGetUniformLocation(s_ColorMatrixProgram.glprogid, "colmat");
+ s_DepthMatrixUniform = glGetUniformLocation(s_DepthMatrixProgram.glprogid, "colmat");
+ s_ColorCbufid = -1;
+ s_DepthCbufid = -1;
+
+ s_ActiveTexture = -1;
+ s_NextStage = -1;
+ for(int i=0; i<8; i++)
+ s_Textures[i] = -1;
}
+
TextureCache::~TextureCache()
{
- if (s_TempFramebuffer)
+ s_ColorMatrixProgram.Destroy();
+ s_DepthMatrixProgram.Destroy();
+
+ for(std::map<u64, VBOCache>::iterator it = s_VBO.begin(); it != s_VBO.end(); it++) {
+ glDeleteBuffers(1, &it->second.vbo);
+ glDeleteVertexArrays(1, &it->second.vao);
+ }
+ s_VBO.clear();
+
+ if (s_TempFramebuffer)
{
- glDeleteFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
- s_TempFramebuffer = 0;
- }
+ glDeleteFramebuffers(1, (GLuint*)&s_TempFramebuffer);
+ s_TempFramebuffer = 0;
+ }
}
void TextureCache::DisableStage(unsigned int stage)
{
- glActiveTexture(GL_TEXTURE0 + stage);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_TEXTURE_RECTANGLE_ARB);
}
+void TextureCache::SetStage ()
+{
+ // -1 is the initial value as we don't know which testure should be bound
+ if(s_ActiveTexture != (u32)-1)
+ glActiveTexture(GL_TEXTURE0 + s_ActiveTexture);
+}
+
+void TextureCache::SetNextStage ( unsigned int stage )
+{
+ s_NextStage = stage;
+}
+
+
+
}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h
index a26aa4049e..a41c86e0b3 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h
@@ -32,7 +32,10 @@ namespace OGL
class TextureCache : public ::TextureCache
{
public:
+ TextureCache();
static void DisableStage(unsigned int stage);
+ static void SetStage();
+ static void SetNextStage(unsigned int stage);
private:
struct TCacheEntry : TCacheEntryBase
@@ -45,7 +48,7 @@ private:
int gl_iformat;
int gl_type;
- bool bHaveMipMaps;
+ int m_tex_levels;
//TexMode0 mode; // current filter and clamp modes that texture is set to
//TexMode1 mode1; // current filter and clamp modes that texture is set to
@@ -63,9 +66,6 @@ private:
void Bind(unsigned int stage);
bool Save(const char filename[], unsigned int level);
-
- private:
- void SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1);
};
~TextureCache();
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp
index c73d3abdbf..c076563310 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp
@@ -23,7 +23,7 @@
#include "TextureConverter.h"
#include "TextureConversionShader.h"
#include "TextureCache.h"
-#include "PixelShaderCache.h"
+#include "ProgramShaderCache.h"
#include "VertexShaderManager.h"
#include "FramebufferManager.h"
#include "Globals.h"
@@ -50,64 +50,73 @@ static GLuint s_dstRenderBuffer = 0; // for encoding to RAM
const int renderBufferWidth = 1024;
const int renderBufferHeight = 1024;
-static FRAGMENTSHADER s_rgbToYuyvProgram;
-static FRAGMENTSHADER s_yuyvToRgbProgram;
+static SHADER s_rgbToYuyvProgram;
+static SHADER s_yuyvToRgbProgram;
// Not all slots are taken - but who cares.
const u32 NUM_ENCODING_PROGRAMS = 64;
-static FRAGMENTSHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS];
-
-void CreateRgbToYuyvProgram()
-{
- // Output is BGRA because that is slightly faster than RGBA.
- const char *FProgram =
- "uniform samplerRECT samp0 : register(s0);\n"
- "void main(\n"
- " out float4 ocol0 : COLOR0,\n"
- " in float2 uv0 : TEXCOORD0)\n"
+static SHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS];
+
+static GLuint s_encode_VBO = 0;
+static GLuint s_encode_VAO = 0;
+static GLuint s_decode_VBO = 0;
+static GLuint s_decode_VAO = 0;
+static TargetRectangle s_cached_sourceRc;
+static int s_cached_srcWidth = 0;
+static int s_cached_srcHeight = 0;
+
+static const char *VProgram =
+ "in vec2 rawpos;\n"
+ "in vec2 tex0;\n"
+ "out vec2 uv0;\n"
+ "void main()\n"
"{\n"
- " float2 uv1 = float2(uv0.x + 1.0f, uv0.y);\n"
- " float3 c0 = texRECT(samp0, uv0).rgb;\n"
- " float3 c1 = texRECT(samp0, uv1).rgb;\n"
- " float3 y_const = float3(0.257f,0.504f,0.098f);\n"
- " float3 u_const = float3(-0.148f,-0.291f,0.439f);\n"
- " float3 v_const = float3(0.439f,-0.368f,-0.071f);\n"
- " float4 const3 = float4(0.0625f,0.5f,0.0625f,0.5f);\n"
- " float3 c01 = (c0 + c1) * 0.5f;\n"
- " ocol0 = float4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n"
+ " uv0 = tex0;\n"
+ " gl_Position = vec4(rawpos,0,1);\n"
"}\n";
- if (!PixelShaderCache::CompilePixelShader(s_rgbToYuyvProgram, FProgram))
- ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program.");
-}
-
-void CreateYuyvToRgbProgram()
+void CreatePrograms()
{
- const char *FProgram =
- "uniform samplerRECT samp0 : register(s0);\n"
- "void main(\n"
- " out float4 ocol0 : COLOR0,\n"
- " in float2 uv0 : TEXCOORD0)\n"
- "{\n"
- " float4 c0 = texRECT(samp0, uv0).rgba;\n"
-
- " float f = step(0.5, frac(uv0.x));\n"
- " float y = lerp(c0.b, c0.r, f);\n"
- " float yComp = 1.164f * (y - 0.0625f);\n"
- " float uComp = c0.g - 0.5f;\n"
- " float vComp = c0.a - 0.5f;\n"
-
- " ocol0 = float4(yComp + (1.596f * vComp),\n"
- " yComp - (0.813f * vComp) - (0.391f * uComp),\n"
- " yComp + (2.018f * uComp),\n"
- " 1.0f);\n"
- "}\n";
-
- if (!PixelShaderCache::CompilePixelShader(s_yuyvToRgbProgram, FProgram))
- ERROR_LOG(VIDEO, "Failed to create YUYV to RGB fragment program.");
+ // Output is BGRA because that is slightly faster than RGBA.
+ const char *FProgramRgbToYuyv =
+ "uniform sampler2DRect samp9;\n"
+ "in vec2 uv0;\n"
+ "out vec4 ocol0;\n"
+ "void main()\n"
+ "{\n"
+ " vec3 c0 = texture2DRect(samp9, uv0).rgb;\n"
+ " vec3 c1 = texture2DRect(samp9, uv0 + vec2(1.0, 0.0)).rgb;\n"
+ " vec3 c01 = (c0 + c1) * 0.5;\n"
+ " vec3 y_const = vec3(0.257,0.504,0.098);\n"
+ " vec3 u_const = vec3(-0.148,-0.291,0.439);\n"
+ " vec3 v_const = vec3(0.439,-0.368,-0.071);\n"
+ " vec4 const3 = vec4(0.0625,0.5,0.0625f,0.5);\n"
+ " ocol0 = vec4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n"
+ "}\n";
+
+ const char *FProgramYuyvToRgb =
+ "uniform sampler2DRect samp9;\n"
+ "in vec2 uv0;\n"
+ "out vec4 ocol0;\n"
+ "void main()\n"
+ "{\n"
+ " vec4 c0 = texture2DRect(samp9, uv0).rgba;\n"
+ " float f = step(0.5, fract(uv0.x));\n"
+ " float y = mix(c0.b, c0.r, f);\n"
+ " float yComp = 1.164f * (y - 0.0625f);\n"
+ " float uComp = c0.g - 0.5f;\n"
+ " float vComp = c0.a - 0.5f;\n"
+ " ocol0 = vec4(yComp + (1.596f * vComp),\n"
+ " yComp - (0.813f * vComp) - (0.391f * uComp),\n"
+ " yComp + (2.018f * uComp),\n"
+ " 1.0f);\n"
+ "}\n";
+
+ ProgramShaderCache::CompileShader(s_rgbToYuyvProgram, VProgram, FProgramRgbToYuyv);
+ ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgram, FProgramYuyvToRgb);
}
-FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
+SHADER &GetOrCreateEncodingShader(u32 format)
{
if (format > NUM_ENCODING_PROGRAMS)
{
@@ -117,7 +126,7 @@ FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
if (s_encodingPrograms[format].glprogid == 0)
{
- const char* shader = TextureConversionShader::GenerateEncodingShader(format,API_OPENGL);
+ const char* shader = TextureConversionShader::GenerateEncodingShader(format, API_OPENGL);
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader)
@@ -130,20 +139,43 @@ FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
}
#endif
- if (!PixelShaderCache::CompilePixelShader(s_encodingPrograms[format], shader)) {
- ERROR_LOG(VIDEO, "Failed to create encoding fragment program");
- }
+ ProgramShaderCache::CompileShader(s_encodingPrograms[format], VProgram, shader);
}
return s_encodingPrograms[format];
}
void Init()
{
- glGenFramebuffersEXT(1, &s_texConvFrameBuffer);
-
- glGenRenderbuffersEXT(1, &s_dstRenderBuffer);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, renderBufferWidth, renderBufferHeight);
+ glGenFramebuffers(1, &s_texConvFrameBuffer);
+
+ glGenBuffers(1, &s_encode_VBO );
+ glGenVertexArrays(1, &s_encode_VAO );
+ glBindBuffer(GL_ARRAY_BUFFER, s_encode_VBO );
+ glBindVertexArray( s_encode_VAO );
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL);
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
+ s_cached_sourceRc.top = -1;
+ s_cached_sourceRc.bottom = -1;
+ s_cached_sourceRc.left = -1;
+ s_cached_sourceRc.right = -1;
+
+ glGenBuffers(1, &s_decode_VBO );
+ glGenVertexArrays(1, &s_decode_VAO );
+ glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO );
+ glBindVertexArray( s_decode_VAO );
+ s_cached_srcWidth = -1;
+ s_cached_srcHeight = -1;
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL);
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
+
+ glGenRenderbuffers(1, &s_dstRenderBuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, s_dstRenderBuffer);
+
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, renderBufferWidth, renderBufferHeight);
s_srcTextureWidth = 0;
s_srcTextureHeight = 0;
@@ -152,16 +184,20 @@ void Init()
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
- CreateRgbToYuyvProgram();
- CreateYuyvToRgbProgram();
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+
+ CreatePrograms();
}
void Shutdown()
{
glDeleteTextures(1, &s_srcTexture);
- glDeleteRenderbuffersEXT(1, &s_dstRenderBuffer);
- glDeleteFramebuffersEXT(1, &s_texConvFrameBuffer);
+ glDeleteRenderbuffers(1, &s_dstRenderBuffer);
+ glDeleteFramebuffers(1, &s_texConvFrameBuffer);
+ glDeleteBuffers(1, &s_encode_VBO );
+ glDeleteVertexArrays(1, &s_encode_VAO );
+ glDeleteBuffers(1, &s_decode_VBO );
+ glDeleteVertexArrays(1, &s_decode_VAO );
s_rgbToYuyvProgram.Destroy();
s_yuyvToRgbProgram.Destroy();
@@ -174,8 +210,8 @@ void Shutdown()
s_texConvFrameBuffer = 0;
}
-void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const TargetRectangle& sourceRc,
- u8* destAddr, int dstWidth, int dstHeight, int readStride,
+void EncodeToRamUsingShader(GLuint srcTexture, const TargetRectangle& sourceRc,
+ u8* destAddr, int dstWidth, int dstHeight, int readStride,
bool toTexture, bool linearFilter)
{
@@ -184,42 +220,52 @@ void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const Tar
// attach render buffer as color destination
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, s_dstRenderBuffer);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, s_dstRenderBuffer);
GL_REPORT_ERRORD();
- for (int i = 1; i < 8; ++i)
- TextureCache::DisableStage(i);
-
// set source texture
- glActiveTexture(GL_TEXTURE0);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture);
+ glActiveTexture(GL_TEXTURE0+9);
+ glBindTexture(GL_TEXTURE_RECTANGLE, srcTexture);
if (linearFilter)
{
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
else
{
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
GL_REPORT_ERRORD();
glViewport(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight);
- PixelShaderCache::SetCurrentShader(shader.glprogid);
-
- // Draw...
- glBegin(GL_QUADS);
- glTexCoord2f((float)sourceRc.left, (float)sourceRc.top); glVertex2f(-1,-1);
- glTexCoord2f((float)sourceRc.left, (float)sourceRc.bottom); glVertex2f(-1,1);
- glTexCoord2f((float)sourceRc.right, (float)sourceRc.bottom); glVertex2f(1,1);
- glTexCoord2f((float)sourceRc.right, (float)sourceRc.top); glVertex2f(1,-1);
- glEnd();
+ GL_REPORT_ERRORD();
+ if(!(s_cached_sourceRc == sourceRc)) {
+ GLfloat vertices[] = {
+ -1.f, -1.f,
+ (float)sourceRc.left, (float)sourceRc.top,
+ -1.f, 1.f,
+ (float)sourceRc.left, (float)sourceRc.bottom,
+ 1.f, 1.f,
+ (float)sourceRc.right, (float)sourceRc.bottom,
+ 1.f, -1.f,
+ (float)sourceRc.right, (float)sourceRc.top
+ };
+ glBindBuffer(GL_ARRAY_BUFFER, s_encode_VBO );
+ glBufferData(GL_ARRAY_BUFFER, 4*4*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
+
+ s_cached_sourceRc = sourceRc;
+ }
+
+ glBindVertexArray( s_encode_VAO );
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+
GL_REPORT_ERRORD();
// .. and then read back the results.
@@ -266,9 +312,7 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt))
format |= _GX_TF_CTF;
- FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format);
- if (texconv_shader.glprogid == 0)
- return 0;
+ SHADER& texconv_shader = GetOrCreateEncodingShader(format);
u8 *dest_ptr = Memory::GetPointer(address);
@@ -285,14 +329,18 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
// extra pixels are copied but not displayed in the resulting texture
s32 expandedWidth = (width + blkW) & (~blkW);
s32 expandedHeight = (height + blkH) & (~blkH);
-
+
float sampleStride = bScaleByHalf ? 2.f : 1.f;
- TextureConversionShader::SetShaderParameters((float)expandedWidth,
- (float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this?
- (float)Renderer::EFBToScaledX(source.left),
- (float)Renderer::EFBToScaledY(EFB_HEIGHT - source.top - expandedHeight),
- Renderer::EFBToScaledXf(sampleStride),
- Renderer::EFBToScaledYf(sampleStride));
+
+ float params[] = {
+ Renderer::EFBToScaledXf(sampleStride), Renderer::EFBToScaledYf(sampleStride),
+ 0.0f, 0.0f,
+ (float)expandedWidth, (float)Renderer::EFBToScaledY(expandedHeight)-1,
+ (float)Renderer::EFBToScaledX(source.left), (float)Renderer::EFBToScaledY(EFB_HEIGHT - source.top - expandedHeight)
+ };
+
+ texconv_shader.Bind();
+ glUniform4fv(texconv_shader.UniformLocations[C_COLORS], 2, params);
TargetRectangle scaledSource;
scaledSource.top = 0;
@@ -305,7 +353,7 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
int readStride = (expandedWidth * cacheBytes) /
TexDecoder_GetBlockWidthInTexels(format);
- EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource,
+ EncodeToRamUsingShader(source_texture, scaledSource,
dest_ptr, expandedWidth / samples, expandedHeight, readStride,
true, bScaleByHalf > 0 && !bFromZBuffer);
return size_in_bytes; // TODO: D3D11 is calculating this value differently!
@@ -315,10 +363,12 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight)
{
g_renderer->ResetAPIState();
- EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
+
+ s_rgbToYuyvProgram.Bind();
+
+ EncodeToRamUsingShader(srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
FramebufferManager::SetFramebuffer(0);
VertexShaderManager::SetViewportChanged();
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
TextureCache::DisableStage(0);
g_renderer->RestoreAPIState();
GL_REPORT_ERRORD();
@@ -326,7 +376,7 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* des
// Should be scale free.
-void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture)
+void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destRenderbuf)
{
u8* srcAddr = Memory::GetPointer(xfbAddr);
if (!srcAddr)
@@ -342,51 +392,60 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur
// switch to texture converter frame buffer
// attach destTexture as color destination
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, destRenderbuf);
GL_REPORT_FBO_ERROR();
- for (int i = 1; i < 8; ++i)
- TextureCache::DisableStage(i);
-
// activate source texture
// set srcAddr as data for source texture
- glActiveTexture(GL_TEXTURE0);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture);
+ glActiveTexture(GL_TEXTURE0+9);
+ glBindTexture(GL_TEXTURE_RECTANGLE, s_srcTexture);
// TODO: make this less slow. (How?)
- if((GLsizei)s_srcTextureWidth == (GLsizei)srcFmtWidth && (GLsizei)s_srcTextureHeight == (GLsizei)srcHeight)
+ if ((GLsizei)s_srcTextureWidth == (GLsizei)srcFmtWidth && (GLsizei)s_srcTextureHeight == (GLsizei)srcHeight)
{
- glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,0,0,s_srcTextureWidth, s_srcTextureHeight,
+ glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0,0,0,s_srcTextureWidth, s_srcTextureHeight,
GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
}
else
{
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)srcFmtWidth, (GLsizei)srcHeight,
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA8, (GLsizei)srcFmtWidth, (GLsizei)srcHeight,
0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
s_srcTextureWidth = (GLsizei)srcFmtWidth;
s_srcTextureHeight = (GLsizei)srcHeight;
}
glViewport(0, 0, srcWidth, srcHeight);
-
- PixelShaderCache::SetCurrentShader(s_yuyvToRgbProgram.glprogid);
+ s_yuyvToRgbProgram.Bind();
GL_REPORT_ERRORD();
-
- glBegin(GL_QUADS);
- glTexCoord2f((float)srcFmtWidth, (float)srcHeight); glVertex2f(1,-1);
- glTexCoord2f((float)srcFmtWidth, 0); glVertex2f(1,1);
- glTexCoord2f(0, 0); glVertex2f(-1,1);
- glTexCoord2f(0, (float)srcHeight); glVertex2f(-1,-1);
- glEnd();
+
+ if(s_cached_srcHeight != srcHeight || s_cached_srcWidth != srcWidth) {
+ GLfloat vertices[] = {
+ 1.f, -1.f,
+ (float)srcFmtWidth, (float)srcHeight,
+ 1.f, 1.f,
+ (float)srcFmtWidth, 0.f,
+ -1.f, 1.f,
+ 0.f, 0.f,
+ -1.f, -1.f,
+ 0.f, (float)srcHeight
+ };
+
+ glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO );
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*4, vertices, GL_STREAM_DRAW);
+
+ s_cached_srcHeight = srcHeight;
+ s_cached_srcWidth = srcWidth;
+ }
+
+ glBindVertexArray( s_decode_VAO );
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ GL_REPORT_ERRORD();
// reset state
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
- TextureCache::DisableStage(0);
VertexShaderManager::SetViewportChanged();
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h
index 4113778603..b226e20180 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h
@@ -35,7 +35,7 @@ void Shutdown();
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight);
-void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
+void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destRenderbuf);
// returns size of the encoded data (in bytes)
int EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp
index 6ea10fc077..228eeb757d 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp
@@ -29,10 +29,9 @@
#include "ImageWrite.h"
#include "BPMemory.h"
#include "TextureCache.h"
-#include "PixelShaderCache.h"
#include "PixelShaderManager.h"
-#include "VertexShaderCache.h"
#include "VertexShaderManager.h"
+#include "ProgramShaderCache.h"
#include "VertexShaderGen.h"
#include "VertexLoader.h"
#include "VertexManager.h"
@@ -40,6 +39,9 @@
#include "OpcodeDecoding.h"
#include "FileUtil.h"
#include "Debugger.h"
+#include "StreamBuffer.h"
+#include "PerfQueryBase.h"
+#include "Render.h"
#include "main.h"
@@ -48,62 +50,117 @@ extern NativeVertexFormat *g_nativeVertexFmt;
namespace OGL
{
+//This are the initially requeted size for the buffers expresed in bytes
+const u32 MAX_IBUFFER_SIZE = 2*1024*1024;
+const u32 MAX_VBUFFER_SIZE = 16*1024*1024;
-//static GLint max_Index_size = 0;
-
-//static GLuint s_vboBuffers[MAXVBOBUFFERCOUNT] = {0};
-//static int s_nCurVBOIndex = 0; // current free buffer
+static StreamBuffer *s_vertexBuffer;
+static StreamBuffer *s_indexBuffer;
+static u32 s_baseVertex;
+static u32 s_offset[3];
VertexManager::VertexManager()
{
- // TODO: doesn't seem to be used anywhere
-
- //glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*)&max_Index_size);
- //
- //if (max_Index_size > MAXIBUFFERSIZE)
- // max_Index_size = MAXIBUFFERSIZE;
- //
- //GL_REPORT_ERRORD();
+ CreateDeviceObjects();
+}
- glEnableClientState(GL_VERTEX_ARRAY);
- GL_REPORT_ERRORD();
+VertexManager::~VertexManager()
+{
+ DestroyDeviceObjects();
}
void VertexManager::CreateDeviceObjects()
{
+ s_vertexBuffer = new StreamBuffer(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE);
+ m_vertex_buffers = s_vertexBuffer->getBuffer();
+ s_indexBuffer = new StreamBuffer(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE, (StreamType)(DETECT_MASK & ~PINNED_MEMORY));
+ m_index_buffers = s_indexBuffer->getBuffer();
-
+ m_CurrentVertexFmt = NULL;
+ m_last_vao = 0;
}
+
void VertexManager::DestroyDeviceObjects()
{
+ GL_REPORT_ERRORD();
+ glBindBuffer(GL_ARRAY_BUFFER, 0 );
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0 );
+ GL_REPORT_ERROR();
+ delete s_vertexBuffer;
+ delete s_indexBuffer;
+ GL_REPORT_ERROR();
}
-void VertexManager::Draw()
+void VertexManager::PrepareDrawBuffers(u32 stride)
{
- if (IndexGenerator::GetNumTriangles() > 0)
+ u32 vertex_data_size = IndexGenerator::GetNumVerts() * stride;
+ u32 triangle_index_size = IndexGenerator::GetTriangleindexLen();
+ u32 line_index_size = IndexGenerator::GetLineindexLen();
+ u32 point_index_size = IndexGenerator::GetPointindexLen();
+ u32 index_size = (triangle_index_size+line_index_size+point_index_size) * sizeof(u16);
+
+ s_vertexBuffer->Alloc(vertex_data_size, stride);
+ u32 offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size);
+ s_baseVertex = offset / stride;
+
+ s_indexBuffer->Alloc(index_size);
+ if(triangle_index_size)
{
- glDrawElements(GL_TRIANGLES, IndexGenerator::GetTriangleindexLen(), GL_UNSIGNED_SHORT, TIBuffer);
- INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ s_offset[0] = s_indexBuffer->Upload((u8*)GetTriangleIndexBuffer(), triangle_index_size * sizeof(u16));
}
- if (IndexGenerator::GetNumLines() > 0)
+ if(line_index_size)
{
- glDrawElements(GL_LINES, IndexGenerator::GetLineindexLen(), GL_UNSIGNED_SHORT, LIBuffer);
- INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ s_offset[1] = s_indexBuffer->Upload((u8*)GetLineIndexBuffer(), line_index_size * sizeof(u16));
}
- if (IndexGenerator::GetNumPoints() > 0)
+ if(point_index_size)
{
- glDrawElements(GL_POINTS, IndexGenerator::GetPointindexLen(), GL_UNSIGNED_SHORT, PIBuffer);
- INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ s_offset[2] = s_indexBuffer->Upload((u8*)GetPointIndexBuffer(), point_index_size * sizeof(u16));
+ }
+}
+
+void VertexManager::Draw(u32 stride)
+{
+ u32 triangle_index_size = IndexGenerator::GetTriangleindexLen();
+ u32 line_index_size = IndexGenerator::GetLineindexLen();
+ u32 point_index_size = IndexGenerator::GetPointindexLen();
+ if(g_ogl_config.bSupportsGLBaseVertex) {
+ if (triangle_index_size > 0)
+ {
+ glDrawElementsBaseVertex(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
+ if (line_index_size > 0)
+ {
+ glDrawElementsBaseVertex(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1], s_baseVertex);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
+ if (point_index_size > 0)
+ {
+ glDrawElementsBaseVertex(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2], s_baseVertex);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
+ } else {
+ if (triangle_index_size > 0)
+ {
+ glDrawElements(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0]);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
+ if (line_index_size > 0)
+ {
+ glDrawElements(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1]);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
+ if (point_index_size > 0)
+ {
+ glDrawElements(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2]);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
}
}
void VertexManager::vFlush()
{
- if (LocalVBuffer == s_pCurBufferPointer) return;
- if (Flushed) return;
- Flushed=true;
- VideoFifo_CheckEFBAccess();
#if defined(_DEBUG) || defined(DEBUGFAST)
PRIM_LOG("frame%d:\n texgen=%d, numchan=%d, dualtex=%d, ztex=%d, cole=%d, alpe=%d, ze=%d", g_ActiveConfig.iSaveTargetId, xfregs.numTexGen.numTexGens,
xfregs.numChan.numColorChans, xfregs.dualTexTrans.enabled, bpmem.ztex2.op,
@@ -134,13 +191,15 @@ void VertexManager::vFlush()
(void)GL_REPORT_ERROR();
- //glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]);
- //glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - LocalVBuffer, LocalVBuffer, GL_STREAM_DRAW);
- GL_REPORT_ERRORD();
+ GLVertexFormat *nativeVertexFmt = (GLVertexFormat*)g_nativeVertexFmt;
+ u32 stride = nativeVertexFmt->GetVertexStride();
+
+ if(m_last_vao != nativeVertexFmt->VAO) {
+ glBindVertexArray(nativeVertexFmt->VAO);
+ m_last_vao = nativeVertexFmt->VAO;
+ }
- // setup the pointers
- if (g_nativeVertexFmt)
- g_nativeVertexFmt->SetupVertexPointers();
+ PrepareDrawBuffers(stride);
GL_REPORT_ERRORD();
u32 usedtextures = 0;
@@ -153,11 +212,12 @@ void VertexManager::vFlush()
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt);
- for (int i = 0; i < 8; i++)
+ for (u32 i = 0; i < 8; i++)
{
if (usedtextures & (1 << i))
{
- glActiveTexture(GL_TEXTURE0 + i);
+ TextureCache::SetNextStage(i);
+ g_renderer->SetSamplerState(i % 4, i / 4);
FourTexUnits &tex = bpmem.tex[i >> 2];
TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i,
(tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5,
@@ -178,59 +238,64 @@ void VertexManager::vFlush()
}
}
- // set global constants
- VertexShaderManager::SetConstants();
- PixelShaderManager::SetConstants();
-
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate
&& bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
-#ifdef USE_DUAL_SOURCE_BLEND
- bool dualSourcePossible = GLEW_ARB_blend_func_extended;
+ // Makes sure we can actually do Dual source blending
+ bool dualSourcePossible = g_ActiveConfig.backend_info.bSupportsDualSourceBlend;
// finally bind
- FRAGMENTSHADER* ps;
if (dualSourcePossible)
{
if (useDstAlpha)
{
// If host supports GL_ARB_blend_func_extended, we can do dst alpha in
// the same pass as regular rendering.
- g_renderer->SetBlendMode(true);
- ps = PixelShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components);
+ ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components);
}
else
{
- g_renderer->SetBlendMode(true);
- ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
+ ProgramShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
}
}
else
{
- ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
+ ProgramShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
}
-#else
- bool dualSourcePossible = false;
- FRAGMENTSHADER* ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
-#endif
- VERTEXSHADER* vs = VertexShaderCache::SetShader(g_nativeVertexFmt->m_components);
- if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid); // Lego Star Wars crashes here.
- if (vs) VertexShaderCache::SetCurrentShader(vs->glprogid);
- Draw();
+ // set global constants
+ VertexShaderManager::SetConstants();
+ PixelShaderManager::SetConstants();
+ ProgramShaderCache::UploadConstants();
+
+ // setup the pointers
+ if (g_nativeVertexFmt)
+ g_nativeVertexFmt->SetupVertexPointers();
+ GL_REPORT_ERRORD();
+
+ g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
+ Draw(stride);
+ g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
+ //ERROR_LOG(VIDEO, "PerfQuery result: %d", g_perf_query->GetQueryResult(bpmem.zcontrol.early_ztest ? PQ_ZCOMP_OUTPUT_ZCOMPLOC : PQ_ZCOMP_OUTPUT));
// run through vertex groups again to set alpha
if (useDstAlpha && !dualSourcePossible)
{
- ps = PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components);
- if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid);
-
+ ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components);
+ if (!g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ {
+ // Need to set these again, if we don't support UBO
+ VertexShaderManager::SetConstants();
+ PixelShaderManager::SetConstants();
+ }
+
// only update alpha
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glDisable(GL_BLEND);
- Draw();
+ Draw(stride);
+
// restore color mask
g_renderer->SetColorMask();
@@ -238,22 +303,21 @@ void VertexManager::vFlush()
glEnable(GL_BLEND);
}
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
-
- //s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers);
- s_pCurBufferPointer = LocalVBuffer;
- IndexGenerator::Start(TIBuffer,LIBuffer,PIBuffer);
-
+
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS)
{
// save the shaders
+ ProgramShaderCache::PCacheEntry prog = ProgramShaderCache::GetShaderProgram();
char strfile[255];
sprintf(strfile, "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
- std::ofstream fps(strfile);
- fps << ps->strprog.c_str();
+ std::ofstream fps;
+ OpenFStream(fps, strfile, std::ios_base::out);
+ fps << prog.shader.strpprog.c_str();
sprintf(strfile, "%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
- std::ofstream fvs(strfile);
- fvs << vs->strprog.c_str();
+ std::ofstream fvs;
+ OpenFStream(fvs, strfile, std::ios_base::out);
+ fvs << prog.shader.strvprog.c_str();
}
if (g_ActiveConfig.iLog & CONF_SAVETARGETS)
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h
index 5cec1bf97e..6a33799d98 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h
@@ -24,6 +24,19 @@
namespace OGL
{
+ class GLVertexFormat : public NativeVertexFormat
+ {
+ PortableVertexDeclaration vtx_decl;
+
+ public:
+ GLVertexFormat();
+ ~GLVertexFormat();
+
+ virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
+ virtual void SetupVertexPointers();
+
+ GLuint VAO;
+ };
// Handles the OpenGL details of drawing lots of vertices quickly.
// Other functionality is moving out.
@@ -31,14 +44,20 @@ class VertexManager : public ::VertexManager
{
public:
VertexManager();
-
+ ~VertexManager();
NativeVertexFormat* CreateNativeVertexFormat();
void CreateDeviceObjects();
void DestroyDeviceObjects();
+
+ // NativeVertexFormat use this
+ GLuint m_vertex_buffers;
+ GLuint m_index_buffers;
+ GLuint m_last_vao;
private:
- void Draw();
- // temp
+ void Draw(u32 stride);
void vFlush();
+ void PrepareDrawBuffers(u32 stride);
+ NativeVertexFormat *m_CurrentVertexFmt;
};
}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp
index dbbb7ee29b..038021c490 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp
@@ -26,7 +26,7 @@
#include "Render.h"
#include "VertexShaderGen.h"
#include "VertexShaderManager.h"
-#include "VertexShaderCache.h"
+#include "ProgramShaderCache.h"
#include "VertexManager.h"
#include "VertexLoader.h"
#include "XFMemory.h"
@@ -37,236 +37,104 @@
namespace OGL
{
-VertexShaderCache::VSCache VertexShaderCache::vshaders;
-GLuint VertexShaderCache::CurrentShader;
-bool VertexShaderCache::ShaderEnabled;
-
-VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry = NULL;
-VERTEXSHADERUID VertexShaderCache::last_uid;
-
-static int s_nMaxVertexInstructions;
-
-
-void VertexShaderCache::Init()
+void SetVSConstant4fvByName(const char * name, unsigned int offset, const float *f, const unsigned int count = 1)
{
- glEnable(GL_VERTEX_PROGRAM_ARB);
- ShaderEnabled = true;
- CurrentShader = 0;
- last_entry = NULL;
-
- glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions);
- if (strstr((const char*)glGetString(GL_VENDOR), "Humper") != NULL) s_nMaxVertexInstructions = 4096;
-#if CG_VERSION_NUM == 2100
- if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
+ ProgramShaderCache::PCacheEntry tmp = ProgramShaderCache::GetShaderProgram();
+ for (int a = 0; a < NUM_UNIFORMS; ++a)
{
- s_nMaxVertexInstructions = 4096;
+ if (!strcmp(name, UniformNames[a]))
+ {
+ if (tmp.shader.UniformLocations[a] == -1)
+ return;
+ else
+ {
+ glUniform4fv(tmp.shader.UniformLocations[a] + offset, count, f);
+ return;
+ }
+ }
}
-#endif
}
-void VertexShaderCache::Shutdown()
+void Renderer::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{
- for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter)
- iter->second.Destroy();
- vshaders.clear();
-}
+ float const buf[4] = {f1, f2, f3, f4};
-
-VERTEXSHADER* VertexShaderCache::SetShader(u32 components)
-{
- VERTEXSHADERUID uid;
- GetVertexShaderId(&uid, components);
- if (last_entry)
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- if (uid == last_uid)
- {
- GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
- ValidateVertexShaderIDs(API_OPENGL, vshaders[uid].safe_uid, vshaders[uid].shader.strprog, components);
- return &last_entry->shader;
- }
+ ProgramShaderCache::SetMultiVSConstant4fv(const_number, buf, 1);
+ return;
}
-
- last_uid = uid;
-
- VSCache::iterator iter = vshaders.find(uid);
- if (iter != vshaders.end())
+ for (unsigned int a = 0; a < 9; ++a)
{
- VSCacheEntry &entry = iter->second;
- last_entry = &entry;
-
- GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
- ValidateVertexShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, components);
- return &last_entry->shader;
- }
-
- // Make an entry in the table
- VSCacheEntry& entry = vshaders[uid];
- last_entry = &entry;
- const char *code = GenerateVertexShaderCode(components, API_OPENGL);
- GetSafeVertexShaderId(&entry.safe_uid, components);
-
-#if defined(_DEBUG) || defined(DEBUGFAST)
- if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
- static int counter = 0;
- char szTemp[MAX_PATH];
- sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
-
- SaveData(szTemp, code);
- }
-#endif
-
- if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) {
- GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
- return NULL;
+ if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - VSVar_Loc[a].reg;
+ SetVSConstant4fvByName(VSVar_Loc[a].name, offset, buf);
+ return;
+ }
}
-
- INCSTAT(stats.numVertexShadersCreated);
- SETSTAT(stats.numVertexShadersAlive, vshaders.size());
- GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
- return &last_entry->shader;
}
-bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
+void Renderer::SetVSConstant4fv(unsigned int const_number, const float *f)
{
- // Reset GL error before compiling shaders. Yeah, we need to investigate the causes of these.
- GLenum err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR)
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- ERROR_LOG(VIDEO, "glError %08x before VS!", err);
- }
-
-#if defined HAVE_CG && HAVE_CG
- char stropt[64];
- sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions);
- const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
- CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgvProf, "main", opts);
- if (!cgIsProgram(tempprog)) {
- static int num_failures = 0;
- char szTemp[MAX_PATH];
- sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
- file << pstrprogram;
- file.close();
-
- PanicAlert("Failed to compile vertex shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%d):\n%s",
- szTemp,
- g_cgfProf,
- cgGetLastListing(g_cgcontext));
-
- cgDestroyProgram(tempprog);
- ERROR_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
- ERROR_LOG(VIDEO, "%s", pstrprogram);
- return false;
+ ProgramShaderCache::SetMultiVSConstant4fv(const_number, f, 1);
+ return;
}
-
- if (cgGetError() != CG_NO_ERROR)
+ for (unsigned int a = 0; a < 9; ++a)
{
- WARN_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
- WARN_LOG(VIDEO, "%s", pstrprogram);
- }
-
- // This looks evil - we modify the program through the const char * we got from cgGetProgramString!
- // It SHOULD not have any nasty side effects though - but you never know...
- char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
- char *plocal = strstr(pcompiledprog, "program.local");
- while (plocal != NULL) {
- const char* penv = " program.env";
- memcpy(plocal, penv, 13);
- plocal = strstr(plocal + 13, "program.local");
- }
- glGenProgramsARB(1, &vs.glprogid);
- SetCurrentShader(vs.glprogid);
-
- glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
- err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR) {
- ERROR_LOG(VIDEO, "%s", pstrprogram);
- ERROR_LOG(VIDEO, "%s", pcompiledprog);
+ if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - VSVar_Loc[a].reg;
+ SetVSConstant4fvByName(VSVar_Loc[a].name, offset, f);
+ return;
+ }
}
-
- cgDestroyProgram(tempprog);
-#endif
-
- if (g_ActiveConfig.bEnableShaderDebugging)
- vs.strprog = pstrprogram;
-
- return true;
}
-void VertexShaderCache::DisableShader()
+void Renderer::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{
- if (ShaderEnabled)
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- glDisable(GL_VERTEX_PROGRAM_ARB);
- ShaderEnabled = false;
+ ProgramShaderCache::SetMultiVSConstant4fv(const_number, f, count);
+ return;
+ }
+ for (unsigned int a = 0; a < 9; ++a)
+ {
+ if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - VSVar_Loc[a].reg;
+ SetVSConstant4fvByName(VSVar_Loc[a].name, offset, f, count);
+ return;
+ }
}
}
-
-void VertexShaderCache::SetCurrentShader(GLuint Shader)
+void Renderer::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
{
- if (!ShaderEnabled)
+ float buf[4 * C_VENVCONST_END];
+ for (unsigned int i = 0; i < count; i++)
{
- glEnable(GL_VERTEX_PROGRAM_ARB);
- ShaderEnabled= true;
+ buf[4*i ] = *f++;
+ buf[4*i+1] = *f++;
+ buf[4*i+2] = *f++;
+ buf[4*i+3] = 0.f;
}
- if (CurrentShader != Shader)
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- if(Shader != 0)
- CurrentShader = Shader;
- glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
+ ProgramShaderCache::SetMultiVSConstant4fv(const_number, buf, count);
+ return;
}
-}
-
-void Renderer::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
-{
- glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, const_number, f1, f2, f3, f4);
-}
-
-void Renderer::SetVSConstant4fv(unsigned int const_number, const float *f)
-{
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
-}
-
-void Renderer::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
-{
- if(GLEW_EXT_gpu_program_parameters)
- {
- glProgramEnvParameters4fvEXT(GL_VERTEX_PROGRAM_ARB, const_number, count, f);
- }
- else
- {
- for (unsigned int i = 0; i < count; i++,f+=4)
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, f);
- }
-}
-
-void Renderer::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
-{
- if(GLEW_EXT_gpu_program_parameters)
+ for (unsigned int a = 0; a < 9; ++a)
{
- float buf[4 * C_VENVCONST_END];
- for (unsigned int i = 0; i < count; i++)
- {
- buf[4*i ] = *f++;
- buf[4*i+1] = *f++;
- buf[4*i+2] = *f++;
- buf[4*i+3] = 0.f;
- }
- glProgramEnvParameters4fvEXT(GL_VERTEX_PROGRAM_ARB, const_number, count, buf);
- }
- else
- {
- for (unsigned int i = 0; i < count; i++)
- {
- float buf[4];
- buf[0] = *f++;
- buf[1] = *f++;
- buf[2] = *f++;
- buf[3] = 0.f;
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, buf);
- }
- }
+ if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - VSVar_Loc[a].reg;
+ SetVSConstant4fvByName(VSVar_Loc[a].name, offset, buf, count);
+ return;
+ }
+ }
}
} // namespace OGL
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h
deleted file mode 100644
index 6f4cbe25c2..0000000000
--- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (C) 2003 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#ifndef _VERTEXSHADERCACHE_H_
-#define _VERTEXSHADERCACHE_H_
-
-#include <map>
-#include <string>
-
-#include "BPMemory.h"
-#include "VertexShaderGen.h"
-
-namespace OGL
-{
-
-struct VERTEXSHADER
-{
- VERTEXSHADER() : glprogid(0) {}
- GLuint glprogid; // opengl program id
-
- std::string strprog;
-};
-
-class VertexShaderCache
-{
- struct VSCacheEntry
- {
- VERTEXSHADER shader;
- VERTEXSHADERUIDSAFE safe_uid;
- VSCacheEntry() {}
- void Destroy() {
- // printf("Destroying vs %i\n", shader.glprogid);
- glDeleteProgramsARB(1, &shader.glprogid);
- shader.glprogid = 0;
- }
- };
-
- typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
-
- static VSCache vshaders;
-
- static VSCacheEntry* last_entry;
- static VERTEXSHADERUID last_uid;
-
- static GLuint CurrentShader;
- static bool ShaderEnabled;
-
-public:
- static void Init();
- static void Shutdown();
-
- static VERTEXSHADER* SetShader(u32 components);
- static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram);
-
- static void SetCurrentShader(GLuint Shader);
- static void DisableShader();
-
-};
-
-} // namespace OGL
-
-#endif // _VERTEXSHADERCACHE_H_
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VideoBackend.h b/Source/Plugins/Plugin_VideoOGL/Src/VideoBackend.h
index 4c7414794d..2520c72763 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/VideoBackend.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/VideoBackend.h
@@ -15,6 +15,7 @@ class VideoBackend : public VideoBackendHardware
std::string GetName();
void Video_Prepare();
+ void Video_Cleanup();
void ShowConfig(void* parent);
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp
index 05f21beed1..ddce3bb01f 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp
@@ -55,6 +55,7 @@ Make AA apply instantly during gameplay if possible
#include "LogManager.h"
#include <cstdarg>
+#include <algorithm>
#ifdef _WIN32
#include "EmuWindow.h"
@@ -79,10 +80,9 @@ Make AA apply instantly during gameplay if possible
#include "VertexLoader.h"
#include "VertexLoaderManager.h"
#include "VertexManager.h"
-#include "PixelShaderCache.h"
#include "PixelShaderManager.h"
-#include "VertexShaderCache.h"
#include "VertexShaderManager.h"
+#include "ProgramShaderCache.h"
#include "CommandProcessor.h"
#include "PixelEngine.h"
#include "TextureConverter.h"
@@ -92,6 +92,8 @@ Make AA apply instantly during gameplay if possible
#include "FramebufferManager.h"
#include "Core.h"
#include "Host.h"
+#include "SamplerCache.h"
+#include "PerfQuery.h"
#include "VideoState.h"
#include "VideoBackend.h"
@@ -107,37 +109,39 @@ std::string VideoBackend::GetName()
void GetShaders(std::vector<std::string> &shaders)
{
- shaders.clear();
- if (File::IsDirectory(File::GetUserPath(D_SHADERS_IDX)))
- {
- File::FSTEntry entry;
- File::ScanDirectoryTree(File::GetUserPath(D_SHADERS_IDX), entry);
- for (u32 i = 0; i < entry.children.size(); i++)
- {
- std::string name = entry.children[i].virtualName.c_str();
- if (!strcasecmp(name.substr(name.size() - 4).c_str(), ".txt"))
- name = name.substr(0, name.size() - 4);
- shaders.push_back(name);
- }
- }
- else
- {
- File::CreateDir(File::GetUserPath(D_SHADERS_IDX).c_str());
- }
+ shaders.clear();
+ if (File::IsDirectory(File::GetUserPath(D_SHADERS_IDX)))
+ {
+ File::FSTEntry entry;
+ File::ScanDirectoryTree(File::GetUserPath(D_SHADERS_IDX), entry);
+ for (u32 i = 0; i < entry.children.size(); i++)
+ {
+ std::string name = entry.children[i].virtualName.c_str();
+ if (!strcasecmp(name.substr(name.size() - 4).c_str(), ".txt")) {
+ name = name.substr(0, name.size() - 4);
+ shaders.push_back(name);
+ }
+ }
+ std::sort(shaders.begin(), shaders.end());
+ }
+ else
+ {
+ File::CreateDir(File::GetUserPath(D_SHADERS_IDX).c_str());
+ }
}
void InitBackendInfo()
{
g_Config.backend_info.APIType = API_OPENGL;
- g_Config.backend_info.bUseRGBATextures = false;
+ g_Config.backend_info.bUseRGBATextures = true;
g_Config.backend_info.bUseMinimalMipCount = false;
g_Config.backend_info.bSupports3DVision = false;
- g_Config.backend_info.bSupportsDualSourceBlend = false; // supported, but broken
+ //g_Config.backend_info.bSupportsDualSourceBlend = true; // is gpu depenend and must be set in renderer
g_Config.backend_info.bSupportsFormatReinterpretation = false;
g_Config.backend_info.bSupportsPixelLighting = true;
// aamodes
- const char* caamodes[] = {"None", "2x", "4x", "8x", "8x CSAA", "8xQ CSAA", "16x CSAA", "16xQ CSAA"};
+ const char* caamodes[] = {"None", "2x", "4x", "8x", "8x CSAA", "8xQ CSAA", "16x CSAA", "16xQ CSAA", "4x SSAA"};
g_Config.backend_info.AAModes.assign(caamodes, caamodes + sizeof(caamodes)/sizeof(*caamodes));
// pp shaders
@@ -190,21 +194,24 @@ void VideoBackend::Video_Prepare()
CommandProcessor::Init();
PixelEngine::Init();
- g_texture_cache = new TextureCache;
-
BPInit();
g_vertex_manager = new VertexManager;
+ g_perf_query = new PerfQuery;
Fifo_Init(); // must be done before OpcodeDecoder_Init()
OpcodeDecoder_Init();
- VertexShaderCache::Init();
VertexShaderManager::Init();
- PixelShaderCache::Init();
PixelShaderManager::Init();
+ ProgramShaderCache::Init();
PostProcessing::Init();
+ g_texture_cache = new TextureCache();
+ g_sampler_cache = new SamplerCache();
+ Renderer::Init();
GL_REPORT_ERRORD();
VertexLoaderManager::Init();
TextureConverter::Init();
+#ifndef _M_GENERIC
DLCache::Init();
+#endif
// Notify the core that the video backend is ready
Host_Message(WM_USER_CREATE);
@@ -213,32 +220,40 @@ void VideoBackend::Video_Prepare()
void VideoBackend::Shutdown()
{
s_BackendInitialized = false;
+ GLInterface->Shutdown();
+}
+void VideoBackend::Video_Cleanup() {
+
if (g_renderer)
{
s_efbAccessRequested = false;
s_FifoShuttingDown = false;
s_swapRequested = false;
+#ifndef _M_GENERIC
DLCache::Shutdown();
+#endif
Fifo_Shutdown();
- PostProcessing::Shutdown();
// The following calls are NOT Thread Safe
// And need to be called from the video thread
+ Renderer::Shutdown();
TextureConverter::Shutdown();
VertexLoaderManager::Shutdown();
- VertexShaderCache::Shutdown();
+ delete g_sampler_cache;
+ g_sampler_cache = NULL;
+ delete g_texture_cache;
+ g_texture_cache = NULL;
+ PostProcessing::Shutdown();
+ ProgramShaderCache::Shutdown();
VertexShaderManager::Shutdown();
PixelShaderManager::Shutdown();
- PixelShaderCache::Shutdown();
delete g_vertex_manager;
- delete g_texture_cache;
+ g_vertex_manager = NULL;
OpcodeDecoder_Shutdown();
delete g_renderer;
g_renderer = NULL;
- g_texture_cache = NULL;
}
- GLInterface->Shutdown();
}
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt b/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt
index 15db15e654..0488f728b8 100644
--- a/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt
+++ b/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt
@@ -10,6 +10,7 @@ set(SRCS Src/BPMemLoader.cpp
Src/OpcodeDecoder.cpp
Src/SWPixelEngine.cpp
Src/Rasterizer.cpp
+ Src/RasterFont.cpp
Src/SWRenderer.cpp
Src/SetupUnit.cpp
Src/SWStatistics.cpp
diff --git a/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj b/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj
index 66cfab9b01..0f18d096f8 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj
+++ b/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj
@@ -184,6 +184,7 @@
<ClCompile Include="Src\OpcodeDecoder.cpp" />
<ClCompile Include="Src\SWPixelEngine.cpp" />
<ClCompile Include="Src\Rasterizer.cpp" />
+ <ClCompile Include="Src\RasterFont.cpp" />
<ClCompile Include="Src\SWRenderer.cpp" />
<ClCompile Include="Src\SetupUnit.cpp" />
<ClCompile Include="Src\SWStatistics.cpp" />
@@ -217,6 +218,7 @@
<ClInclude Include="Src\OpcodeDecoder.h" />
<ClInclude Include="Src\SWPixelEngine.h" />
<ClInclude Include="Src\Rasterizer.h" />
+ <ClInclude Include="Src\RasterFont.h" />
<ClInclude Include="Src\SWRenderer.h" />
<ClInclude Include="Src\SetupUnit.h" />
<ClInclude Include="Src\SWStatistics.h" />
diff --git a/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj.filters b/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj.filters
index 4bc1901325..14be6ff447 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj.filters
+++ b/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj.filters
@@ -13,6 +13,7 @@
<ClCompile Include="Src\OpcodeDecoder.cpp" />
<ClCompile Include="Src\SWPixelEngine.cpp" />
<ClCompile Include="Src\Rasterizer.cpp" />
+ <ClCompile Include="Src\RasterFont.cpp" />
<ClCompile Include="Src\SWRenderer.cpp" />
<ClCompile Include="Src\SetupUnit.cpp" />
<ClCompile Include="Src\SWStatistics.cpp" />
@@ -39,6 +40,7 @@
<ClInclude Include="Src\OpcodeDecoder.h" />
<ClInclude Include="Src\SWPixelEngine.h" />
<ClInclude Include="Src\Rasterizer.h" />
+ <ClInclude Include="Src\RasterFont.h" />
<ClInclude Include="Src\SWRenderer.h" />
<ClInclude Include="Src\SetupUnit.h" />
<ClInclude Include="Src\SWStatistics.h" />
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp
index f05f9f8b57..0d7c77c767 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp
@@ -90,6 +90,21 @@ void SWBPWritten(int address, int newvalue)
SWPixelEngine::pereg.boxBottom = newvalue >> 10;
SWPixelEngine::pereg.boxTop = newvalue & 0x3ff;
break;
+ case BPMEM_CLEAR_PIXEL_PERF:
+ // TODO: I didn't test if the value written to this register affects the amount of cleared registers
+ SWPixelEngine::pereg.perfZcompInputZcomplocLo = 0;
+ SWPixelEngine::pereg.perfZcompInputZcomplocHi = 0;
+ SWPixelEngine::pereg.perfZcompOutputZcomplocLo = 0;
+ SWPixelEngine::pereg.perfZcompOutputZcomplocHi = 0;
+ SWPixelEngine::pereg.perfZcompInputLo = 0;
+ SWPixelEngine::pereg.perfZcompInputHi = 0;
+ SWPixelEngine::pereg.perfZcompOutputLo = 0;
+ SWPixelEngine::pereg.perfZcompOutputHi = 0;
+ SWPixelEngine::pereg.perfBlendInputLo = 0;
+ SWPixelEngine::pereg.perfBlendInputHi = 0;
+ SWPixelEngine::pereg.perfEfbCopyClocksLo = 0;
+ SWPixelEngine::pereg.perfEfbCopyClocksHi = 0;
+ break;
case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here.
break;
case BPMEM_LOADTLUT1: // Load a Texture Look Up Table
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp
index e9a3525d84..c4755b50bf 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp
@@ -65,6 +65,13 @@ namespace Clipper
OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
OutputVertexData *Vertices[NUM_INDICES];
+ void DoState(PointerWrap &p)
+ {
+ p.DoArray(m_ViewOffset,2);
+ for (int i = 0; i< NUM_CLIPPED_VERTICES; ++i)
+ ClippedVertices[i].DoState(p);
+ }
+
void Init()
{
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h
index 5e5dd4d02c..babc8b4e88 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h
@@ -21,6 +21,7 @@
#include "Common.h"
#include "NativeVertexFormat.h"
+#include "ChunkFile.h"
namespace Clipper
@@ -36,6 +37,8 @@ namespace Clipper
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface);
void PerspectiveDivide(OutputVertexData *vertex);
+
+ void DoState(PointerWrap &p);
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp
index 6722ec7935..77d87988c8 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp
@@ -28,6 +28,7 @@ u8 efb[EFB_WIDTH*EFB_HEIGHT*6];
namespace EfbInterface
{
+
u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4];
inline u32 GetColorOffset(u16 x, u16 y)
@@ -40,6 +41,12 @@ namespace EfbInterface
return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START;
}
+ void DoState(PointerWrap &p)
+ {
+ p.DoArray(efb, EFB_WIDTH*EFB_HEIGHT*6);
+ p.DoArray(efbColorTexture, EFB_WIDTH*EFB_HEIGHT*4);
+ }
+
void SetPixelAlphaOnly(u32 offset, u8 a)
{
switch (bpmem.zcontrol.pixel_format)
@@ -454,10 +461,11 @@ namespace EfbInterface
SetPixelAlphaOnly(offset, color[ALP_C]);
}
- void SetDepth(u16 x, u16 y, u32 depth)
- {
- SetPixelDepth(GetDepthOffset(x, y), depth);
- }
+ void SetDepth(u16 x, u16 y, u32 depth)
+ {
+ if (bpmem.zmode.updateenable)
+ SetPixelDepth(GetDepthOffset(x, y), depth);
+ }
void GetColor(u16 x, u16 y, u8 *color)
{
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h
index 15d19e7783..fdad69567c 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h
@@ -47,6 +47,7 @@ namespace EfbInterface
void UpdateColorTexture();
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format
+ void DoState(PointerWrap &p);
}
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h b/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h
index d19844105f..e2d87e207e 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h
@@ -19,6 +19,7 @@
#define _NATIVEVERTEXFORMAT_H
#include "Vec3.h"
+#include "ChunkFile.h"
#ifdef WIN32
#define LOADERDECL __cdecl
@@ -92,6 +93,18 @@ struct OutputVertexData
#undef LINTERP
#undef LINTERP_INT
}
+ void DoState(PointerWrap &p)
+ {
+ mvPosition.DoState(p);
+ p.Do(projectedPosition);
+ screenPosition.DoState(p);
+ for (int i = 0; i < 3;++i)
+ normal[i].DoState(p);
+ p.DoArray(color, sizeof color);
+ for (int i = 0; i < 8;++i)
+ texCoords[i].DoState(p);
+ }
+
};
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp
index 0091e4eaca..4848cb4d43 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp
@@ -35,7 +35,6 @@ typedef void (*DecodingFunction)(u32);
namespace OpcodeDecoder
{
-
static DecodingFunction currentFunction = NULL;
static u32 minCommandSize;
static u16 streamSize;
@@ -46,6 +45,20 @@ static bool inObjectStream;
static u8 lastPrimCmd;
+void DoState(PointerWrap &p)
+{
+ p.Do(minCommandSize);
+ // Not sure what is wrong with this. Something(s) in here is causing dolphin to crash/hang when loading states saved from another run of dolphin. Doesn't seem too important anyway...
+ //vertexLoader.DoState(p);
+ p.Do(readOpcode);
+ p.Do(inObjectStream);
+ p.Do(lastPrimCmd);
+ p.Do(streamSize);
+ p.Do(streamAddress);
+ if (p.GetMode() == PointerWrap::MODE_READ)
+ ResetDecoding();
+}
+
void DecodePrimitiveStream(u32 iBufferSize)
{
u32 vertexSize = vertexLoader.GetVertexSize();
@@ -125,7 +138,9 @@ void DecodeStandard(u32 bufferSize)
if (Cmd == GX_NOP)
return;
-
+ // Causes a SIGBUS error on Android
+ // XXX: Investigate
+#ifndef ANDROID
// check if switching in or out of an object
// only used for debuggging
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
@@ -139,7 +154,7 @@ void DecodeStandard(u32 bufferSize)
lastPrimCmd = Cmd & 0x87;
DebugUtil::OnObjectBegin();
}
-
+#endif
switch(Cmd)
{
case GX_NOP:
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h
index 635fcc24ee..53715b2832 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h
@@ -20,6 +20,7 @@
#define _OPCODEDECODER_H_
#include "CommonTypes.h"
+#include "ChunkFile.h"
namespace OpcodeDecoder
{
@@ -57,6 +58,8 @@ namespace OpcodeDecoder
bool CommandRunnable(u32 iBufferSize);
void Run(u32 iBufferSize);
+
+ void DoState(PointerWrap &p);
}
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.cpp
new file mode 100644
index 0000000000..fe20146e31
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.cpp
@@ -0,0 +1,223 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "../../Plugin_VideoOGL/Src/GLUtil.h"
+
+#include <string.h>
+
+#include "RasterFont.h"
+// globals
+
+const GLubyte rasters[][13] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
+ {0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00},
+ {0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18},
+ {0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70},
+ {0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e},
+ {0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c},
+ {0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30},
+ {0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00},
+ {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03},
+ {0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c},
+ {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18},
+ {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e},
+ {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e},
+ {0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c},
+ {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
+ {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
+ {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff},
+ {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
+ {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
+ {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06},
+ {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60},
+ {0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e},
+ {0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18},
+ {0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
+ {0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
+ {0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc},
+ {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
+ {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff},
+ {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
+ {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
+ {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e},
+ {0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
+ {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3},
+ {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
+ {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3},
+ {0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3},
+ {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e},
+ {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
+ {0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c},
+ {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
+ {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e},
+ {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff},
+ {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
+ {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
+ {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
+ {0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
+ {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
+ {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff},
+ {0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c},
+ {0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60},
+ {0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18},
+ {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70},
+ {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
+ {0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03},
+ {0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e},
+ {0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0},
+ {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00},
+ {0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00},
+ {0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0},
+ {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78},
+ {0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+ {0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00},
+ {0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00},
+ {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
+ {0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f},
+ {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+ {0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
+};
+
+RasterFont::RasterFont()
+{
+ // set GL modes
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ // create the raster font
+ fontOffset = glGenLists(128);
+ for (int i = 32; i < 127; i++) {
+ glNewList(i + fontOffset, GL_COMPILE);
+ glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
+ glEndList();
+ }
+
+ temp_buffer = new char[TEMP_BUFFER_SIZE];
+}
+
+RasterFont::~RasterFont()
+{
+ glDeleteLists(fontOffset, 128);
+ delete [] temp_buffer;
+}
+
+void RasterFont::printString(const char *s, double x, double y, double z)
+{
+ int length = (int)strlen(s);
+ if (!length)
+ return;
+ if (length >= TEMP_BUFFER_SIZE)
+ length = TEMP_BUFFER_SIZE - 1;
+
+ // Sanitize string to avoid GL errors.
+ char *s2 = temp_buffer;
+ memcpy(s2, s, length);
+ s2[length] = 0;
+ for (int i = 0; i < length; i++) {
+ if (s2[i] < 32 || s2[i] > 126)
+ s2[i] = '!';
+ }
+
+ // go to the right spot
+ glRasterPos3d(x, y, z);
+ GL_REPORT_ERRORD();
+
+ glPushAttrib (GL_LIST_BIT);
+ glListBase(fontOffset);
+ glCallLists((GLsizei)strlen(s2), GL_UNSIGNED_BYTE, (GLubyte *) s2);
+ GL_REPORT_ERRORD();
+ glPopAttrib();
+ GL_REPORT_ERRORD();
+}
+
+void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z)
+{
+ int length = (int)strlen(s);
+ int x = (int)(screen_width/2.0 - (length/2.0)*char_width);
+ printString(s, x, y, z);
+}
+
+void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight)
+{
+ double x = start_x;
+ double y = start_y;
+ char temp[1024];
+ char *t = temp;
+ while (*text)
+ {
+ if (*text == '\n')
+ {
+ *t = 0;
+ printString(temp, x, y, z);
+ y -= char_height * 2.0f / bbHeight;
+ x = start_x;
+ t = temp;
+ }
+ else if (*text == '\r')
+ {
+ t = temp;
+ }
+ else if (*text == '\t')
+ {
+ //todo: add tabs every something like 4*char_width
+ *t = 0;
+ int cpos = (int)strlen(temp);
+ int newpos = (cpos + 4) & (~3);
+ printString(temp, x, y, z);
+ x = start_x + (char_width*newpos) * 2.0f / bbWidth;
+ t = temp;
+ *t++ = ' ';
+ }
+ else
+ *t++ = *text;
+
+ text++;
+ }
+
+ // ????
+ if (t != text)
+ {
+ *t = 0;
+ printString(temp, x, y, z);
+ }
+}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.h b/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.h
new file mode 100644
index 0000000000..3ebc684dd0
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef _RASTERFONT_H_
+#define _RASTERFONT_H_
+
+class RasterFont {
+public:
+ RasterFont();
+ ~RasterFont(void);
+ static int debug;
+
+ // some useful constants
+ enum {char_width = 10};
+ enum {char_height = 15};
+
+ // and the happy helper functions
+ void printString(const char *s, double x, double y, double z=0.0);
+ void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
+
+ void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
+private:
+ int fontOffset;
+ char *temp_buffer;
+ enum {TEMP_BUFFER_SIZE = 64 * 1024};
+};
+
+#endif // _RASTERFONT_H_
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp
index 225400e08b..badb123fa0 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp
@@ -23,6 +23,7 @@
#include "BPMemLoader.h"
#include "XFMemLoader.h"
#include "Tev.h"
+#include "SWPixelEngine.h"
#include "SWStatistics.h"
#include "SWVideoConfig.h"
@@ -62,6 +63,28 @@ s32 scissorBottom = 0;
Tev tev;
RasterBlock rasterBlock;
+void DoState(PointerWrap &p)
+{
+ ZSlope.DoState(p);
+ WSlope.DoState(p);
+ for (int i=0;i<2;++i)
+ for (int n=0; n<4; ++n)
+ ColorSlopes[i][n].DoState(p);
+ for (int i=0;i<8;++i)
+ for (int n=0; n<3; ++n)
+ TexSlopes[i][n].DoState(p);
+ p.Do(vertex0X);
+ p.Do(vertex0Y);
+ p.Do(vertexOffsetX);
+ p.Do(vertexOffsetY);
+ p.Do(scissorLeft);
+ p.Do(scissorTop);
+ p.Do(scissorRight);
+ p.Do(scissorBottom);
+ tev.DoState(p);
+ p.Do(rasterBlock);
+}
+
void Init()
{
tev.Init();
@@ -127,9 +150,15 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
if (bpmem.zcontrol.early_ztest && bpmem.zmode.testenable && g_SWVideoConfig.bZComploc)
{
- // early z
- if (!EfbInterface::ZCompare(x, y, z))
- return;
+ // TODO: Test if perf regs are incremented even if test is disabled
+ SWPixelEngine::pereg.IncZInputQuadCount(true);
+ if (bpmem.zmode.testenable)
+ {
+ // early z
+ if (!EfbInterface::ZCompare(x, y, z))
+ return;
+ }
+ SWPixelEngine::pereg.IncZOutputQuadCount(true);
}
RasterBlockPixel& pixel = rasterBlock.Pixel[xi][yi];
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h
index f8850571a9..784c4a8d62 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h
@@ -19,6 +19,7 @@
#define _RASTERIZER_H_
#include "NativeVertexFormat.h"
+#include "ChunkFile.h"
namespace Rasterizer
{
@@ -37,6 +38,12 @@ namespace Rasterizer
float f0;
float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); }
+ void DoState(PointerWrap &p)
+ {
+ p.Do(dfdx);
+ p.Do(dfdy);
+ p.Do(f0);
+ }
};
struct RasterBlockPixel
@@ -53,6 +60,8 @@ namespace Rasterizer
s32 TextureLod[16];
bool TextureLinear[16];
};
+
+ void DoState(PointerWrap &p);
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp
index b9afc1abb5..6cc4ee4dc8 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp
@@ -57,6 +57,15 @@ CPReg cpreg; // shared between gfx and emulator thread
void DoState(PointerWrap &p)
{
p.Do(cpreg);
+ p.DoArray(commandBuffer, commandBufferSize);
+ p.Do(readPos);
+ p.Do(writePos);
+ p.Do(et_UpdateInterrupts);
+ p.Do(interruptSet);
+ p.Do(interruptWaiting);
+
+ // Is this right?
+ p.DoArray(g_pVideoData,writePos);
}
// does it matter that there is no synchronization between threads during writes?
@@ -115,15 +124,15 @@ void RunGpu()
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
{
// We are going to do FP math on the main thread so have to save the current state
- SaveSSEState();
- LoadDefaultSSEState();
+ FPURoundMode::SaveSIMDState();
+ FPURoundMode::LoadDefaultSIMDState();
// run the opcode decoder
do {
RunBuffer();
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
- LoadSSEState();
+ FPURoundMode::LoadSIMDState();
}
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp
index 33a6164b01..118e59629e 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp
@@ -53,6 +53,8 @@ void DoState(PointerWrap &p)
p.Do(pereg);
p.Do(g_bSignalTokenInterrupt);
p.Do(g_bSignalFinishInterrupt);
+ p.Do(et_SetTokenOnMainThread);
+ p.Do(et_SetFinishOnMainThread);
}
void UpdateInterrupts();
@@ -77,7 +79,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
u16 address = _iAddress & 0xFFF;
- if (address <= 0x16)
+ if (address <= 0x2e)
_uReturnValue = ((u16*)&pereg)[address >> 1];
}
@@ -109,7 +111,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
}
break;
default:
- if (address <= 0x16)
+ if (address <= 0x2e)
((u16*)&pereg)[address >> 1] = _iValue;
break;
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h
index 6a87143e8c..351e53456d 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h
@@ -38,6 +38,21 @@ namespace SWPixelEngine
PE_BBOX_RIGHT = 0x012, // Flip Right
PE_BBOX_TOP = 0x014, // Flip Top
PE_BBOX_BOTTOM = 0x016, // Flip Bottom
+
+ // NOTE: Order not verified
+ // These indicate the number of quads that are being used as input/output for each particular stage
+ PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L = 0x18,
+ PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H = 0x1a,
+ PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L = 0x1c,
+ PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H = 0x1e,
+ PE_PERF_ZCOMP_INPUT_L = 0x20,
+ PE_PERF_ZCOMP_INPUT_H = 0x22,
+ PE_PERF_ZCOMP_OUTPUT_L = 0x24,
+ PE_PERF_ZCOMP_OUTPUT_H = 0x26,
+ PE_PERF_BLEND_INPUT_L = 0x28,
+ PE_PERF_BLEND_INPUT_H = 0x2a,
+ PE_PERF_EFB_COPY_CLOCKS_L = 0x2c,
+ PE_PERF_EFB_COPY_CLOCKS_H = 0x2e,
};
union UPEZConfReg
@@ -125,10 +140,72 @@ namespace SWPixelEngine
UPECtrlReg ctrl;
u16 unk0;
u16 token;
+
u16 boxLeft;
u16 boxRight;
u16 boxTop;
u16 boxBottom;
+
+ u16 perfZcompInputZcomplocLo;
+ u16 perfZcompInputZcomplocHi;
+ u16 perfZcompOutputZcomplocLo;
+ u16 perfZcompOutputZcomplocHi;
+ u16 perfZcompInputLo;
+ u16 perfZcompInputHi;
+ u16 perfZcompOutputLo;
+ u16 perfZcompOutputHi;
+ u16 perfBlendInputLo;
+ u16 perfBlendInputHi;
+ u16 perfEfbCopyClocksLo;
+ u16 perfEfbCopyClocksHi;
+
+ // NOTE: hardware doesn't process individual pixels but quads instead. Current software renderer architecture works on pixels though, so we have this "quad" hack here to only increment the registers on every fourth rendered pixel
+ void IncZInputQuadCount(bool early_ztest)
+ {
+ static int quad = 0;
+ if (++quad != 3)
+ return;
+ quad = 0;
+
+ if (early_ztest)
+ {
+ if (++perfZcompInputZcomplocLo == 0)
+ perfZcompInputZcomplocHi++;
+ }
+ else
+ {
+ if (++perfZcompInputLo == 0)
+ perfZcompInputHi++;
+ }
+ }
+ void IncZOutputQuadCount(bool early_ztest)
+ {
+ static int quad = 0;
+ if (++quad != 3)
+ return;
+ quad = 0;
+
+ if (early_ztest)
+ {
+ if (++perfZcompOutputZcomplocLo == 0)
+ perfZcompOutputZcomplocHi++;
+ }
+ else
+ {
+ if (++perfZcompOutputLo == 0)
+ perfZcompOutputHi++;
+ }
+ }
+ void IncBlendInputQuadCount()
+ {
+ static int quad = 0;
+ if (++quad != 3)
+ return;
+ quad = 0;
+
+ if (++perfBlendInputLo == 0)
+ perfBlendInputHi++;
+ }
};
extern PEReg pereg;
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp
index fb472cfdba..111e6ca57b 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp
@@ -19,7 +19,7 @@
#include <math.h>
#include "../../Plugin_VideoOGL/Src/GLUtil.h"
-#include "../../Plugin_VideoOGL/Src/RasterFont.h"
+#include "RasterFont.h"
#include "SWRenderer.h"
#include "SWStatistics.h"
@@ -30,6 +30,7 @@ static GLint uni_tex = -1;
static GLuint program;
// Rasterfont isn't compatible with GLES
+// degasus: I think it does, but I can't test it
#ifndef USE_GLES
RasterFont* s_pfont = NULL;
#endif
@@ -99,11 +100,11 @@ void SWRenderer::RenderText(const char* pstr, int left, int top, u32 color)
int nBackbufferWidth = (int)GLInterface->GetBackBufferWidth();
int nBackbufferHeight = (int)GLInterface->GetBackBufferHeight();
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
- ((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
+ ((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
s_pfont->printMultilineText(pstr,
- left * 2.0f / (float)nBackbufferWidth - 1,
- 1 - top * 2.0f / (float)nBackbufferHeight,
- 0, nBackbufferWidth, nBackbufferHeight);
+ left * 2.0f / (float)nBackbufferWidth - 1,
+ 1 - top * 2.0f / (float)nBackbufferHeight,
+ 0, nBackbufferWidth, nBackbufferHeight);
#endif
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp
index cc5ee66772..1c1eeb2005 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp
@@ -328,4 +328,15 @@ void SWVertexLoader::LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData
vertexLoader->m_texCoordLoader[index]();
}
-
+void SWVertexLoader::DoState(PointerWrap &p)
+{
+ p.DoArray(m_AttributeLoaders, sizeof m_AttributeLoaders);
+ p.Do(m_VertexSize);
+ p.Do(*m_CurrentVat);
+ p.Do(m_positionLoader);
+ p.Do(m_normalLoader);
+ p.DoArray(m_colorLoader, sizeof m_colorLoader);
+ p.Do(m_NumAttributeLoaders);
+ m_SetupUnit->DoState(p);
+ p.Do(m_TexGenSpecialCase);
+} \ No newline at end of file
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h
index 91a0d8e911..e05346a7a5 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h
@@ -22,6 +22,7 @@
#include "NativeVertexFormat.h"
#include "CPMemLoader.h"
+#include "ChunkFile.h"
class SetupUnit;
@@ -69,7 +70,7 @@ public:
u32 GetVertexSize() { return m_VertexSize; }
void LoadVertex();
-
+ void DoState(PointerWrap &p);
};
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp
index 07947e0ee7..a6705a5236 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp
@@ -23,36 +23,36 @@ SWVideoConfig g_SWVideoConfig;
SWVideoConfig::SWVideoConfig()
{
- bFullscreen = false;
- bHideCursor = false;
- renderToMainframe = false;
+ bFullscreen = false;
+ bHideCursor = false;
+ renderToMainframe = false;
bHwRasterizer = false;
- bShowStats = false;
+ bShowStats = false;
- bDumpTextures = false;
- bDumpObjects = false;
- bDumpFrames = false;
+ bDumpTextures = false;
+ bDumpObjects = false;
+ bDumpFrames = false;
bZComploc = true;
bZFreeze = true;
- bDumpTevStages = false;
+ bDumpTevStages = false;
bDumpTevTextureFetches = false;
- drawStart = 0;
- drawEnd = 100000;
+ drawStart = 0;
+ drawEnd = 100000;
}
void SWVideoConfig::Load(const char* ini_file)
{
- std::string temp;
- IniFile iniFile;
- iniFile.Load(ini_file);
-
- iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware
- iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false);
+ std::string temp;
+ IniFile iniFile;
+ iniFile.Load(ini_file);
+
+ iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware
+ iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false);
iniFile.Get("Rendering", "HwRasterizer", &bHwRasterizer, false);
iniFile.Get("Rendering", "ZComploc", &bZComploc, true);
@@ -72,11 +72,11 @@ void SWVideoConfig::Load(const char* ini_file)
void SWVideoConfig::Save(const char* ini_file)
{
- IniFile iniFile;
- iniFile.Load(ini_file);
+ IniFile iniFile;
+ iniFile.Load(ini_file);
- iniFile.Set("Hardware", "Fullscreen", bFullscreen);
- iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
+ iniFile.Set("Hardware", "Fullscreen", bFullscreen);
+ iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
iniFile.Set("Rendering", "HwRasterizer", bHwRasterizer);
iniFile.Set("Rendering", "ZComploc", &bZComploc);
@@ -92,7 +92,7 @@ void SWVideoConfig::Save(const char* ini_file)
iniFile.Set("Misc", "DrawStart", drawStart);
iniFile.Set("Misc", "DrawEnd", drawEnd);
-
- iniFile.Save(ini_file);
+
+ iniFile.Save(ini_file);
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp
index 332e83d0e8..b524ded329 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp
@@ -39,6 +39,9 @@
#include "FileUtil.h"
#include "VideoBackend.h"
#include "Core.h"
+#include "OpcodeDecoder.h"
+#include "SWVertexLoader.h"
+#include "SWStatistics.h"
#define VSYNC_ENABLED 0
@@ -93,9 +96,33 @@ bool VideoSoftware::Initialize(void *&window_handle)
return true;
}
-void VideoSoftware::DoState(PointerWrap&)
+void VideoSoftware::DoState(PointerWrap& p)
{
- // NYI
+ bool software = true;
+ p.Do(software);
+ if (p.GetMode() == PointerWrap::MODE_READ && software == false)
+ // change mode to abort load of incompatible save state.
+ p.SetMode(PointerWrap::MODE_VERIFY);
+
+ // TODO: incomplete?
+ SWCommandProcessor::DoState(p);
+ SWPixelEngine::DoState(p);
+ EfbInterface::DoState(p);
+ OpcodeDecoder::DoState(p);
+ Clipper::DoState(p);
+ p.Do(swxfregs);
+ p.Do(bpmem);
+ p.Do(swstats);
+
+ // CP Memory
+ p.DoArray(arraybases, 16);
+ p.DoArray(arraystrides, 16);
+ p.Do(MatrixIndexA);
+ p.Do(MatrixIndexB);
+ p.Do(g_VtxDesc.Hex);
+ p.DoArray(g_VtxAttr, 8);
+ p.DoMarker("CP Memory");
+
}
void VideoSoftware::CheckInvalidState()
@@ -132,18 +159,26 @@ void VideoSoftware::EmuStateChange(EMUSTATE_CHANGE newState)
void VideoSoftware::Shutdown()
{
+ // TODO: should be in Video_Cleanup
HwRasterizer::Shutdown();
SWRenderer::Shutdown();
+
GLInterface->Shutdown();
}
+void VideoSoftware::Video_Cleanup()
+{
+}
+
// This is called after Video_Initialize() from the Core
void VideoSoftware::Video_Prepare()
{
GLInterface->MakeCurrent();
// Init extension support.
- // Required for WGL SwapInterval
#ifndef USE_GLES
+#ifdef __APPLE__
+ glewExperimental = 1;
+#endif
if (glewInit() != GLEW_OK) {
ERROR_LOG(VIDEO, "glewInit() failed!Does your video card support OpenGL 2.x?");
return;
@@ -198,6 +233,12 @@ u32 VideoSoftware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputDa
return value;
}
+u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type)
+{
+ // TODO:
+ return 0;
+}
+
bool VideoSoftware::Video_Screenshot(const char *_szFilename)
{
return false;
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp
index 6e0fab57d8..d2185e31d5 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp
@@ -25,13 +25,13 @@
void SetupUnit::Init(u8 primitiveType)
{
- m_PrimType = primitiveType;
+ m_PrimType = primitiveType;
- m_VertexCounter = 0;
- m_VertPointer[0] = &m_Vertices[0];
- m_VertPointer[1] = &m_Vertices[1];
- m_VertPointer[2] = &m_Vertices[2];
- m_VertWritePointer = m_VertPointer[0];
+ m_VertexCounter = 0;
+ m_VertPointer[0] = &m_Vertices[0];
+ m_VertPointer[1] = &m_Vertices[1];
+ m_VertPointer[2] = &m_Vertices[2];
+ m_VertWritePointer = m_VertPointer[0];
}
void SetupUnit::SetupVertex()
@@ -169,3 +169,21 @@ void SetupUnit::SetupLineStrip()
void SetupUnit::SetupPoint()
{}
+
+void SetupUnit::DoState(PointerWrap &p)
+{
+ // TODO: some or all of this is making the save states stop working once dolphin is closed...sometimes (usually)
+ // I have no idea what specifically is wrong, or if this is even important. Disabling it doesn't seem to make any noticible difference...
+/* p.Do(m_PrimType);
+ p.Do(m_VertexCounter);
+ for (int i = 0; i < 3; ++i)
+ m_Vertices[i].DoState(p);
+
+ if (p.GetMode() == PointerWrap::MODE_READ)
+ {
+ m_VertPointer[0] = &m_Vertices[0];
+ m_VertPointer[1] = &m_Vertices[1];
+ m_VertPointer[2] = &m_Vertices[2];
+ m_VertWritePointer = m_VertPointer[0];
+ }*/
+}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h
index 45a575afcb..f337de21a2 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h
@@ -21,6 +21,7 @@
#include "Common.h"
#include "NativeVertexFormat.h"
+#include "ChunkFile.h"
class SetupUnit
{
@@ -45,6 +46,7 @@ public:
OutputVertexData* GetVertex() { return m_VertWritePointer; }
void SetupVertex();
+ void DoState(PointerWrap &p);
};
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp
index 927f8931e9..fa072508eb 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp
@@ -20,11 +20,13 @@
#include "Tev.h"
#include "EfbInterface.h"
#include "TextureSampler.h"
+#include "XFMemLoader.h"
+#include "SWPixelEngine.h"
#include "SWStatistics.h"
#include "SWVideoConfig.h"
#include "DebugUtil.h"
-#include <math.h>
+#include <cmath>
#ifdef _DEBUG
#define ALLOW_TEV_DUMPS 1
@@ -747,10 +749,22 @@ void Tev::Draw()
}
- // stuff to do!
- // here, where we'll have to add/handle x range adjustment (if related BP register it's enabled)
- // x_adjust = sqrt((x-center)^2 + k^2)/k
- // ze *= x_adjust
+ if(bpmem.fogRange.Base.Enabled)
+ {
+ // TODO: This is untested and should definitely be checked against real hw.
+ // - No idea if offset is really normalized against the viewport width or against the projection matrix or yet something else
+ // - scaling of the "k" coefficient isn't clear either.
+
+ // First, calculate the offset from the viewport center (normalized to 0..1)
+ float offset = (Position[0] - (bpmem.fogRange.Base.Center - 342)) / (float)swxfregs.viewport.wd;
+ // Based on that, choose the index such that points which are far away from the z-axis use the 10th "k" value and such that central points use the first value.
+ int index = 9 - std::abs(offset) * 9.f;
+ index = (index < 0) ? 0 : (index > 9) ? 9 : 0; // TODO: Shouldn't be necessary!
+ // Look up coefficient... Seems like multiplying by 4 makes Fortune Street work properly (fog is too strong without the factor)
+ float k = bpmem.fogRange.K[index/2].GetValue(index%2) * 4.f;
+ float x_adjust = sqrt(offset*offset + k*k)/k;
+ ze *= x_adjust; // NOTE: This is basically dividing by a cosine (hidden behind GXInitFogAdjTable): 1/cos = c/b = sqrt(a^2+b^2)/b
+ }
ze -= bpmem.fog.c_proj_fsel.GetC();
@@ -787,8 +801,13 @@ void Tev::Draw()
bool late_ztest = !bpmem.zcontrol.early_ztest || !g_SWVideoConfig.bZComploc;
if (late_ztest && bpmem.zmode.testenable)
{
- if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2]))
- return;
+ // TODO: Check against hw if these values get incremented even if depth testing is disabled
+ SWPixelEngine::pereg.IncZInputQuadCount(false);
+
+ if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2]))
+ return;
+
+ SWPixelEngine::pereg.IncZOutputQuadCount(false);
}
#if ALLOW_TEV_DUMPS
@@ -812,6 +831,7 @@ void Tev::Draw()
#endif
INCSTAT(swstats.thisFrame.tevPixelsOut);
+ SWPixelEngine::pereg.IncBlendInputQuadCount();
EfbInterface::BlendTev(Position[0], Position[1], output);
}
@@ -827,3 +847,31 @@ void Tev::SetRegColor(int reg, int comp, bool konst, s16 color)
Reg[reg][comp] = color;
}
}
+
+void Tev::DoState(PointerWrap &p)
+{
+ p.DoArray(Reg, sizeof(Reg));
+
+ p.DoArray(KonstantColors, sizeof(KonstantColors));
+ p.DoArray(TexColor,4);
+ p.DoArray(RasColor,4);
+ p.DoArray(StageKonst,4);
+ p.DoArray(Zero16,4);
+
+ p.DoArray(FixedConstants,9);
+ p.Do(AlphaBump);
+ p.DoArray(IndirectTex, sizeof(IndirectTex));
+ p.Do(TexCoord);
+
+ p.DoArray(m_BiasLUT,4);
+ p.DoArray(m_ScaleLShiftLUT,4);
+ p.DoArray(m_ScaleRShiftLUT,4);
+
+ p.DoArray(Position,3);
+ p.DoArray(Color, sizeof(Color));
+ p.DoArray(Uv, 8);
+ p.DoArray(IndirectLod,4);
+ p.DoArray(IndirectLinear,4);
+ p.DoArray(TextureLod,16);
+ p.DoArray(TextureLinear,16);
+}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h
index bdd265170c..1d1bc8d2ba 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h
@@ -19,6 +19,7 @@
#define _TEV_H_
#include "BPMemLoader.h"
+#include "ChunkFile.h"
class Tev
{
@@ -96,6 +97,8 @@ public:
void SetRegColor(int reg, int comp, bool konst, s16 color);
enum { ALP_C, BLU_C, GRN_C, RED_C };
+
+ void DoState(PointerWrap &p);
};
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp
index c95365eddd..e7bb4b91f2 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp
@@ -88,13 +88,13 @@ void TransformPosition(const InputVertexData *src, OutputVertexData *dst)
const float* mat = (const float*)&swxfregs.posMatrices[src->posMtx * 4];
MultiplyVec3Mat34(src->position, mat, dst->mvPosition);
- if (swxfregs.projection[6] == 0)
+ if (swxfregs.projection.type == GX_PERSPECTIVE)
{
- MultipleVec3Perspective(dst->mvPosition, swxfregs.projection, dst->projectedPosition);
+ MultipleVec3Perspective(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
}
else
{
- MultipleVec3Ortho(dst->mvPosition, swxfregs.projection, dst->projectedPosition);
+ MultipleVec3Ortho(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
}
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h b/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h
index 3a36a13307..80460edd60 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <math.h>
+#include "ChunkFile.h"
class Vec3
{
@@ -111,6 +112,12 @@ public:
{
memset((void *)this,0,sizeof(float)*3);
}
+ void DoState(PointerWrap &p)
+ {
+ p.Do(x);
+ p.Do(y);
+ p.Do(z);
+ }
};
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h b/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h
index 3e1490031f..37fe817f07 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h
@@ -21,12 +21,15 @@ class VideoSoftware : public VideoBackend
void ShowConfig(void* parent);
void Video_Prepare();
+ void Video_Cleanup();
void Video_EnterLoop();
void Video_ExitLoop();
void Video_BeginField(u32, FieldType, u32, u32);
void Video_EndField();
+
u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
+ u32 Video_GetQueryResult(PerfQueryType type);
void Video_AddMessage(const char* pstr, unsigned int milliseconds);
void Video_ClearMessages();
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp
index bd085a3edf..e7122d2f71 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp
@@ -34,7 +34,7 @@ IntegerSetting<T>::IntegerSetting(wxWindow* parent, const wxString& label, T& se
VideoConfigDialog::VideoConfigDialog(wxWindow* parent, const std::string& title, const std::string& _ininame) :
wxDialog(parent, -1,
- wxString(wxT("Dolphin ")).append(wxString::FromAscii(title.c_str())).append(wxT(" Graphics Configuration")),
+ wxString(wxT("Dolphin ")).append(StrToWxStr(title)).append(wxT(" Graphics Configuration")),
wxDefaultPosition, wxDefaultSize),
vconfig(g_SWVideoConfig),
ininame(_ininame)
@@ -64,10 +64,10 @@ VideoConfigDialog::VideoConfigDialog(wxWindow* parent, const std::string& title,
it = g_available_video_backends.begin(),
itend = g_available_video_backends.end();
for (; it != itend; ++it)
- choice_backend->AppendString(wxString::FromAscii((*it)->GetName().c_str()));
+ choice_backend->AppendString(StrToWxStr((*it)->GetName()));
// TODO: How to get the translated plugin name?
- choice_backend->SetStringSelection(wxString::FromAscii(g_video_backend->GetName().c_str()));
+ choice_backend->SetStringSelection(StrToWxStr(g_video_backend->GetName()));
choice_backend->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDialog::Event_Backend, this);
szr_rendering->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5);
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h b/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h
index f5bb8c3c43..86e8e6c9d8 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h
@@ -85,6 +85,9 @@ struct Light
#define LIGHTATTN_NONE 2
#define LIGHTATTN_DIR 3
+#define GX_PERSPECTIVE 0
+#define GX_ORTHOGRAPHIC 1
+
union LitChannel
{
struct
@@ -160,6 +163,12 @@ struct Viewport
float farZ;
};
+struct Projection
+{
+ float rawProjection[6];
+ u32 type; // only GX_PERSPECTIVE or GX_ORTHOGRAPHIC are allowed
+};
+
union TexMtxInfo
{
struct
@@ -218,7 +227,7 @@ struct XFRegisters
TXFMatrixIndexA MatrixIndexA; // 0x1018
TXFMatrixIndexB MatrixIndexB; // 0x1019
Viewport viewport; // 0x101a - 0x101f
- float projection[7]; // 0x1020 - 0x1026
+ Projection projection; // 0x1020 - 0x1026
u32 unk8[24]; // 0x1027 - 0x103e
u32 numTexGens; // 0x103f
TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
diff --git a/Source/TestSuite/d.supp b/Source/TestSuite/d.supp
index 7580b904f9..ce6909e7ca 100644
--- a/Source/TestSuite/d.supp
+++ b/Source/TestSuite/d.supp
@@ -105,22 +105,6 @@
{
<insert a suppression name here>
Memcheck:Cond
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- fun:cgCreateProgram
-}
-{
- <insert a suppression name here>
- Memcheck:Cond
obj:/usr/lib/libGLcore.so.169.12
obj:/usr/lib/libGLcore.so.169.12
fun:*
@@ -149,27 +133,4 @@
obj:/usr/lib/libasound.so.2.0.0
obj:*
}
-{
- <insert a suppression name here>
- Memcheck:Cond
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- fun:cgCreateProgram
- fun:_ZN15PixelShaderMngr18CompilePixelShaderER14FRAGMENTSHADERPKc
-}
-{
- <insert a suppression name here>
- Memcheck:Cond
- obj:/usr/lib/libCg.so
- obj:/usr/lib/libCg.so
- obj:*
-}
diff --git a/Source/VSProps/Dolphin.Win32.props b/Source/VSProps/Dolphin.Win32.props
index 7ffd5a3037..a8921b499b 100644
--- a/Source/VSProps/Dolphin.Win32.props
+++ b/Source/VSProps/Dolphin.Win32.props
@@ -7,8 +7,8 @@
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
- <AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\Cg;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName);..\..\..\Externals\openssl\$(PlatformName);..\..\..\Externals\libusb\$(PlatformName)</AdditionalLibraryDirectories>
- <AdditionalDependencies>libusb-1.0.lib;portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;cg.lib;cgGL.lib;opengl32.lib;glew32s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;libeay32.lib;ssleay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName);..\..\..\Externals\openssl\$(PlatformName);..\..\..\Externals\libusb\$(PlatformName)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libusb-1.0.lib;portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;opengl32.lib;glew32s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;libeay32.lib;ssleay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
diff --git a/Source/VSProps/Dolphin.x64.props b/Source/VSProps/Dolphin.x64.props
index e9591c4fdb..435250280a 100644
--- a/Source/VSProps/Dolphin.x64.props
+++ b/Source/VSProps/Dolphin.x64.props
@@ -8,8 +8,8 @@
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
- <AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\Cg64;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName);..\..\..\Externals\openssl\$(PlatformName);..\..\..\Externals\libusb\$(PlatformName)</AdditionalLibraryDirectories>
- <AdditionalDependencies>libusb-1.0.lib;portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;cg.lib;cgGL.lib;opengl32.lib;glew64s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;libeay32.lib;ssleay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName);..\..\..\Externals\openssl\$(PlatformName);..\..\..\Externals\libusb\$(PlatformName)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libusb-1.0.lib;portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;opengl32.lib;glew64s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;libeay32.lib;ssleay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup />