Protect dvdread with a critical section, should fix crashes when running ikaruga from a compressed iso. Some coding standard stuff.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@672 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2008-09-24 20:47:11 +00:00
parent 3883ce6ee9
commit 08e81eddb9
6 changed files with 116 additions and 165 deletions

View File

@ -49,13 +49,13 @@ class CriticalSection
#elif __GNUC__ #elif __GNUC__
pthread_mutex_t mutex; pthread_mutex_t mutex;
#endif #endif
public: public:
CriticalSection(int spincount = 1000); CriticalSection(int spincount = 1000);
~CriticalSection(); ~CriticalSection();
void Enter(); void Enter();
bool TryEnter(); bool TryEnter();
void Leave(); void Leave();
}; };
#ifdef _WIN32 #ifdef _WIN32
@ -66,23 +66,22 @@ typedef void* (*ThreadFunc)(void* arg);
class Thread class Thread
{ {
public: public:
Thread(ThreadFunc entry, void* arg);
~Thread();
Thread(ThreadFunc entry, void* arg); void WaitForDeath();
~Thread(); void SetAffinity(int mask);
static void SetCurrentThreadAffinity(int mask);
void WaitForDeath();
void SetAffinity(int mask);
static void SetCurrentThreadAffinity(int mask);
private: private:
#ifdef _WIN32 #ifdef _WIN32
HANDLE m_hThread; HANDLE m_hThread;
DWORD m_threadId; DWORD m_threadId;
#elif __GNUC__ #elif __GNUC__
pthread_t thread_id; pthread_t thread_id;
#endif #endif
}; };

View File

