diff --git a/common/build/Utilities/Utilities.cbp b/common/build/Utilities/Utilities.cbp
index 4ee3d0b232..585bc4c499 100644
--- a/common/build/Utilities/Utilities.cbp
+++ b/common/build/Utilities/Utilities.cbp
@@ -160,7 +160,8 @@
-
+
+
@@ -172,7 +173,8 @@
-
+
+
@@ -201,7 +203,7 @@
-
+
diff --git a/common/build/Utilities/utilities.vcproj b/common/build/Utilities/utilities.vcproj
index 993fef8fac..6d7bf5ee1f 100644
--- a/common/build/Utilities/utilities.vcproj
+++ b/common/build/Utilities/utilities.vcproj
@@ -276,7 +276,7 @@
>
+
+
@@ -453,6 +457,10 @@
RelativePath="..\..\include\Utilities\SafeArray.inl"
>
+
+
diff --git a/common/include/Utilities/Assertions.h b/common/include/Utilities/Assertions.h
index b70bf2bcb1..d08fc8510c 100644
--- a/common/include/Utilities/Assertions.h
+++ b/common/include/Utilities/Assertions.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 );
diff --git a/common/include/Utilities/Dependencies.h b/common/include/Utilities/Dependencies.h
index 82345dc354..98b3e7e8a9 100644
--- a/common/include/Utilities/Dependencies.h
+++ b/common/include/Utilities/Dependencies.h
@@ -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
@@ -174,6 +185,9 @@ extern const wxChar* __fastcall pxExpandMsg( const wxChar* key, const wxChar* en
extern const wxChar* __fastcall pxGetTranslation( const wxChar* message );
extern bool pxIsEnglish( int id );
+extern wxString fromUTF8( const char* src );
+extern wxString fromAscii( const char* src );
+
// --------------------------------------------------------------------------------------
// wxLt(x) [macro]
// --------------------------------------------------------------------------------------
@@ -220,3 +234,6 @@ extern bool pxIsEnglish( int id );
#define pxE(key, english) pxExpandMsg( wxT(key), english )
#include "Utilities/Assertions.h"
+#include "Utilities/Exceptions.h"
+#include "Utilities/ScopedPtr.h"
+#include "Utilities/ScopedAlloc.h"
diff --git a/common/include/Utilities/Exceptions.h b/common/include/Utilities/Exceptions.h
index 6d103504c1..ca73656774 100644
--- a/common/include/Utilities/Exceptions.h
+++ b/common/include/Utilities/Exceptions.h
@@ -15,8 +15,8 @@
#pragma once
-#include "Dependencies.h"
-#include "StringHelpers.h"
+#include "Assertions.h"
+#include "ScopedPtr.h"
// --------------------------------------------------------------------------------------
// DESTRUCTOR_CATCHALL - safe destructor helper
@@ -43,6 +43,7 @@
namespace Exception
{
int MakeNewType();
+ BaseException* FromErrno( const wxString& streamname, int errcode );
// --------------------------------------------------------------------------------------
// BaseException
@@ -92,6 +93,8 @@ namespace Exception
virtual BaseException* Clone() const=0;
};
+ typedef ScopedPtr ScopedExcept;
+
// --------------------------------------------------------------------------------------
// Ps2Generic Exception
// --------------------------------------------------------------------------------------
@@ -337,3 +340,4 @@ public: \
}
using Exception::BaseException;
+using Exception::ScopedExcept;
diff --git a/common/include/Utilities/FixedPointTypes.h b/common/include/Utilities/FixedPointTypes.h
index 71c4519112..58f2eb6e1b 100644
--- a/common/include/Utilities/FixedPointTypes.h
+++ b/common/include/Utilities/FixedPointTypes.h
@@ -16,7 +16,6 @@
#pragma once
#include "Dependencies.h"
-#include "Exceptions.h"
template< int Precision >
struct FixedInt
diff --git a/common/include/Utilities/General.h b/common/include/Utilities/General.h
index 7b78ec9382..4cba92cd50 100644
--- a/common/include/Utilities/General.h
+++ b/common/include/Utilities/General.h
@@ -167,20 +167,12 @@ 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();
extern u64 GetCPUTicks();
extern wxString GetOSVersionString();
-
-extern void* __fastcall pcsx2_aligned_malloc(size_t size, size_t align);
-extern void* __fastcall pcsx2_aligned_realloc(void* handle, size_t size, size_t align);
-extern void pcsx2_aligned_free(void* pmem);
-
-// aligned_malloc: Implement/declare linux equivalents here!
-#if !defined(_MSC_VER) && !defined(HAVE_ALIGNED_MALLOC)
-# define _aligned_malloc pcsx2_aligned_malloc
-# define _aligned_free pcsx2_aligned_free
-# define _aligned_realloc pcsx2_aligned_realloc
-#endif
diff --git a/common/include/Utilities/SafeArray.h b/common/include/Utilities/SafeArray.h
index 2c90d955b8..6e6d940b97 100644
--- a/common/include/Utilities/SafeArray.h
+++ b/common/include/Utilities/SafeArray.h
@@ -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();
diff --git a/common/include/Utilities/SafeArray.inl b/common/include/Utilities/SafeArray.inl
index d0ea200d06..259651176f 100644
--- a/common/include/Utilities/SafeArray.inl
+++ b/common/include/Utilities/SafeArray.inl
@@ -90,6 +90,13 @@ void SafeArray::Dispose()
safe_free( m_ptr );
}
+template< typename T >
+T* SafeArray::_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::SafeList( int initialSize, const wxChar* name )
}
+template< typename T >
+T* SafeList::_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 >
diff --git a/common/include/Utilities/ScopedAlloc.h b/common/include/Utilities/ScopedAlloc.h
new file mode 100644
index 0000000000..8aa2084e96
--- /dev/null
+++ b/common/include/Utilities/ScopedAlloc.h
@@ -0,0 +1,233 @@
+/* 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 .
+ */
+
+#pragma once
+
+#include "Exceptions.h"
+
+// 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 ))
+
+
+extern void* __fastcall pcsx2_aligned_malloc(size_t size, size_t align);
+extern void* __fastcall pcsx2_aligned_realloc(void* handle, size_t size, size_t align);
+extern void pcsx2_aligned_free(void* pmem);
+
+// aligned_malloc: Implement/declare linux equivalents here!
+#if !defined(_MSC_VER) && !defined(HAVE_ALIGNED_MALLOC)
+# define _aligned_malloc pcsx2_aligned_malloc
+# define _aligned_free pcsx2_aligned_free
+# define _aligned_realloc pcsx2_aligned_realloc
+#endif
+
+
+// --------------------------------------------------------------------------------------
+// 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
+{
+public:
+ ScopedAlloc( size_t size=0 ) : BaseScopedAlloc()
+ {
+ Alloc(size);
+ }
+
+ virtual ~ScopedAlloc() throw()
+ {
+ Alloc(0);
+ }
+
+ virtual void Alloc( size_t newsize )
+ {
+ safe_free(this->m_buffer);
+ this->m_size = newsize;
+ if (!this->m_size) return;
+
+ this->m_buffer = (T*)malloc( this->m_size * sizeof(T) );
+ if (!this->m_buffer)
+ throw Exception::OutOfMemory("ScopedAlloc");
+ }
+
+ virtual void Resize( size_t newsize )
+ {
+ this->m_size = newsize;
+ this->m_buffer = (T*)realloc(this->m_buffer * sizeof(T), newsize);
+
+ if (!this->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
+{
+public:
+ ScopedAlignedAlloc( size_t size=0 ) : BaseScopedAlloc()
+ {
+ Alloc(size);
+ }
+
+ virtual ~ScopedAlignedAlloc() throw()
+ {
+ Alloc(0);
+ }
+
+ virtual void Alloc( size_t newsize )
+ {
+ safe_aligned_free(this->m_buffer);
+ this->m_size = newsize;
+ if (!this->m_size) return;
+
+ this->m_buffer = (T*)_aligned_malloc( this->m_size * sizeof(T), align );
+ if (!this->m_buffer)
+ throw Exception::OutOfMemory(L"ScopedAlignedAlloc");
+ }
+
+ virtual void Resize( size_t newsize )
+ {
+ this->m_size = newsize;
+ this->m_buffer = (T*)_aligned_realloc(this->m_buffer, newsize * sizeof(T), align);
+
+ if (!this->m_buffer)
+ throw Exception::OutOfMemory(L"ScopedAlignedAlloc::Resize");
+ }
+};
diff --git a/common/include/Utilities/ScopedPtr.h b/common/include/Utilities/ScopedPtr.h
index f2dd48dc1e..76a0b510db 100644
--- a/common/include/Utilities/ScopedPtr.h
+++ b/common/include/Utilities/ScopedPtr.h
@@ -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;
}
diff --git a/common/include/Utilities/StringHelpers.h b/common/include/Utilities/StringHelpers.h
index 9a1d148059..1c40692991 100644
--- a/common/include/Utilities/StringHelpers.h
+++ b/common/include/Utilities/StringHelpers.h
@@ -17,6 +17,7 @@
#include "Dependencies.h"
#include "SafeArray.h"
+#include "ScopedAlloc.h"
#include
@@ -63,9 +64,6 @@ public:
extern void px_fputs( FILE* fp, const char* src );
-extern wxString fromUTF8( const char* src );
-extern wxString fromAscii( const char* src );
-
// wxWidgets lacks one of its own...
extern const wxRect wxDefaultRect;
@@ -128,7 +126,6 @@ struct ParsedAssignmentString
// accepts Ascii/UTF8 only.
//
-
// --------------------------------------------------------------------------------------
// FastFormatAscii
// --------------------------------------------------------------------------------------
@@ -136,8 +133,9 @@ struct ParsedAssignmentString
class FastFormatAscii
{
protected:
- SafeArray* m_dest;
+ ScopedAlignedAlloc* m_dest;
bool m_deleteDest;
+ uint m_Length;
public:
FastFormatAscii();
@@ -147,12 +145,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 +178,9 @@ public:
class FastFormatUnicode
{
protected:
- SafeArray* m_dest;
+ ScopedAlignedAlloc* m_dest;
bool m_deleteDest;
+ uint m_Length;
public:
FastFormatUnicode();
@@ -175,16 +193,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)
diff --git a/common/include/Utilities/pxEvents.h b/common/include/Utilities/pxEvents.h
index 04dc516564..c4c1c2f9fd 100644
--- a/common/include/Utilities/pxEvents.h
+++ b/common/include/Utilities/pxEvents.h
@@ -35,7 +35,7 @@ class SynchronousActionState
protected:
bool m_posted;
Threading::Semaphore m_sema;
- ScopedPtr m_exception;
+ ScopedExcept m_exception;
public:
sptr return_value;
diff --git a/common/include/Utilities/pxStreams.h b/common/include/Utilities/pxStreams.h
new file mode 100644
index 0000000000..1eb07714d1
--- /dev/null
+++ b/common/include/Utilities/pxStreams.h
@@ -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 .
+ */
+
+// --------------------------------------------------------------------------------------
+// pxStreamWriter
+// --------------------------------------------------------------------------------------
+class pxStreamWriter
+{
+ DeclareNoncopyableObject(pxStreamWriter);
+
+protected:
+ wxString m_filename;
+ ScopedPtr m_outstream;
+
+public:
+ pxStreamWriter(const wxString& filename, ScopedPtr& 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& 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 m_stream;
+
+public:
+ pxStreamReader(const wxString& filename, ScopedPtr& input);
+ pxStreamReader(const wxString& filename, wxInputStream* input);
+
+ virtual ~pxStreamReader() throw() {}
+ virtual void Read( void* dest, size_t size );
+
+ void SetStream( const wxString& filename, ScopedPtr& 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) );
+ }
+};
diff --git a/common/src/Utilities/CMakeLists.txt b/common/src/Utilities/CMakeLists.txt
index a219b45a56..72c51a5a53 100644
--- a/common/src/Utilities/CMakeLists.txt
+++ b/common/src/Utilities/CMakeLists.txt
@@ -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
diff --git a/common/src/Utilities/Exceptions.cpp b/common/src/Utilities/Exceptions.cpp
index 11b4ee1783..893365f039 100644
--- a/common/src/Utilities/Exceptions.cpp
+++ b/common/src/Utilities/Exceptions.cpp
@@ -169,24 +169,20 @@ 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()),
+ SetDiagMsg( 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()
) );
-
- SetDiagMsg( msg );
}
Exception::RuntimeError::RuntimeError( const std::exception& ex, const wxString& prefix )
{
IsSilent = false;
- const wxString msg( wxsFormat( L"STL Exception%s: %s",
- (prefix.IsEmpty() ? prefix.c_str() : wxsFormat(L" (%s)", prefix.c_str()).c_str()),
+ SetDiagMsg( pxsFmt( L"STL Exception%s: %s",
+ (prefix.IsEmpty() ? prefix.c_str() : pxsFmt(L" (%s)", prefix.c_str()).c_str()),
fromUTF8( ex.what() ).c_str()
) );
-
- SetDiagMsg( msg );
}
// --------------------------------------------------------------------------------------
@@ -207,7 +203,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 +220,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 +230,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, int 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 ));
+ }
+}
diff --git a/common/src/Utilities/FastFormatString.cpp b/common/src/Utilities/FastFormatString.cpp
index 24085fbc44..175a8ae27c 100644
--- a/common/src/Utilities/FastFormatString.cpp
+++ b/common/src/Utilities/FastFormatString.cpp
@@ -15,6 +15,7 @@
#include "PrecompiledHeader.h"
#include "Threading.h"
+
#include "TlsVariable.inl"
#include "SafeArray.inl"
@@ -36,6 +37,8 @@ template class SafeAlignedArray;
// system deadlock.
static const int MaxFormattedStringLength = 0x80000;
+typedef ScopedAlignedAlloc CharBufferType;
+
// --------------------------------------------------------------------------------------
// FastFormatBuffers
// --------------------------------------------------------------------------------------
@@ -50,7 +53,7 @@ class FastFormatBuffers
protected:
typedef char CharType;
- typedef SafeAlignedArray BufferType;
+ typedef CharBufferType BufferType;
static const uint BufferCount = 4;
@@ -66,10 +69,7 @@ public:
for (uint i=0; i > m_buffer_tls(buffer_is_avail);
-static __ri void format_that_ascii_mess( SafeArray& buffer, uint writepos, const char* fmt, va_list argptr )
+//static __ri void format_that_ascii_mess( SafeArray& 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& 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& 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& 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* GetFormatBuffer( bool& deleteDest )
+CharBufferType* GetFormatBuffer( bool& deleteDest )
{
deleteDest = false;
if (buffer_is_avail)
@@ -220,7 +225,8 @@ SafeArray* GetFormatBuffer( bool& deleteDest )
}
deleteDest = true;
- return new SafeArray(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; iGetPtr();
+ for ( uint i=0; i ptr( const_cast(this)->m_except.DetachPtr() );
+ ScopedExcept ptr( const_cast(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()
diff --git a/common/src/Utilities/pxStreams.cpp b/common/src/Utilities/pxStreams.cpp
new file mode 100644
index 0000000000..3d960a430c
--- /dev/null
+++ b/common/src/Utilities/pxStreams.cpp
@@ -0,0 +1,205 @@
+/* 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 .
+ */
+
+#include "PrecompiledHeader.h"
+#include "wxBaseTools.h"
+#include "pxStreams.h"
+
+#include
+
+#include
+
+// --------------------------------------------------------------------------------------
+// pxStreamReader (implementations)
+// --------------------------------------------------------------------------------------
+// Interface for reading data from a gzip stream.
+//
+
+pxStreamReader::pxStreamReader(const wxString& filename, ScopedPtr& 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& 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& 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& 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());
+}
diff --git a/common/src/Utilities/pxTextStream.cpp b/common/src/Utilities/pxTextStream.cpp
deleted file mode 100644
index a380e06155..0000000000
--- a/common/src/Utilities/pxTextStream.cpp
+++ /dev/null
@@ -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 .
- */
-
-#include "PrecompiledHeader.h"
-#include "wxBaseTools.h"
-#include
-
-
-// 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());
-}
diff --git a/common/src/Utilities/wxAppWithHelpers.cpp b/common/src/Utilities/wxAppWithHelpers.cpp
index aee33ccd3c..8a1b28f9ac 100644
--- a/common/src/Utilities/wxAppWithHelpers.cpp
+++ b/common/src/Utilities/wxAppWithHelpers.cpp
@@ -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 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 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 deleteMe( m_except );
+ ScopedExcept deleteMe( m_except );
if( deleteMe ) deleteMe->Rethrow();
}
diff --git a/pcsx2/CDVD/CDVD.h b/pcsx2/CDVD/CDVD.h
index 7ff20ab458..ca5ee28108 100644
--- a/pcsx2/CDVD/CDVD.h
+++ b/pcsx2/CDVD/CDVD.h
@@ -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;
diff --git a/pcsx2/CDVD/CDVDaccess.cpp b/pcsx2/CDVD/CDVDaccess.cpp
index 5ffa4dce96..ca39f2f876 100644
--- a/pcsx2/CDVD/CDVDaccess.cpp
+++ b/pcsx2/CDVD/CDVDaccess.cpp
@@ -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;
diff --git a/pcsx2/CDVD/CDVDisoReader.cpp b/pcsx2/CDVD/CDVDisoReader.cpp
index 1dd544e896..d9a22afcba 100644
--- a/pcsx2/CDVD/CDVDisoReader.cpp
+++ b/pcsx2/CDVD/CDVDisoReader.cpp
@@ -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;
}
diff --git a/pcsx2/CDVD/IsoFS/IsoFS.cpp b/pcsx2/CDVD/IsoFS/IsoFS.cpp
index 8abe5f6716..48c98de1c3 100644
--- a/pcsx2/CDVD/IsoFS/IsoFS.cpp
+++ b/pcsx2/CDVD/IsoFS/IsoFS.cpp
@@ -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() );
diff --git a/pcsx2/CDVD/IsoFileFormats.cpp b/pcsx2/CDVD/IsoFileFormats.cpp
index 81daf56ad0..140913b9a2 100644
--- a/pcsx2/CDVD/IsoFileFormats.cpp
+++ b/pcsx2/CDVD/IsoFileFormats.cpp
@@ -16,400 +16,540 @@
#include "PrecompiledHeader.h"
#include "IopCommon.h"
-
-#include
-#include
-#include
-
#include "IsoFileFormats.h"
-static bool detect(isoFile *iso)
+#include
+
+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();
+ static const wxFileOffset datalen = flen - BlockDumpHeaderSize;
+ pxAssert( (datalen % (m_blocksize + 4)) == 0);
- for (int i = 0; i < iso->dtablesize; i++)
+ m_dtablesize = datalen / (m_blocksize + 4);
+ m_dtable = new u32[m_dtablesize];
+
+ 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 );
+ return;
}
- 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)
+{
+ // Find and ignore blocks that have already been dumped:
+ for (uint i=0; i( 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."));
+
+ if (!(m_flags & ISOFLAGS_BLOCKDUMP_V2))
+ {
+ 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; iIsOk();
+}
+
+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 );
-}
-
diff --git a/pcsx2/CDVD/IsoFileFormats.h b/pcsx2/CDVD/IsoFileFormats.h
index e0a5b134d9..9263d30a26 100644
--- a/pcsx2/CDVD/IsoFileFormats.h
+++ b/pcsx2/CDVD/IsoFileFormats.h
@@ -13,11 +13,11 @@
* If not, see .
*/
-#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 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 m_dtable;
+ int m_dtablesize;
+
+ ScopedPtr m_outstream;
+
+ // Currently unused internal buffer (it was used for compressed
+ // iso support, before it was removed).
+ //ScopedArray 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__ */
diff --git a/pcsx2/CDVD/IsoFileTools.cpp b/pcsx2/CDVD/IsoFileTools.cpp
deleted file mode 100644
index 3c0be3bdd8..0000000000
--- a/pcsx2/CDVD/IsoFileTools.cpp
+++ /dev/null
@@ -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 .
- */
-
-#include "PrecompiledHeader.h"
-#include "IsoFileTools.h"
-
-#ifdef _WIN32
-# include
-
-
-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
diff --git a/pcsx2/CDVD/IsoFileTools.h b/pcsx2/CDVD/IsoFileTools.h
deleted file mode 100644
index 5c4469469c..0000000000
--- a/pcsx2/CDVD/IsoFileTools.h
+++ /dev/null
@@ -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 .
- */
-
-#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
-#include
-#include
-
-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);
-
diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt
index d3f9f9d370..efa1d1cb37 100644
--- a/pcsx2/CMakeLists.txt
+++ b/pcsx2/CMakeLists.txt
@@ -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
diff --git a/pcsx2/COP0.cpp b/pcsx2/COP0.cpp
index ed8b5620e3..455a8054e6 100644
--- a/pcsx2/COP0.cpp
+++ b/pcsx2/COP0.cpp
@@ -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();
diff --git a/pcsx2/Linux/pcsx2.cbp b/pcsx2/Linux/pcsx2.cbp
index a0a92cd286..56d067c1d6 100644
--- a/pcsx2/Linux/pcsx2.cbp
+++ b/pcsx2/Linux/pcsx2.cbp
@@ -249,8 +249,6 @@
-
-
diff --git a/pcsx2/PrecompiledHeader.h b/pcsx2/PrecompiledHeader.h
index 600039b406..c8bdcffc83 100644
--- a/pcsx2/PrecompiledHeader.h
+++ b/pcsx2/PrecompiledHeader.h
@@ -88,13 +88,11 @@ typedef int BOOL;
#include "Pcsx2Defs.h"
#include "i18n.h"
-#include "Utilities/Assertions.h"
#include "Utilities/FixedPointTypes.h"
#include "Utilities/wxBaseTools.h"
#include "Utilities/ScopedPtr.h"
#include "Utilities/Path.h"
#include "Utilities/Console.h"
-#include "Utilities/Exceptions.h"
#include "Utilities/MemcpyFast.h"
#include "Utilities/General.h"
#include "x86emitter/tools.h"
diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp
index faaee3531f..93779a3d99 100644
--- a/pcsx2/System.cpp
+++ b/pcsx2/System.cpp
@@ -163,7 +163,7 @@ class CpuInitializer
{
public:
ScopedPtr MyCpu;
- ScopedPtr 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()
{
diff --git a/pcsx2/System.h b/pcsx2/System.h
index b8d9e17e41..1df237c4ba 100644
--- a/pcsx2/System.h
+++ b/pcsx2/System.h
@@ -43,8 +43,8 @@ protected:
class SysCpuProviderPack
{
protected:
- ScopedPtr m_RecExceptionEE;
- ScopedPtr m_RecExceptionIOP;
+ ScopedExcept m_RecExceptionEE;
+ ScopedExcept m_RecExceptionIOP;
public:
ScopedPtr CpuProviders;
diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp
index 579ef3a1d1..a19e23f824 100644
--- a/pcsx2/gui/AppMain.cpp
+++ b/pcsx2/gui/AppMain.cpp
@@ -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 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 deleteMe( m_except );
+ ScopedExcept deleteMe( m_except );
m_except = NULL;
if( !HandlePluginError( *deleteMe ) )
diff --git a/pcsx2/gui/Dialogs/ConfirmationDialogs.cpp b/pcsx2/gui/Dialogs/ConfirmationDialogs.cpp
index 9a664d4043..fb95c87aaf 100644
--- a/pcsx2/gui/Dialogs/ConfirmationDialogs.cpp
+++ b/pcsx2/gui/Dialogs/ConfirmationDialogs.cpp
@@ -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"," );
diff --git a/pcsx2/gui/IsoDropTarget.cpp b/pcsx2/gui/IsoDropTarget.cpp
index 1b320da4a6..dcc740cdc3 100644
--- a/pcsx2/gui/IsoDropTarget.cpp
+++ b/pcsx2/gui/IsoDropTarget.cpp
@@ -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;
}
diff --git a/pcsx2/gui/MainMenuClicks.cpp b/pcsx2/gui/MainMenuClicks.cpp
index 37890b7e4d..53458bb244 100644
--- a/pcsx2/gui/MainMenuClicks.cpp
+++ b/pcsx2/gui/MainMenuClicks.cpp
@@ -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 (*.*)"));
diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
index 470d58976c..1affaf6adf 100644
--- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
+++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
@@ -1249,14 +1249,6 @@
RelativePath="..\..\CDVD\CDVDisoReader.h"
>
-
-
-
-
m_cpuException;
- static ScopedPtr m_Exception;
+ static ScopedExcept m_Exception;
#else
# define SETJMP_CODE(x)
#endif