mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-03 03:22:30 +02:00
73da6f4f3f
# By Jordan Woyak (46) and others # Via Jordan Woyak (2) and others * master: (70 commits) Fixes two memory leaks, one is pretty bad for OSX. Yell at pauldachz if this doesn't work. Or... say thanks. Added a BluetoothEnumerateInstalledServices call so that the wiimote remembers the pairing. Make ARMJit core default CPU core on ARM architecture Fix a StringUtil regression from the arm-noglsl merge Small improvement to cmpli/cmpi in ARMJit. Merge latest ArmEmitter changes from ppsspp while we're at it. Ah. I blame vim on this typo entirely. Add disabled code for authenticating wiimotes on Windows. Add the missing FPR cache Buildfix. Yell at the user if they change window size while dumping frames, and some other avi dumping stuff. Not sure if this is the right way to handle this, but it makes the save states perfectly stable. That's all that really matters, right? Abort loading states from incompatible graphics backends. ARM Support without GLSL Improve VideoSoftware save states. They are fairly stable, but not perfect. OpcodeDecoder::DoState() needs to be fixed. Begin implementing save states to video software. Kind of works, sometimes. Make error message for loading save state with wrong dsp engine shorter. Abort load state if it uses a different dsp engine, instead of crashing. Update the gameini of F-zero. Efb to Ram is no longer the default choice. fix last commit by neobrain ... Conflicts: Source/Core/VideoCommon/Src/Fifo.cpp
253 lines
6.7 KiB
C++
253 lines
6.7 KiB
C++
// 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 "MemoryUtil.h"
|
|
#include "Thread.h"
|
|
#include "Atomic.h"
|
|
#include "OpcodeDecoding.h"
|
|
#include "CommandProcessor.h"
|
|
#include "PixelEngine.h"
|
|
#include "ChunkFile.h"
|
|
#include "Fifo.h"
|
|
#include "HW/Memmap.h"
|
|
#include "Core.h"
|
|
#include "CoreTiming.h"
|
|
|
|
volatile bool g_bSkipCurrentFrame = false;
|
|
extern u8* g_pVideoData;
|
|
|
|
namespace
|
|
{
|
|
static volatile bool GpuRunningState = false;
|
|
static volatile bool EmuRunningState = false;
|
|
static std::mutex m_csHWVidOccupied;
|
|
// STATE_TO_SAVE
|
|
static u8 *videoBuffer;
|
|
static int size = 0;
|
|
} // namespace
|
|
|
|
void Fifo_DoState(PointerWrap &p)
|
|
{
|
|
p.DoArray(videoBuffer, FIFO_SIZE);
|
|
p.Do(size);
|
|
p.DoPointer(g_pVideoData, videoBuffer);
|
|
p.Do(g_bSkipCurrentFrame);
|
|
}
|
|
|
|
void Fifo_PauseAndLock(bool doLock, bool unpauseOnUnlock)
|
|
{
|
|
if (doLock)
|
|
{
|
|
EmulatorState(false);
|
|
if (!Core::IsGPUThread())
|
|
m_csHWVidOccupied.lock();
|
|
_dbg_assert_(COMMON, !CommandProcessor::fifo.isGpuReadingData);
|
|
}
|
|
else
|
|
{
|
|
if (unpauseOnUnlock)
|
|
EmulatorState(true);
|
|
if (!Core::IsGPUThread())
|
|
m_csHWVidOccupied.unlock();
|
|
}
|
|
}
|
|
|
|
|
|
void Fifo_Init()
|
|
{
|
|
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);
|
|
}
|
|
|
|
u8* GetVideoBufferStartPtr()
|
|
{
|
|
return videoBuffer;
|
|
}
|
|
|
|
u8* GetVideoBufferEndPtr()
|
|
{
|
|
return &videoBuffer[size];
|
|
}
|
|
|
|
void Fifo_SetRendering(bool enabled)
|
|
{
|
|
g_bSkipCurrentFrame = !enabled;
|
|
}
|
|
|
|
// May be executed from any thread, even the graphics thread.
|
|
// Created to allow for self shutdown.
|
|
void ExitGpuLoop()
|
|
{
|
|
// This should break the wait loop in CPU thread
|
|
CommandProcessor::fifo.bFF_GPReadEnable = false;
|
|
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
|
while(fifo.isGpuReadingData) Common::YieldCPU();
|
|
// Terminate GPU thread loop
|
|
GpuRunningState = false;
|
|
EmuRunningState = true;
|
|
}
|
|
|
|
void EmulatorState(bool running)
|
|
{
|
|
EmuRunningState = running;
|
|
}
|
|
|
|
|
|
// Description: RunGpuLoop() sends data through this function.
|
|
void ReadDataFromFifo(u8* _uData, u32 len)
|
|
{
|
|
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, 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;
|
|
}
|
|
|
|
void ResetVideoBuffer()
|
|
{
|
|
g_pVideoData = videoBuffer;
|
|
size = 0;
|
|
}
|
|
|
|
|
|
// Description: Main FIFO update loop
|
|
// Purpose: Keep the Core HW updated about the CPU-GPU distance
|
|
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())
|
|
{
|
|
if (!GpuRunningState) break;
|
|
|
|
fifo.isGpuReadingData = true;
|
|
CommandProcessor::isPossibleWaitingSetDrawDone = fifo.bFF_GPLinkEnable ? true : false;
|
|
|
|
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 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.
|
|
// If we don't, s_swapRequested or s_efbAccessRequested won't be set to false
|
|
// leading the CPU thread to wait in Video_BeginField or Video_AccessEFB thus slowing things down.
|
|
VideoFifo_CheckAsyncRequest();
|
|
CommandProcessor::isPossibleWaitingSetDrawDone = false;
|
|
}
|
|
|
|
fifo.isGpuReadingData = false;
|
|
|
|
|
|
if (EmuRunningState)
|
|
Common::YieldCPU();
|
|
else
|
|
{
|
|
// While the emu is paused, we still handle async requests then sleep.
|
|
while (!EmuRunningState)
|
|
{
|
|
g_video_backend->PeekMessages();
|
|
m_csHWVidOccupied.unlock();
|
|
Common::SleepCurrentThread(1);
|
|
m_csHWVidOccupied.lock();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool AtBreakpoint()
|
|
{
|
|
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
|
return fifo.bFF_BPEnable && (fifo.CPReadPointer == fifo.CPBreakpoint);
|
|
}
|
|
|
|
void RunGpu()
|
|
{
|
|
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
|
while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() )
|
|
{
|
|
u8 *uData = Memory::GetPointer(fifo.CPReadPointer);
|
|
|
|
FPURoundMode::SaveSIMDState();
|
|
FPURoundMode::LoadDefaultSIMDState();
|
|
ReadDataFromFifo(uData, 32);
|
|
u32 count = OpcodeDecoder_Run(g_bSkipCurrentFrame);
|
|
FPURoundMode::LoadSIMDState();
|
|
|
|
//DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base");
|
|
|
|
if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase;
|
|
else fifo.CPReadPointer += 32;
|
|
|
|
fifo.CPReadWriteDistance -= 32;
|
|
}
|
|
CommandProcessor::SetCpStatus();
|
|
}
|