@ -24,31 +24,32 @@
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
#include "PeripheralInterface.h" #include "PeripheralInterface.h"
#include "Memmap.h" #include "Memmap.h"
#include "Thread.h"
#include "../VolumeHandler.h" #include "../VolumeHandler.h"
namespace DVDInterface namespace DVDInterface
{ {
/* /*
20975: 00000000 DVD (zzz_80146b84 ??, 0x80146bf8) : DVD(r): 0xcc006004 20975: 00000000 DVD (zzz_80146b84 ??, 0x80146bf8) : DVD(r): 0xcc006004
20976: 00000000 DVD (zzz_80146b84 ??, 0x80146c00) : DVD(w): 0x00000000 @ 0xcc006004 20976: 00000000 DVD (zzz_80146b84 ??, 0x80146c00) : DVD(w): 0x00000000 @ 0xcc006004
20977: 00000000 DVD (DVDLowRead, 0x801448a8) : DVD(w): 0x00000020 @ 0xcc006018 20977: 00000000 DVD (DVDLowRead, 0x801448a8) : DVD(w): 0x00000020 @ 0xcc006018
20978: 00000000 DVD (Read, 0x80144744) : DVD(w): 0xa8000000 @ 0xcc006008 20978: 00000000 DVD (Read, 0x80144744) : DVD(w): 0xa8000000 @ 0xcc006008
20979: 00000000 DVD (Read, 0x80144750) : DVD(w): 0x01094227 @ 0xcc00600c 20979: 00000000 DVD (Read, 0x80144750) : DVD(w): 0x01094227 @ 0xcc00600c
20980: 00000000 DVD (Read, 0x80144758) : DVD(w): 0x00000020 @ 0xcc006010 20980: 00000000 DVD (Read, 0x80144758) : DVD(w): 0x00000020 @ 0xcc006010
20981: 00000000 DVD (Read, 0x8014475c) : DVD(w): 0x8167cc80 @ 0xcc006014 20981: 00000000 DVD (Read, 0x8014475c) : DVD(w): 0x8167cc80 @ 0xcc006014
20982: 00000000 DVD (Read, 0x80144760) : DVD(w): 0x00000020 @ 0xcc006018 20982: 00000000 DVD (Read, 0x80144760) : DVD(w): 0x00000020 @ 0xcc006018
20983: 00000000 DVD (Read, 0x80144768) : DVD(w): 0x00000003 @ 0xcc00601c 20983: 00000000 DVD (Read, 0x80144768) : DVD(w): 0x00000003 @ 0xcc00601c
20984: 00000000 DVD: DVD: Read ISO: DVDOffset=0425089c, DMABuffer=0167cc80, SrcLength=00000020, DMALength=00000020 20984: 00000000 DVD: DVD: Read ISO: DVDOffset=0425089c, DMABuffer=0167cc80, SrcLength=00000020, DMALength=00000020
20989: 00000000 DVD (zzz_801442fc ??, 0x80144388) : DVD(r): 0xcc006000 20989: 00000000 DVD (zzz_801442fc ??, 0x80144388) : DVD(r): 0xcc006000
20990: 00000000 DVD (zzz_801442fc ??, 0x801443d8) : DVD(w): 0x0000003a @ 0xcc006000 20990: 00000000 DVD (zzz_801442fc ??, 0x801443d8) : DVD(w): 0x0000003a @ 0xcc006000
20992: 00000000 DVD (zzz_801442fc ??, 0x801444d0) : DVD(w): 0x00000000 @ 0xcc006004 20992: 00000000 DVD (zzz_801442fc ??, 0x801444d0) : DVD(w): 0x00000000 @ 0xcc006004
20993: 00000000 DVD (zzz_80146e44 ??, 0x80146fcc) : DVD(r): 0xcc006018 20993: 00000000 DVD (zzz_80146e44 ??, 0x80146fcc) : DVD(r): 0xcc006018
After this, Cubivore infinitely calls DVDGetDriveStatus, which does not even After this, Cubivore infinitely calls DVDGetDriveStatus, which does not even
bother to check any DVD regs. Waiting for interrupt? bother to check any DVD regs. Waiting for interrupt?
*/ */
// internal hardware addresses // internal hardware addresses
enum enum
@ -178,6 +179,8 @@ DVDMemStruct dvdMem;
u32 g_ErrorCode = 0x00; u32 g_ErrorCode = 0x00;
bool g_bDiscInside = true; bool g_bDiscInside = true;
Common::CriticalSection dvdread_section;
void DoState(PointerWrap &p) void DoState(PointerWrap &p)
{ {
p.Do(dvdMem); p.Do(dvdMem);
@ -238,7 +241,11 @@ bool IsLidOpen()
bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength) bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength)
{ {
return VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength); // We won't need the crit sec when DTK streaming has been rewritten correctly.
dvdread_section.Enter();
bool retval = VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength);
dvdread_section.Leave();
return retval;
} }
bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples) bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples)
@ -430,7 +437,7 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
// u32 sourcelength = dvdMem.Command[2]; // u32 sourcelength = dvdMem.Command[2];
#endif #endif
u32 destbuffer = dvdMem.DMAAddress.Address; u32 destbuffer = dvdMem.DMAAddress.Address;
u32 destlength = dvdMem.DMALength.Length; u32 destlength = dvdMem.DMALength.Length;
dvdMem.DMALength.Length = 0; dvdMem.DMALength.Length = 0;
LOG(DVDINTERFACE, "[WARNING] DVD: Get drive info offset=%08x, destbuffer=%08x, destlength=%08x", offset * 4, destbuffer, destlength); LOG(DVDINTERFACE, "[WARNING] DVD: Get drive info offset=%08x, destbuffer=%08x, destlength=%08x", offset * 4, destbuffer, destlength);
@ -455,12 +462,12 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
if (g_bDiscInside) if (g_bDiscInside)
{ {
u32 iDVDOffset = dvdMem.Command[1] << 2; u32 iDVDOffset = dvdMem.Command[1] << 2;
u32 iSrcLength = dvdMem.Command[2]; u32 iSrcLength = dvdMem.Command[2];
if (false) { iSrcLength++; } // avoid warning if (false) { iSrcLength++; } // avoid warning << wtf is this?
LOG(DVDINTERFACE, "DVD: Read ISO: DVDOffset=%08x, DMABuffer=%08x, SrcLength=%08x, DMALength=%08x",iDVDOffset,dvdMem.DMAAddress.Address,iSrcLength,dvdMem.DMALength.Length); LOG(DVDINTERFACE, "DVD: Read ISO: DVDOffset=%08x, DMABuffer=%08x, SrcLength=%08x, DMALength=%08x",iDVDOffset,dvdMem.DMAAddress.Address,iSrcLength,dvdMem.DMALength.Length);
_dbg_assert_(DVDINTERFACE, iSrcLength == dvdMem.DMALength.Length); _dbg_assert_(DVDINTERFACE, iSrcLength == dvdMem.DMALength.Length);
if (VolumeHandler::ReadToPtr(Memory::GetPointer(dvdMem.DMAAddress.Address), iDVDOffset, dvdMem.DMALength.Length) != true) if (DVDRead(iDVDOffset, dvdMem.DMAAddress.Address, dvdMem.DMALength.Length) != true)
{ {
PanicAlert("Cant read from DVD_Plugin - DVD-Interface: Fatal Error"); PanicAlert("Cant read from DVD_Plugin - DVD-Interface: Fatal Error");
} }
@ -481,9 +488,9 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
// Command0 <- Position on DVD shr 2 // Command0 <- Position on DVD shr 2
//========================================================================================================= //=========================================================================================================
case 0xAB: case 0xAB:
{ {
#ifdef LOGGING #ifdef LOGGING
u32 offset = dvdMem.Command[1] << 2; u32 offset = dvdMem.Command[1] << 2;
#endif #endif
LOG(DVDINTERFACE, "DVD: Trying to seek: offset=%08x", offset); LOG(DVDINTERFACE, "DVD: Trying to seek: offset=%08x", offset);
} }
@ -514,9 +521,9 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
// ugly hack to catch the disable command // ugly hack to catch the disable command
if (dvdMem.Command[1]!=0) if (dvdMem.Command[1]!=0)
{ {
#ifdef LOGGING #ifdef LOGGING
u8 subCommand = (dvdMem.Command[0] & 0x00FF0000) >> 16; u8 subCommand = (dvdMem.Command[0] & 0x00FF0000) >> 16;
#endif #endif
dvdMem.AudioPos = dvdMem.Command[1] << 2; dvdMem.AudioPos = dvdMem.Command[1] << 2;
@ -587,4 +594,4 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
g_ErrorCode = 0x00; g_ErrorCode = 0x00;
} }
} // namespace } // namespace

View File

@ -26,55 +26,37 @@ CVolumeGC::CVolumeGC(IBlobReader* _pReader)
: m_pReader(_pReader) : m_pReader(_pReader)
{} {}
CVolumeGC::~CVolumeGC() CVolumeGC::~CVolumeGC()
{ {
delete m_pReader; delete m_pReader;
} }
bool CVolumeGC::Read(u64 _Offset, u64 _Length, u8* _pBuffer) const
bool
CVolumeGC::Read(u64 _Offset, u64 _Length, u8* _pBuffer) const
{ {
if (m_pReader == NULL) if (m_pReader == NULL)
{ return false;
return(false); return m_pReader->Read(_Offset, _Length, _pBuffer);
}
return(m_pReader->Read(_Offset, _Length, _pBuffer));
} }
std::string CVolumeGC::GetName() const
std::string
CVolumeGC::GetName() const
{ {
if (m_pReader == NULL) if (m_pReader == NULL)
{ return false;
return(false);
}
char Name[128]; char Name[128];
if (!Read(0x20, 0x60, (u8*)&Name)) if (!Read(0x20, 0x60, (u8*)&Name))
{ return false;
return(false);
}
return(Name); return Name;
} }
std::string CVolumeGC::GetUniqueID() const
std::string
CVolumeGC::GetUniqueID() const
{ {
static const std::string NO_UID("NO_UID"); static const std::string NO_UID("NO_UID");
if (m_pReader == NULL) if (m_pReader == NULL)
{
return NO_UID; return NO_UID;
}
char id[6]; char id[6];
if (!Read(0, sizeof(id), reinterpret_cast<u8*>(id))) if (!Read(0, sizeof(id), reinterpret_cast<u8*>(id)))
{ {
PanicAlert("Failed to read unique ID from disc image"); PanicAlert("Failed to read unique ID from disc image");
@ -84,14 +66,10 @@ CVolumeGC::GetUniqueID() const
return std::string(id, sizeof(id)); return std::string(id, sizeof(id));
} }
IVolume::ECountry CVolumeGC::GetCountry() const
IVolume::ECountry
CVolumeGC::GetCountry() const
{ {
if (!m_pReader) if (!m_pReader)
{ return COUNTRY_UNKNOWN;
return(COUNTRY_UNKNOWN);
}
u8 CountryCode; u8 CountryCode;
m_pReader->Read(3, 1, &CountryCode); m_pReader->Read(3, 1, &CountryCode);
@ -141,17 +119,12 @@ CVolumeGC::GetCountry() const
return(country); return(country);
} }
u64 CVolumeGC::GetSize() const
u64
CVolumeGC::GetSize() const
{ {
if (m_pReader) if (m_pReader)
{ return (size_t)m_pReader->GetDataSize();
return((size_t)m_pReader->GetDataSize());
}
else else
{ return 0;
return(0);
}
} }
} // namespace } // namespace

View File

@ -20,35 +20,23 @@
#include "Volume.h" #include "Volume.h"
#include "Blob.h" #include "Blob.h"
// // --- this volume type is used for GC disc images ---
// --- this volume type is used for GC and for decrypted Wii images ---
//
namespace DiscIO namespace DiscIO
{ {
class CVolumeGC class CVolumeGC : public IVolume
: public IVolume
{ {
public: public:
CVolumeGC(IBlobReader* _pReader);
~CVolumeGC();
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
std::string GetName() const;
std::string GetUniqueID() const;
ECountry GetCountry() const;
u64 GetSize() const;
CVolumeGC(IBlobReader* _pReader); private:
IBlobReader* m_pReader;
~CVolumeGC();
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
std::string GetName() const;
std::string GetUniqueID() const;
ECountry GetCountry() const;
u64 GetSize() const;
private:
IBlobReader* m_pReader;
}; };
} // namespace
} // namespace

View File

@ -22,43 +22,33 @@
#include "Blob.h" #include "Blob.h"
#include "AES/aes.h" #include "AES/aes.h"
//
// --- this volume type is used for encrypted Wii images --- // --- this volume type is used for encrypted Wii images ---
//
namespace DiscIO namespace DiscIO
{ {
class CVolumeWiiCrypted class CVolumeWiiCrypted : public IVolume
: public IVolume
{ {
public: public:
CVolumeWiiCrypted(IBlobReader* _pReader, u64 _VolumeOffset, const unsigned char* _pVolumeKey);
~CVolumeWiiCrypted();
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
std::string GetName() const;
std::string GetUniqueID() const;
ECountry GetCountry() const;
u64 GetSize() const;
CVolumeWiiCrypted(IBlobReader* _pReader, u64 _VolumeOffset, const unsigned char* _pVolumeKey); private:
IBlobReader* m_pReader;
~CVolumeWiiCrypted(); u8* m_pBuffer;
AES_KEY m_AES_KEY;
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const; u64 m_VolumeOffset;
std::string GetName() const; mutable u64 m_LastDecryptedBlockOffset;
mutable unsigned char m_LastDecryptedBlock[0x8000];
std::string GetUniqueID() const;
ECountry GetCountry() const;
u64 GetSize() const;
private:
IBlobReader* m_pReader;
u8* m_pBuffer;
AES_KEY m_AES_KEY;
u64 m_VolumeOffset;
mutable u64 m_LastDecryptedBlockOffset;
mutable unsigned char m_LastDecryptedBlock[0x8000];
}; };
} // namespace } // namespace
#endif #endif

View File

@ -24,6 +24,7 @@
namespace DSound namespace DSound
{ {
#define BUFSIZE 32768 #define BUFSIZE 32768
#define MAXWAIT 70 //ms #define MAXWAIT 70 //ms
@ -33,31 +34,33 @@ HANDLE hThread;
StreamCallback callback; StreamCallback callback;
//lite mojs
IDirectSound8* ds; IDirectSound8* ds;
IDirectSoundBuffer* dsBuffer; IDirectSoundBuffer* dsBuffer;
//tja.. behövs
int bufferSize; //i bytes int bufferSize; //i bytes
int totalRenderedBytes; int totalRenderedBytes;
int sampleRate; int sampleRate;
//med den här synkar vi stängning.. // playback position
//0=vi spelar oväsen, 1=stäng tråden NU! int currentPos;
int lastPos;
short realtimeBuffer[1024 * 1024];
// We set this to shut down the sound thread.
// 0=keep playing, 1=stop playing NOW.
volatile int threadData; volatile int threadData;
inline int FIX128(int x) inline int FIX128(int x)
{ {
return(x & (~127)); return(x & (~127));
} }
int DSound_GetSampleRate() int DSound_GetSampleRate()
{ {
return(sampleRate); return(sampleRate);
} }
bool CreateBuffer() bool CreateBuffer()
{ {
PCMWAVEFORMAT pcmwf; PCMWAVEFORMAT pcmwf;
@ -92,7 +95,6 @@ bool CreateBuffer()
} }
} }
bool WriteDataToBuffer(DWORD dwOffset, // Our own write cursor. bool WriteDataToBuffer(DWORD dwOffset, // Our own write cursor.
char* soundData, // Start of our data. char* soundData, // Start of our data.
DWORD dwSoundBytes) // Size of block to copy. DWORD dwSoundBytes) // Size of block to copy.
@ -126,18 +128,12 @@ bool WriteDataToBuffer(DWORD dwOffset, // Our own write cursor.
return(false); return(false);
} }
inline int ModBufferSize(int x) inline int ModBufferSize(int x)
{ {
return((x + bufferSize) % bufferSize); return((x + bufferSize) % bufferSize);
} }
// The audio thread.
int currentPos;
int lastPos;
short realtimeBuffer[1024 * 1024];
//Själva tråden
DWORD WINAPI soundThread(void*) DWORD WINAPI soundThread(void*)
{ {
currentPos = 0; currentPos = 0;
@ -157,6 +153,8 @@ DWORD WINAPI soundThread(void*)
if (numBytesToRender >= 256) if (numBytesToRender >= 256)
{ {
if (numBytesToRender > sizeof(realtimeBuffer))
MessageBox(0,"soundThread: too big render call",0,0);
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2); (*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2);
WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender); WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
@ -174,7 +172,6 @@ DWORD WINAPI soundThread(void*)
return(0); //hurra! return(0); //hurra!
} }
bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback) bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
{ {
callback = _callback; callback = _callback;
@ -189,15 +186,13 @@ bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
//vi vill ha access till DSOUND så... //vi vill ha access till DSOUND så...
if (FAILED(DirectSoundCreate8(0, &ds, 0))) if (FAILED(DirectSoundCreate8(0, &ds, 0)))
{ return false;
return(false);
}
ds->SetCooperativeLevel(window, DSSCL_NORMAL); ds->SetCooperativeLevel(window, DSSCL_NORMAL);
if (!CreateBuffer()) if (!CreateBuffer())
{ {
return(false); return false;
} }
DWORD num1; DWORD num1;
@ -209,21 +204,19 @@ bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
DWORD h; DWORD h;
hThread = CreateThread(0, 0, soundThread, 0, 0, &h); hThread = CreateThread(0, 0, soundThread, 0, 0, &h);
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL); SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
return(true); return true;
} }
void DSound_UpdateSound() void DSound_UpdateSound()
{ {
SetEvent(soundSyncEvent); SetEvent(soundSyncEvent);
} }
void DSound_StopSound() void DSound_StopSound()
{ {
EnterCriticalSection(&soundCriticalSection); EnterCriticalSection(&soundCriticalSection);
threadData = 1; threadData = 1;
//kick the thread if it's waiting // kick the thread if it's waiting
SetEvent(soundSyncEvent); SetEvent(soundSyncEvent);
LeaveCriticalSection(&soundCriticalSection); LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(hThread, INFINITE); WaitForSingleObject(hThread, INFINITE);
@ -233,9 +226,10 @@ void DSound_StopSound()
ds->Release(); ds->Release();
CloseHandle(soundSyncEvent); CloseHandle(soundSyncEvent);
soundSyncEvent = INVALID_HANDLE_VALUE;
hThread = INVALID_HANDLE_VALUE;
} }
int DSound_GetCurSample() int DSound_GetCurSample()
{ {
EnterCriticalSection(&soundCriticalSection); EnterCriticalSection(&soundCriticalSection);
@ -246,9 +240,9 @@ int DSound_GetCurSample()
return(playCursor); return(playCursor);
} }
float DSound_GetTimer() float DSound_GetTimer()
{ {
return((float)DSound_GetCurSample() * (1.0f / (4.0f * sampleRate))); return((float)DSound_GetCurSample() * (1.0f / (4.0f * sampleRate)));
} }
}
} // namespace