mirror of https://github.com/PCSX2/pcsx2.git
wxIsoFile branch: (needs linux testing)
* Convert IsoFileFormats.cpp into a class. * Use wxFile and wxFileInputStream instead of windows/posix specific file functions. * Added new ScopedAlloc classes, which are very simple dependency-free templates for exception-safe allocations. * FastFormatString: Improved performance ad fixed an obscure bug. * Drag&Drop (UI) - Improved the friendliness and responsiveness, so that PCSX2 doesn't end up tying up an explorer window while it prompts the user or issues error messages. git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxIsoFile@3934 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
4ee1781ce2
commit
2b4d7cc384
|
@ -160,7 +160,8 @@
|
|||
<Unit filename="../../include/Utilities/RedtapeWindows.h" />
|
||||
<Unit filename="../../include/Utilities/RwMutex.h" />
|
||||
<Unit filename="../../include/Utilities/SafeArray.h" />
|
||||
<Unit filename="../../include/Utilities/ScopedPtr.h" />
|
||||
<Unit filename="../../include/Utilities/ScopedAlloc.h" />
|
||||
<Unit filename="../../include/Utilities/ScopedPtr.h" />
|
||||
<Unit filename="../../include/Utilities/ScopedPtrMT.h" />
|
||||
<Unit filename="../../include/Utilities/StringHelpers.h" />
|
||||
<Unit filename="../../include/Utilities/Threading.h" />
|
||||
|
@ -172,7 +173,8 @@
|
|||
<Unit filename="../../include/Utilities/pxEvents.h" />
|
||||
<Unit filename="../../include/Utilities/pxRadioPanel.h" />
|
||||
<Unit filename="../../include/Utilities/pxStaticText.h" />
|
||||
<Unit filename="../../include/Utilities/win_memzero.h" />
|
||||
<Unit filename="../../include/Utilities/pxStreams.h" />
|
||||
<Unit filename="../../include/Utilities/win_memzero.h" />
|
||||
<Unit filename="../../include/Utilities/wxAppWithHelpers.h" />
|
||||
<Unit filename="../../include/Utilities/wxBaseTools.h" />
|
||||
<Unit filename="../../include/Utilities/wxGuiTools.h" />
|
||||
|
@ -201,7 +203,7 @@
|
|||
<Unit filename="../../src/Utilities/pxCheckBox.cpp" />
|
||||
<Unit filename="../../src/Utilities/pxRadioPanel.cpp" />
|
||||
<Unit filename="../../src/Utilities/pxStaticText.cpp" />
|
||||
<Unit filename="../../src/Utilities/pxTextStream.cpp" />
|
||||
<Unit filename="../../src/Utilities/pxStreams.cpp" />
|
||||
<Unit filename="../../src/Utilities/pxTranslate.cpp" />
|
||||
<Unit filename="../../src/Utilities/pxWindowTextWriter.cpp" />
|
||||
<Unit filename="../../src/Utilities/vssprintf.cpp" />
|
||||
|
|
|
@ -276,7 +276,7 @@
|
|||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\Utilities\pxTextStream.cpp"
|
||||
RelativePath="..\..\src\Utilities\pxStreams.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
|
@ -441,6 +441,10 @@
|
|||
RelativePath="..\..\include\Utilities\pxStaticText.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\Utilities\pxStreams.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\Utilities\RedtapeWindows.h"
|
||||
>
|
||||
|
@ -453,6 +457,10 @@
|
|||
RelativePath="..\..\include\Utilities\SafeArray.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\Utilities\ScopedAlloc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\Utilities\ScopedPtr.h"
|
||||
>
|
||||
|
|
|
@ -157,16 +157,16 @@ extern pxDoAssertFnType* pxDoAssert;
|
|||
// IndexBoundsCheckDev.
|
||||
|
||||
#define IndexBoundsCheck( objname, idx, sze ) pxAssertMsg( (uint)(idx) < (uint)(sze), \
|
||||
wxsFormat( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
||||
pxsFmt( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
||||
|
||||
#define IndexBoundsCheckDev( objname, idx, sze ) pxAssertDev( (uint)(idx) < (uint)(sze), \
|
||||
wxsFormat( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
||||
pxsFmt( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
||||
|
||||
#define IndexBoundsAssume( objname, idx, sze ) pxAssumeMsg( (uint)(idx) < (uint)(sze), \
|
||||
wxsFormat( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
||||
pxsFmt( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
||||
|
||||
#define IndexBoundsAssumeDev( objname, idx, sze ) pxAssumeDev( (uint)(idx) < (uint)(sze), \
|
||||
wxsFormat( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
||||
pxsFmt( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
||||
|
||||
|
||||
extern void pxOnAssert( const DiagnosticOrigin& origin, const wxChar* msg=NULL );
|
||||
|
|
|
@ -23,7 +23,13 @@
|
|||
// --------------------------------------------------------------------------------------
|
||||
|
||||
class wxOutputStream;
|
||||
class wxFileOutputStream;
|
||||
class wxFFileOutputStream;
|
||||
|
||||
class wxInputStream;
|
||||
class wxFileInputStream;
|
||||
class wxFFileInputStream;
|
||||
|
||||
class wxPoint;
|
||||
class wxRect;
|
||||
class wxSize;
|
||||
|
@ -38,6 +44,11 @@ namespace Threading
|
|||
class pxThread;
|
||||
}
|
||||
|
||||
namespace Exception
|
||||
{
|
||||
class BaseException;
|
||||
}
|
||||
|
||||
// This should prove useful....
|
||||
#define wxsFormat wxString::Format
|
||||
|
||||
|
@ -219,4 +230,6 @@ extern bool pxIsEnglish( int id );
|
|||
|
||||
#define pxE(key, english) pxExpandMsg( wxT(key), english )
|
||||
|
||||
#include "Utilities/ScopedPtr.h"
|
||||
#include "Utilities/ScopedMalloc.h"
|
||||
#include "Utilities/Assertions.h"
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
namespace Exception
|
||||
{
|
||||
int MakeNewType();
|
||||
BaseException* FromErrno( const wxString& streamname, errno_t errcode );
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// BaseException
|
||||
|
@ -92,6 +93,8 @@ namespace Exception
|
|||
virtual BaseException* Clone() const=0;
|
||||
};
|
||||
|
||||
typedef ScopedPtr<BaseException> ScopedExcept;
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Ps2Generic Exception
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -337,3 +340,4 @@ public: \
|
|||
}
|
||||
|
||||
using Exception::BaseException;
|
||||
using Exception::ScopedExcept;
|
||||
|
|
|
@ -167,6 +167,9 @@ namespace HostSys
|
|||
}
|
||||
}
|
||||
|
||||
// Safe version of Munmap -- NULLs the pointer variable immediately after free'ing it.
|
||||
#define SafeSysMunmap( ptr, size ) \
|
||||
((void) ( HostSys::Munmap( (uptr)(ptr), size ), (ptr) = NULL ))
|
||||
|
||||
extern void InitCPUTicks();
|
||||
extern u64 GetTickFrequency();
|
||||
|
|
|
@ -15,34 +15,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
// pxUSE_SECURE_MALLOC - enables bounds checking on scoped malloc allocations.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Safe deallocation macros -- checks pointer validity (non-null) when needed, and sets
|
||||
// pointer to null after deallocation.
|
||||
#ifndef pxUSE_SECURE_MALLOC
|
||||
#define pxUSE_SECURE_MALLOC 0
|
||||
#endif
|
||||
|
||||
#define safe_delete( ptr ) \
|
||||
((void) (delete (ptr)), (ptr) = NULL)
|
||||
|
||||
#define safe_delete_array( ptr ) \
|
||||
((void) (delete[] (ptr)), (ptr) = NULL)
|
||||
|
||||
// No checks for NULL -- wxWidgets says it's safe to skip NULL checks and it runs on
|
||||
// just about every compiler and libc implementation of any recentness.
|
||||
#define safe_free( ptr ) \
|
||||
( (void) (free( ptr ), !!0), (ptr) = NULL )
|
||||
//((void) (( ( (ptr) != NULL ) && (free( ptr ), !!0) ), (ptr) = NULL))
|
||||
|
||||
#define safe_fclose( ptr ) \
|
||||
((void) (( ( (ptr) != NULL ) && (fclose( ptr ), !!0) ), (ptr) = NULL))
|
||||
|
||||
// Implementation note: all known implementations of _aligned_free check the pointer for
|
||||
// NULL status (our implementation under GCC, and microsoft's under MSVC), so no need to
|
||||
// do it here.
|
||||
#define safe_aligned_free( ptr ) \
|
||||
((void) ( _aligned_free( ptr ), (ptr) = NULL ))
|
||||
|
||||
#define SafeSysMunmap( ptr, size ) \
|
||||
((void) ( HostSys::Munmap( (uptr)(ptr), size ), (ptr) = NULL ))
|
||||
|
||||
// Microsoft Windows only macro, useful for freeing out COM objects:
|
||||
#define safe_release( ptr ) \
|
||||
|
@ -76,11 +54,7 @@ protected:
|
|||
|
||||
// A safe array index fetcher. Asserts if the index is out of bounds (dev and debug
|
||||
// builds only -- no bounds checking is done in release builds).
|
||||
T* _getPtr( uint i ) const
|
||||
{
|
||||
IndexBoundsAssumeDev( Name.c_str(), i, m_size );
|
||||
return &m_ptr[i];
|
||||
}
|
||||
T* _getPtr( uint i ) const;
|
||||
|
||||
public:
|
||||
virtual ~SafeArray() throw();
|
||||
|
@ -154,11 +128,7 @@ protected:
|
|||
virtual T* _virtual_realloc( int newsize );
|
||||
void _MakeRoomFor_threshold( int newsize );
|
||||
|
||||
T* _getPtr( uint i ) const
|
||||
{
|
||||
IndexBoundsAssumeDev( Name.c_str(), i, m_length );
|
||||
return &m_ptr[i];
|
||||
}
|
||||
T* _getPtr( uint i ) const;
|
||||
|
||||
public:
|
||||
virtual ~SafeList() throw();
|
||||
|
|
|
@ -90,6 +90,13 @@ void SafeArray<T>::Dispose()
|
|||
safe_free( m_ptr );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
T* SafeArray<T>::_getPtr( uint i ) const
|
||||
{
|
||||
IndexBoundsAssumeDev( Name.c_str(), i, m_size );
|
||||
return &m_ptr[i];
|
||||
}
|
||||
|
||||
// reallocates the array to the explicit size. Can be used to shrink or grow an
|
||||
// array, and bypasses the internal threshold growth indicators.
|
||||
template< typename T >
|
||||
|
@ -203,6 +210,13 @@ SafeList<T>::SafeList( int initialSize, const wxChar* name )
|
|||
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
T* SafeList<T>::_getPtr( uint i ) const
|
||||
{
|
||||
IndexBoundsAssumeDev( Name.c_str(), i, m_length );
|
||||
return &m_ptr[i];
|
||||
}
|
||||
|
||||
// Ensures that the allocation is large enough to fit data of the
|
||||
// amount requested. The memory allocation is not resized smaller.
|
||||
template< typename T >
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// pxUSE_SECURE_MALLOC - enables bounds checking on scoped malloc allocations.
|
||||
|
||||
#ifndef pxUSE_SECURE_MALLOC
|
||||
#define pxUSE_SECURE_MALLOC 0
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Safe deallocation macros -- checks pointer validity (non-null) when needed, and sets
|
||||
// pointer to null after deallocation.
|
||||
|
||||
#define safe_delete( ptr ) \
|
||||
((void) (delete (ptr)), (ptr) = NULL)
|
||||
|
||||
#define safe_delete_array( ptr ) \
|
||||
((void) (delete[] (ptr)), (ptr) = NULL)
|
||||
|
||||
// No checks for NULL -- wxWidgets says it's safe to skip NULL checks and it runs on
|
||||
// just about every compiler and libc implementation of any recentness.
|
||||
#define safe_free( ptr ) \
|
||||
( (void) (free( ptr ), !!0), (ptr) = NULL )
|
||||
//((void) (( ( (ptr) != NULL ) && (free( ptr ), !!0) ), (ptr) = NULL))
|
||||
|
||||
#define safe_fclose( ptr ) \
|
||||
((void) (( ( (ptr) != NULL ) && (fclose( ptr ), !!0) ), (ptr) = NULL))
|
||||
|
||||
// Implementation note: all known implementations of _aligned_free check the pointer for
|
||||
// NULL status (our implementation under GCC, and microsoft's under MSVC), so no need to
|
||||
// do it here.
|
||||
#define safe_aligned_free( ptr ) \
|
||||
((void) ( _aligned_free( ptr ), (ptr) = NULL ))
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// BaseScopedAlloc
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Base class that allows various ScopedMalloc types to be passed to functions that act
|
||||
// on them.
|
||||
//
|
||||
// Rationale: This class and the derived varieties are provided as a simple autonomous self-
|
||||
// destructing container for malloc. The entire class is almost completely dependency free,
|
||||
// and thus can be included everywhere and anywhere without dependency hassles.
|
||||
//
|
||||
template< typename T >
|
||||
class BaseScopedAlloc
|
||||
{
|
||||
protected:
|
||||
T* m_buffer;
|
||||
uint m_size;
|
||||
|
||||
public:
|
||||
BaseScopedAlloc()
|
||||
{
|
||||
m_buffer = NULL;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
virtual ~BaseScopedAlloc() throw()
|
||||
{
|
||||
//pxAssume(m_buffer==NULL);
|
||||
}
|
||||
|
||||
public:
|
||||
size_t GetSize() const { return m_size; }
|
||||
size_t GetLength() const { return m_size; }
|
||||
|
||||
// Allocates the object to the specified size. If an existing allocation is in
|
||||
// place, it is freed and replaced with the new allocation, and all data is lost.
|
||||
// Parameter:
|
||||
// newSize - size of the new allocation, in elements (not bytes!). If the specified
|
||||
// size is 0, the the allocation is freed, same as calling Free().
|
||||
virtual void Alloc( size_t newsize )=0;
|
||||
|
||||
// Re-sizes the allocation to the requested size, without any data loss.
|
||||
// Parameter:
|
||||
// newSize - size of the new allocation, in elements (not bytes!). If the specified
|
||||
// size is 0, the the allocation is freed, same as calling Free().
|
||||
virtual void Resize( size_t newsize )=0;
|
||||
|
||||
void Free()
|
||||
{
|
||||
Alloc( 0 );
|
||||
}
|
||||
|
||||
// Makes enough room for the requested size. Existing data in the array is retained.
|
||||
void MakeRoomFor( uint size )
|
||||
{
|
||||
if (size <= m_size) return;
|
||||
Resize( size );
|
||||
}
|
||||
|
||||
T* GetPtr( uint idx=0 ) const
|
||||
{
|
||||
#if pxUSE_SECURE_MALLOC
|
||||
IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size );
|
||||
#endif
|
||||
return &m_buffer[idx];
|
||||
}
|
||||
|
||||
T& operator[]( uint idx )
|
||||
{
|
||||
#if pxUSE_SECURE_MALLOC
|
||||
IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size );
|
||||
#endif
|
||||
return m_buffer[idx];
|
||||
}
|
||||
|
||||
const T& operator[]( uint idx ) const
|
||||
{
|
||||
#if pxUSE_SECURE_MALLOC
|
||||
IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size );
|
||||
#endif
|
||||
return m_buffer[idx];
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ScopedAlloc
|
||||
// --------------------------------------------------------------------------------------
|
||||
// A simple container class for a standard malloc allocation. By default, no bounds checking
|
||||
// is performed, and there is no option for enabling bounds checking. If bounds checking and
|
||||
// other features are needed, use the more robust SafeArray<> instead.
|
||||
//
|
||||
// See docs for BaseScopedAlloc for details and rationale.
|
||||
//
|
||||
template< typename T >
|
||||
class ScopedAlloc : public BaseScopedAlloc<T>
|
||||
{
|
||||
public:
|
||||
ScopedAlloc( size_t size=0 ) : BaseScopedAlloc()
|
||||
{
|
||||
Alloc(size);
|
||||
}
|
||||
|
||||
virtual ~ScopedAlloc() throw()
|
||||
{
|
||||
Alloc(0);
|
||||
}
|
||||
|
||||
virtual void Alloc( size_t newsize )
|
||||
{
|
||||
safe_free(m_buffer);
|
||||
m_size = newsize;
|
||||
if (!m_size) return;
|
||||
|
||||
m_buffer = (T*)malloc( m_size * sizeof(T) );
|
||||
if (!m_buffer)
|
||||
throw Exception::OutOfMemory("ScopedAlloc");
|
||||
}
|
||||
|
||||
virtual void Resize( size_t newsize )
|
||||
{
|
||||
m_size = newsize;
|
||||
m_buffer = (T*)realloc(m_buffer * sizeof(T), newsize);
|
||||
|
||||
if (!m_buffer)
|
||||
throw Exception::OutOfMemory("ScopedAlloc::Resize");
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ScopedAlignedAlloc
|
||||
// --------------------------------------------------------------------------------------
|
||||
// A simple container class for an aligned allocation. By default, no bounds checking is
|
||||
// performed, and there is no option for enabling bounds checking. If bounds checking and
|
||||
// other features are needed, use the more robust SafeArray<> instead.
|
||||
//
|
||||
// See docs for BaseScopedAlloc for details and rationale.
|
||||
//
|
||||
template< typename T, uint align >
|
||||
class ScopedAlignedAlloc : public BaseScopedAlloc<T>
|
||||
{
|
||||
public:
|
||||
ScopedAlignedAlloc( size_t size=0 ) : BaseScopedAlloc()
|
||||
{
|
||||
Alloc(size);
|
||||
}
|
||||
|
||||
virtual ~ScopedAlignedAlloc() throw()
|
||||
{
|
||||
Alloc(0);
|
||||
}
|
||||
|
||||
virtual void Alloc( size_t newsize )
|
||||
{
|
||||
safe_aligned_free(m_buffer);
|
||||
m_size = newsize;
|
||||
if (!m_size) return;
|
||||
|
||||
m_buffer = (T*)_aligned_malloc( m_size * sizeof(T), align );
|
||||
if (!m_buffer)
|
||||
throw Exception::OutOfMemory(L"ScopedAlignedAlloc");
|
||||
}
|
||||
|
||||
virtual void Resize( size_t newsize )
|
||||
{
|
||||
m_size = newsize;
|
||||
m_buffer = (T*)_aligned_realloc(m_buffer, newsize * sizeof(T), align);
|
||||
|
||||
if (!m_buffer)
|
||||
throw Exception::OutOfMemory(L"ScopedAlignedAlloc::Resize");
|
||||
}
|
||||
};
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Assertions.h"
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ScopedPtr
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -170,6 +172,7 @@ public:
|
|||
{
|
||||
Delete();
|
||||
m_array = ptr;
|
||||
m_valid_range = 0xffffffff;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "Dependencies.h"
|
||||
#include "SafeArray.h"
|
||||
#include "ScopedMalloc.h"
|
||||
|
||||
#include <wx/tokenzr.h>
|
||||
|
||||
|
@ -128,7 +129,6 @@ struct ParsedAssignmentString
|
|||
// accepts Ascii/UTF8 only.
|
||||
//
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// FastFormatAscii
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -136,8 +136,9 @@ struct ParsedAssignmentString
|
|||
class FastFormatAscii
|
||||
{
|
||||
protected:
|
||||
SafeArray<char>* m_dest;
|
||||
ScopedAlignedAlloc<char,16>* m_dest;
|
||||
bool m_deleteDest;
|
||||
uint m_Length;
|
||||
|
||||
public:
|
||||
FastFormatAscii();
|
||||
|
@ -147,12 +148,31 @@ public:
|
|||
|
||||
void Clear();
|
||||
bool IsEmpty() const;
|
||||
uint Length() const { return m_Length; }
|
||||
|
||||
const char* c_str() const { return m_dest->GetPtr(); }
|
||||
operator const char*() const { return m_dest->GetPtr(); }
|
||||
|
||||
const wxString GetString() const;
|
||||
//operator wxString() const;
|
||||
|
||||
FastFormatAscii& operator+=(const wxString& s)
|
||||
{
|
||||
Write( "%ls", s.c_str() );
|
||||
return *this;
|
||||
}
|
||||
|
||||
FastFormatAscii& operator+=(const wxChar* psz )
|
||||
{
|
||||
Write( "%ls", psz );
|
||||
return *this;
|
||||
}
|
||||
|
||||
FastFormatAscii& operator+=(const char* psz )
|
||||
{
|
||||
Write( "%s", psz );
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -161,8 +181,9 @@ public:
|
|||
class FastFormatUnicode
|
||||
{
|
||||
protected:
|
||||
SafeArray<char>* m_dest;
|
||||
ScopedAlignedAlloc<char,16>* m_dest;
|
||||
bool m_deleteDest;
|
||||
uint m_Length;
|
||||
|
||||
public:
|
||||
FastFormatUnicode();
|
||||
|
@ -175,16 +196,39 @@ public:
|
|||
|
||||
void Clear();
|
||||
bool IsEmpty() const;
|
||||
uint Length() const { return m_Length; }
|
||||
|
||||
FastFormatUnicode& ToUpper();
|
||||
FastFormatUnicode& ToLower();
|
||||
|
||||
const wxChar* c_str() const { return (const wxChar*)m_dest->GetPtr(); }
|
||||
operator const wxChar*() const { return (const wxChar*)m_dest->GetPtr(); }
|
||||
operator wxString() const { return (const wxChar*)m_dest->GetPtr(); }
|
||||
|
||||
FastFormatUnicode& operator+=(const wxString& s)
|
||||
{
|
||||
Write( L"%s", s.c_str() );
|
||||
return *this;
|
||||
}
|
||||
|
||||
FastFormatUnicode& operator+=(const wxChar* psz )
|
||||
{
|
||||
Write( L"%s", psz );
|
||||
return *this;
|
||||
}
|
||||
|
||||
FastFormatUnicode& operator+=(const char* psz );
|
||||
};
|
||||
|
||||
extern bool pxParseAssignmentString( const wxString& src, wxString& ldest, wxString& rdest );
|
||||
|
||||
#define pxsFmt FastFormatUnicode().Write
|
||||
#define pxsFmtV FastFormatUnicode().WriteV
|
||||
#define pxsFmt FastFormatUnicode().Write
|
||||
#define pxsFmtV FastFormatUnicode().WriteV
|
||||
|
||||
extern wxString& operator+=(wxString& str1, const FastFormatUnicode& str2);
|
||||
extern wxString operator+(const wxString& str1, const FastFormatUnicode& str2);
|
||||
extern wxString operator+(const wxChar* str1, const FastFormatUnicode& str2);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Custom internal sprintf functions, which are ASCII only (even in UNICODE builds)
|
||||
|
|
|
@ -35,7 +35,7 @@ class SynchronousActionState
|
|||
protected:
|
||||
bool m_posted;
|
||||
Threading::Semaphore m_sema;
|
||||
ScopedPtr<BaseException> m_exception;
|
||||
ScopedExcept m_exception;
|
||||
|
||||
public:
|
||||
sptr return_value;
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxStreamWriter
|
||||
// --------------------------------------------------------------------------------------
|
||||
class pxStreamWriter
|
||||
{
|
||||
DeclareNoncopyableObject(pxStreamWriter);
|
||||
|
||||
protected:
|
||||
wxString m_filename;
|
||||
ScopedPtr<wxOutputStream> m_outstream;
|
||||
|
||||
public:
|
||||
pxStreamWriter(const wxString& filename, ScopedPtr<wxOutputStream>& output);
|
||||
pxStreamWriter(const wxString& filename, wxOutputStream* output);
|
||||
|
||||
virtual ~pxStreamWriter() throw() {}
|
||||
virtual void Write( const void* data, size_t size );
|
||||
|
||||
void Close() { m_outstream.Delete(); }
|
||||
wxOutputStream* GetBaseStream() const { return m_outstream; }
|
||||
|
||||
void SetStream( const wxString& filename, ScopedPtr<wxOutputStream>& stream );
|
||||
void SetStream( const wxString& filename, wxOutputStream* stream );
|
||||
|
||||
wxString GetStreamName() const { return m_filename; }
|
||||
|
||||
template< typename T >
|
||||
void Write( const T& data )
|
||||
{
|
||||
Write( &data, sizeof(data) );
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxStreamReader
|
||||
// --------------------------------------------------------------------------------------
|
||||
class pxStreamReader
|
||||
{
|
||||
DeclareNoncopyableObject(pxStreamReader);
|
||||
|
||||
protected:
|
||||
wxString m_filename;
|
||||
ScopedPtr<wxInputStream> m_stream;
|
||||
|
||||
public:
|
||||
pxStreamReader(const wxString& filename, ScopedPtr<wxInputStream>& input);
|
||||
pxStreamReader(const wxString& filename, wxInputStream* input);
|
||||
|
||||
virtual ~pxStreamReader() throw() {}
|
||||
virtual void Read( void* dest, size_t size );
|
||||
|
||||
void SetStream( const wxString& filename, ScopedPtr<wxInputStream>& stream );
|
||||
void SetStream( const wxString& filename, wxInputStream* stream );
|
||||
|
||||
wxInputStream* GetBaseStream() const { return m_stream; }
|
||||
void Close() { m_stream.Delete(); }
|
||||
|
||||
wxString GetStreamName() const { return m_filename; }
|
||||
|
||||
template< typename T >
|
||||
void Read( T& dest )
|
||||
{
|
||||
Read( &dest, sizeof(dest) );
|
||||
}
|
||||
};
|
|
@ -113,7 +113,7 @@ set(UtilitiesSources
|
|||
pxCheckBox.cpp
|
||||
pxRadioPanel.cpp
|
||||
pxStaticText.cpp
|
||||
pxTextStream.cpp
|
||||
pxStreams.cpp
|
||||
pxTranslate.cpp
|
||||
pxWindowTextWriter.cpp
|
||||
Semaphore.cpp
|
||||
|
@ -149,8 +149,10 @@ set(UtilitiesHeaders
|
|||
../../include/Utilities/pxCheckBox.h
|
||||
../../include/Utilities/pxRadioPanel.h
|
||||
../../include/Utilities/pxStaticText.h
|
||||
../../include/Utilities/pxStreams.h
|
||||
../../include/Utilities/RedtapeWindows.h
|
||||
../../include/Utilities/SafeArray.h
|
||||
../../include/Utilities/ScopedAlloc.h
|
||||
../../include/Utilities/ScopedPtr.h
|
||||
../../include/Utilities/ScopedPtrMT.h
|
||||
../../include/Utilities/StringHelpers.h
|
||||
|
|
|
@ -169,8 +169,8 @@ Exception::RuntimeError::RuntimeError( const std::runtime_error& ex, const wxStr
|
|||
{
|
||||
IsSilent = false;
|
||||
|
||||
const wxString msg( wxsFormat( L"STL Runtime Error%s: %s",
|
||||
(prefix.IsEmpty() ? prefix.c_str() : wxsFormat(L" (%s)", prefix.c_str()).c_str()),
|
||||
const wxString msg( pxsFmt( L"STL Runtime Error%s: %s",
|
||||
(prefix.IsEmpty() ? prefix.c_str() : pxsFmt(L" (%s)", prefix.c_str()).c_str()),
|
||||
fromUTF8( ex.what() ).c_str()
|
||||
) );
|
||||
|
||||
|
@ -181,8 +181,8 @@ Exception::RuntimeError::RuntimeError( const std::exception& ex, const wxString&
|
|||
{
|
||||
IsSilent = false;
|
||||
|
||||
const wxString msg( wxsFormat( L"STL Exception%s: %s",
|
||||
(prefix.IsEmpty() ? prefix.c_str() : wxsFormat(L" (%s)", prefix.c_str()).c_str()),
|
||||
const wxString msg( pxsFmt( L"STL Exception%s: %s",
|
||||
(prefix.IsEmpty() ? prefix.c_str() : pxsFmt(L" (%s)", prefix.c_str()).c_str()),
|
||||
fromUTF8( ex.what() ).c_str()
|
||||
) );
|
||||
|
||||
|
@ -207,7 +207,7 @@ wxString Exception::OutOfMemory::FormatDiagnosticMessage() const
|
|||
wxString Exception::OutOfMemory::FormatDisplayMessage() const
|
||||
{
|
||||
if (m_message_user.IsEmpty()) return FormatDisplayMessage();
|
||||
return m_message_user + wxsFormat( L"\n\nInternal allocation descriptor: %s", AllocDescription.c_str());
|
||||
return m_message_user + pxsFmt( L"\n\nInternal allocation descriptor: %s", AllocDescription.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
@ -224,7 +224,7 @@ wxString Exception::CancelEvent::FormatDisplayMessage() const
|
|||
|
||||
wxString Exception::Stream::FormatDiagnosticMessage() const
|
||||
{
|
||||
return wxsFormat(
|
||||
return pxsFmt(
|
||||
L"%s\n\tFile/Object: %s",
|
||||
m_message_diag.c_str(), StreamName.c_str()
|
||||
);
|
||||
|
@ -234,8 +234,46 @@ wxString Exception::Stream::FormatDisplayMessage() const
|
|||
{
|
||||
wxString retval( m_message_user );
|
||||
if (!StreamName.IsEmpty())
|
||||
retval += L"\n\n" + wxsFormat( _("Path: %s"), StreamName.c_str() );
|
||||
retval += L"\n\n" + pxsFmt( _("Path: %s"), StreamName.c_str() );
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Exceptions from Errno (POSIX)
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// Translates an Errno code into an exception.
|
||||
// Throws an exception based on the given error code (usually taken from ANSI C's errno)
|
||||
BaseException* Exception::FromErrno( const wxString& streamname, errno_t errcode )
|
||||
{
|
||||
pxAssumeDev( errcode != 0, "Invalid NULL error code? (errno)" );
|
||||
|
||||
switch( errcode )
|
||||
{
|
||||
case EINVAL:
|
||||
pxFailDev( L"Invalid argument" );
|
||||
return &(new Exception::Stream( streamname ))->SetDiagMsg(L"Invalid argument? (likely caused by an unforgivable programmer error!)" );
|
||||
|
||||
case EACCES: // Access denied!
|
||||
return new Exception::AccessDenied( streamname );
|
||||
|
||||
case EMFILE: // Too many open files!
|
||||
return &(new Exception::CannotCreateStream( streamname ))->SetDiagMsg(L"Too many open files"); // File handle allocation failure
|
||||
|
||||
case EEXIST:
|
||||
return &(new Exception::CannotCreateStream( streamname ))->SetDiagMsg(L"File already exists");
|
||||
|
||||
case ENOENT: // File not found!
|
||||
return new Exception::FileNotFound( streamname );
|
||||
|
||||
case EPIPE:
|
||||
return &(new Exception::BadStream( streamname ))->SetDiagMsg(L"Broken pipe");
|
||||
|
||||
case EBADF:
|
||||
return &(new Exception::BadStream( streamname ))->SetDiagMsg(L"Bad file number");
|
||||
|
||||
default:
|
||||
return &(new Exception::Stream( streamname ))->SetDiagMsg(pxsFmt( L"General file/stream error [errno: %d]", errcode ));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Threading.h"
|
||||
|
||||
#include "TlsVariable.inl"
|
||||
#include "SafeArray.inl"
|
||||
|
||||
|
@ -36,6 +37,8 @@ template class SafeAlignedArray<u8,16>;
|
|||
// system deadlock.
|
||||
static const int MaxFormattedStringLength = 0x80000;
|
||||
|
||||
typedef ScopedAlignedAlloc<char,16> CharBufferType;
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// FastFormatBuffers
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -50,7 +53,7 @@ class FastFormatBuffers
|
|||
|
||||
protected:
|
||||
typedef char CharType;
|
||||
typedef SafeAlignedArray<CharType,16> BufferType;
|
||||
typedef CharBufferType BufferType;
|
||||
|
||||
static const uint BufferCount = 4;
|
||||
|
||||
|
@ -66,10 +69,7 @@ public:
|
|||
|
||||
for (uint i=0; i<BufferCount; ++i)
|
||||
{
|
||||
m_buffers[i].Name = wxsFormat(L"%s Formatting Buffer (slot%d)",
|
||||
(sizeof(CharType)==1) ? L"UTF8/Ascii" : L"Wide-char", i);
|
||||
m_buffers[i].MakeRoomFor(1024);
|
||||
m_buffers[i].ChunkSize = 2048;
|
||||
m_buffers[i].Alloc(1024);
|
||||
}
|
||||
|
||||
m_curslot = 0;
|
||||
|
@ -92,14 +92,14 @@ public:
|
|||
BufferType& GrabBuffer()
|
||||
{
|
||||
++m_curslot;
|
||||
pxAssume(m_curslot<BufferCount);
|
||||
pxAssume(m_curslot < BufferCount);
|
||||
return m_buffers[m_curslot];
|
||||
}
|
||||
|
||||
void ReleaseBuffer()
|
||||
{
|
||||
--m_curslot;
|
||||
pxAssume(m_curslot<BufferCount);
|
||||
pxAssume(m_curslot < BufferCount);
|
||||
}
|
||||
|
||||
BufferType& operator[](uint i)
|
||||
|
@ -150,7 +150,8 @@ public:
|
|||
static bool buffer_is_avail = false;
|
||||
static GlobalBufferManager< BaseTlsVariable< FastFormatBuffers > > m_buffer_tls(buffer_is_avail);
|
||||
|
||||
static __ri void format_that_ascii_mess( SafeArray<char>& buffer, uint writepos, const char* fmt, va_list argptr )
|
||||
//static __ri void format_that_ascii_mess( SafeArray<char>& buffer, uint writepos, const char* fmt, va_list argptr )
|
||||
static __ri void format_that_ascii_mess( CharBufferType& buffer, uint writepos, const char* fmt, va_list argptr )
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
|
@ -173,26 +174,27 @@ static __ri void format_that_ascii_mess( SafeArray<char>& buffer, uint writepos,
|
|||
|
||||
len += writepos;
|
||||
if (len < size) break;
|
||||
buffer.ExactAlloc( len + 31 );
|
||||
buffer.Alloc( len + 128 );
|
||||
};
|
||||
|
||||
// performing an assertion or log of a truncated string is unsafe, so let's not; even
|
||||
// though it'd be kinda nice if we did.
|
||||
}
|
||||
|
||||
static __ri void format_that_unicode_mess( SafeArray<char>& buffer, uint writepos, const wxChar* fmt, va_list argptr)
|
||||
// returns the length of the formatted string, in characters (wxChars).
|
||||
static __ri uint format_that_unicode_mess( CharBufferType& buffer, uint writepos, const wxChar* fmt, va_list argptr)
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
int size = buffer.GetLength() / sizeof(wxChar);
|
||||
int len = wxVsnprintf((wxChar*)buffer.GetPtr(writepos*2), size-writepos, fmt, argptr);
|
||||
int len = wxVsnprintf((wxChar*)buffer.GetPtr(writepos*sizeof(wxChar)), size-writepos, fmt, argptr);
|
||||
|
||||
// some implementations of vsnprintf() don't NUL terminate
|
||||
// the string if there is not enough space for it so
|
||||
// always do it manually
|
||||
((wxChar*)buffer.GetPtr())[size-1] = L'\0';
|
||||
|
||||
if( size >= MaxFormattedStringLength ) break;
|
||||
if( size >= MaxFormattedStringLength ) return size-1;
|
||||
|
||||
// vsnprintf() may return either -1 (traditional Unix behavior) or the
|
||||
// total number of characters which would have been written if the
|
||||
|
@ -202,15 +204,18 @@ static __ri void format_that_unicode_mess( SafeArray<char>& buffer, uint writepo
|
|||
len = size + (size/4);
|
||||
|
||||
len += writepos;
|
||||
if (len < size) break;
|
||||
buffer.ExactAlloc( (len + 31) * sizeof(wxChar) );
|
||||
if (len < size) return len;
|
||||
buffer.Alloc( (len + 128) * sizeof(wxChar) );
|
||||
};
|
||||
|
||||
// performing an assertion or log of a truncated string is unsafe, so let's not; even
|
||||
// though it'd be kinda nice if we did.
|
||||
|
||||
pxAssume( false );
|
||||
return 0; // unreachable.
|
||||
}
|
||||
|
||||
SafeArray<char>* GetFormatBuffer( bool& deleteDest )
|
||||
CharBufferType* GetFormatBuffer( bool& deleteDest )
|
||||
{
|
||||
deleteDest = false;
|
||||
if (buffer_is_avail)
|
||||
|
@ -220,7 +225,8 @@ SafeArray<char>* GetFormatBuffer( bool& deleteDest )
|
|||
}
|
||||
|
||||
deleteDest = true;
|
||||
return new SafeArray<char>(2048, L"Temporary string formatting buffer");
|
||||
|
||||
return new CharBufferType(2048);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -248,6 +254,7 @@ FastFormatUnicode::~FastFormatUnicode() throw()
|
|||
|
||||
void FastFormatUnicode::Clear()
|
||||
{
|
||||
m_Length = 0;
|
||||
((wxChar*)m_dest->GetPtr())[0] = 0;
|
||||
}
|
||||
|
||||
|
@ -255,16 +262,18 @@ FastFormatUnicode& FastFormatUnicode::WriteV( const char* fmt, va_list argptr )
|
|||
{
|
||||
wxString converted( fromUTF8(FastFormatAscii().WriteV( fmt, argptr )) );
|
||||
|
||||
uint inspos = wxStrlen((wxChar*)m_dest->GetPtr());
|
||||
m_dest->MakeRoomFor((inspos + converted.Length() + 31)*sizeof(wxChar));
|
||||
wxStrcpy( &((wxChar*)m_dest->GetPtr())[inspos], converted );
|
||||
|
||||
const uint inspos = m_Length;
|
||||
const uint convLen = converted.Length();
|
||||
m_dest->MakeRoomFor((inspos + convLen + 64) * sizeof(wxChar));
|
||||
memcpy_fast( &((wxChar*)m_dest->GetPtr())[inspos], converted, (convLen+1)*sizeof(wxChar) );
|
||||
m_Length += convLen;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FastFormatUnicode& FastFormatUnicode::WriteV( const wxChar* fmt, va_list argptr )
|
||||
{
|
||||
format_that_unicode_mess( *m_dest, wxStrlen((wxChar*)m_dest->GetPtr()), fmt, argptr );
|
||||
m_Length = format_that_unicode_mess( *m_dest, m_Length, fmt, argptr );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -291,6 +300,53 @@ bool FastFormatUnicode::IsEmpty() const
|
|||
return ((wxChar&)(*m_dest)[0]) == 0;
|
||||
}
|
||||
|
||||
FastFormatUnicode& FastFormatUnicode::ToUpper()
|
||||
{
|
||||
wxChar* ch = (wxChar*)m_dest->GetPtr();
|
||||
for ( uint i=0; i<m_Length; ++i, ++ch )
|
||||
*ch = (wxChar)wxToupper(*ch);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FastFormatUnicode& FastFormatUnicode::ToLower()
|
||||
{
|
||||
wxChar* ch = (wxChar*)m_dest->GetPtr();
|
||||
for ( uint i=0; i<m_Length; ++i, ++ch )
|
||||
*ch = (wxChar)wxTolower(*ch);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FastFormatUnicode& FastFormatUnicode::operator+=(const char* psz )
|
||||
{
|
||||
Write( L"%s", fromUTF8(psz).c_str() );
|
||||
return *this;
|
||||
}
|
||||
|
||||
wxString& operator+=(wxString& str1, const FastFormatUnicode& str2)
|
||||
{
|
||||
str1.Append(str2.c_str(), str2.Length());
|
||||
return str1;
|
||||
}
|
||||
|
||||
wxString operator+(const wxString& str1, const FastFormatUnicode& str2)
|
||||
{
|
||||
wxString s = str1;
|
||||
s += str2;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
wxString operator+(const wxChar* str1, const FastFormatUnicode& str2)
|
||||
{
|
||||
wxString s = str1;
|
||||
s += str2;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// FastFormatAscii (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
|
|
@ -154,7 +154,7 @@ bool Threading::_WaitGui_RecursionGuard( const wxChar* name )
|
|||
|
||||
if( !guard.IsReentrant() ) return false;
|
||||
pxThreadLog.Write( pxGetCurrentThreadName(),
|
||||
wxsFormat(L"Yield recursion in %s; opening modal dialog.", name)
|
||||
pxsFmt(L"Yield recursion in %s; opening modal dialog.", name)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ bool Threading::pxThread::AffinityAssert_AllowFromSelf( const DiagnosticOrigin&
|
|||
if( IsSelf() ) return true;
|
||||
|
||||
if( IsDevBuild )
|
||||
pxOnAssert( origin, wxsFormat( L"Thread affinity violation: Call allowed from '%s' thread only.", GetName().c_str() ) );
|
||||
pxOnAssert( origin, pxsFmt( L"Thread affinity violation: Call allowed from '%s' thread only.", GetName().c_str() ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ bool Threading::pxThread::AffinityAssert_DisallowFromSelf( const DiagnosticOrigi
|
|||
if( !IsSelf() ) return true;
|
||||
|
||||
if( IsDevBuild )
|
||||
pxOnAssert( origin, wxsFormat( L"Thread affinity violation: Call is *not* allowed from '%s' thread.", GetName().c_str() ) );
|
||||
pxOnAssert( origin, pxsFmt( L"Thread affinity violation: Call is *not* allowed from '%s' thread.", GetName().c_str() ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -404,10 +404,8 @@ void Threading::pxThread::RethrowException() const
|
|||
// pointer might still be invalid after detachment, so might as well just detach and check
|
||||
// after.
|
||||
|
||||
ScopedPtr<BaseException> ptr( const_cast<pxThread*>(this)->m_except.DetachPtr() );
|
||||
ScopedExcept ptr( const_cast<pxThread*>(this)->m_except.DetachPtr() );
|
||||
if( ptr ) ptr->Rethrow();
|
||||
|
||||
//m_except->Rethrow();
|
||||
}
|
||||
|
||||
static bool m_BlockDeletions = false;
|
||||
|
@ -429,13 +427,13 @@ void Threading::pxThread::_selfRunningTest( const wxChar* name ) const
|
|||
{
|
||||
if( HasPendingException() )
|
||||
{
|
||||
pxThreadLog.Error( GetName(), wxsFormat(L"An exception was thrown while waiting on a %s.", name) );
|
||||
pxThreadLog.Error( GetName(), pxsFmt(L"An exception was thrown while waiting on a %s.", name) );
|
||||
RethrowException();
|
||||
}
|
||||
|
||||
if( !m_running )
|
||||
{
|
||||
throw Exception::CancelEvent( wxsFormat(
|
||||
throw Exception::CancelEvent( pxsFmt(
|
||||
L"Blocking thread %s was terminated while another thread was waiting on a %s.",
|
||||
GetName().c_str(), name )
|
||||
);
|
||||
|
@ -558,7 +556,7 @@ void Threading::pxThread::_try_virtual_invoke( void (pxThread::*method)() )
|
|||
catch( Exception::RuntimeError& ex )
|
||||
{
|
||||
BaseException* woot = ex.Clone();
|
||||
woot->DiagMsg() += wxsFormat( L"(thread:%s)", GetName().c_str() );
|
||||
woot->DiagMsg() += pxsFmt( L"(thread:%s)", GetName().c_str() );
|
||||
m_except = woot;
|
||||
}
|
||||
#ifndef PCSX2_DEVBUILD
|
||||
|
@ -568,13 +566,13 @@ void Threading::pxThread::_try_virtual_invoke( void (pxThread::*method)() )
|
|||
// the MSVC debugger (or by silent random annoying fail on debug-less linux).
|
||||
/*catch( std::logic_error& ex )
|
||||
{
|
||||
throw BaseException( wxsFormat( L"STL Logic Error (thread:%s): %s",
|
||||
throw BaseException( pxsFmt( L"STL Logic Error (thread:%s): %s",
|
||||
GetName().c_str(), fromUTF8( ex.what() ).c_str() )
|
||||
);
|
||||
}
|
||||
catch( std::exception& ex )
|
||||
{
|
||||
throw BaseException( wxsFormat( L"STL exception (thread:%s): %s",
|
||||
throw BaseException( pxsFmt( L"STL exception (thread:%s): %s",
|
||||
GetName().c_str(), fromUTF8( ex.what() ).c_str() )
|
||||
);
|
||||
}*/
|
||||
|
@ -584,7 +582,7 @@ void Threading::pxThread::_try_virtual_invoke( void (pxThread::*method)() )
|
|||
catch( BaseException& ex )
|
||||
{
|
||||
BaseException* woot = ex.Clone();
|
||||
woot->DiagMsg() += wxsFormat( L"(thread:%s)", GetName().c_str() );
|
||||
woot->DiagMsg() += pxsFmt( L"(thread:%s)", GetName().c_str() );
|
||||
m_except = woot;
|
||||
}
|
||||
#endif
|
||||
|
@ -862,12 +860,12 @@ __fi void* Threading::_AtomicCompareExchangePointer( volatile uptr& target, uptr
|
|||
|
||||
wxString Exception::BaseThreadError::FormatDiagnosticMessage() const
|
||||
{
|
||||
return wxsFormat( m_message_diag, (m_thread==NULL) ? L"Null Thread Object" : m_thread->GetName().c_str());
|
||||
return pxsFmt( m_message_diag, (m_thread==NULL) ? L"Null Thread Object" : m_thread->GetName().c_str());
|
||||
}
|
||||
|
||||
wxString Exception::BaseThreadError::FormatDisplayMessage() const
|
||||
{
|
||||
return wxsFormat( m_message_user, (m_thread==NULL) ? L"Null Thread Object" : m_thread->GetName().c_str());
|
||||
return pxsFmt( m_message_user, (m_thread==NULL) ? L"Null Thread Object" : m_thread->GetName().c_str());
|
||||
}
|
||||
|
||||
pxThread& Exception::BaseThreadError::Thread()
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "wxBaseTools.h"
|
||||
#include "pxStreams.h"
|
||||
|
||||
#include <wx/stream.h>
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxStreamReader (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Interface for reading data from a gzip stream.
|
||||
//
|
||||
|
||||
pxStreamReader::pxStreamReader(const wxString& filename, ScopedPtr<wxInputStream>& input)
|
||||
: m_filename( filename )
|
||||
, m_stream( input.DetachPtr() )
|
||||
{
|
||||
}
|
||||
|
||||
pxStreamReader::pxStreamReader(const wxString& filename, wxInputStream* input)
|
||||
: m_filename( filename )
|
||||
, m_stream( input )
|
||||
{
|
||||
}
|
||||
|
||||
void pxStreamReader::SetStream( const wxString& filename, ScopedPtr<wxInputStream>& stream )
|
||||
{
|
||||
m_filename = filename;
|
||||
m_stream = stream.DetachPtr();
|
||||
}
|
||||
|
||||
void pxStreamReader::SetStream( const wxString& filename, wxInputStream* stream )
|
||||
{
|
||||
m_filename = filename;
|
||||
m_stream = stream;
|
||||
}
|
||||
|
||||
void pxStreamReader::Read( void* dest, size_t size )
|
||||
{
|
||||
m_stream->Read(dest, size);
|
||||
if (m_stream->GetLastError() == wxSTREAM_READ_ERROR)
|
||||
{
|
||||
int err = errno;
|
||||
if (!err)
|
||||
throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot read from file (bad file handle?)");
|
||||
|
||||
ScopedExcept ex(Exception::FromErrno(m_filename, err));
|
||||
ex->SetDiagMsg( L"cannot read from file: " + ex->DiagMsg() );
|
||||
ex->Rethrow();
|
||||
}
|
||||
|
||||
// IMPORTANT! The underlying file/source Eof() stuff is not really reliable, so we
|
||||
// must always use the explicit check against the number of bytes read to determine
|
||||
// end-of-stream conditions.
|
||||
|
||||
if ((size_t)m_stream->LastRead() < size)
|
||||
throw Exception::EndOfStream( m_filename );
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxStreamWriter
|
||||
// --------------------------------------------------------------------------------------
|
||||
pxStreamWriter::pxStreamWriter(const wxString& filename, ScopedPtr<wxOutputStream>& output)
|
||||
: m_filename( filename )
|
||||
, m_outstream( output.DetachPtr() )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
pxStreamWriter::pxStreamWriter(const wxString& filename, wxOutputStream* output)
|
||||
: m_filename( filename )
|
||||
, m_outstream( output )
|
||||
{
|
||||
}
|
||||
|
||||
void pxStreamWriter::SetStream( const wxString& filename, ScopedPtr<wxOutputStream>& stream )
|
||||
{
|
||||
m_filename = filename;
|
||||
m_outstream = stream.DetachPtr();
|
||||
}
|
||||
|
||||
void pxStreamWriter::SetStream( const wxString& filename, wxOutputStream* stream )
|
||||
{
|
||||
m_filename = filename;
|
||||
m_outstream = stream;
|
||||
}
|
||||
|
||||
|
||||
void pxStreamWriter::Write( const void* src, size_t size )
|
||||
{
|
||||
m_outstream->Write(src, size);
|
||||
if(m_outstream->GetLastError() == wxSTREAM_WRITE_ERROR)
|
||||
{
|
||||
int err = errno;
|
||||
if (!err)
|
||||
throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot write to file/stream.");
|
||||
|
||||
ScopedExcept ex(Exception::FromErrno(m_filename, err));
|
||||
ex->SetDiagMsg( L"Cannot write to file: " + ex->DiagMsg() );
|
||||
ex->Rethrow();
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxTextStream
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// Returns TRUE if the source is UTF8, or FALSE if it's just ASCII crap.
|
||||
bool pxReadLine( wxInputStream& input, std::string& dest )
|
||||
{
|
||||
dest.clear();
|
||||
bool isUTF8 = false;
|
||||
while ( true )
|
||||
{
|
||||
char c;
|
||||
input.Read(&c, sizeof(c));
|
||||
if( c == 0 ) break;
|
||||
if( input.Eof() ) break;
|
||||
if( c == '\n' ) break; // eat on UNIX
|
||||
if( c == '\r' )
|
||||
{
|
||||
input.Read(&c, sizeof(c));
|
||||
if( c == 0 ) break;
|
||||
if( input.Eof() ) break;
|
||||
if( c == '\n' ) break;
|
||||
|
||||
input.Ungetch(c);
|
||||
break;
|
||||
}
|
||||
dest += c;
|
||||
if( c & 0x80 ) isUTF8 = true;
|
||||
}
|
||||
|
||||
return isUTF8;
|
||||
}
|
||||
|
||||
void pxReadLine( wxInputStream& input, wxString& dest, std::string& intermed )
|
||||
{
|
||||
dest.clear();
|
||||
if( pxReadLine( input, intermed ) )
|
||||
dest = fromUTF8(intermed.c_str());
|
||||
else
|
||||
{
|
||||
// Optimized ToAscii conversion.
|
||||
// wx3.0 : NOT COMPATIBLE!! (on linux anyway)
|
||||
const char* ascii = intermed.c_str();
|
||||
while( *ascii != 0 ) dest += (wchar_t)(unsigned char)*ascii++;
|
||||
}
|
||||
}
|
||||
|
||||
void pxReadLine( wxInputStream& input, wxString& dest )
|
||||
{
|
||||
std::string line;
|
||||
pxReadLine( input, dest, line );
|
||||
}
|
||||
|
||||
wxString pxReadLine( wxInputStream& input )
|
||||
{
|
||||
wxString result;
|
||||
pxReadLine( input, result );
|
||||
return result;
|
||||
}
|
||||
|
||||
void pxWriteLine( wxOutputStream& output )
|
||||
{
|
||||
output.Write( "\n", 1 );
|
||||
}
|
||||
|
||||
void pxWriteLine( wxOutputStream& output, const wxString& text )
|
||||
{
|
||||
if( !text.IsEmpty() )
|
||||
{
|
||||
pxToUTF8 utf8(text);
|
||||
output.Write(utf8, utf8.Length());
|
||||
}
|
||||
pxWriteLine( output );
|
||||
}
|
||||
|
||||
void pxWriteMultiline( wxOutputStream& output, const wxString& src )
|
||||
{
|
||||
if( src.IsEmpty() ) return;
|
||||
|
||||
wxString result( src );
|
||||
result.Replace( L"\r\n", L"\n" );
|
||||
result.Replace( L"\r", L"\n" );
|
||||
|
||||
pxToUTF8 utf8(result);
|
||||
output.Write(utf8, utf8.Length());
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "wxBaseTools.h"
|
||||
#include <wx/stream.h>
|
||||
|
||||
|
||||
// Returns TRUE if the source is UTF8, or FALSE if it's just ASCII crap.
|
||||
bool pxReadLine( wxInputStream& input, std::string& dest )
|
||||
{
|
||||
dest.clear();
|
||||
bool isUTF8 = false;
|
||||
while ( true )
|
||||
{
|
||||
char c;
|
||||
input.Read(&c, sizeof(c));
|
||||
if( c == 0 ) break;
|
||||
if( input.Eof() ) break;
|
||||
if( c == '\n' ) break; // eat on UNIX
|
||||
if( c == '\r' )
|
||||
{
|
||||
input.Read(&c, sizeof(c));
|
||||
if( c == 0 ) break;
|
||||
if( input.Eof() ) break;
|
||||
if( c == '\n' ) break;
|
||||
|
||||
input.Ungetch(c);
|
||||
break;
|
||||
}
|
||||
dest += c;
|
||||
if( c & 0x80 ) isUTF8 = true;
|
||||
}
|
||||
|
||||
return isUTF8;
|
||||
}
|
||||
|
||||
void pxReadLine( wxInputStream& input, wxString& dest, std::string& intermed )
|
||||
{
|
||||
dest.clear();
|
||||
if( pxReadLine( input, intermed ) )
|
||||
dest = fromUTF8(intermed.c_str());
|
||||
else
|
||||
{
|
||||
// Optimized ToAscii conversion.
|
||||
// wx3.0 : NOT COMPATIBLE!! (on linux anyway)
|
||||
const char* ascii = intermed.c_str();
|
||||
while( *ascii != 0 ) dest += (wchar_t)(unsigned char)*ascii++;
|
||||
}
|
||||
}
|
||||
|
||||
void pxReadLine( wxInputStream& input, wxString& dest )
|
||||
{
|
||||
std::string line;
|
||||
pxReadLine( input, dest, line );
|
||||
}
|
||||
|
||||
wxString pxReadLine( wxInputStream& input )
|
||||
{
|
||||
wxString result;
|
||||
pxReadLine( input, result );
|
||||
return result;
|
||||
}
|
||||
|
||||
void pxWriteLine( wxOutputStream& output )
|
||||
{
|
||||
output.Write( "\n", 1 );
|
||||
}
|
||||
|
||||
void pxWriteLine( wxOutputStream& output, const wxString& text )
|
||||
{
|
||||
if( !text.IsEmpty() )
|
||||
{
|
||||
pxToUTF8 utf8(text);
|
||||
output.Write(utf8, utf8.Length());
|
||||
}
|
||||
pxWriteLine( output );
|
||||
}
|
||||
|
||||
void pxWriteMultiline( wxOutputStream& output, const wxString& src )
|
||||
{
|
||||
if( src.IsEmpty() ) return;
|
||||
|
||||
wxString result( src );
|
||||
result.Replace( L"\r\n", L"\n" );
|
||||
result.Replace( L"\r", L"\n" );
|
||||
|
||||
pxToUTF8 utf8(result);
|
||||
output.Write(utf8, utf8.Length());
|
||||
}
|
|
@ -145,12 +145,12 @@ void pxActionEvent::SetException( const BaseException& ex )
|
|||
|
||||
void pxActionEvent::SetException( BaseException* ex )
|
||||
{
|
||||
const wxString& prefix( wxsFormat(L"(%s) ", GetClassInfo()->GetClassName()) );
|
||||
const wxString& prefix( pxsFmt(L"(%s) ", GetClassInfo()->GetClassName()) );
|
||||
ex->DiagMsg() = prefix + ex->DiagMsg();
|
||||
|
||||
if( !m_state )
|
||||
{
|
||||
ScopedPtr<BaseException> exptr( ex ); // auto-delete it after handling.
|
||||
ScopedExcept exptr( ex ); // auto-delete it after handling.
|
||||
ex->Rethrow();
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ void pxSynchronousCommandEvent::SetException( BaseException* ex )
|
|||
{
|
||||
if( !m_sync )
|
||||
{
|
||||
ScopedPtr<BaseException> exptr( ex ); // auto-delete it after handling.
|
||||
ScopedExcept exptr( ex ); // auto-delete it after handling.
|
||||
ex->Rethrow();
|
||||
}
|
||||
|
||||
|
@ -278,7 +278,7 @@ pxExceptionEvent::pxExceptionEvent( const BaseException& ex )
|
|||
|
||||
void pxExceptionEvent::InvokeEvent()
|
||||
{
|
||||
ScopedPtr<BaseException> deleteMe( m_except );
|
||||
ScopedExcept deleteMe( m_except );
|
||||
if( deleteMe ) deleteMe->Rethrow();
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ static __fi s32 msf_to_lba(u8 m, u8 s, u8 f)
|
|||
return lsn;
|
||||
}
|
||||
|
||||
static __fi void lsn_to_msf(u8 *Time, s32 lsn)
|
||||
static __fi void lsn_to_msf(u8* Time, s32 lsn)
|
||||
{
|
||||
u8 m, s, f;
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ int lastLSN; // needed for block dumping
|
|||
|
||||
// Records last read block length for block dumping
|
||||
//static int plsn = 0;
|
||||
static isoFile *blockDumpFile = NULL;
|
||||
static isoFile blockDumpFile;
|
||||
|
||||
// Assertion check for CDVD != NULL (in devel and debug builds), because its handier than
|
||||
// relying on DEP exceptions -- and a little more reliable too.
|
||||
|
@ -341,56 +341,57 @@ bool DoCDVDopen()
|
|||
|
||||
int cdtype = DoCDVDdetectDiskType();
|
||||
|
||||
if (EmuConfig.CdvdDumpBlocks && (cdtype != CDVD_TYPE_NODISC))
|
||||
if (!EmuConfig.CdvdDumpBlocks || (cdtype == CDVD_TYPE_NODISC))
|
||||
{
|
||||
// TODO: Add a blockdumps configurable folder, and use that instead of CWD().
|
||||
blockDumpFile.Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: "Untitled" should use pnach/slus name resolution, slus if no patch,
|
||||
// and finally an "Untitled-[ElfCRC]" if no slus.
|
||||
// TODO: Add a blockdumps configurable folder, and use that instead of CWD().
|
||||
|
||||
wxString somepick( Path::GetFilenameWithoutExt( m_SourceFilename[m_CurrentSourceType] ) );
|
||||
if( somepick.IsEmpty() )
|
||||
somepick = L"Untitled";
|
||||
// TODO: "Untitled" should use pnach/slus name resolution, slus if no patch,
|
||||
// and finally an "Untitled-[ElfCRC]" if no slus.
|
||||
|
||||
wxString temp( Path::Combine( wxGetCwd(), somepick ) );
|
||||
wxString somepick( Path::GetFilenameWithoutExt( m_SourceFilename[m_CurrentSourceType] ) );
|
||||
if( somepick.IsEmpty() )
|
||||
somepick = L"Untitled";
|
||||
|
||||
wxString temp( Path::Combine( wxGetCwd(), somepick ) );
|
||||
|
||||
#ifdef ENABLE_TIMESTAMPS
|
||||
wxDateTime curtime( wxDateTime::GetTimeNow() );
|
||||
wxDateTime curtime( wxDateTime::GetTimeNow() );
|
||||
|
||||
temp += wxsFormat( L" (%04d-%02d-%02d %02d-%02d-%02d)",
|
||||
curtime.GetYear(), curtime.GetMonth(), curtime.GetDay(),
|
||||
curtime.GetHour(), curtime.GetMinute(), curtime.GetSecond()
|
||||
);
|
||||
temp += pxsFmt( L" (%04d-%02d-%02d %02d-%02d-%02d)",
|
||||
curtime.GetYear(), curtime.GetMonth(), curtime.GetDay(),
|
||||
curtime.GetHour(), curtime.GetMinute(), curtime.GetSecond()
|
||||
);
|
||||
#endif
|
||||
temp += L".dump";
|
||||
temp += L".dump";
|
||||
|
||||
cdvdTD td;
|
||||
CDVD->getTD(0, &td);
|
||||
cdvdTD td;
|
||||
CDVD->getTD(0, &td);
|
||||
|
||||
blockDumpFile = isoCreate(temp.ToUTF8(), ISOFLAGS_BLOCKDUMP_V3);
|
||||
blockDumpFile.Create(temp, ISOFLAGS_BLOCKDUMP_V3);
|
||||
|
||||
if( blockDumpFile != NULL )
|
||||
{
|
||||
int blockofs = 0, blocksize = CD_FRAMESIZE_RAW, blocks = td.lsn;
|
||||
|
||||
// hack: Because of limitations of the current cdvd design, we can't query the blocksize
|
||||
// of the underlying media. So lets make a best guess:
|
||||
|
||||
switch(cdtype)
|
||||
{
|
||||
case CDVD_TYPE_PS2DVD:
|
||||
case CDVD_TYPE_DVDV:
|
||||
case CDVD_TYPE_DETCTDVDS:
|
||||
case CDVD_TYPE_DETCTDVDD:
|
||||
blocksize = 2048;
|
||||
break;
|
||||
}
|
||||
isoSetFormat(blockDumpFile, blockofs, blocksize, blocks);
|
||||
}
|
||||
}
|
||||
else
|
||||
if( blockDumpFile.IsOpened() )
|
||||
{
|
||||
blockDumpFile = NULL;
|
||||
int blockofs = 0;
|
||||
uint blocksize = CD_FRAMESIZE_RAW;
|
||||
uint blocks = td.lsn;
|
||||
|
||||
// hack: Because of limitations of the current cdvd design, we can't query the blocksize
|
||||
// of the underlying media. So lets make a best guess:
|
||||
|
||||
switch(cdtype)
|
||||
{
|
||||
case CDVD_TYPE_PS2DVD:
|
||||
case CDVD_TYPE_DVDV:
|
||||
case CDVD_TYPE_DETCTDVDS:
|
||||
case CDVD_TYPE_DETCTDVDD:
|
||||
blocksize = 2048;
|
||||
break;
|
||||
}
|
||||
blockDumpFile.WriteFormat(blockofs, blocksize, blocks);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -399,7 +400,8 @@ bool DoCDVDopen()
|
|||
void DoCDVDclose()
|
||||
{
|
||||
CheckNullCDVD();
|
||||
if(blockDumpFile) isoClose(blockDumpFile);
|
||||
blockDumpFile.Close();
|
||||
|
||||
if( CDVD->close != NULL )
|
||||
CDVD->close();
|
||||
|
||||
|
@ -411,9 +413,9 @@ s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode)
|
|||
CheckNullCDVD();
|
||||
int ret = CDVD->readSector(buffer,lsn,mode);
|
||||
|
||||
if(ret == 0 && blockDumpFile != NULL )
|
||||
if (ret == 0 && blockDumpFile.IsOpened())
|
||||
{
|
||||
isoWriteBlock(blockDumpFile, buffer, lsn);
|
||||
blockDumpFile.WriteBlock(buffer, lsn);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -450,9 +452,9 @@ s32 DoCDVDgetBuffer(u8* buffer)
|
|||
CheckNullCDVD();
|
||||
int ret = CDVD->getBuffer2(buffer);
|
||||
|
||||
if (ret == 0 && blockDumpFile != NULL)
|
||||
if (ret == 0 && blockDumpFile.IsOpened())
|
||||
{
|
||||
isoWriteBlock(blockDumpFile, buffer, lastLSN);
|
||||
blockDumpFile.WriteBlock(buffer, lastLSN);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
static u8 *pbuffer;
|
||||
static u8 cdbuffer[2352] = {0};
|
||||
static isoFile *iso = NULL;
|
||||
static isoFile iso;
|
||||
|
||||
static int psize, cdtype;
|
||||
|
||||
|
@ -38,8 +38,7 @@ static s32 layer1start = -1;
|
|||
|
||||
void CALLBACK ISOclose()
|
||||
{
|
||||
isoClose(iso);
|
||||
iso = NULL;
|
||||
iso.Close();
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOopen(const char* pTitle)
|
||||
|
@ -52,14 +51,19 @@ s32 CALLBACK ISOopen(const char* pTitle)
|
|||
return -1;
|
||||
}
|
||||
|
||||
iso = isoOpen(pTitle);
|
||||
if (iso == NULL)
|
||||
// The current plugin API doesn't expect exceptions to propagate out of the API
|
||||
// calls, so we need to catch them, log them, and return -1.
|
||||
|
||||
try {
|
||||
iso.Open(fromUTF8(pTitle));
|
||||
}
|
||||
catch( BaseException& ex )
|
||||
{
|
||||
Console.Error( "CDVDiso Error: Failed loading %s", pTitle );
|
||||
Console.Error( ex.FormatDiagnosticMessage() );
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (iso->type)
|
||||
switch (iso.GetType())
|
||||
{
|
||||
case ISOTYPE_DVD:
|
||||
cdtype = CDVD_TYPE_PS2DVD;
|
||||
|
@ -113,7 +117,7 @@ s32 CALLBACK ISOgetTD(u8 Track, cdvdTD *Buffer)
|
|||
{
|
||||
if (Track == 0)
|
||||
{
|
||||
Buffer->lsn = iso->blocks;
|
||||
Buffer->lsn = iso.GetBlockCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -129,7 +133,7 @@ s32 CALLBACK ISOgetTD(u8 Track, cdvdTD *Buffer)
|
|||
|
||||
static bool testForPartitionInfo( const u8 (&tempbuffer)[CD_FRAMESIZE_RAW] )
|
||||
{
|
||||
const int off = iso->blockofs;
|
||||
const int off = iso.GetBlockOffset();
|
||||
|
||||
// test for: CD001
|
||||
return (
|
||||
|
@ -143,9 +147,9 @@ static bool testForPartitionInfo( const u8 (&tempbuffer)[CD_FRAMESIZE_RAW] )
|
|||
|
||||
static bool FindLayer1Start()
|
||||
{
|
||||
if( (layer1start != -1) || (iso->blocks < 0x230540) ) return true;
|
||||
if( (layer1start != -1) || (iso.GetBlockCount() < 0x230540) ) return true;
|
||||
|
||||
Console.WriteLn("CDVDiso: searching for layer1...");
|
||||
Console.WriteLn("isoFile: searching for layer1...");
|
||||
|
||||
int blockresult = -1;
|
||||
|
||||
|
@ -156,28 +160,28 @@ static bool FindLayer1Start()
|
|||
wxString layerCacheFile( Path::Combine(GetSettingsFolder().ToString(), L"LayerBreakCache.ini") );
|
||||
wxFileConfig layerCacheIni( wxEmptyString, wxEmptyString, layerCacheFile, wxEmptyString, wxCONFIG_USE_RELATIVE_PATH );
|
||||
|
||||
wxString cacheKey;
|
||||
cacheKey.Printf( L"%X", HashTools::Hash( iso->filename, strlen( iso->filename ) ) );
|
||||
FastFormatUnicode cacheKey;
|
||||
cacheKey.Write( L"%X", HashTools::Hash( (s8*)iso.GetFilename().c_str(), iso.GetFilename().Length() * sizeof(wxChar) ) );
|
||||
|
||||
blockresult = layerCacheIni.Read( cacheKey, -1 );
|
||||
if( blockresult != -1 )
|
||||
{
|
||||
u8 tempbuffer[CD_FRAMESIZE_RAW];
|
||||
isoReadBlock(iso, tempbuffer, blockresult);
|
||||
iso.ReadBlock(tempbuffer, blockresult);
|
||||
|
||||
if( testForPartitionInfo( tempbuffer ) )
|
||||
{
|
||||
Console.WriteLn( "CDVDiso: loaded second layer from settings cache, sector=0x%8.8x", blockresult );
|
||||
Console.WriteLn( "isoFile: loaded second layer from settings cache, sector=0x%08x", blockresult );
|
||||
layer1start = blockresult;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Warning( "CDVDiso: second layer info in the settings cache appears to be obsolete or invalid." );
|
||||
Console.Warning( "isoFile: second layer info in the settings cache appears to be obsolete or invalid. Ignoring..." );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DevCon.WriteLn( "CDVDiso: no cached info for second layer found." );
|
||||
DevCon.WriteLn( "isoFile: no cached info for second layer found." );
|
||||
}
|
||||
|
||||
if( layer1start == -1 )
|
||||
|
@ -197,28 +201,29 @@ static bool FindLayer1Start()
|
|||
// to create the window and pass progress increments back to it.
|
||||
|
||||
|
||||
uint midsector = (iso->blocks / 2) & ~0xf;
|
||||
uint midsector = (iso.GetBlockCount() / 2) & ~0xf;
|
||||
uint deviation = 0;
|
||||
|
||||
while( (layer1start == -1) && (deviation < midsector-16) )
|
||||
{
|
||||
u8 tempbuffer[CD_FRAMESIZE_RAW];
|
||||
isoReadBlock(iso, tempbuffer, midsector-deviation);
|
||||
iso.ReadBlock(tempbuffer, midsector-deviation);
|
||||
|
||||
if(testForPartitionInfo( tempbuffer ))
|
||||
layer1start = midsector-deviation;
|
||||
else
|
||||
{
|
||||
isoReadBlock(iso, tempbuffer, midsector+deviation);
|
||||
iso.ReadBlock(tempbuffer, midsector+deviation);
|
||||
if( testForPartitionInfo( tempbuffer ) )
|
||||
layer1start = midsector+deviation;
|
||||
}
|
||||
|
||||
if( layer1start != -1 )
|
||||
{
|
||||
if( !pxAssertDev( tempbuffer[iso->blockofs] == 0x01, "Layer1-Detect: CD001 tag found, but the partition type is invalid." ) )
|
||||
const int blockofs = iso.GetBlockOffset();
|
||||
if( !pxAssertDev( tempbuffer[blockofs] == 0x01, "Layer1-Detect: CD001 tag found, but the partition type is invalid." ) )
|
||||
{
|
||||
Console.Error( "CDVDiso: Invalid partition type on layer 1!? (type=0x%x)", tempbuffer[iso->blockofs] );
|
||||
Console.Error( "isoFile: Invalid partition type on layer 1!? (type=0x%x)", tempbuffer[blockofs] );
|
||||
}
|
||||
}
|
||||
deviation += 16;
|
||||
|
@ -226,12 +231,12 @@ static bool FindLayer1Start()
|
|||
|
||||
if( layer1start == -1 )
|
||||
{
|
||||
Console.Warning("CDVDiso: Couldn't find second layer... ignoring");
|
||||
Console.Error("isoFile: Couldn't find layer1... iso image is probably corrupt or incomplete.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLn("CDVDiso: second layer found at sector 0x%8.8x", layer1start);
|
||||
Console.WriteLn( Color_Blue, "isoFile: second layer found at sector 0x%08x", layer1start);
|
||||
|
||||
// Save layer information to configuration:
|
||||
|
||||
|
@ -249,7 +254,7 @@ s32 CALLBACK ISOgetDualInfo(s32* dualType, u32* _layer1start)
|
|||
if(layer1start<0)
|
||||
{
|
||||
*dualType = 0;
|
||||
*_layer1start = iso->blocks;
|
||||
*_layer1start = iso.GetBlockCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -374,44 +379,43 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
|
|||
{
|
||||
int _lsn = lsn;
|
||||
|
||||
if (_lsn < 0) lsn = iso->blocks + _lsn;
|
||||
if (lsn > iso->blocks) return -1;
|
||||
if (_lsn < 0) lsn = iso.GetBlockCount() + _lsn;
|
||||
if (lsn > iso.GetBlockCount()) return -1;
|
||||
|
||||
if(mode == CDVD_MODE_2352)
|
||||
{
|
||||
isoReadBlock(iso, tempbuffer, lsn);
|
||||
iso.ReadBlock(tempbuffer, lsn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
isoReadBlock(iso, cdbuffer, lsn);
|
||||
iso.ReadBlock(cdbuffer, lsn);
|
||||
|
||||
pbuffer = cdbuffer;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case CDVD_MODE_2352:
|
||||
psize = 2352;
|
||||
break;
|
||||
case CDVD_MODE_2340:
|
||||
pbuffer += 12;
|
||||
psize = 2340;
|
||||
break;
|
||||
case CDVD_MODE_2328:
|
||||
pbuffer += 24;
|
||||
psize = 2328;
|
||||
break;
|
||||
case CDVD_MODE_2048:
|
||||
pbuffer += 24;
|
||||
psize = 2048;
|
||||
break;
|
||||
case CDVD_MODE_2352:
|
||||
// Unreachable due to shortcut above.
|
||||
pxAssume(false);
|
||||
break;
|
||||
|
||||
case CDVD_MODE_2340:
|
||||
pbuffer += 12;
|
||||
psize = 2340;
|
||||
break;
|
||||
case CDVD_MODE_2328:
|
||||
pbuffer += 24;
|
||||
psize = 2328;
|
||||
break;
|
||||
case CDVD_MODE_2048:
|
||||
pbuffer += 24;
|
||||
psize = 2048;
|
||||
break;
|
||||
|
||||
jNO_DEFAULT
|
||||
}
|
||||
|
||||
// version 3 blockdumps have no pbuffer header, so lets reset back to the
|
||||
// original pointer. :)
|
||||
if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
|
||||
pbuffer = cdbuffer;
|
||||
|
||||
memcpy_fast(tempbuffer,pbuffer,psize);
|
||||
memcpy_fast(tempbuffer, pbuffer, psize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -420,10 +424,10 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
|
|||
{
|
||||
int _lsn = lsn;
|
||||
|
||||
if (_lsn < 0) lsn = iso->blocks + _lsn;
|
||||
if (lsn > iso->blocks) return -1;
|
||||
if (_lsn < 0) lsn = iso.GetBlockCount() + _lsn;
|
||||
if (lsn > iso.GetBlockCount()) return -1;
|
||||
|
||||
isoReadBlock(iso, cdbuffer, lsn);
|
||||
iso.ReadBlock(cdbuffer, lsn);
|
||||
pbuffer = cdbuffer;
|
||||
|
||||
switch (mode)
|
||||
|
@ -445,17 +449,12 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
|
|||
break;
|
||||
}
|
||||
|
||||
// version 3 blockdumps have no pbuffer header, so lets reset back to the
|
||||
// original pointer. :)
|
||||
if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
|
||||
pbuffer = cdbuffer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOgetBuffer2(u8* buffer)
|
||||
{
|
||||
memcpy_fast(buffer,pbuffer,psize);
|
||||
memcpy_fast(buffer, pbuffer, psize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ IsoDirectory::IsoDirectory(SectorSource& r)
|
|||
}
|
||||
|
||||
if( !isValid )
|
||||
throw Exception::FileNotFound(L"IsoFS") // FIXME: Should report the name of the ISO here...
|
||||
throw Exception::FileNotFound(L"IsoFileSystem") // FIXME: Should report the name of the ISO here...
|
||||
.SetDiagMsg(L"IsoFS could not find the root directory on the ISO image.");
|
||||
|
||||
DevCon.WriteLn( L"(IsoFS) Filesystem is " + FStype_ToString() );
|
||||
|
|
|
@ -16,400 +16,527 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "IopCommon.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "IsoFileFormats.h"
|
||||
|
||||
static bool detect(isoFile *iso)
|
||||
#include <errno.h>
|
||||
|
||||
static const uint BlockDumpHeaderSize = 16;
|
||||
|
||||
bool isoFile::detect()
|
||||
{
|
||||
u8 buf[2456];
|
||||
u8* pbuf;
|
||||
|
||||
if (!isoReadBlock(iso, buf, 16)) return false; // Not readable
|
||||
ReadBlock(buf, 16);
|
||||
|
||||
pbuf = (( iso->flags & ISOFLAGS_BLOCKDUMP_V3 ) ? buf : (buf + 24));
|
||||
pbuf = buf + 24;
|
||||
|
||||
if (strncmp((char*)(pbuf+1), "CD001", 5)) return false; // Not ISO 9660 compliant
|
||||
|
||||
if (*(u16*)(pbuf+166) == 2048)
|
||||
iso->type = ISOTYPE_CD;
|
||||
m_type = ISOTYPE_CD;
|
||||
else
|
||||
iso->type = ISOTYPE_DVD;
|
||||
m_type = ISOTYPE_DVD;
|
||||
|
||||
return true; // We can deal with this.
|
||||
}
|
||||
|
||||
static bool _isoReadDtable(isoFile *iso)
|
||||
void isoFile::_ReadDtable()
|
||||
{
|
||||
uint ret;
|
||||
_IsoPart& headpart( m_parts[0] );
|
||||
|
||||
_seekfile(iso->handle, 0, SEEK_END);
|
||||
iso->dtablesize = (_tellfile(iso->handle) - 16) / (iso->blocksize + 4);
|
||||
iso->dtable = (u32*)malloc(iso->dtablesize * 4);
|
||||
wxFileOffset flen = headpart.handle->GetLength();
|
||||
m_dtablesize = (flen - BlockDumpHeaderSize) / (m_blocksize + 4);
|
||||
m_dtable = new u32[m_dtablesize];
|
||||
|
||||
for (int i = 0; i < iso->dtablesize; i++)
|
||||
headpart.Seek(BlockDumpHeaderSize);
|
||||
|
||||
for (int i=0; i < m_dtablesize; ++i)
|
||||
{
|
||||
_seekfile(iso->handle, 16 + (iso->blocksize + 4) * i, SEEK_SET);
|
||||
ret = _readfile(iso->handle, &iso->dtable[i], 4);
|
||||
if (ret < 4) return false;
|
||||
headpart.Read(m_dtable[i]);
|
||||
headpart.Seek(m_blocksize, wxFromCurrent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool tryIsoType(isoFile *iso, u32 size, s32 offset, s32 blockofs)
|
||||
bool isoFile::tryIsoType(u32 _size, s32 _offset, s32 _blockofs)
|
||||
{
|
||||
iso->blocksize = size;
|
||||
iso->offset = offset;
|
||||
iso->blockofs = blockofs;
|
||||
m_blocksize = _size;
|
||||
m_offset = _offset;
|
||||
m_blockofs = _blockofs;
|
||||
|
||||
return detect(iso);
|
||||
return detect();
|
||||
}
|
||||
|
||||
// based on florin's CDVDbin detection code :)
|
||||
// Returns true if the image is valid/known/supported, or false if not (iso->type == ISOTYPE_ILLEGAL).
|
||||
bool isoDetect(isoFile *iso)
|
||||
// Parameter:
|
||||
//
|
||||
//
|
||||
// Returns true if the image is valid/known/supported, or false if not (type == ISOTYPE_ILLEGAL).
|
||||
bool isoFile::Detect( bool readType )
|
||||
{
|
||||
char buf[32];
|
||||
int len;
|
||||
int len = m_filename.Length();
|
||||
|
||||
iso->type = ISOTYPE_ILLEGAL;
|
||||
m_type = ISOTYPE_ILLEGAL;
|
||||
|
||||
len = strlen(iso->filename);
|
||||
_IsoPart& headpart( m_parts[0] );
|
||||
|
||||
_seekfile(iso->handle, 0, SEEK_SET);
|
||||
_readfile(iso->handle, buf, 4);
|
||||
headpart.Seek( 0 );
|
||||
headpart.Read( buf, 4 );
|
||||
|
||||
if (strncmp(buf, "BDV2", 4) == 0)
|
||||
{
|
||||
iso->flags = ISOFLAGS_BLOCKDUMP_V2;
|
||||
_readfile(iso->handle, &iso->blocksize, 4);
|
||||
_readfile(iso->handle, &iso->blocks, 4);
|
||||
_readfile(iso->handle, &iso->blockofs, 4);
|
||||
_isoReadDtable(iso);
|
||||
return (detect(iso));
|
||||
}
|
||||
else if (strncmp(buf, "BDV3", 4) == 0)
|
||||
{
|
||||
iso->flags = ISOFLAGS_BLOCKDUMP_V3;
|
||||
_readfile(iso->handle, &iso->blocksize, 4);
|
||||
_readfile(iso->handle, &iso->blocks, 4);
|
||||
_readfile(iso->handle, &iso->blockofs, 4);
|
||||
_isoReadDtable(iso);
|
||||
return (detect(iso));
|
||||
}
|
||||
else
|
||||
{
|
||||
iso->blocks = 16;
|
||||
m_flags = ISOFLAGS_BLOCKDUMP_V2;
|
||||
headpart.Read(m_blocksize);
|
||||
headpart.Read(m_blocks);
|
||||
headpart.Read(m_blockofs);
|
||||
|
||||
if (readType)
|
||||
{
|
||||
_ReadDtable();
|
||||
return detect();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tryIsoType(iso, 2048, 0, 24)) return true; // ISO 2048
|
||||
if (tryIsoType(iso, 2336, 0, 16)) return true; // RAW 2336
|
||||
if (tryIsoType(iso, 2352, 0, 0)) return true; // RAW 2352
|
||||
if (tryIsoType(iso, 2448, 0, 0)) return true; // RAWQ 2448
|
||||
if (tryIsoType(iso, 2048, 150 * 2048, 24)) return true; // NERO ISO 2048
|
||||
if (tryIsoType(iso, 2352, 150 * 2048, 0)) return true; // NERO RAW 2352
|
||||
if (tryIsoType(iso, 2448, 150 * 2048, 0)) return true; // NERO RAWQ 2448
|
||||
if (tryIsoType(iso, 2048, -8, 24)) return true; // ISO 2048
|
||||
if (tryIsoType(iso, 2352, -8, 0)) return true; // RAW 2352
|
||||
if (tryIsoType(iso, 2448, -8, 0)) return true; // RAWQ 2448
|
||||
// First sanity check: no sane CD image has less than 16 sectors, since that's what
|
||||
// we need simply to contain a TOC. So if the file size is not large enough to
|
||||
// accommodate that, it is NOT a CD image --->
|
||||
|
||||
wxFileOffset size = headpart.handle->GetLength();
|
||||
|
||||
if (size < (2048 * 16)) return false;
|
||||
|
||||
m_blocks = 16;
|
||||
|
||||
if (tryIsoType(2048, 0, 24)) return true; // ISO 2048
|
||||
if (tryIsoType(2336, 0, 16)) return true; // RAW 2336
|
||||
if (tryIsoType(2352, 0, 0)) return true; // RAW 2352
|
||||
if (tryIsoType(2448, 0, 0)) return true; // RAWQ 2448
|
||||
|
||||
if (tryIsoType(2048, 150 * 2048, 24)) return true; // NERO ISO 2048
|
||||
if (tryIsoType(2352, 150 * 2048, 0)) return true; // NERO RAW 2352
|
||||
if (tryIsoType(2448, 150 * 2048, 0)) return true; // NERO RAWQ 2448
|
||||
|
||||
if (tryIsoType(2048, -8, 24)) return true; // ISO 2048
|
||||
if (tryIsoType(2352, -8, 0)) return true; // RAW 2352
|
||||
if (tryIsoType(2448, -8, 0)) return true; // RAWQ 2448
|
||||
|
||||
m_offset = 0;
|
||||
m_blocksize = CD_FRAMESIZE_RAW;
|
||||
m_blockofs = 0;
|
||||
m_type = ISOTYPE_AUDIO;
|
||||
|
||||
iso->offset = 0;
|
||||
iso->blocksize = CD_FRAMESIZE_RAW;
|
||||
iso->blockofs = 0;
|
||||
iso->type = ISOTYPE_AUDIO;
|
||||
return true;
|
||||
}
|
||||
|
||||
isoFile *isoOpen(const char *filename)
|
||||
// Generates format header information for blockdumps.
|
||||
void isoFile::WriteFormat(int _blockofs, uint _blocksize, uint _blocks)
|
||||
{
|
||||
isoFile *iso;
|
||||
m_blocksize = _blocksize;
|
||||
m_blocks = _blocks;
|
||||
m_blockofs = _blockofs;
|
||||
|
||||
iso = (isoFile*)malloc(sizeof(isoFile));
|
||||
if (iso == NULL) return NULL;
|
||||
Console.WriteLn("blockoffset = %d", m_blockofs);
|
||||
Console.WriteLn("blocksize = %u", m_blocksize);
|
||||
Console.WriteLn("blocks = %u", m_blocks);
|
||||
|
||||
memzero( *iso );
|
||||
strcpy(iso->filename, filename);
|
||||
|
||||
iso->handle = _openfile( iso->filename, O_RDONLY);
|
||||
if (iso->handle == NULL)
|
||||
if (m_flags & ISOFLAGS_BLOCKDUMP_V2)
|
||||
{
|
||||
Console.Error("ISO loader: Cannot access %s", iso->filename);
|
||||
Console.Error(">> Make sure the iso file is not mounted in any disk emulation software! <<");
|
||||
return NULL;
|
||||
outWrite("BDV2", 4);
|
||||
outWrite(m_blocksize);
|
||||
outWrite(m_blocks);
|
||||
outWrite(m_blockofs);
|
||||
}
|
||||
}
|
||||
|
||||
void isoFile::_ReadBlockD(u8* dst, uint lsn)
|
||||
{
|
||||
_IsoPart& headpart( m_parts[0] );
|
||||
|
||||
// Console.WriteLn("_isoReadBlockD %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs);
|
||||
|
||||
memset(dst, 0, m_blockofs);
|
||||
for (int i = 0; i < m_dtablesize; ++i)
|
||||
{
|
||||
if (m_dtable[i] != lsn) continue;
|
||||
|
||||
// We store the LSN (u32) along with each block inside of blockdumps, so the
|
||||
// seek position ends up being based on (m_blocksize + 4) instead of just m_blocksize.
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
u32 check_lsn;
|
||||
headpart.Seek( BlockDumpHeaderSize + (i * (m_blocksize + 4)) );
|
||||
m_parts[0].Read( check_lsn );
|
||||
pxAssert( check_lsn == lsn );
|
||||
#else
|
||||
headpart.Seek( BlockDumpHeaderSize + (i * (m_blocksize + 4)) + 4 );
|
||||
#endif
|
||||
|
||||
m_parts[0].Read( dst + m_blockofs, m_blocksize );
|
||||
}
|
||||
|
||||
if (!isoDetect(iso)) return NULL;
|
||||
Console.WriteLn("Block %u not found in dump", lsn);
|
||||
}
|
||||
|
||||
Console.WriteLn("detected blocksize = %u", iso->blocksize);
|
||||
void isoFile::_ReadBlock(u8* dst, uint lsn)
|
||||
{
|
||||
pxAssumeMsg(lsn <= m_blocks, "Invalid lsn passed into isoFile::_ReadBlock.");
|
||||
pxAssumeMsg(m_numparts, "Invalid isoFile object state; an iso file needs at least one part!");
|
||||
|
||||
if ((strlen(iso->filename) > 3) && strncmp(iso->filename + (strlen(iso->filename) - 3), "I00", 3) == 0)
|
||||
uint i;
|
||||
for (i = 0; i < m_numparts-1; ++i)
|
||||
{
|
||||
int i;
|
||||
|
||||
_closefile(iso->handle);
|
||||
iso->flags |= ISOFLAGS_MULTI;
|
||||
iso->blocks = 0;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
iso->filename[strlen(iso->filename) - 1] = '0' + i;
|
||||
iso->multih[i].handle = _openfile(iso->filename, O_RDONLY);
|
||||
|
||||
if (iso->multih[i].handle == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
iso->multih[i].slsn = iso->blocks;
|
||||
_seekfile(iso->multih[i].handle, 0, SEEK_END);
|
||||
iso->blocks += (u32)((_tellfile(iso->multih[i].handle) - iso->offset) / (iso->blocksize));
|
||||
iso->multih[i].elsn = iso->blocks - 1;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
// lsn indexes should always go in order; use an assertion just to be sure:
|
||||
pxAssume(lsn >= m_parts[i].slsn);
|
||||
if (lsn <= m_parts[i].elsn) break;
|
||||
}
|
||||
|
||||
if (iso->flags == 0)
|
||||
wxFileOffset ofs = (wxFileOffset)(lsn - m_parts[i].slsn) * m_blocksize + m_offset;
|
||||
|
||||
// Console.WriteLn("_isoReadBlock %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs);
|
||||
|
||||
memset(dst, 0, m_blockofs);
|
||||
m_parts[i].Seek(ofs);
|
||||
m_parts[i].Read(dst + m_blockofs, m_blocksize);
|
||||
}
|
||||
|
||||
void isoFile::ReadBlock(u8* dst, uint lsn)
|
||||
{
|
||||
if (lsn > m_blocks)
|
||||
{
|
||||
_seekfile(iso->handle, 0, SEEK_END);
|
||||
iso->blocks = (u32)((_tellfile(iso->handle) - iso->offset) / (iso->blocksize));
|
||||
FastFormatUnicode msg;
|
||||
msg.Write("isoFile error: Block index is past the end of file! (%u > %u).", lsn, m_blocks);
|
||||
|
||||
pxAssertDev(false, msg);
|
||||
Console.Error(msg);
|
||||
|
||||
// [TODO] : Throw exception?
|
||||
// Typically an error like this is bad; indicating an invalid dump or corrupted
|
||||
// iso file.
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_flags == ISOFLAGS_BLOCKDUMP_V2)
|
||||
_ReadBlockD(dst, lsn);
|
||||
else
|
||||
_ReadBlock(dst, lsn);
|
||||
|
||||
if (m_type == ISOTYPE_CD)
|
||||
{
|
||||
lsn_to_msf(dst + 12, lsn);
|
||||
dst[15] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
void isoFile::_WriteBlock(const u8* src, uint lsn)
|
||||
{
|
||||
wxFileOffset ofs = (wxFileOffset)lsn * m_blocksize + m_offset;
|
||||
|
||||
m_outstream->SeekO( ofs );
|
||||
outWrite( src + m_blockofs, m_blocksize );
|
||||
}
|
||||
|
||||
void isoFile::_WriteBlockD(const u8* src, uint lsn)
|
||||
{
|
||||
outWrite<u32>( lsn );
|
||||
outWrite( src + m_blockofs, m_blocksize );
|
||||
}
|
||||
|
||||
void isoFile::WriteBlock(const u8* src, uint lsn)
|
||||
{
|
||||
if (m_flags == ISOFLAGS_BLOCKDUMP_V2)
|
||||
_WriteBlockD(src, lsn);
|
||||
else
|
||||
_WriteBlock(src, lsn);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// IsoFile (implementations) : Init / Open / Create
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
isoFile::isoFile()
|
||||
{
|
||||
_init();
|
||||
}
|
||||
|
||||
isoFile::~isoFile() throw()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void isoFile::_init()
|
||||
{
|
||||
m_type = ISOTYPE_ILLEGAL;
|
||||
m_flags = 0;
|
||||
|
||||
m_offset = 0;
|
||||
m_blockofs = 0;
|
||||
m_blocksize = 0;
|
||||
m_blocks = 0;
|
||||
|
||||
m_dtable = 0;
|
||||
m_dtablesize = 0;
|
||||
}
|
||||
|
||||
// Tests for a filename extension in both upper and lower case, if the filesystem happens
|
||||
// to be case-sensitive.
|
||||
bool pxFileExists_WithExt( const wxFileName& filename, const wxString& ext )
|
||||
{
|
||||
wxFileName part1 = filename;
|
||||
part1.SetExt( ext.Lower() );
|
||||
|
||||
if (part1.FileExists()) return true;
|
||||
if (!wxFileName::IsCaseSensitive()) return false;
|
||||
|
||||
part1.SetExt( ext.Upper() );
|
||||
return part1.FileExists();
|
||||
}
|
||||
|
||||
void pxStream_OpenCheck( const wxStreamBase& stream, const wxString& fname, const wxString& mode )
|
||||
{
|
||||
if (stream.IsOk()) return;
|
||||
|
||||
ScopedExcept ex(Exception::FromErrno(fname, errno));
|
||||
ex->SetDiagMsg( pxsFmt(L"Unable to open the file for %s: %s", mode.c_str(), ex->DiagMsg().c_str()) );
|
||||
ex->Rethrow();
|
||||
}
|
||||
|
||||
// multi-part ISO support is provided for FAT32 compatibility; so that large 4GB+ isos
|
||||
// can be split into multiple smaller files.
|
||||
//
|
||||
// Returns TRUE if multiple parts for the ISO are found. Returns FALSE if only one
|
||||
// part is found.
|
||||
void isoFile::FindParts()
|
||||
{
|
||||
wxFileName nameparts( m_filename );
|
||||
wxString curext( nameparts.GetExt() );
|
||||
wxChar prefixch = wxTolower(curext[0]);
|
||||
|
||||
// Multi-part rules!
|
||||
// * The first part can either be the proper extension (ISO, MDF, etc) or the numerical
|
||||
// extension (I00, I01, M00, M01, etc).
|
||||
// * Numerical extensions MUST begin at 00 (I00 etc), regardless of if the first part
|
||||
// is proper or numerical.
|
||||
|
||||
uint i = 0;
|
||||
|
||||
if ((curext.Length() == 3) && (curext[1] == L'0') && (curext[2] == L'0'))
|
||||
{
|
||||
// First file is an OO, so skip 0 in the loop below:
|
||||
i = 1;
|
||||
}
|
||||
|
||||
FastFormatUnicode extbuf;
|
||||
|
||||
extbuf.Write( L"%c%02u", prefixch, i );
|
||||
nameparts.SetExt( extbuf );
|
||||
if (!pxFileExists_WithExt(nameparts, extbuf)) return;
|
||||
|
||||
DevCon.WriteLn( Color_Blue, "isoFile: multi-part %s detected...", curext.Upper().c_str() );
|
||||
ConsoleIndentScope indent;
|
||||
|
||||
for (; i < MaxSplits; ++i)
|
||||
{
|
||||
extbuf.Clear();
|
||||
extbuf.Write( L"%c%02u", prefixch, i );
|
||||
if (!pxFileExists_WithExt(nameparts, extbuf)) break;
|
||||
|
||||
_IsoPart& thispart( m_parts[m_numparts] );
|
||||
|
||||
thispart.handle = new wxFileInputStream( nameparts.GetFullPath() );
|
||||
pxStream_OpenCheck( *thispart.handle, nameparts.GetFullPath(), L"reading" );
|
||||
|
||||
m_blocks += thispart.CalculateBlocks( m_blocks, m_blocksize );
|
||||
|
||||
DevCon.WriteLn( Color_Blue, L"\tblocks %u - %u in: %s",
|
||||
thispart.slsn, thispart.elsn,
|
||||
nameparts.GetFullPath().c_str()
|
||||
);
|
||||
++m_numparts;
|
||||
}
|
||||
|
||||
//Console.WriteLn( Color_Blue, "isoFile: multi-part ISO loaded (%u parts found)", m_numparts );
|
||||
}
|
||||
|
||||
// Tests the specified filename to see if it is a supported ISO type. This function typically
|
||||
// executes faster than isoFile::Open since it does not do the following:
|
||||
// * check for multi-part ISOs. I tests for header info in the main/root ISO only.
|
||||
// * load blockdump indexes.
|
||||
//
|
||||
// Note that this is a member method, and that it will clobber any existing ISO state.
|
||||
// (assertions are generated in debug mode if the object state is not already closed).
|
||||
bool isoFile::Test( const wxString& srcfile )
|
||||
{
|
||||
pxAssertMsg( !m_parts[0].handle, "Warning! isoFile::Test is about to clobber whatever existing iso bound to this isoFile object!" );
|
||||
|
||||
Close();
|
||||
m_filename = srcfile;
|
||||
|
||||
m_parts[0].handle = new wxFileInputStream( m_filename );
|
||||
pxStream_OpenCheck( *m_parts[0].handle, m_filename, L"reading" );
|
||||
|
||||
m_numparts = 1;
|
||||
m_parts[0].slsn = 0;
|
||||
|
||||
// elsn is unknown at this time, but is also unused when m_numparts == 1.
|
||||
// (and if numparts is incremented, elsn will get assigned accordingly)
|
||||
|
||||
return Detect( false );
|
||||
}
|
||||
|
||||
void isoFile::Open( const wxString& srcfile )
|
||||
{
|
||||
Close();
|
||||
m_filename = srcfile;
|
||||
|
||||
m_parts[0].handle = new wxFileInputStream( m_filename );
|
||||
pxStream_OpenCheck( *m_parts[0].handle, m_filename, L"reading" );
|
||||
|
||||
m_numparts = 1;
|
||||
m_parts[0].slsn = 0;
|
||||
|
||||
// elsn is unknown at this time, but is also unused when m_numparts == 1.
|
||||
// (and if numparts is incremented, elsn will get assigned accordingly)
|
||||
|
||||
if (!Detect())
|
||||
throw Exception::BadStream().SetUserMsg(wxLt("Unrecognized ISO file format."));
|
||||
|
||||
m_blocks = m_parts[0].CalculateBlocks( 0, m_blocksize );
|
||||
|
||||
FindParts();
|
||||
if (m_numparts > 1)
|
||||
{
|
||||
Console.WriteLn( Color_Blue, "isoFile: multi-part ISO detected. %u parts found." );
|
||||
}
|
||||
|
||||
const char* isotypename = NULL;
|
||||
switch(iso->type)
|
||||
switch(m_type)
|
||||
{
|
||||
case ISOTYPE_CD: isotypename = "CD"; break;
|
||||
case ISOTYPE_DVD: isotypename = "DVD"; break;
|
||||
case ISOTYPE_AUDIO: isotypename = "Audio CD"; break;
|
||||
case ISOTYPE_DVDDL: isotypename = "DVDDL"; break;
|
||||
|
||||
case ISOTYPE_DVDDL:
|
||||
isotypename = "DVD9 (dual-layer)";
|
||||
break;
|
||||
|
||||
case ISOTYPE_ILLEGAL:
|
||||
default:
|
||||
isotypename = "illegal media";
|
||||
break;
|
||||
}
|
||||
Console.WriteLn("isoOpen(%s): %s ok.", isotypename, iso->filename);
|
||||
Console.WriteLn("The iso has %u blocks (size %u).", iso->blocks, iso->blocksize);
|
||||
Console.WriteLn("The iso offset is %d, and the block offset is %d.", iso->offset, iso->blockofs);
|
||||
|
||||
return iso;
|
||||
Console.WriteLn(Color_StrongBlue, L"isoFile open ok: %s", m_filename.c_str());
|
||||
|
||||
ConsoleIndentScope indent;
|
||||
Console.WriteLn("Image type = %s", isotypename);
|
||||
Console.WriteLn("Fileparts = %u", m_numparts);
|
||||
DevCon.WriteLn ("blocks = %u", m_blocks);
|
||||
DevCon.WriteLn ("offset = %d", m_offset);
|
||||
DevCon.WriteLn ("blocksize = %u", m_blocksize);
|
||||
DevCon.WriteLn ("blockoffset = %d", m_blockofs);
|
||||
}
|
||||
|
||||
isoFile *isoCreate(const char *filename, int flags)
|
||||
void isoFile::Create(const wxString& filename, int flags)
|
||||
{
|
||||
char Zfile[256];
|
||||
Close();
|
||||
m_filename = filename;
|
||||
|
||||
isoFile* iso = (isoFile*)malloc(sizeof(isoFile));
|
||||
if (iso == NULL) return NULL;
|
||||
m_flags = flags;
|
||||
m_offset = 0;
|
||||
m_blockofs = 24;
|
||||
m_blocksize = 2048;
|
||||
|
||||
memzero(*iso);
|
||||
strcpy(iso->filename, filename);
|
||||
m_outstream = new wxFileOutputStream( m_filename );
|
||||
pxStream_OpenCheck( *m_outstream, m_filename, L"writing" );
|
||||
|
||||
iso->flags = flags;
|
||||
iso->offset = 0;
|
||||
iso->blockofs = 24;
|
||||
iso->blocksize = 2048;
|
||||
Console.WriteLn("isoFile create ok: %s ", m_filename.c_str());
|
||||
}
|
||||
|
||||
if (iso->flags & (ISOFLAGS_Z | ISOFLAGS_Z2 | ISOFLAGS_BZ2))
|
||||
void isoFile::Close()
|
||||
{
|
||||
for (uint i=0; i<MaxSplits; ++i)
|
||||
m_parts[i].handle.Delete();
|
||||
|
||||
m_dtable.Delete();
|
||||
|
||||
_init();
|
||||
}
|
||||
|
||||
bool isoFile::IsOpened() const
|
||||
{
|
||||
return m_parts[0].handle && m_parts[0].handle->IsOk();
|
||||
}
|
||||
|
||||
void isoFile::outWrite( const void* src, size_t size )
|
||||
{
|
||||
m_outstream->Write(src, size);
|
||||
if(m_outstream->GetLastError() == wxSTREAM_WRITE_ERROR)
|
||||
{
|
||||
sprintf(Zfile, "%s.table", iso->filename);
|
||||
iso->htable = _openfile(Zfile, O_WRONLY);
|
||||
int err = errno;
|
||||
if (!err)
|
||||
throw Exception::BadStream(m_filename).SetDiagMsg(pxsFmt(L"An error occurred while writing %u bytes to file", size));
|
||||
|
||||
if (iso->htable == NULL) return NULL;
|
||||
ScopedExcept ex(Exception::FromErrno(m_filename, err));
|
||||
ex->SetDiagMsg( pxsFmt(L"An error occurred while writing %u bytes to file: %s", size, ex->DiagMsg().c_str()) );
|
||||
ex->Rethrow();
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// _IsoPart
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
_IsoPart::~_IsoPart() throw()
|
||||
{
|
||||
}
|
||||
|
||||
void _IsoPart::Read( void* dest, size_t size )
|
||||
{
|
||||
handle->Read(dest, size);
|
||||
if (handle->GetLastError() == wxSTREAM_READ_ERROR)
|
||||
{
|
||||
int err = errno;
|
||||
if (!err)
|
||||
throw Exception::BadStream(filename).SetDiagMsg(L"Cannot read from file (bad file handle?)");
|
||||
|
||||
ScopedExcept ex(Exception::FromErrno(filename, err));
|
||||
ex->SetDiagMsg( L"cannot read from file: " + ex->DiagMsg() );
|
||||
ex->Rethrow();
|
||||
}
|
||||
|
||||
iso->handle = _openfile(iso->filename, O_WRONLY | O_CREAT);
|
||||
// IMPORTANT! The underlying file/source Eof() stuff is not really reliable, so we
|
||||
// must always use the explicit check against the number of bytes read to determine
|
||||
// end-of-stream conditions.
|
||||
|
||||
if (iso->handle == NULL)
|
||||
{
|
||||
Console.Error("Error loading %s", iso->filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Console.WriteLn("isoCreate: %s ok", iso->filename);
|
||||
Console.WriteLn("offset = %d", iso->offset);
|
||||
|
||||
return iso;
|
||||
if ((size_t)handle->LastRead() < size)
|
||||
throw Exception::EndOfStream( filename );
|
||||
}
|
||||
|
||||
bool isoSetFormat(isoFile *iso, int blockofs, uint blocksize, uint blocks)
|
||||
void _IsoPart::Seek(wxFileOffset pos, wxSeekMode mode)
|
||||
{
|
||||
iso->blocksize = blocksize;
|
||||
iso->blocks = blocks;
|
||||
iso->blockofs = blockofs;
|
||||
|
||||
Console.WriteLn("blockofs = %d", iso->blockofs);
|
||||
Console.WriteLn("blocksize = %u", iso->blocksize);
|
||||
Console.WriteLn("blocks = %u", iso->blocks);
|
||||
|
||||
if (iso->flags & ISOFLAGS_BLOCKDUMP_V2)
|
||||
{
|
||||
if (_writefile(iso->handle, "BDV2", 4) < 4) return false;
|
||||
if (_writefile(iso->handle, &blocksize, 4) < 4) return false;
|
||||
if (_writefile(iso->handle, &blocks, 4) < 4) return false;
|
||||
if (_writefile(iso->handle, &blockofs, 4) < 4) return false;
|
||||
}
|
||||
else if (iso->flags & ISOFLAGS_BLOCKDUMP_V3)
|
||||
{
|
||||
if (_writefile(iso->handle, "BDV3", 4) < 4) return false;
|
||||
if (_writefile(iso->handle, &blocksize, 4) < 4) return false;
|
||||
if (_writefile(iso->handle, &blocks, 4) < 4) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
handle->SeekI(pos, mode);
|
||||
}
|
||||
|
||||
bool _isoReadBlock(isoFile *iso, u8 *dst, int lsn)
|
||||
void _IsoPart::SeekEnd(wxFileOffset pos)
|
||||
{
|
||||
u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
|
||||
|
||||
memset(dst, 0, iso->blockofs);
|
||||
_seekfile(iso->handle, ofs, SEEK_SET);
|
||||
|
||||
uint ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize);
|
||||
|
||||
if (ret < iso->blocksize)
|
||||
{
|
||||
Console.Error("read error in _isoReadBlock." );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
handle->SeekI(pos, wxFromEnd);
|
||||
}
|
||||
|
||||
bool _isoReadBlockD(isoFile *iso, u8 *dst, uint lsn)
|
||||
wxFileOffset _IsoPart::Tell() const
|
||||
{
|
||||
uint ret;
|
||||
|
||||
// Console.WriteLn("_isoReadBlockD %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs);
|
||||
|
||||
memset(dst, 0, iso->blockofs);
|
||||
for (int i = 0; i < iso->dtablesize; i++)
|
||||
{
|
||||
if (iso->dtable[i] != lsn) continue;
|
||||
|
||||
_seekfile(iso->handle, 16 + i * (iso->blocksize + 4) + 4, SEEK_SET);
|
||||
ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize);
|
||||
|
||||
if (ret < iso->blocksize) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
Console.WriteLn("Block %u not found in dump", lsn);
|
||||
|
||||
return false;
|
||||
return handle->TellI();
|
||||
}
|
||||
|
||||
bool _isoReadBlockM(isoFile *iso, u8 *dst, uint lsn)
|
||||
// returns the number of blocks contained in this part of the iso image.
|
||||
uint _IsoPart::CalculateBlocks( uint startBlock, uint blocksize )
|
||||
{
|
||||
u64 ofs;
|
||||
uint ret, i;
|
||||
wxFileOffset partsize = handle->GetLength();
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if ((lsn >= iso->multih[i].slsn) && (lsn <= iso->multih[i].elsn))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 8) return false;
|
||||
|
||||
ofs = (u64)(lsn - iso->multih[i].slsn) * iso->blocksize + iso->offset;
|
||||
|
||||
// Console.WriteLn("_isoReadBlock %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs);
|
||||
|
||||
memset(dst, 0, iso->blockofs);
|
||||
_seekfile(iso->multih[i].handle, ofs, SEEK_SET);
|
||||
ret = _readfile(iso->multih[i].handle, dst + iso->blockofs, iso->blocksize);
|
||||
|
||||
if (ret < iso->blocksize)
|
||||
{
|
||||
Console.Error("read error in _isoReadBlockM");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
slsn = startBlock;
|
||||
uint numBlocks = partsize / blocksize;
|
||||
elsn = startBlock + numBlocks - 1;
|
||||
return numBlocks;
|
||||
}
|
||||
|
||||
bool isoReadBlock(isoFile *iso, u8 *dst, uint lsn)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (lsn > iso->blocks)
|
||||
{
|
||||
Console.WriteLn("isoReadBlock: %u > %u", lsn, iso->blocks);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iso->flags & ISOFLAGS_BLOCKDUMP_V2)
|
||||
ret = _isoReadBlockD(iso, dst, lsn);
|
||||
else if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
|
||||
ret = _isoReadBlockD(iso, dst, lsn);
|
||||
else if (iso->flags & ISOFLAGS_MULTI)
|
||||
ret = _isoReadBlockM(iso, dst, lsn);
|
||||
else
|
||||
ret = _isoReadBlock(iso, dst, lsn);
|
||||
|
||||
if (!ret) return false;
|
||||
|
||||
if (iso->type == ISOTYPE_CD)
|
||||
{
|
||||
lsn_to_msf(dst + 12, lsn);
|
||||
dst[15] = 2;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool _isoWriteBlock(isoFile *iso, u8 *src, uint lsn)
|
||||
{
|
||||
uint ret;
|
||||
u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
|
||||
|
||||
_seekfile(iso->handle, ofs, SEEK_SET);
|
||||
ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize);
|
||||
if (ret < iso->blocksize) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _isoWriteBlockD(isoFile *iso, u8 *src, uint lsn)
|
||||
{
|
||||
uint ret;
|
||||
|
||||
ret = _writefile(iso->handle, &lsn, 4);
|
||||
if (ret < 4) return false;
|
||||
ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize);
|
||||
|
||||
if (ret < iso->blocksize) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isoWriteBlock(isoFile *iso, u8 *src, uint lsn)
|
||||
{
|
||||
if (iso->flags & ISOFLAGS_BLOCKDUMP_V3)
|
||||
return _isoWriteBlockD(iso, src, lsn);
|
||||
else
|
||||
return _isoWriteBlock(iso, src, lsn);
|
||||
}
|
||||
|
||||
void isoClose(isoFile *iso)
|
||||
{
|
||||
if (iso == NULL ) return;
|
||||
if (iso->handle) _closefile(iso->handle);
|
||||
if (iso->htable) _closefile(iso->htable);
|
||||
safe_free( iso->buffer );
|
||||
safe_free( iso->dtable );
|
||||
safe_free( iso );
|
||||
}
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __LIBISO_H__
|
||||
#define __LIBISO_H__
|
||||
#pragma once
|
||||
|
||||
#include "CDVD.h"
|
||||
#include "IsoFileTools.h"
|
||||
#include "wx/wfstream.h"
|
||||
|
||||
|
||||
enum isoType
|
||||
{
|
||||
|
@ -30,49 +30,134 @@ enum isoType
|
|||
|
||||
enum isoFlags
|
||||
{
|
||||
ISOFLAGS_Z = 0x0001,
|
||||
ISOFLAGS_Z2 = 0x0002,
|
||||
ISOFLAGS_BLOCKDUMP_V2 = 0x0004,
|
||||
ISOFLAGS_MULTI = 0x0008,
|
||||
ISOFLAGS_BZ2 = 0x0010,
|
||||
ISOFLAGS_BLOCKDUMP_V3 = 0x0020
|
||||
};
|
||||
|
||||
static const int CD_FRAMESIZE_RAW = 2448;
|
||||
|
||||
struct _multih
|
||||
// --------------------------------------------------------------------------------------
|
||||
// MultiPartIso
|
||||
// --------------------------------------------------------------------------------------
|
||||
// An encapsulating class for array boundschecking and easy ScopedPointer behavior.
|
||||
//
|
||||
class _IsoPart
|
||||
{
|
||||
u32 slsn;
|
||||
u32 elsn;
|
||||
void *handle;
|
||||
DeclareNoncopyableObject( _IsoPart );
|
||||
|
||||
public:
|
||||
// starting block index of this part of the iso.
|
||||
u32 slsn;
|
||||
// ending bock index of this part of the iso.
|
||||
u32 elsn;
|
||||
|
||||
wxString filename;
|
||||
ScopedPtr<wxFileInputStream> handle;
|
||||
|
||||
public:
|
||||
_IsoPart() {}
|
||||
~_IsoPart() throw();
|
||||
|
||||
void Read( void* dest, size_t size );
|
||||
|
||||
void Seek(wxFileOffset pos, wxSeekMode mode = wxFromStart);
|
||||
void SeekEnd(wxFileOffset pos=0);
|
||||
wxFileOffset Tell() const;
|
||||
uint CalculateBlocks( uint startBlock, uint blocksize );
|
||||
|
||||
template< typename T >
|
||||
void Read( T& dest )
|
||||
{
|
||||
Read( &dest, sizeof(dest) );
|
||||
}
|
||||
};
|
||||
|
||||
struct isoFile
|
||||
// --------------------------------------------------------------------------------------
|
||||
// isoFile
|
||||
// --------------------------------------------------------------------------------------
|
||||
class isoFile
|
||||
{
|
||||
char filename[256];
|
||||
isoType type;
|
||||
u32 flags;
|
||||
s32 offset;
|
||||
s32 blockofs;
|
||||
u32 blocksize;
|
||||
u32 blocks;
|
||||
void *handle;
|
||||
void *htable;
|
||||
char *Ztable;
|
||||
u32 *dtable;
|
||||
int dtablesize;
|
||||
_multih multih[8];
|
||||
int buflsn;
|
||||
u8 *buffer;
|
||||
DeclareNoncopyableObject( isoFile );
|
||||
|
||||
protected:
|
||||
static const uint MaxSplits = 8;
|
||||
|
||||
protected:
|
||||
wxString m_filename;
|
||||
uint m_numparts;
|
||||
_IsoPart m_parts[MaxSplits];
|
||||
|
||||
isoType m_type;
|
||||
u32 m_flags;
|
||||
|
||||
s32 m_offset;
|
||||
s32 m_blockofs;
|
||||
u32 m_blocksize;
|
||||
|
||||
// total number of blocks in the ISO image (including all parts)
|
||||
u32 m_blocks;
|
||||
|
||||
// dtable / dtablesize are used when reading blockdumps
|
||||
ScopedArray<u32> m_dtable;
|
||||
int m_dtablesize;
|
||||
|
||||
ScopedPtr<wxFileOutputStream> m_outstream;
|
||||
|
||||
// Currently unused internal buffer (it was used for compressed
|
||||
// iso support, before it was removed).
|
||||
//ScopedArray<u8> m_buffer;
|
||||
//int m_buflsn;
|
||||
|
||||
public:
|
||||
isoFile();
|
||||
virtual ~isoFile() throw();
|
||||
|
||||
bool IsOpened() const;
|
||||
|
||||
isoType GetType() const { return m_type; }
|
||||
|
||||
// Returns the number of blocks in the ISO image.
|
||||
uint GetBlockCount() const { return m_blocks; }
|
||||
|
||||
int GetBlockOffset() const { return m_blockofs; }
|
||||
|
||||
const wxString& GetFilename() const
|
||||
{
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
bool Test( const wxString& srcfile );
|
||||
void Open( const wxString& srcfile );
|
||||
void Create(const wxString& filename, int mode);
|
||||
void Close();
|
||||
bool Detect( bool readType=true );
|
||||
|
||||
void WriteFormat(int blockofs, uint blocksize, uint blocks);
|
||||
|
||||
void ReadBlock(u8* dst, uint lsn);
|
||||
void WriteBlock(const u8* src, uint lsn);
|
||||
|
||||
protected:
|
||||
bool detect();
|
||||
void _init();
|
||||
void _ReadDtable();
|
||||
void _ReadBlock(u8* dst, uint lsn);
|
||||
void _ReadBlockD(u8* dst, uint lsn);
|
||||
|
||||
void _WriteBlock(const u8* src, uint lsn);
|
||||
void _WriteBlockD(const u8* src, uint lsn);
|
||||
|
||||
bool tryIsoType(u32 _size, s32 _offset, s32 _blockofs);
|
||||
void FindParts();
|
||||
|
||||
void outWrite( const void* src, size_t size );
|
||||
|
||||
template< typename T >
|
||||
void outWrite( const T& data )
|
||||
{
|
||||
outWrite( &data, sizeof(data) );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
extern isoFile *isoOpen(const char *filename);
|
||||
extern isoFile *isoCreate(const char *filename, int mode);
|
||||
extern bool isoSetFormat(isoFile *iso, int blockofs, uint blocksize, uint blocks);
|
||||
extern bool isoDetect(isoFile *iso);
|
||||
extern bool isoReadBlock(isoFile *iso, u8 *dst, uint lsn);
|
||||
extern bool isoWriteBlock(isoFile *iso, u8 *src, uint lsn);
|
||||
extern void isoClose(isoFile *iso);
|
||||
|
||||
#endif /* __LIBISO_H__ */
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "IsoFileTools.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <wx/msw/wrapwin.h>
|
||||
|
||||
|
||||
void *_openfile(const char *filename, int flags)
|
||||
{
|
||||
HANDLE handle;
|
||||
|
||||
// Console.WriteLn("_openfile %s, %d", filename, flags & O_RDONLY);
|
||||
if (flags & O_WRONLY)
|
||||
{
|
||||
int _flags = CREATE_NEW;
|
||||
if (flags & O_CREAT) _flags = CREATE_ALWAYS;
|
||||
handle = CreateFile(fromUTF8(filename), GENERIC_WRITE, 0, NULL, _flags, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle = CreateFile(fromUTF8(filename), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
}
|
||||
|
||||
return (handle == INVALID_HANDLE_VALUE) ? NULL : handle;
|
||||
}
|
||||
|
||||
u64 _tellfile(void *handle)
|
||||
{
|
||||
u64 ofs;
|
||||
PLONG _ofs = (LONG*) & ofs;
|
||||
_ofs[1] = 0;
|
||||
_ofs[0] = SetFilePointer(handle, 0, &_ofs[1], FILE_CURRENT);
|
||||
return ofs;
|
||||
}
|
||||
|
||||
int _seekfile(void *handle, u64 offset, int whence)
|
||||
{
|
||||
u64 ofs = (u64)offset;
|
||||
PLONG _ofs = (LONG*) & ofs;
|
||||
|
||||
// Console.WriteLn("_seekfile %p, %d_%d", handle, _ofs[1], _ofs[0]);
|
||||
|
||||
SetFilePointer(handle, _ofs[0], &_ofs[1], (whence == SEEK_SET) ? FILE_BEGIN : FILE_END);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 _readfile(void *handle, void *dst, int size)
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
ReadFile(handle, dst, size, &ret, NULL);
|
||||
// Console.WriteLn("_readfile(%p, %d) = %d; %d", handle, size, ret, GetLastError());
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 _writefile(void *handle, const void *src, int size)
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
// _seekfile(handle, _tellfile(handle));
|
||||
WriteFile(handle, src, size, &ret, NULL);
|
||||
// Console.WriteLn("_readfile(%p, %d) = %d", handle, size, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _closefile(void *handle)
|
||||
{
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void *_openfile(const char *filename, int flags)
|
||||
{
|
||||
// Console.WriteLn("_openfile %s %x", filename, flags);
|
||||
|
||||
if (flags & O_WRONLY)
|
||||
return fopen64(filename, "wb");
|
||||
else
|
||||
return fopen64(filename, "rb");
|
||||
}
|
||||
|
||||
u64 _tellfile(void *handle)
|
||||
{
|
||||
FILE* fp = (FILE*)handle;
|
||||
s64 cursize = ftell(fp);
|
||||
|
||||
if (cursize == -1)
|
||||
{
|
||||
// try 64bit
|
||||
cursize = ftello64(fp);
|
||||
if (cursize < -1)
|
||||
{
|
||||
// zero top 32 bits
|
||||
cursize &= 0xffffffff;
|
||||
}
|
||||
}
|
||||
return cursize;
|
||||
}
|
||||
|
||||
int _seekfile(void *handle, u64 offset, int whence)
|
||||
{
|
||||
int seekerr = fseeko64((FILE*)handle, offset, whence);
|
||||
|
||||
if (seekerr == -1) Console.Error("Failed to seek.");
|
||||
|
||||
return seekerr;
|
||||
}
|
||||
|
||||
u32 _readfile(void *handle, void *dst, int size)
|
||||
{
|
||||
return fread(dst, 1, size, (FILE*)handle);
|
||||
}
|
||||
|
||||
u32 _writefile(void *handle, const void *src, int size)
|
||||
{
|
||||
return fwrite(src, 1, size, (FILE*)handle);
|
||||
}
|
||||
|
||||
void _closefile(void *handle)
|
||||
{
|
||||
fclose((FILE*)handle);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,44 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE_SOURCE
|
||||
#endif
|
||||
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
|
||||
#ifndef __USE_FILE_OFFSET64
|
||||
#define __USE_FILE_OFFSET64
|
||||
#endif
|
||||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include "IopCommon.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
extern void *_openfile(const char *filename, int flags);
|
||||
extern u64 _tellfile(void *handle);
|
||||
extern int _seekfile(void *handle, u64 offset, int whence);
|
||||
extern u32 _readfile(void *handle, void *dst, int size);
|
||||
extern u32 _writefile(void *handle, const void *src, int size);
|
||||
extern void _closefile(void *handle);
|
||||
|
|
@ -238,7 +238,6 @@ set(pcsx2CDVDSources
|
|||
CDVD/CDVD.cpp
|
||||
CDVD/CDVDisoReader.cpp
|
||||
CDVD/IsoFileFormats.cpp
|
||||
CDVD/IsoFileTools.cpp
|
||||
CDVD/IsoFS/IsoFile.cpp
|
||||
CDVD/IsoFS/IsoFSCDVD.cpp
|
||||
CDVD/IsoFS/IsoFS.cpp)
|
||||
|
@ -251,7 +250,6 @@ set(pcsx2CDVDHeaders
|
|||
CDVD/CDVD_internal.h
|
||||
CDVD/CDVDisoReader.h
|
||||
CDVD/IsoFileFormats.h
|
||||
CDVD/IsoFileTools.h
|
||||
CDVD/IsoFS/IsoDirectory.h
|
||||
CDVD/IsoFS/IsoFileDescriptor.h
|
||||
CDVD/IsoFS/IsoFile.h
|
||||
|
|
|
@ -37,7 +37,7 @@ __ri void cpuUpdateOperationMode() {
|
|||
|
||||
void __fastcall WriteCP0Status(u32 value) {
|
||||
|
||||
DMA_LOG("COP0 Status write = 0x%08x", value);
|
||||
//DMA_LOG("COP0 Status write = 0x%08x", value);
|
||||
|
||||
cpuRegs.CP0.n.Status.val = value;
|
||||
cpuUpdateOperationMode();
|
||||
|
|
|
@ -249,8 +249,6 @@
|
|||
<Unit filename="../CDVD/IsoFS/SectorSource.h" />
|
||||
<Unit filename="../CDVD/IsoFileFormats.cpp" />
|
||||
<Unit filename="../CDVD/IsoFileFormats.h" />
|
||||
<Unit filename="../CDVD/IsoFileTools.cpp" />
|
||||
<Unit filename="../CDVD/IsoFileTools.h" />
|
||||
<Unit filename="../COP0.cpp" />
|
||||
<Unit filename="../COP0.h" />
|
||||
<Unit filename="../COP2.cpp" />
|
||||
|
|
|
@ -163,7 +163,7 @@ class CpuInitializer
|
|||
{
|
||||
public:
|
||||
ScopedPtr<CpuType> MyCpu;
|
||||
ScopedPtr<BaseException> ExThrown;
|
||||
ScopedExcept ExThrown;
|
||||
|
||||
CpuInitializer();
|
||||
virtual ~CpuInitializer() throw();
|
||||
|
@ -213,6 +213,9 @@ CpuInitializer< CpuType >::~CpuInitializer() throw()
|
|||
MyCpu->Shutdown();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// CpuInitializerSet
|
||||
// --------------------------------------------------------------------------------------
|
||||
class CpuInitializerSet
|
||||
{
|
||||
public:
|
||||
|
@ -233,7 +236,6 @@ public:
|
|||
};
|
||||
|
||||
|
||||
|
||||
// returns the translated error message for the Virtual Machine failing to allocate!
|
||||
static wxString GetMemoryErrorVM()
|
||||
{
|
||||
|
|
|
@ -43,8 +43,8 @@ protected:
|
|||
class SysCpuProviderPack
|
||||
{
|
||||
protected:
|
||||
ScopedPtr<BaseException> m_RecExceptionEE;
|
||||
ScopedPtr<BaseException> m_RecExceptionIOP;
|
||||
ScopedExcept m_RecExceptionEE;
|
||||
ScopedExcept m_RecExceptionIOP;
|
||||
|
||||
public:
|
||||
ScopedPtr<CpuInitializerSet> CpuProviders;
|
||||
|
|
|
@ -75,7 +75,7 @@ int AppOpenModalDialog( wxWindow* parent=NULL )
|
|||
return DialogType( parent ).ShowModal();
|
||||
}
|
||||
|
||||
static bool HandlePluginError( Exception::BaseException& ex )
|
||||
static bool HandlePluginError( BaseException& ex )
|
||||
{
|
||||
if( !pxDialogExists( L"CoreSettings" ) )
|
||||
{
|
||||
|
@ -127,7 +127,7 @@ void PluginErrorEvent::InvokeEvent()
|
|||
{
|
||||
if( !m_except ) return;
|
||||
|
||||
ScopedPtr<BaseException> deleteMe( m_except );
|
||||
ScopedExcept deleteMe( m_except );
|
||||
m_except = NULL;
|
||||
|
||||
if( !HandlePluginError( *deleteMe ) )
|
||||
|
@ -141,7 +141,7 @@ void PluginInitErrorEvent::InvokeEvent()
|
|||
{
|
||||
if( !m_except ) return;
|
||||
|
||||
ScopedPtr<BaseException> deleteMe( m_except );
|
||||
ScopedExcept deleteMe( m_except );
|
||||
m_except = NULL;
|
||||
|
||||
if( !HandlePluginError( *deleteMe ) )
|
||||
|
|
|
@ -166,7 +166,7 @@ wxWindowID pxIssueConfirmation( wxDialogWithHelpers& confirmDlg, const MsgButton
|
|||
cfg->SetRecordDefaults( recdef );
|
||||
cfg->SetPath( L"/" );
|
||||
|
||||
result.LowerCase();
|
||||
result.MakeLower();
|
||||
wxArrayString split;
|
||||
SplitString( split, result, L"," );
|
||||
|
||||
|
|
|
@ -31,47 +31,66 @@ wxString GetMsg_ConfirmSysReset()
|
|||
);
|
||||
}
|
||||
|
||||
bool IsoDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
|
||||
// --------------------------------------------------------------------------------------
|
||||
// DroppedTooManyFiles
|
||||
// --------------------------------------------------------------------------------------
|
||||
class DroppedTooManyFiles : public pxActionEvent
|
||||
{
|
||||
ScopedCoreThreadPopup stopped_core;
|
||||
protected:
|
||||
wxWindowID m_ownerid;
|
||||
|
||||
if( filenames.GetCount() > 1 )
|
||||
public:
|
||||
DroppedTooManyFiles( const wxWindow* window )
|
||||
: pxActionEvent()
|
||||
{
|
||||
wxDialogWithHelpers dialog( m_WindowBound, _("Drag and Drop Error") );
|
||||
dialog += dialog.Heading(AddAppName(_("It is an error to drop multiple files onto a %s window. One at a time please, thank you.")));
|
||||
pxIssueConfirmation( dialog, MsgButtons().Cancel() );
|
||||
return false;
|
||||
m_ownerid = window->GetId();
|
||||
}
|
||||
|
||||
Console.WriteLn( L"(Drag&Drop) Received filename: " + filenames[0] );
|
||||
virtual ~DroppedTooManyFiles() throw() { }
|
||||
virtual DroppedTooManyFiles *Clone() const { return new DroppedTooManyFiles(*this); }
|
||||
|
||||
// ---------------
|
||||
// ELF CHECK
|
||||
// ---------------
|
||||
protected:
|
||||
virtual void InvokeEvent()
|
||||
{
|
||||
wxFileInputStream filechk( filenames[0] );
|
||||
ScopedCoreThreadPopup stopped_core;
|
||||
|
||||
if( !filechk.IsOk() )
|
||||
throw Exception::CannotCreateStream( filenames[0] );
|
||||
wxDialogWithHelpers dialog( wxWindow::FindWindowById(m_ownerid), _("Drag and Drop Error") );
|
||||
dialog += dialog.Heading(AddAppName(_("It is an error to drop multiple files onto a %s window. One at a time please, thank you.")));
|
||||
pxIssueConfirmation( dialog, MsgButtons().Cancel() );
|
||||
}
|
||||
};
|
||||
|
||||
u8 ident[16];
|
||||
filechk.Read( ident, 16 );
|
||||
static const u8 elfIdent[4] = { 0x7f, 'E', 'L', 'F' };
|
||||
// --------------------------------------------------------------------------------------
|
||||
// DroppedElf
|
||||
// --------------------------------------------------------------------------------------
|
||||
class DroppedElf : public pxActionEvent
|
||||
{
|
||||
protected:
|
||||
wxWindowID m_ownerid;
|
||||
|
||||
if( ((u32&)ident) == ((u32&)elfIdent) )
|
||||
public:
|
||||
DroppedElf( const wxWindow* window )
|
||||
: pxActionEvent()
|
||||
{
|
||||
Console.WriteLn( L"(Drag&Drop) Found ELF file type!" );
|
||||
m_ownerid = window->GetId();
|
||||
}
|
||||
|
||||
g_Conf->CurrentELF = filenames[0];
|
||||
virtual ~DroppedElf() throw() { }
|
||||
virtual DroppedElf *Clone() const { return new DroppedElf(*this); }
|
||||
|
||||
protected:
|
||||
virtual void InvokeEvent()
|
||||
{
|
||||
ScopedCoreThreadPopup stopped_core;
|
||||
|
||||
bool confirmed = true;
|
||||
if( SysHasValidState() )
|
||||
{
|
||||
wxDialogWithHelpers dialog( m_WindowBound, _("Confirm PS2 Reset") );
|
||||
wxDialogWithHelpers dialog( wxWindow::FindWindowById(m_ownerid), _("Confirm PS2 Reset") );
|
||||
|
||||
dialog += dialog.Heading(AddAppName(_("You have dropped the following ELF binary into %s:\n\n")));
|
||||
dialog += dialog.GetCharHeight();
|
||||
dialog += dialog.Text( filenames[0] );
|
||||
dialog += dialog.Text( g_Conf->CurrentELF );
|
||||
dialog += dialog.GetCharHeight();
|
||||
dialog += dialog.Heading(GetMsg_ConfirmSysReset());
|
||||
|
||||
|
@ -85,32 +104,106 @@ bool IsoDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filen
|
|||
}
|
||||
else
|
||||
stopped_core.AllowResume();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------
|
||||
// ISO CHECK
|
||||
// ---------------
|
||||
// --------------------------------------------------------------------------------------
|
||||
// DroppedIso
|
||||
// --------------------------------------------------------------------------------------
|
||||
class DroppedIso : public pxActionEvent
|
||||
{
|
||||
protected:
|
||||
wxWindowID m_ownerid;
|
||||
wxString m_filename;
|
||||
|
||||
// FIXME : The whole IsoFileFormats api (meaning isoOpen / isoDetect / etc) needs to be
|
||||
// converted to C++ and wxInputStream . Until then this is a nasty little exception unsafe
|
||||
// hack ;)
|
||||
|
||||
isoFile iso;
|
||||
memzero(iso);
|
||||
iso.handle = _openfile(filenames[0].ToUTF8(), O_RDONLY);
|
||||
|
||||
if( iso.handle == NULL )
|
||||
throw Exception::CannotCreateStream( filenames[0] );
|
||||
|
||||
if (isoDetect(&iso))
|
||||
public:
|
||||
DroppedIso( const wxWindow* window, const wxString& filename )
|
||||
: pxActionEvent()
|
||||
, m_filename( filename )
|
||||
{
|
||||
Console.WriteLn( L"(Drag&Drop) Found valid ISO file type!" );
|
||||
SwapOrReset_Iso(m_WindowBound, stopped_core, filenames[0], AddAppName(_("You have dropped the following ISO image into %s:")));
|
||||
m_ownerid = window->GetId();
|
||||
}
|
||||
|
||||
_closefile( iso.handle );
|
||||
return true;
|
||||
virtual ~DroppedIso() throw() { }
|
||||
virtual DroppedIso *Clone() const { return new DroppedIso(*this); }
|
||||
|
||||
protected:
|
||||
virtual void InvokeEvent()
|
||||
{
|
||||
ScopedCoreThreadPopup stopped_core;
|
||||
SwapOrReset_Iso(wxWindow::FindWindowById(m_ownerid), stopped_core, m_filename,
|
||||
AddAppName(_("You have dropped the following ISO image into %s:"))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
bool IsoDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
|
||||
{
|
||||
// WARNING: Doing *anything* from the context of OnDropFiles will result in Windows
|
||||
// Explorer getting tied up waiting for a response from the application's message pump.
|
||||
// So whenever possible, issue messages from this function only, such that the
|
||||
// messages are processed later on after the application has allowed Explorer to resume
|
||||
// itself.
|
||||
//
|
||||
// This most likely *includes* throwing exceptions, hence all exceptions here-in being
|
||||
// caught and re-packaged as messages posted back to the application, so that the drag&
|
||||
// drop procedure is free to release the Windows Explorer from the tyranny of drag&drop
|
||||
// interplay.
|
||||
|
||||
try
|
||||
{
|
||||
if( filenames.GetCount() > 1 )
|
||||
{
|
||||
wxGetApp().AddIdleEvent( DroppedTooManyFiles(m_WindowBound) );
|
||||
return false;
|
||||
}
|
||||
|
||||
Console.WriteLn( L"(Drag&Drop) Received filename: " + filenames[0] );
|
||||
|
||||
// ---------------
|
||||
// ELF CHECK
|
||||
// ---------------
|
||||
{
|
||||
wxFileInputStream filechk( filenames[0] );
|
||||
|
||||
if( !filechk.IsOk() )
|
||||
throw Exception::CannotCreateStream( filenames[0] );
|
||||
|
||||
u8 ident[16];
|
||||
filechk.Read( ident, 16 );
|
||||
static const u8 elfIdent[4] = { 0x7f, 'E', 'L', 'F' };
|
||||
|
||||
if( ((u32&)ident) == ((u32&)elfIdent) )
|
||||
{
|
||||
Console.WriteLn( L"(Drag&Drop) Found ELF file type!" );
|
||||
|
||||
g_Conf->CurrentELF = filenames[0];
|
||||
|
||||
wxGetApp().PostEvent( DroppedElf(m_WindowBound) );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------
|
||||
// ISO CHECK
|
||||
// ---------------
|
||||
|
||||
isoFile iso;
|
||||
|
||||
if (iso.Test( filenames[0] ))
|
||||
{
|
||||
DevCon.WriteLn( L"(Drag&Drop) Found valid ISO file type!" );
|
||||
wxGetApp().PostEvent( DroppedIso(m_WindowBound, filenames[0]) );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (BaseException& ex)
|
||||
{
|
||||
wxGetApp().AddIdleEvent( pxExceptionEvent(ex) );
|
||||
}
|
||||
catch (std::runtime_error& ex)
|
||||
{
|
||||
wxGetApp().AddIdleEvent( pxExceptionEvent(Exception::RuntimeError(ex)) );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ void MainEmuFrame::Menu_ResetAllSettings_Click(wxCommandEvent &event)
|
|||
|
||||
{
|
||||
ScopedCoreThreadPopup suspender;
|
||||
if( !Msgbox::OkCancel( wxsFormat(
|
||||
if( !Msgbox::OkCancel( pxsFmt(
|
||||
pxE( ".Popup:DeleteSettings",
|
||||
L"This command clears %s settings and allows you to re-run the First-Time Wizard. You will need to "
|
||||
L"manually restart %s after this operation.\n\n"
|
||||
|
@ -222,12 +222,13 @@ static wxString JoinFiletypes( const wxChar** src )
|
|||
if( !dest.IsEmpty() )
|
||||
dest += L";";
|
||||
|
||||
dest += wxsFormat(L"*.%s", *src);
|
||||
dest += pxsFmt(L"*.%s", *src);
|
||||
|
||||
#ifdef __LINUX__
|
||||
// omgosh! linux is CaSE SeNSiTiVE!!
|
||||
dest += wxsFormat(L";*.%s", *src).MakeUpper();
|
||||
#endif
|
||||
if (wxFileName::IsCaseSensitive())
|
||||
{
|
||||
// omgosh! the filesystem is CaSE SeNSiTiVE!!
|
||||
dest += pxsFmt(L";*.%s", *src).ToUpper();
|
||||
}
|
||||
|
||||
++src;
|
||||
}
|
||||
|
@ -248,13 +249,13 @@ bool MainEmuFrame::_DoSelectIsoBrowser( wxString& result )
|
|||
|
||||
wxArrayString isoFilterTypes;
|
||||
|
||||
isoFilterTypes.Add(wxsFormat(_("All Supported (%s)"), (isoSupportedLabel + L" .dump").c_str()));
|
||||
isoFilterTypes.Add(pxsFmt(_("All Supported (%s)"), (isoSupportedLabel + L" .dump").c_str()));
|
||||
isoFilterTypes.Add(isoSupportedList + L";*.dump");
|
||||
|
||||
isoFilterTypes.Add(wxsFormat(_("Disc Images (%s)"), isoSupportedLabel.c_str() ));
|
||||
isoFilterTypes.Add(pxsFmt(_("Disc Images (%s)"), isoSupportedLabel.c_str() ));
|
||||
isoFilterTypes.Add(isoSupportedList);
|
||||
|
||||
isoFilterTypes.Add(wxsFormat(_("Blockdumps (%s)"), L".dump" ));
|
||||
isoFilterTypes.Add(pxsFmt(_("Blockdumps (%s)"), L".dump" ));
|
||||
isoFilterTypes.Add(L"*.dump");
|
||||
|
||||
isoFilterTypes.Add(_("All Files (*.*)"));
|
||||
|
|
|
@ -1249,14 +1249,6 @@
|
|||
RelativePath="..\..\CDVD\CDVDisoReader.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\IsoFileTools.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\IsoFileTools.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
|
|
@ -16,41 +16,6 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "Win32.h"
|
||||
|
||||
// Translates an Errno code into an exception.
|
||||
// Throws an exception based on the given error code (usually taken from ANSI C's errno)
|
||||
void StreamException_ThrowFromErrno( const wxString& streamname, errno_t errcode )
|
||||
{
|
||||
if( errcode == 0 ) return;
|
||||
|
||||
switch( errcode )
|
||||
{
|
||||
case EINVAL:
|
||||
pxFailDev( L"Invalid argument" );
|
||||
throw Exception::Stream( streamname ).SetDiagMsg(L"Invalid argument" );
|
||||
|
||||
case EACCES: // Access denied!
|
||||
throw Exception::AccessDenied( streamname );
|
||||
|
||||
case EMFILE: // Too many open files!
|
||||
throw Exception::CannotCreateStream( streamname ).SetDiagMsg(L"Too many open files"); // File handle allocation failure
|
||||
|
||||
case EEXIST:
|
||||
throw Exception::CannotCreateStream( streamname ).SetDiagMsg(L"File already exists");
|
||||
|
||||
case ENOENT: // File not found!
|
||||
throw Exception::FileNotFound( streamname );
|
||||
|
||||
case EPIPE:
|
||||
throw Exception::BadStream( streamname ).SetDiagMsg(L"Broken pipe");
|
||||
|
||||
case EBADF:
|
||||
throw Exception::BadStream( streamname ).SetDiagMsg(L"Bad file number");
|
||||
|
||||
default:
|
||||
throw Exception::Stream( streamname ).SetDiagMsg(wxsFormat( L"General file/stream error [errno: %d]", errcode ));
|
||||
}
|
||||
}
|
||||
|
||||
// Throws an exception based on the value returned from GetLastError.
|
||||
// Performs an option return value success/fail check on hresult.
|
||||
void StreamException_ThrowLastError( const wxString& streamname, HANDLE result )
|
||||
|
@ -86,21 +51,6 @@ void StreamException_ThrowLastError( const wxString& streamname, HANDLE result )
|
|||
}
|
||||
}
|
||||
|
||||
// returns TRUE if an error occurred.
|
||||
bool StreamException_LogFromErrno( const wxString& streamname, const wxChar* action, errno_t result )
|
||||
{
|
||||
try
|
||||
{
|
||||
StreamException_ThrowFromErrno( streamname, result );
|
||||
}
|
||||
catch( Exception::Stream& ex )
|
||||
{
|
||||
Console.WriteLn( Color_Yellow, L"%s: %s", action, ex.FormatDiagnosticMessage().c_str() );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// returns TRUE if an error occurred.
|
||||
bool StreamException_LogLastError( const wxString& streamname, const wxChar* action, HANDLE result )
|
||||
{
|
||||
|
|
|
@ -716,7 +716,7 @@ void recStep( void )
|
|||
# define SETJMP_CODE(x) x
|
||||
static jmp_buf m_SetJmp_StateCheck;
|
||||
static ScopedPtr<BaseR5900Exception> m_cpuException;
|
||||
static ScopedPtr<BaseException> m_Exception;
|
||||
static ScopedExcept m_Exception;
|
||||
#else
|
||||
# define SETJMP_CODE(x)
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue