mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-25 09:35:35 +00:00
da088e62ad
For testing purpose only (I can't test with lots of games) because it may break some sync. Besides, I'm not satisfied with the way things are done. So just uncomment "//#define THREAD_VIDEO_WAKEUP_ONIDLE" in thread.h in order to test it. Works fine with movies, 2D and simple 3D in ZWW at least. If it's ok I'll clean up the code. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@658 8ced0084-cf51-0410-be5f-012b33b47a6e
200 lines
5.4 KiB
C++
200 lines
5.4 KiB
C++
// Copyright (C) 2003-2008 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.h>
|
|
|
|
#include "MemoryUtil.h"
|
|
#include "Thread.h"
|
|
#include "OpcodeDecoding.h"
|
|
|
|
#include "Fifo.h"
|
|
|
|
#define FIFO_SIZE (1024*1024)
|
|
|
|
FifoReader fifo;
|
|
|
|
// STATE_TO_SAVE
|
|
static u8 *videoBuffer;
|
|
static int size = 0;
|
|
static int readptr = 0;
|
|
|
|
void Fifo_DoState(PointerWrap &p) {
|
|
p.DoArray(videoBuffer, FIFO_SIZE);
|
|
p.Do(size);
|
|
p.Do(readptr);
|
|
}
|
|
|
|
void Fifo_Init()
|
|
{
|
|
videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE);
|
|
fifo.Init(videoBuffer, videoBuffer); //zero length. there is no data yet.
|
|
}
|
|
|
|
void Fifo_Shutdown()
|
|
{
|
|
FreeMemoryPages(videoBuffer, FIFO_SIZE);
|
|
}
|
|
|
|
int FAKE_GetFifoSize()
|
|
{
|
|
if (size < readptr)
|
|
{
|
|
PanicAlert("GFX Fifo underrun encountered (size = %i, readptr = %i)", size, readptr);
|
|
}
|
|
return (size - readptr);
|
|
}
|
|
|
|
u8 FAKE_PeekFifo8(u32 _uOffset)
|
|
{
|
|
return videoBuffer[readptr + _uOffset];
|
|
}
|
|
|
|
u16 FAKE_PeekFifo16(u32 _uOffset)
|
|
{
|
|
return Common::swap16(*(u16*)&videoBuffer[readptr + _uOffset]);
|
|
}
|
|
|
|
u32 FAKE_PeekFifo32(u32 _uOffset)
|
|
{
|
|
return Common::swap32(*(u32*)&videoBuffer[readptr + _uOffset]);
|
|
}
|
|
|
|
u8 FAKE_ReadFifo8()
|
|
{
|
|
return videoBuffer[readptr++];
|
|
}
|
|
|
|
int FAKE_GetPosition()
|
|
{
|
|
return readptr;
|
|
}
|
|
|
|
u16 FAKE_ReadFifo16()
|
|
{
|
|
u16 val = Common::swap16(*(u16*)(videoBuffer+readptr));
|
|
readptr += 2;
|
|
return val;
|
|
}
|
|
|
|
u32 FAKE_ReadFifo32()
|
|
{
|
|
u32 val = Common::swap32(*(u32*)(videoBuffer+readptr));
|
|
readptr += 4;
|
|
return val;
|
|
}
|
|
|
|
void FAKE_SkipFifo(u32 skip)
|
|
{
|
|
readptr += skip;
|
|
}
|
|
|
|
void Video_SendFifoData(u8* _uData)
|
|
{
|
|
memcpy(videoBuffer + size, _uData, 32);
|
|
size += 32;
|
|
if (size + 32 >= FIFO_SIZE)
|
|
{
|
|
if (FAKE_GetFifoSize() > readptr)
|
|
{
|
|
PanicAlert("FIFO out of bounds (sz = %i, at %08x)", FAKE_GetFifoSize(), readptr);
|
|
}
|
|
// DebugLog("FAKE BUFFER LOOPS");
|
|
memmove(&videoBuffer[0], &videoBuffer[readptr], FAKE_GetFifoSize());
|
|
// memset(&videoBuffer[FAKE_GetFifoSize()], 0, FIFO_SIZE - FAKE_GetFifoSize());
|
|
size = FAKE_GetFifoSize();
|
|
readptr = 0;
|
|
}
|
|
OpcodeDecoder_Run();
|
|
}
|
|
|
|
|
|
//TODO - turn inside out, have the "reader" ask for bytes instead
|
|
// See Core.cpp for threading idea
|
|
void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
|
{
|
|
SCPFifoStruct &_fifo = *video_initialize.pCPFifo;
|
|
#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32)
|
|
HANDLE hEventOnIdle= OpenEventA(EVENT_ALL_ACCESS,FALSE,(LPCSTR)"EventOnIdle");
|
|
if (hEventOnIdle==NULL) PanicAlert("Fifo_EnterLoop() -> EventOnIdle NULL");
|
|
#endif
|
|
|
|
// TODO(ector): Don't peek so often!
|
|
while (video_initialize.pPeekMessages())
|
|
{
|
|
#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32)
|
|
if (MsgWaitForMultipleObjects(1, &hEventOnIdle, FALSE, 1L, QS_ALLEVENTS) == WAIT_ABANDONED)
|
|
break;
|
|
#endif
|
|
if (_fifo.CPReadWriteDistance < 1) //fifo.CPLoWatermark)
|
|
#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32)
|
|
continue;
|
|
#else
|
|
Common::SleepCurrentThread(1);
|
|
#endif
|
|
//etc...
|
|
|
|
// check if we are able to run this buffer
|
|
if ((_fifo.bFF_GPReadEnable) && !(_fifo.bFF_BPEnable && _fifo.bFF_Breakpoint))
|
|
{
|
|
#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32)
|
|
while(_fifo.CPReadWriteDistance > 0)
|
|
#else
|
|
int count = 200;
|
|
while(_fifo.CPReadWriteDistance > 0 && count)
|
|
#endif
|
|
{
|
|
// check if we are on a breakpoint
|
|
if (_fifo.bFF_BPEnable)
|
|
{
|
|
if (_fifo.CPReadPointer == _fifo.CPBreakpoint)
|
|
{
|
|
_fifo.bFF_Breakpoint = 1;
|
|
video_initialize.pUpdateInterrupts();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// read the data and send it to the VideoPlugin
|
|
u8 *uData = video_initialize.pGetMemoryPointer(_fifo.CPReadPointer);
|
|
#ifdef _WIN32
|
|
EnterCriticalSection(&_fifo.sync);
|
|
#endif
|
|
_fifo.CPReadPointer += 32;
|
|
Video_SendFifoData(uData);
|
|
#ifdef _WIN32
|
|
InterlockedExchangeAdd((LONG*)&_fifo.CPReadWriteDistance, -32);
|
|
LeaveCriticalSection(&_fifo.sync);
|
|
#endif
|
|
// increase the ReadPtr
|
|
if (_fifo.CPReadPointer >= _fifo.CPEnd)
|
|
{
|
|
_fifo.CPReadPointer = _fifo.CPBase;
|
|
//LOG(COMMANDPROCESSOR, "BUFFER LOOP");
|
|
}
|
|
#ifndef THREAD_VIDEO_WAKEUP_ONIDLE
|
|
count--;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
}
|
|
#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32)
|
|
CloseHandle(hEventOnIdle);
|
|
#endif
|
|
}
|
|
|