mirror of https://github.com/PCSX2/pcsx2.git
CDVD: merging and removing remnants of plugin
This commit is contained in:
parent
a70bfbdaa9
commit
029461c5ae
|
@ -60,8 +60,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bin2cpp", "tools\bin2cpp\bi
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libjpeg", "3rdparty\libjpeg\libjpeg.vcxproj", "{BC236261-77E8-4567-8D09-45CD02965EB6}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdvdGigaherz", "plugins\cdvdGigaherz\src\Windows\cdvdGigaherz.vcxproj", "{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "portaudio", "3rdparty\portaudio\build\msvc\portaudio.vcxproj", "{0A18A071-125E-442F-AFF7-A3F68ABECF99}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DEV9ghzdrk", "plugins\dev9ghzdrk\Win32\DEV9ghzdrk.vcxproj", "{BBE4E5FB-530A-4D18-A633-35AF0577B7F3}"
|
||||
|
@ -360,26 +358,6 @@ Global
|
|||
{BC236261-77E8-4567-8D09-45CD02965EB6}.Release|Win32.Build.0 = Release|Win32
|
||||
{BC236261-77E8-4567-8D09-45CD02965EB6}.Release|x64.ActiveCfg = Release|x64
|
||||
{BC236261-77E8-4567-8D09-45CD02965EB6}.Release|x64.Build.0 = Release|x64
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Debug|x64.Build.0 = Debug|x64
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Devel|Win32.ActiveCfg = Release|Win32
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Devel|Win32.Build.0 = Release|Win32
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Devel|x64.ActiveCfg = Release|x64
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Devel|x64.Build.0 = Release|x64
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release AVX2|Win32.ActiveCfg = Release|Win32
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release AVX2|Win32.Build.0 = Release|Win32
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release AVX2|x64.ActiveCfg = Release|x64
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release AVX2|x64.Build.0 = Release|x64
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release SSE4|Win32.ActiveCfg = Release|Win32
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release SSE4|Win32.Build.0 = Release|Win32
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release SSE4|x64.ActiveCfg = Release|x64
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release SSE4|x64.Build.0 = Release|x64
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release|Win32.Build.0 = Release|Win32
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release|x64.ActiveCfg = Release|x64
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}.Release|x64.Build.0 = Release|x64
|
||||
{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.ActiveCfg = Debug (NO ASIO)|Win32
|
||||
{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.Build.0 = Debug (NO ASIO)|Win32
|
||||
{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.ActiveCfg = Debug (NO ASIO)|x64
|
||||
|
@ -620,7 +598,6 @@ Global
|
|||
{4639972E-424E-4E13-8B07-CA403C481346} = {88F517F9-CE1C-4005-9BDF-4481FEB55053}
|
||||
{677B7D11-D5E1-40B3-88B1-9A4DF83D2213} = {2D6F0A62-A247-4CCF-947F-FCD54BE16103}
|
||||
{BC236261-77E8-4567-8D09-45CD02965EB6} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
{5CF88D5F-64DD-4EDC-9F1A-436BD502940A} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF}
|
||||
{0A18A071-125E-442F-AFF7-A3F68ABECF99} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
{BBE4E5FB-530A-4D18-A633-35AF0577B7F3} = {7A407562-D70F-4F0A-9D3E-B32506416003}
|
||||
{7A407562-D70F-4F0A-9D3E-B32506416003} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF}
|
||||
|
@ -635,6 +612,10 @@ Global
|
|||
{12728250-16EC-4DC6-94D7-E21DD88947F8} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
<<<<<<< HEAD
|
||||
SolutionGuid = {0BC474EA-3628-45D3-9DBC-E22D0B7E0F77}
|
||||
=======
|
||||
SolutionGuid = {E0DF661E-BE9A-4467-A034-16AA535A1CB5}
|
||||
>>>>>>> CDVD: merging and removing remnants of plugin
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -82,26 +82,6 @@ endif()
|
|||
# be build.
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
#---------------------------------------
|
||||
# CDVDnull
|
||||
#---------------------------------------
|
||||
if(GTKn_FOUND)
|
||||
set(CDVDnull TRUE)
|
||||
endif()
|
||||
#---------------------------------------
|
||||
|
||||
#---------------------------------------
|
||||
# cdvdGigaherz
|
||||
#---------------------------------------
|
||||
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/plugins/cdvdGigaherz" OR NOT Linux)
|
||||
set(cdvdGigaherz FALSE)
|
||||
elseif(Linux AND GTKn_FOUND AND LIBUDEV_FOUND)
|
||||
set(cdvdGigaherz TRUE)
|
||||
else()
|
||||
set(cdvdGigaherz FALSE)
|
||||
print_dep("Skip build of cdvdGigaherz: missing dependencies" "${msg_dep_cdvdgiga}")
|
||||
endif()
|
||||
#---------------------------------------
|
||||
|
||||
#---------------------------------------
|
||||
# dev9null
|
||||
|
|
|
@ -74,8 +74,7 @@ typedef struct _keyEvent
|
|||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \
|
||||
defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \
|
||||
defined(USBdefs) || defined(FWdefs)
|
||||
defined(SPU2defs) || defined(DEV9defs) || defined(USBdefs) || defined(FWdefs)
|
||||
#define COMMONdefs
|
||||
#endif
|
||||
|
||||
|
@ -83,7 +82,6 @@ typedef struct _keyEvent
|
|||
#define PS2E_LT_GS 0x01
|
||||
#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=-
|
||||
#define PS2E_LT_SPU2 0x04
|
||||
#define PS2E_LT_CDVD 0x08
|
||||
#define PS2E_LT_DEV9 0x10
|
||||
#define PS2E_LT_USB 0x20
|
||||
#define PS2E_LT_FW 0x40
|
||||
|
@ -93,7 +91,6 @@ typedef struct _keyEvent
|
|||
#define PS2E_GS_VERSION 0x0006
|
||||
#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=-
|
||||
#define PS2E_SPU2_VERSION 0x0005
|
||||
#define PS2E_CDVD_VERSION 0x0005
|
||||
#define PS2E_DEV9_VERSION 0x0003
|
||||
#define PS2E_USB_VERSION 0x0003
|
||||
#define PS2E_FW_VERSION 0x0002
|
||||
|
@ -131,69 +128,6 @@ typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8) ? 1 : -1];
|
|||
|
||||
typedef int(CALLBACK *SIOchangeSlotCB)(int slot);
|
||||
|
||||
typedef struct _cdvdSubQ
|
||||
{
|
||||
u8 ctrl : 4; // control and mode bits
|
||||
u8 mode : 4; // control and mode bits
|
||||
u8 trackNum; // current track number (1 to 99)
|
||||
u8 trackIndex; // current index within track (0 to 99)
|
||||
u8 trackM; // current minute location on the disc (BCD encoded)
|
||||
u8 trackS; // current sector location on the disc (BCD encoded)
|
||||
u8 trackF; // current frame location on the disc (BCD encoded)
|
||||
u8 pad; // unused
|
||||
u8 discM; // current minute offset from first track (BCD encoded)
|
||||
u8 discS; // current sector offset from first track (BCD encoded)
|
||||
u8 discF; // current frame offset from first track (BCD encoded)
|
||||
} cdvdSubQ;
|
||||
|
||||
typedef struct _cdvdTD
|
||||
{ // NOT bcd coded
|
||||
u32 lsn;
|
||||
u8 type;
|
||||
} cdvdTD;
|
||||
|
||||
typedef struct _cdvdTN
|
||||
{
|
||||
u8 strack; //number of the first track (usually 1)
|
||||
u8 etrack; //number of the last track
|
||||
} cdvdTN;
|
||||
|
||||
// CDVDreadTrack mode values:
|
||||
#define CDVD_MODE_2352 0 // full 2352 bytes
|
||||
#define CDVD_MODE_2340 1 // skip sync (12) bytes
|
||||
#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes
|
||||
#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes
|
||||
#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq
|
||||
|
||||
// CDVDgetDiskType returns:
|
||||
#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc
|
||||
#define CDVD_TYPE_DVDV 0xfe // DVD Video
|
||||
#define CDVD_TYPE_CDDA 0xfd // Audio CD
|
||||
#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD
|
||||
#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio)
|
||||
#define CDVD_TYPE_PS2CD 0x12 // PS2 CD
|
||||
#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio)
|
||||
#define CDVD_TYPE_PSCD 0x10 // PS CD
|
||||
#define CDVD_TYPE_UNKNOWN 0x05 // Unknown
|
||||
#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided
|
||||
#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided
|
||||
#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd
|
||||
#define CDVD_TYPE_DETCT 0x01 // Detecting
|
||||
#define CDVD_TYPE_NODISC 0x00 // No Disc
|
||||
|
||||
// CDVDgetTrayStatus returns:
|
||||
#define CDVD_TRAY_CLOSE 0x00
|
||||
#define CDVD_TRAY_OPEN 0x01
|
||||
|
||||
// cdvdTD.type (track types for cds)
|
||||
#define CDVD_AUDIO_TRACK 0x01
|
||||
#define CDVD_MODE1_TRACK 0x41
|
||||
#define CDVD_MODE2_TRACK 0x61
|
||||
|
||||
#define CDVD_AUDIO_MASK 0x00
|
||||
#define CDVD_DATA_MASK 0x40
|
||||
// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel)
|
||||
|
||||
typedef void (*DEV9callback)(int cycles);
|
||||
typedef int (*DEV9handler)(void);
|
||||
|
||||
|
@ -367,55 +301,6 @@ s32 CALLBACK SPU2test();
|
|||
|
||||
#endif
|
||||
|
||||
/* CDVD plugin API */
|
||||
|
||||
// if this file is included with this define
|
||||
// the next api will not be skipped by the compiler
|
||||
#if defined(CDVDdefs) || defined(BUILTIN_CDVD_PLUGIN)
|
||||
|
||||
// basic funcs
|
||||
|
||||
s32 CALLBACK CDVDinit();
|
||||
s32 CALLBACK CDVDopen(const char *pTitleFilename);
|
||||
void CALLBACK CDVDclose();
|
||||
void CALLBACK CDVDshutdown();
|
||||
void CALLBACK CDVDsetSettingsDir(const char *dir);
|
||||
void CALLBACK CDVDsetLogDir(const char *dir);
|
||||
|
||||
s32 CALLBACK CDVDreadTrack(u32 lsn, int mode);
|
||||
|
||||
// return can be NULL (for async modes)
|
||||
u8 *CALLBACK CDVDgetBuffer();
|
||||
|
||||
s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ *subq); //read subq from disc (only cds have subq data)
|
||||
s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information
|
||||
s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type
|
||||
s32 CALLBACK CDVDgetTOC(void *toc); //gets ps2 style toc from disc
|
||||
s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx
|
||||
s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx
|
||||
s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray
|
||||
s32 CALLBACK CDVDctrlTrayClose(); //close disc tray
|
||||
|
||||
// extended funcs
|
||||
|
||||
void CALLBACK CDVDconfigure();
|
||||
void CALLBACK CDVDabout();
|
||||
s32 CALLBACK CDVDtest();
|
||||
void CALLBACK CDVDnewDiskCB(void (*callback)());
|
||||
|
||||
// new funcs
|
||||
|
||||
// read a track directly
|
||||
s32 CALLBACK CDVDreadSector(u8 *buffer, u32 lsn, int mode);
|
||||
|
||||
// improved getBuffer
|
||||
s32 CALLBACK CDVDgetBuffer2(u8 *buffer);
|
||||
|
||||
// tool function
|
||||
s32 CALLBACK CDVDgetDualInfo(s32 *dualType, u32 *_layer1start);
|
||||
|
||||
#endif
|
||||
|
||||
/* DEV9 plugin API */
|
||||
|
||||
// if this file is included with this define
|
||||
|
@ -597,41 +482,6 @@ typedef void(CALLBACK *_SPU2setTimeStretcher)(short int enable);
|
|||
|
||||
typedef void(CALLBACK *_SPU2async)(u32 cycles);
|
||||
|
||||
|
||||
// CDVD
|
||||
// NOTE: The read/write functions CANNOT use XMM/MMX regs
|
||||
// If you want to use them, need to save and restore current ones
|
||||
typedef s32(CALLBACK *_CDVDopen)(const char *pTitleFilename);
|
||||
|
||||
// Initiates an asynchronous track read operation.
|
||||
// Returns -1 on error (invalid track)
|
||||
// Returns 0 on success.
|
||||
typedef s32(CALLBACK *_CDVDreadTrack)(u32 lsn, int mode);
|
||||
|
||||
// *OBSOLETE* returns a pointer to the buffer, or NULL if data hasn't finished
|
||||
// loading yet.
|
||||
typedef u8 *(CALLBACK *_CDVDgetBuffer)();
|
||||
|
||||
// Copies loaded data to the target buffer.
|
||||
// Returns -2 if the asynchronous read is still pending.
|
||||
// Returns -1 if the asyncronous read failed.
|
||||
// Returns 0 on success.
|
||||
typedef s32(CALLBACK *_CDVDgetBuffer2)(u8 *buffer);
|
||||
|
||||
typedef s32(CALLBACK *_CDVDreadSubQ)(u32 lsn, cdvdSubQ *subq);
|
||||
typedef s32(CALLBACK *_CDVDgetTN)(cdvdTN *Buffer);
|
||||
typedef s32(CALLBACK *_CDVDgetTD)(u8 Track, cdvdTD *Buffer);
|
||||
typedef s32(CALLBACK *_CDVDgetTOC)(void *toc);
|
||||
typedef s32(CALLBACK *_CDVDgetDiskType)();
|
||||
typedef s32(CALLBACK *_CDVDgetTrayStatus)();
|
||||
typedef s32(CALLBACK *_CDVDctrlTrayOpen)();
|
||||
typedef s32(CALLBACK *_CDVDctrlTrayClose)();
|
||||
typedef s32(CALLBACK *_CDVDreadSector)(u8 *buffer, u32 lsn, int mode);
|
||||
typedef s32(CALLBACK *_CDVDgetDualInfo)(s32 *dualType, u32 *_layer1start);
|
||||
|
||||
typedef void(CALLBACK *_CDVDnewDiskCB)(void (*callback)());
|
||||
|
||||
|
||||
// DEV9
|
||||
// NOTE: The read/write functions CANNOT use XMM/MMX regs
|
||||
// If you want to use them, need to save and restore current ones
|
||||
|
|
|
@ -178,7 +178,6 @@ enum PS2E_ComponentTypes {
|
|||
PS2E_TYPE_GS = 0,
|
||||
PS2E_TYPE_PAD,
|
||||
PS2E_TYPE_SPU2,
|
||||
PS2E_TYPE_CDVD,
|
||||
PS2E_TYPE_DEV9,
|
||||
PS2E_TYPE_USB,
|
||||
PS2E_TYPE_FW,
|
||||
|
@ -190,7 +189,6 @@ enum PluginLibVersion {
|
|||
PS2E_VER_GS = 0x1000,
|
||||
PS2E_VER_PAD = 0x1000,
|
||||
PS2E_VER_SPU2 = 0x1000,
|
||||
PS2E_VER_CDVD = 0x1000,
|
||||
PS2E_VER_DEV9 = 0x1000,
|
||||
PS2E_VER_USB = 0x1000,
|
||||
PS2E_VER_FW = 0x1000,
|
||||
|
|
|
@ -317,7 +317,7 @@ s32 cdvdWriteConfig(const u8* config)
|
|||
|
||||
static MutexRecursive Mutex_NewDiskCB;
|
||||
|
||||
// Sets ElfCRC to the CRC of the game bound to the CDVD plugin.
|
||||
// Sets ElfCRC to the CRC of the game bound to the CDVD source.
|
||||
static __fi ElfObject* loadElf( const wxString filename )
|
||||
{
|
||||
if (filename.StartsWith(L"host"))
|
||||
|
@ -625,7 +625,7 @@ void SaveStateBase::cdvdFreeze()
|
|||
|
||||
if (IsLoading())
|
||||
{
|
||||
// Make sure the Cdvd plugin has the expected track loaded into the buffer.
|
||||
// Make sure the Cdvd source has the expected track loaded into the buffer.
|
||||
// If cdvd.Readed is cleared it means we need to load the SeekToSector (ie, a
|
||||
// seek is in progress!)
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
|
||||
#include "IopCommon.h"
|
||||
#include "CDVD/CDVDaccess.h"
|
||||
#include "CDVDaccess.h"
|
||||
|
||||
#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
|
||||
#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
|
||||
|
|
|
@ -36,10 +36,11 @@
|
|||
#include "DebugTools/SymbolMap.h"
|
||||
#include "AppConfig.h"
|
||||
|
||||
CDVD_API* CDVD = NULL;
|
||||
|
||||
const wxChar* CDVD_SourceLabels[] =
|
||||
{
|
||||
L"ISO",
|
||||
L"Plugin",
|
||||
L"Disc",
|
||||
L"NoDisc",
|
||||
NULL
|
||||
|
@ -250,10 +251,13 @@ static void DetectDiskType()
|
|||
|
||||
int baseMediaType = CDVD->getDiskType();
|
||||
int mType = -1;
|
||||
|
||||
|
||||
// Paranoid mode: do not trust the plugin's detection system to work correctly.
|
||||
// (.. and there's no reason plugins should be doing their own detection anyway).
|
||||
|
||||
//TODO_CDVD We're not using CDVD plugins anymore but I believe both ISO and Disc use their own
|
||||
//detection system. Possible code reduction here
|
||||
|
||||
switch(baseMediaType)
|
||||
{
|
||||
#if 0
|
||||
|
@ -320,8 +324,6 @@ CDVD_SourceType CDVDsys_GetSourceType()
|
|||
|
||||
void CDVDsys_ChangeSource( CDVD_SourceType type )
|
||||
{
|
||||
GetCorePlugins().Close( PluginId_CDVD );
|
||||
|
||||
switch( m_CurrentSourceType = type )
|
||||
{
|
||||
case CDVD_SourceType::Iso:
|
||||
|
@ -336,10 +338,6 @@ void CDVDsys_ChangeSource( CDVD_SourceType type )
|
|||
CDVD = &CDVDapi_NoDisc;
|
||||
break;
|
||||
|
||||
case CDVD_SourceType::Plugin:
|
||||
CDVD = &CDVDapi_Plugin;
|
||||
break;
|
||||
|
||||
jNO_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
@ -359,13 +357,15 @@ bool DoCDVDopen()
|
|||
// question marks if the filename is another language.
|
||||
// Likely Fix: Force new versions of CDVD plugins to expect UTF8 instead.
|
||||
|
||||
//TODO_CDVD check if ISO and Disc use UTF8
|
||||
|
||||
auto CurrentSourceType = enum_cast(m_CurrentSourceType);
|
||||
int ret = CDVD->open( !m_SourceFilename[CurrentSourceType].IsEmpty() ?
|
||||
static_cast<const char*>(m_SourceFilename[CurrentSourceType].ToUTF8()) : (char*)NULL
|
||||
);
|
||||
|
||||
if( ret == -1 ) return false; // error! (handled by caller)
|
||||
if( ret == 1 ) throw Exception::CancelEvent(L"User canceled the CDVD plugin's open dialog.");
|
||||
//if( ret == 1 ) throw Exception::CancelEvent(L"User canceled the CDVD plugin's open dialog."); <--- TODO_CDVD is this still needed?
|
||||
|
||||
int cdtype = DoCDVDdetectDiskType();
|
||||
|
||||
|
@ -466,6 +466,7 @@ s32 DoCDVDreadTrack(u32 lsn, int mode)
|
|||
{
|
||||
CheckNullCDVD();
|
||||
|
||||
//TODO_CDVD I believe ISO and Disc use the new CDVDgetBuffer style
|
||||
// TEMP: until all the plugins use the new CDVDgetBuffer style
|
||||
switch (mode)
|
||||
{
|
||||
|
|
|
@ -15,12 +15,105 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Plugins.h"
|
||||
typedef struct _cdvdSubQ
|
||||
{
|
||||
u8 ctrl : 4; // control and mode bits
|
||||
u8 mode : 4; // control and mode bits
|
||||
u8 trackNum; // current track number (1 to 99)
|
||||
u8 trackIndex; // current index within track (0 to 99)
|
||||
u8 trackM; // current minute location on the disc (BCD encoded)
|
||||
u8 trackS; // current sector location on the disc (BCD encoded)
|
||||
u8 trackF; // current frame location on the disc (BCD encoded)
|
||||
u8 pad; // unused
|
||||
u8 discM; // current minute offset from first track (BCD encoded)
|
||||
u8 discS; // current sector offset from first track (BCD encoded)
|
||||
u8 discF; // current frame offset from first track (BCD encoded)
|
||||
} cdvdSubQ;
|
||||
|
||||
typedef struct _cdvdTD
|
||||
{ // NOT bcd coded
|
||||
u32 lsn;
|
||||
u8 type;
|
||||
} cdvdTD;
|
||||
|
||||
typedef struct _cdvdTN
|
||||
{
|
||||
u8 strack; //number of the first track (usually 1)
|
||||
u8 etrack; //number of the last track
|
||||
} cdvdTN;
|
||||
|
||||
// CDVDreadTrack mode values:
|
||||
#define CDVD_MODE_2352 0 // full 2352 bytes
|
||||
#define CDVD_MODE_2340 1 // skip sync (12) bytes
|
||||
#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes
|
||||
#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes
|
||||
#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq
|
||||
|
||||
// CDVDgetDiskType returns:
|
||||
#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc
|
||||
#define CDVD_TYPE_DVDV 0xfe // DVD Video
|
||||
#define CDVD_TYPE_CDDA 0xfd // Audio CD
|
||||
#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD
|
||||
#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio)
|
||||
#define CDVD_TYPE_PS2CD 0x12 // PS2 CD
|
||||
#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio)
|
||||
#define CDVD_TYPE_PSCD 0x10 // PS CD
|
||||
#define CDVD_TYPE_UNKNOWN 0x05 // Unknown
|
||||
#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided
|
||||
#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided
|
||||
#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd
|
||||
#define CDVD_TYPE_DETCT 0x01 // Detecting
|
||||
#define CDVD_TYPE_NODISC 0x00 // No Disc
|
||||
|
||||
// CDVDgetTrayStatus returns:
|
||||
#define CDVD_TRAY_CLOSE 0x00
|
||||
#define CDVD_TRAY_OPEN 0x01
|
||||
|
||||
// cdvdTD.type (track types for cds)
|
||||
#define CDVD_AUDIO_TRACK 0x01
|
||||
#define CDVD_MODE1_TRACK 0x41
|
||||
#define CDVD_MODE2_TRACK 0x61
|
||||
|
||||
#define CDVD_AUDIO_MASK 0x00
|
||||
#define CDVD_DATA_MASK 0x40
|
||||
// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel)
|
||||
|
||||
// CDVD
|
||||
// NOTE: The read/write functions CANNOT use XMM/MMX regs
|
||||
// If you want to use them, need to save and restore current ones
|
||||
typedef s32(CALLBACK* _CDVDopen)(const char* pTitleFilename);
|
||||
|
||||
// Initiates an asynchronous track read operation.
|
||||
// Returns -1 on error (invalid track)
|
||||
// Returns 0 on success.
|
||||
typedef s32(CALLBACK* _CDVDreadTrack)(u32 lsn, int mode);
|
||||
|
||||
// *OBSOLETE* returns a pointer to the buffer, or NULL if data hasn't finished
|
||||
// loading yet.
|
||||
typedef u8* (CALLBACK* _CDVDgetBuffer)();
|
||||
|
||||
// Copies loaded data to the target buffer.
|
||||
// Returns -2 if the asynchronous read is still pending.
|
||||
// Returns -1 if the asyncronous read failed.
|
||||
// Returns 0 on success.
|
||||
typedef s32(CALLBACK* _CDVDgetBuffer2)(u8* buffer);
|
||||
|
||||
typedef s32(CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq);
|
||||
typedef s32(CALLBACK* _CDVDgetTN)(cdvdTN* Buffer);
|
||||
typedef s32(CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD* Buffer);
|
||||
typedef s32(CALLBACK* _CDVDgetTOC)(void* toc);
|
||||
typedef s32(CALLBACK* _CDVDgetDiskType)();
|
||||
typedef s32(CALLBACK* _CDVDgetTrayStatus)();
|
||||
typedef s32(CALLBACK* _CDVDctrlTrayOpen)();
|
||||
typedef s32(CALLBACK* _CDVDctrlTrayClose)();
|
||||
typedef s32(CALLBACK* _CDVDreadSector)(u8* buffer, u32 lsn, int mode);
|
||||
typedef s32(CALLBACK* _CDVDgetDualInfo)(s32* dualType, u32* _layer1start);
|
||||
|
||||
typedef void(CALLBACK* _CDVDnewDiskCB)(void (*callback)());
|
||||
|
||||
enum class CDVD_SourceType : uint8_t
|
||||
{
|
||||
Iso, // use built in ISO api
|
||||
Plugin, // use external plugin
|
||||
Disc, // use built in Disc api
|
||||
NoDisc, // use built in CDVDnull
|
||||
};
|
||||
|
@ -60,9 +153,10 @@ struct CDVD_API
|
|||
// direct CDVD plugin invocation, and add universal block dumping features.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
//TODO_CDVD update comment ^
|
||||
|
||||
extern CDVD_API* CDVD; // currently active CDVD access mode api (either Iso, NoDisc, or Plugin)
|
||||
|
||||
extern CDVD_API CDVDapi_Plugin;
|
||||
extern CDVD_API CDVDapi_Iso;
|
||||
extern CDVD_API CDVDapi_Disc;
|
||||
extern CDVD_API CDVDapi_NoDisc;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
* Copyright (C) 2002-2014 David Quintana [gigaherz]
|
||||
*
|
||||
* 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-
|
||||
|
@ -14,79 +14,485 @@
|
|||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "IopCommon.h"
|
||||
#include "CDVDdiscReader.h"
|
||||
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include <condition_variable>
|
||||
|
||||
void (*newDiscCB)();
|
||||
|
||||
static std::mutex s_keepalive_lock;
|
||||
static std::condition_variable s_keepalive_cv;
|
||||
static std::thread s_keepalive_thread;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// State Information //
|
||||
|
||||
u8 strack;
|
||||
u8 etrack;
|
||||
track tracks[100];
|
||||
|
||||
int curDiskType;
|
||||
int curTrayStatus;
|
||||
|
||||
static u32 csector;
|
||||
int cmode;
|
||||
|
||||
int lastReadInNewDiskCB = 0;
|
||||
u8 directReadSectorBuffer[2448];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Utility Functions //
|
||||
|
||||
inline u8 dec_to_bcd(u8 dec)
|
||||
{
|
||||
return ((dec / 10) << 4) | (dec % 10);
|
||||
}
|
||||
|
||||
inline void lsn_to_msf(u8* minute, u8* second, u8* frame, u32 lsn)
|
||||
{
|
||||
*frame = dec_to_bcd(lsn % 75);
|
||||
lsn /= 75;
|
||||
*second = dec_to_bcd(lsn % 60);
|
||||
lsn /= 60;
|
||||
*minute = dec_to_bcd(lsn % 100);
|
||||
}
|
||||
|
||||
// TocStuff
|
||||
void cdvdParseTOC()
|
||||
{
|
||||
tracks[1].start_lba = 0;
|
||||
|
||||
if (!src->GetSectorCount()) {
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
strack = 1;
|
||||
etrack = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (src->GetMediaType() >= 0) {
|
||||
tracks[1].type = CDVD_MODE1_TRACK;
|
||||
|
||||
strack = 1;
|
||||
etrack = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
strack = 0xFF;
|
||||
etrack = 0;
|
||||
|
||||
for (auto& entry : src->ReadTOC()) {
|
||||
if (entry.track < 1 || entry.track > 99)
|
||||
continue;
|
||||
strack = std::min(strack, entry.track);
|
||||
etrack = std::max(etrack, entry.track);
|
||||
tracks[entry.track].start_lba = entry.lba;
|
||||
if ((entry.control & 0x0C) == 0x04) {
|
||||
std::array<u8, 2352> buffer;
|
||||
// Byte 15 of a raw CD data sector determines the track mode
|
||||
if (src->ReadSectors2352(entry.lba, 1, buffer.data()) && (buffer[15] & 3) == 2) {
|
||||
tracks[entry.track].type = CDVD_MODE2_TRACK;
|
||||
}
|
||||
else {
|
||||
tracks[entry.track].type = CDVD_MODE1_TRACK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
tracks[entry.track].type = CDVD_AUDIO_TRACK;
|
||||
}
|
||||
fprintf(stderr, "Track %u start sector: %u\n", entry.track, entry.lba);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CDVD processing functions //
|
||||
|
||||
std::atomic<bool> s_keepalive_is_open;
|
||||
bool disc_has_changed = false;
|
||||
bool weAreInNewDiskCB = false;
|
||||
|
||||
std::unique_ptr<IOCtlSrc> src;
|
||||
|
||||
extern u32 g_last_sector_block_lsn;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// keepAliveThread throws a read event regularly to prevent drive spin down //
|
||||
|
||||
void keepAliveThread()
|
||||
{
|
||||
u8 throwaway[2352];
|
||||
|
||||
printf(" * CDVD: KeepAlive thread started...\n");
|
||||
std::unique_lock<std::mutex> guard(s_keepalive_lock);
|
||||
|
||||
while (!s_keepalive_cv.wait_for(guard, std::chrono::seconds(30),
|
||||
[]() { return !s_keepalive_is_open; })) {
|
||||
|
||||
//printf(" * keepAliveThread: polling drive.\n");
|
||||
if (src->GetMediaType() >= 0)
|
||||
src->ReadSectors2048(g_last_sector_block_lsn, 1, throwaway);
|
||||
else
|
||||
src->ReadSectors2352(g_last_sector_block_lsn, 1, throwaway);
|
||||
}
|
||||
|
||||
printf(" * CDVD: KeepAlive thread finished.\n");
|
||||
}
|
||||
|
||||
bool StartKeepAliveThread()
|
||||
{
|
||||
s_keepalive_is_open = true;
|
||||
try {
|
||||
s_keepalive_thread = std::thread(keepAliveThread);
|
||||
}
|
||||
catch (std::system_error&) {
|
||||
s_keepalive_is_open = false;
|
||||
}
|
||||
|
||||
return s_keepalive_is_open;
|
||||
}
|
||||
|
||||
void StopKeepAliveThread()
|
||||
{
|
||||
if (!s_keepalive_thread.joinable())
|
||||
return;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_keepalive_lock);
|
||||
s_keepalive_is_open = false;
|
||||
}
|
||||
s_keepalive_cv.notify_one();
|
||||
s_keepalive_thread.join();
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCopen(const char* pTitle)
|
||||
{
|
||||
return 0;
|
||||
#if defined(_WIN32)
|
||||
std::wstring drive = g_Conf->Folders.RunDisc.ToString().ToStdWstring();
|
||||
#else
|
||||
std::string drive = g_Conf->Folders.RunDisc.ToString().ToStdString();
|
||||
#endif
|
||||
GetValidDrive(drive);
|
||||
|
||||
// open device file
|
||||
try {
|
||||
src = std::unique_ptr<IOCtlSrc>(new IOCtlSrc(drive));
|
||||
}
|
||||
catch (std::runtime_error& ex) {
|
||||
fputs(ex.what(), stdout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//setup threading manager
|
||||
if (!cdvdStartThread()) {
|
||||
src.reset();
|
||||
return -1;
|
||||
}
|
||||
StartKeepAliveThread();
|
||||
|
||||
return cdvdRefreshData();
|
||||
}
|
||||
|
||||
void CALLBACK DISCclose()
|
||||
{
|
||||
StopKeepAliveThread();
|
||||
cdvdStopThread();
|
||||
//close device
|
||||
src.reset();
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCreadTrack(u32 lsn, int mode)
|
||||
{
|
||||
return -1;
|
||||
csector = lsn;
|
||||
cmode = mode;
|
||||
|
||||
if (weAreInNewDiskCB) {
|
||||
int ret = cdvdDirectReadSector(lsn, mode, directReadSectorBuffer);
|
||||
if (ret == 0)
|
||||
lastReadInNewDiskCB = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
cdvdRequestSector(lsn, mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return can be NULL (for async modes)
|
||||
u8* CALLBACK DISCgetBuffer()
|
||||
{
|
||||
return NULL;
|
||||
if (lastReadInNewDiskCB) {
|
||||
lastReadInNewDiskCB = 0;
|
||||
return directReadSectorBuffer;
|
||||
}
|
||||
|
||||
return cdvdGetSector(csector, cmode);
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCreadSubQ(u32 lsn, cdvdSubQ* subq)
|
||||
{
|
||||
return -1;
|
||||
// the formatted subq command returns: control/adr, track, index, trk min, trk sec, trk frm, 0x00, abs min, abs sec, abs frm
|
||||
|
||||
if (lsn >= src->GetSectorCount())
|
||||
return -1;
|
||||
|
||||
memset(subq, 0, sizeof(cdvdSubQ));
|
||||
|
||||
lsn_to_msf(&subq->discM, &subq->discS, &subq->discF, lsn + 150);
|
||||
|
||||
u8 i = strack;
|
||||
while (i < etrack && lsn >= tracks[i + 1].start_lba)
|
||||
++i;
|
||||
|
||||
lsn -= tracks[i].start_lba;
|
||||
|
||||
lsn_to_msf(&subq->trackM, &subq->trackS, &subq->trackF, lsn);
|
||||
|
||||
subq->mode = 1;
|
||||
subq->ctrl = tracks[i].type;
|
||||
subq->trackNum = i;
|
||||
subq->trackIndex = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCgetTN(cdvdTN* Buffer)
|
||||
{
|
||||
return -1;
|
||||
Buffer->strack = strack;
|
||||
Buffer->etrack = etrack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCgetTD(u8 Track, cdvdTD* Buffer)
|
||||
{
|
||||
return -1;
|
||||
if (Track == 0) {
|
||||
Buffer->lsn = src->GetSectorCount();
|
||||
Buffer->type = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Track < strack)
|
||||
return -1;
|
||||
if (Track > etrack)
|
||||
return -1;
|
||||
|
||||
Buffer->lsn = tracks[Track].start_lba;
|
||||
Buffer->type = tracks[Track].type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCgetTOC(void* toc)
|
||||
{
|
||||
return -1;
|
||||
u8* tocBuff = static_cast<u8*>(toc);
|
||||
if (curDiskType == CDVD_TYPE_NODISC)
|
||||
return -1;
|
||||
|
||||
if (curDiskType == CDVD_TYPE_DETCTDVDS || curDiskType == CDVD_TYPE_DETCTDVDD) {
|
||||
memset(tocBuff, 0, 2048);
|
||||
|
||||
s32 mt = src->GetMediaType();
|
||||
|
||||
if (mt < 0)
|
||||
return -1;
|
||||
|
||||
if (mt == 0) { //single layer
|
||||
// fake it
|
||||
tocBuff[0] = 0x04;
|
||||
tocBuff[1] = 0x02;
|
||||
tocBuff[2] = 0xF2;
|
||||
tocBuff[3] = 0x00;
|
||||
tocBuff[4] = 0x86;
|
||||
tocBuff[5] = 0x72;
|
||||
|
||||
tocBuff[16] = 0x00; // first sector for layer 0
|
||||
tocBuff[17] = 0x03;
|
||||
tocBuff[18] = 0x00;
|
||||
tocBuff[19] = 0x00;
|
||||
}
|
||||
else if (mt == 1) { //PTP
|
||||
u32 layer1start = src->GetLayerBreakAddress() + 0x30000;
|
||||
|
||||
// dual sided
|
||||
tocBuff[0] = 0x24;
|
||||
tocBuff[1] = 0x02;
|
||||
tocBuff[2] = 0xF2;
|
||||
tocBuff[3] = 0x00;
|
||||
tocBuff[4] = 0x41;
|
||||
tocBuff[5] = 0x95;
|
||||
|
||||
tocBuff[14] = 0x61; // PTP
|
||||
|
||||
tocBuff[16] = 0x00;
|
||||
tocBuff[17] = 0x03;
|
||||
tocBuff[18] = 0x00;
|
||||
tocBuff[19] = 0x00;
|
||||
|
||||
tocBuff[20] = (layer1start >> 24);
|
||||
tocBuff[21] = (layer1start >> 16) & 0xff;
|
||||
tocBuff[22] = (layer1start >> 8) & 0xff;
|
||||
tocBuff[23] = (layer1start >> 0) & 0xff;
|
||||
}
|
||||
else { //OTP
|
||||
u32 layer1start = src->GetLayerBreakAddress() + 0x30000;
|
||||
|
||||
// dual sided
|
||||
tocBuff[0] = 0x24;
|
||||
tocBuff[1] = 0x02;
|
||||
tocBuff[2] = 0xF2;
|
||||
tocBuff[3] = 0x00;
|
||||
tocBuff[4] = 0x41;
|
||||
tocBuff[5] = 0x95;
|
||||
|
||||
tocBuff[14] = 0x71; // OTP
|
||||
|
||||
tocBuff[16] = 0x00;
|
||||
tocBuff[17] = 0x03;
|
||||
tocBuff[18] = 0x00;
|
||||
tocBuff[19] = 0x00;
|
||||
|
||||
tocBuff[24] = (layer1start >> 24);
|
||||
tocBuff[25] = (layer1start >> 16) & 0xff;
|
||||
tocBuff[26] = (layer1start >> 8) & 0xff;
|
||||
tocBuff[27] = (layer1start >> 0) & 0xff;
|
||||
}
|
||||
}
|
||||
else if (curDiskType == CDVD_TYPE_DETCTCD) {
|
||||
// cd toc
|
||||
// (could be replaced by 1 command that reads the full toc)
|
||||
u8 min, sec, frm, i;
|
||||
s32 err;
|
||||
cdvdTN diskInfo;
|
||||
cdvdTD trackInfo;
|
||||
memset(tocBuff, 0, 1024);
|
||||
if (DISCgetTN(&diskInfo) == -1) {
|
||||
diskInfo.etrack = 0;
|
||||
diskInfo.strack = 1;
|
||||
}
|
||||
if (DISCgetTD(0, &trackInfo) == -1)
|
||||
trackInfo.lsn = 0;
|
||||
|
||||
tocBuff[0] = 0x41;
|
||||
tocBuff[1] = 0x00;
|
||||
|
||||
//Number of FirstTrack
|
||||
tocBuff[2] = 0xA0;
|
||||
tocBuff[7] = dec_to_bcd(diskInfo.strack);
|
||||
|
||||
//Number of LastTrack
|
||||
tocBuff[12] = 0xA1;
|
||||
tocBuff[17] = dec_to_bcd(diskInfo.etrack);
|
||||
|
||||
//DiskLength
|
||||
lba_to_msf(trackInfo.lsn, &min, &sec, &frm);
|
||||
tocBuff[22] = 0xA2;
|
||||
tocBuff[27] = dec_to_bcd(min);
|
||||
tocBuff[28] = dec_to_bcd(sec);
|
||||
tocBuff[29] = dec_to_bcd(frm);
|
||||
|
||||
fprintf(stderr, "Track 0: %u mins %u secs %u frames\n", min, sec, frm);
|
||||
|
||||
for (i = diskInfo.strack; i <= diskInfo.etrack; i++) {
|
||||
err = DISCgetTD(i, &trackInfo);
|
||||
lba_to_msf(trackInfo.lsn, &min, &sec, &frm);
|
||||
tocBuff[i * 10 + 30] = trackInfo.type;
|
||||
tocBuff[i * 10 + 32] = err == -1 ? 0 : dec_to_bcd(i); //number
|
||||
tocBuff[i * 10 + 37] = dec_to_bcd(min);
|
||||
tocBuff[i * 10 + 38] = dec_to_bcd(sec);
|
||||
tocBuff[i * 10 + 39] = dec_to_bcd(frm);
|
||||
fprintf(stderr, "Track %u: %u mins %u secs %u frames\n", i, min, sec, frm);
|
||||
}
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCgetDiskType()
|
||||
{
|
||||
return CDVD_TYPE_NODISC;
|
||||
return curDiskType;
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCgetTrayStatus()
|
||||
{
|
||||
return CDVD_TRAY_CLOSE;
|
||||
return curTrayStatus;
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCdummyS32()
|
||||
s32 CALLBACK DISCctrlTrayOpen()
|
||||
{
|
||||
curTrayStatus = CDVD_TRAY_OPEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CALLBACK DISCnewDiskCB(void (* /* callback */)())
|
||||
s32 CALLBACK DISCctrlTrayClose()
|
||||
{
|
||||
curTrayStatus = CDVD_TRAY_CLOSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCreadSector(u8* tempbuffer, u32 lsn, int mode)
|
||||
void CALLBACK DISCnewDiskCB(void (*callback)())
|
||||
{
|
||||
return -1;
|
||||
newDiscCB = callback;
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCgetBuffer2(u8* buffer)
|
||||
s32 CALLBACK DISCreadSector(u8* buffer, u32 lsn, int mode)
|
||||
{
|
||||
return -1;
|
||||
return cdvdDirectReadSector(lsn, mode, buffer);
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCgetBuffer2(u8* dest)
|
||||
{
|
||||
// Do nothing for out of bounds disc sector reads. It prevents some games
|
||||
// from hanging (All-Star Baseball 2005, Hello Kitty: Roller Rescue,
|
||||
// Hot Wheels: Beat That! (NTSC), Ratchet & Clank 3 (PAL),
|
||||
// Test Drive: Eve of Destruction, etc.).
|
||||
if (csector >= src->GetSectorCount())
|
||||
return 0;
|
||||
|
||||
int csize = 2352;
|
||||
switch (cmode) {
|
||||
case CDVD_MODE_2048:
|
||||
csize = 2048;
|
||||
break;
|
||||
case CDVD_MODE_2328:
|
||||
csize = 2328;
|
||||
break;
|
||||
case CDVD_MODE_2340:
|
||||
csize = 2340;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lastReadInNewDiskCB) {
|
||||
lastReadInNewDiskCB = 0;
|
||||
|
||||
memcpy(dest, directReadSectorBuffer, csize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(dest, cdvdGetSector(csector, cmode), csize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK DISCgetDualInfo(s32* dualType, u32* _layer1start)
|
||||
{
|
||||
switch (src->GetMediaType()) {
|
||||
case 1:
|
||||
*dualType = 1;
|
||||
*_layer1start = src->GetLayerBreakAddress() + 1;
|
||||
return 0;
|
||||
case 2:
|
||||
*dualType = 2;
|
||||
*_layer1start = src->GetLayerBreakAddress() + 1;
|
||||
return 0;
|
||||
case 0:
|
||||
*dualType = 0;
|
||||
*_layer1start = 0;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -102,8 +508,8 @@ CDVD_API CDVDapi_Disc =
|
|||
DISCgetTOC,
|
||||
DISCgetDiskType,
|
||||
DISCgetTrayStatus,
|
||||
DISCdummyS32,
|
||||
DISCdummyS32,
|
||||
DISCctrlTrayOpen,
|
||||
DISCctrlTrayClose,
|
||||
|
||||
DISCnewDiskCB,
|
||||
|
||||
|
|
|
@ -18,4 +18,95 @@
|
|||
|
||||
#include "IopCommon.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <mutex>
|
||||
#include <array>
|
||||
|
||||
struct track
|
||||
{
|
||||
u32 start_lba;
|
||||
u8 type;
|
||||
};
|
||||
|
||||
extern u8 strack;
|
||||
extern u8 etrack;
|
||||
extern track tracks[100];
|
||||
|
||||
extern int curDiskType;
|
||||
extern int curTrayStatus;
|
||||
|
||||
struct toc_entry
|
||||
{
|
||||
u32 lba;
|
||||
u8 track;
|
||||
u8 adr : 4;
|
||||
u8 control : 4;
|
||||
};
|
||||
|
||||
class IOCtlSrc
|
||||
{
|
||||
IOCtlSrc(const IOCtlSrc&) = delete;
|
||||
IOCtlSrc& operator=(const IOCtlSrc&) = delete;
|
||||
|
||||
#if defined(_WIN32)
|
||||
HANDLE m_device = INVALID_HANDLE_VALUE;
|
||||
std::wstring m_filename;
|
||||
mutable std::mutex m_lock;
|
||||
#else
|
||||
int m_device = -1;
|
||||
std::string m_filename;
|
||||
#endif
|
||||
|
||||
s32 m_media_type = 0;
|
||||
u32 m_sectors = 0;
|
||||
u32 m_layer_break = 0;
|
||||
std::vector<toc_entry> m_toc;
|
||||
|
||||
bool ReadDVDInfo();
|
||||
bool ReadCDInfo();
|
||||
bool Reopen();
|
||||
|
||||
public:
|
||||
IOCtlSrc(decltype(m_filename) filename);
|
||||
~IOCtlSrc();
|
||||
|
||||
u32 GetSectorCount() const;
|
||||
const std::vector<toc_entry>& ReadTOC() const;
|
||||
bool ReadSectors2048(u32 sector, u32 count, u8* buffer) const;
|
||||
bool ReadSectors2352(u32 sector, u32 count, u8* buffer) const;
|
||||
u32 GetLayerBreakAddress() const;
|
||||
s32 GetMediaType() const;
|
||||
void SetSpindleSpeed(bool restore_defaults) const;
|
||||
bool DiscReady();
|
||||
};
|
||||
|
||||
extern std::unique_ptr<IOCtlSrc> src;
|
||||
|
||||
#if defined(_WIN32)
|
||||
std::vector<std::wstring> GetOpticalDriveList();
|
||||
void GetValidDrive(std::wstring& drive);
|
||||
#else
|
||||
std::vector<std::string> GetOpticalDriveList();
|
||||
void GetValidDrive(std::string& drive);
|
||||
#endif
|
||||
|
||||
extern bool disc_has_changed;
|
||||
extern bool weAreInNewDiskCB;
|
||||
|
||||
extern void (*newDiscCB)();
|
||||
|
||||
bool cdvdStartThread();
|
||||
void cdvdStopThread();
|
||||
void cdvdRequestSector(u32 sector, s32 mode);
|
||||
u8* cdvdGetSector(u32 sector, s32 mode);
|
||||
s32 cdvdDirectReadSector(u32 sector, s32 mode, u8* buffer);
|
||||
s32 cdvdGetMediaType();
|
||||
s32 cdvdRefreshData();
|
||||
void cdvdParseTOC();
|
||||
|
||||
#endif /* __CDVD_DISC_READER_H__ */
|
|
@ -0,0 +1,406 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2014 David Quintana [gigaherz]
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "CDVDdiscReader.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <limits>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
|
||||
const u32 sectors_per_read = 16;
|
||||
|
||||
static_assert(sectors_per_read > 1 && !(sectors_per_read & (sectors_per_read - 1)),
|
||||
"sectors_per_read must by a power of 2");
|
||||
|
||||
struct SectorInfo
|
||||
{
|
||||
u32 lsn;
|
||||
// Sectors are read in blocks, not individually
|
||||
u8 data[2352 * sectors_per_read];
|
||||
};
|
||||
|
||||
u32 g_last_sector_block_lsn;
|
||||
|
||||
static std::thread s_thread;
|
||||
|
||||
static std::mutex s_notify_lock;
|
||||
static std::condition_variable s_notify_cv;
|
||||
static std::mutex s_request_lock;
|
||||
static std::queue<u32> s_request_queue;
|
||||
static std::mutex s_cache_lock;
|
||||
|
||||
static std::atomic<bool> cdvd_is_open;
|
||||
|
||||
//bits: 12 would use 1<<12 entries, or 4096*16 sectors ~ 128MB
|
||||
#define CACHE_SIZE 12
|
||||
|
||||
const u32 CacheSize = 1U << CACHE_SIZE;
|
||||
SectorInfo Cache[CacheSize];
|
||||
|
||||
u32 cdvdSectorHash(u32 lsn)
|
||||
{
|
||||
u32 t = 0;
|
||||
|
||||
int i = 32;
|
||||
u32 m = CacheSize - 1;
|
||||
|
||||
while (i >= 0) {
|
||||
t ^= lsn & m;
|
||||
lsn >>= CACHE_SIZE;
|
||||
i -= CACHE_SIZE;
|
||||
}
|
||||
|
||||
return t & m;
|
||||
}
|
||||
|
||||
void cdvdCacheUpdate(u32 lsn, u8* data)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_cache_lock);
|
||||
u32 entry = cdvdSectorHash(lsn);
|
||||
|
||||
memcpy(Cache[entry].data, data, 2352 * sectors_per_read);
|
||||
Cache[entry].lsn = lsn;
|
||||
}
|
||||
|
||||
bool cdvdCacheCheck(u32 lsn)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_cache_lock);
|
||||
u32 entry = cdvdSectorHash(lsn);
|
||||
|
||||
return Cache[entry].lsn == lsn;
|
||||
}
|
||||
|
||||
bool cdvdCacheFetch(u32 lsn, u8* data)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_cache_lock);
|
||||
u32 entry = cdvdSectorHash(lsn);
|
||||
|
||||
if (Cache[entry].lsn == lsn) {
|
||||
memcpy(data, Cache[entry].data, 2352 * sectors_per_read);
|
||||
return true;
|
||||
}
|
||||
//printf("NOT IN CACHE\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
void cdvdCacheReset()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_cache_lock);
|
||||
for (u32 i = 0; i < CacheSize; i++) {
|
||||
Cache[i].lsn = std::numeric_limits<u32>::max();
|
||||
}
|
||||
}
|
||||
|
||||
bool cdvdReadBlockOfSectors(u32 sector, u8* data)
|
||||
{
|
||||
u32 count = std::min(sectors_per_read, src->GetSectorCount() - sector);
|
||||
const s32 media = src->GetMediaType();
|
||||
|
||||
// TODO: Is it really necessary to retry if it fails? I'm not sure the
|
||||
// second time is really going to be any better.
|
||||
for (int tries = 0; tries < 2; ++tries) {
|
||||
if (media >= 0) {
|
||||
if (src->ReadSectors2048(sector, count, data))
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (src->ReadSectors2352(sector, count, data))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cdvdCallNewDiscCB()
|
||||
{
|
||||
weAreInNewDiskCB = true;
|
||||
newDiscCB();
|
||||
weAreInNewDiskCB = false;
|
||||
}
|
||||
|
||||
bool cdvdUpdateDiscStatus()
|
||||
{
|
||||
bool ready = src->DiscReady();
|
||||
|
||||
if (!ready) {
|
||||
if (!disc_has_changed) {
|
||||
disc_has_changed = true;
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
curTrayStatus = CDVD_TRAY_OPEN;
|
||||
cdvdCallNewDiscCB();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (disc_has_changed) {
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
curTrayStatus = CDVD_TRAY_CLOSE;
|
||||
|
||||
disc_has_changed = false;
|
||||
cdvdRefreshData();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> request_guard(s_request_lock);
|
||||
s_request_queue = decltype(s_request_queue)();
|
||||
}
|
||||
|
||||
cdvdCallNewDiscCB();
|
||||
}
|
||||
}
|
||||
return !ready;
|
||||
}
|
||||
|
||||
void cdvdThread()
|
||||
{
|
||||
u8 buffer[2352 * sectors_per_read];
|
||||
u32 prefetches_left = 0;
|
||||
|
||||
printf(" * CDVD: IO thread started...\n");
|
||||
std::unique_lock<std::mutex> guard(s_notify_lock);
|
||||
|
||||
while (cdvd_is_open) {
|
||||
if (cdvdUpdateDiscStatus()) {
|
||||
// Need to sleep some to avoid an aggressive spin that sucks the cpu dry.
|
||||
s_notify_cv.wait_for(guard, std::chrono::milliseconds(10));
|
||||
prefetches_left = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefetches_left == 0)
|
||||
s_notify_cv.wait_for(guard, std::chrono::milliseconds(250));
|
||||
|
||||
// check again to make sure we're not done here...
|
||||
if (!cdvd_is_open)
|
||||
break;
|
||||
|
||||
// Read request
|
||||
bool handling_request = false;
|
||||
u32 request_lsn;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> request_guard(s_request_lock);
|
||||
if (!s_request_queue.empty()) {
|
||||
request_lsn = s_request_queue.front();
|
||||
s_request_queue.pop();
|
||||
handling_request = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!handling_request) {
|
||||
if (prefetches_left == 0)
|
||||
continue;
|
||||
|
||||
--prefetches_left;
|
||||
|
||||
u32 next_prefetch_lsn = g_last_sector_block_lsn + sectors_per_read;
|
||||
request_lsn = next_prefetch_lsn;
|
||||
}
|
||||
|
||||
// Handle request
|
||||
if (!cdvdCacheCheck(request_lsn)) {
|
||||
if (cdvdReadBlockOfSectors(request_lsn, buffer)) {
|
||||
cdvdCacheUpdate(request_lsn, buffer);
|
||||
}
|
||||
else {
|
||||
// If the read fails, further reads are likely to fail too.
|
||||
prefetches_left = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
g_last_sector_block_lsn = request_lsn;
|
||||
|
||||
if (!handling_request)
|
||||
continue;
|
||||
|
||||
// Prefetch
|
||||
u32 next_prefetch_lsn = g_last_sector_block_lsn + sectors_per_read;
|
||||
if (next_prefetch_lsn >= src->GetSectorCount()) {
|
||||
prefetches_left = 0;
|
||||
}
|
||||
else {
|
||||
const u32 max_prefetches = 16;
|
||||
u32 remaining = src->GetSectorCount() - next_prefetch_lsn;
|
||||
prefetches_left = std::min((remaining + sectors_per_read - 1) / sectors_per_read, max_prefetches);
|
||||
}
|
||||
}
|
||||
printf(" * CDVD: IO thread finished.\n");
|
||||
}
|
||||
|
||||
bool cdvdStartThread()
|
||||
{
|
||||
cdvd_is_open = true;
|
||||
try {
|
||||
s_thread = std::thread(cdvdThread);
|
||||
}
|
||||
catch (std::system_error&) {
|
||||
cdvd_is_open = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
cdvdCacheReset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cdvdStopThread()
|
||||
{
|
||||
cdvd_is_open = false;
|
||||
s_notify_cv.notify_one();
|
||||
s_thread.join();
|
||||
}
|
||||
|
||||
void cdvdRequestSector(u32 sector, s32 mode)
|
||||
{
|
||||
if (sector >= src->GetSectorCount())
|
||||
return;
|
||||
|
||||
// Align to cache block
|
||||
sector &= ~(sectors_per_read - 1);
|
||||
|
||||
if (cdvdCacheCheck(sector))
|
||||
return;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_request_lock);
|
||||
s_request_queue.push(sector);
|
||||
}
|
||||
|
||||
s_notify_cv.notify_one();
|
||||
}
|
||||
|
||||
u8* cdvdGetSector(u32 sector, s32 mode)
|
||||
{
|
||||
static u8 buffer[2352 * sectors_per_read];
|
||||
|
||||
// Align to cache block
|
||||
u32 sector_block = sector & ~(sectors_per_read - 1);
|
||||
|
||||
if (!cdvdCacheFetch(sector_block, buffer))
|
||||
if (cdvdReadBlockOfSectors(sector_block, buffer))
|
||||
cdvdCacheUpdate(sector_block, buffer);
|
||||
|
||||
if (src->GetMediaType() >= 0) {
|
||||
u32 offset = 2048 * (sector - sector_block);
|
||||
return buffer + offset;
|
||||
}
|
||||
|
||||
u32 offset = 2352 * (sector - sector_block);
|
||||
u8* data = buffer + offset;
|
||||
|
||||
switch (mode) {
|
||||
case CDVD_MODE_2048:
|
||||
// Data location depends on CD mode
|
||||
return (data[15] & 3) == 2 ? data + 24 : data + 16;
|
||||
case CDVD_MODE_2328:
|
||||
return data + 24;
|
||||
case CDVD_MODE_2340:
|
||||
return data + 12;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
s32 cdvdDirectReadSector(u32 sector, s32 mode, u8* buffer)
|
||||
{
|
||||
static u8 data[2352 * sectors_per_read];
|
||||
|
||||
if (sector >= src->GetSectorCount())
|
||||
return -1;
|
||||
|
||||
// Align to cache block
|
||||
u32 sector_block = sector & ~(sectors_per_read - 1);
|
||||
|
||||
if (!cdvdCacheFetch(sector_block, data)) {
|
||||
if (cdvdReadBlockOfSectors(sector_block, data))
|
||||
cdvdCacheUpdate(sector_block, data);
|
||||
}
|
||||
|
||||
if (src->GetMediaType() >= 0) {
|
||||
u32 offset = 2048 * (sector - sector_block);
|
||||
memcpy(buffer, data + offset, 2048);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 offset = 2352 * (sector - sector_block);
|
||||
u8* bfr = data + offset;
|
||||
|
||||
switch (mode) {
|
||||
case CDVD_MODE_2048:
|
||||
// Data location depends on CD mode
|
||||
std::memcpy(buffer, (bfr[15] & 3) == 2 ? bfr + 24 : bfr + 16, 2048);
|
||||
return 0;
|
||||
case CDVD_MODE_2328:
|
||||
memcpy(buffer, bfr + 24, 2328);
|
||||
return 0;
|
||||
case CDVD_MODE_2340:
|
||||
memcpy(buffer, bfr + 12, 2340);
|
||||
return 0;
|
||||
default:
|
||||
memcpy(buffer, bfr, 2352);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
s32 cdvdGetMediaType()
|
||||
{
|
||||
return src->GetMediaType();
|
||||
}
|
||||
|
||||
s32 cdvdRefreshData()
|
||||
{
|
||||
const char* diskTypeName = "Unknown";
|
||||
|
||||
//read TOC from device
|
||||
cdvdParseTOC();
|
||||
|
||||
if ((etrack == 0) || (strack > etrack)) {
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
}
|
||||
else {
|
||||
s32 mt = cdvdGetMediaType();
|
||||
|
||||
if (mt < 0)
|
||||
curDiskType = CDVD_TYPE_DETCTCD;
|
||||
else if (mt == 0)
|
||||
curDiskType = CDVD_TYPE_DETCTDVDS;
|
||||
else
|
||||
curDiskType = CDVD_TYPE_DETCTDVDD;
|
||||
}
|
||||
|
||||
curTrayStatus = CDVD_TRAY_CLOSE;
|
||||
|
||||
switch (curDiskType) {
|
||||
case CDVD_TYPE_DETCTDVDD:
|
||||
diskTypeName = "Double-Layer DVD";
|
||||
break;
|
||||
case CDVD_TYPE_DETCTDVDS:
|
||||
diskTypeName = "Single-Layer DVD";
|
||||
break;
|
||||
case CDVD_TYPE_DETCTCD:
|
||||
diskTypeName = "CD-ROM";
|
||||
break;
|
||||
case CDVD_TYPE_NODISC:
|
||||
diskTypeName = "No Disc";
|
||||
break;
|
||||
}
|
||||
|
||||
printf(" * CDVD: Disk Type: %s\n", diskTypeName);
|
||||
|
||||
cdvdCacheReset();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
#define __CDROM_H__
|
||||
|
||||
#include "IopCommon.h"
|
||||
#include "PS2Edefs.h"
|
||||
#include "CDVDaccess.h"
|
||||
|
||||
// Not used.
|
||||
typedef struct {
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2020 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "../CDVDdiscReader.h"
|
||||
|
||||
#include <libudev.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/cdrom.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
std::vector<std::string> GetOpticalDriveList()
|
||||
{
|
||||
udev* udev_context = udev_new();
|
||||
if (!udev_context)
|
||||
return {};
|
||||
|
||||
std::vector<std::string> drives;
|
||||
udev_enumerate* enumerate = udev_enumerate_new(udev_context);
|
||||
if (enumerate) {
|
||||
udev_enumerate_add_match_subsystem(enumerate, "block");
|
||||
udev_enumerate_add_match_property(enumerate, "ID_CDROM_DVD", "1");
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate);
|
||||
|
||||
udev_list_entry* dev_list_entry;
|
||||
udev_list_entry_foreach(dev_list_entry, devices)
|
||||
{
|
||||
const char* path = udev_list_entry_get_name(dev_list_entry);
|
||||
udev_device* device = udev_device_new_from_syspath(udev_context, path);
|
||||
const char* devnode = udev_device_get_devnode(device);
|
||||
if (devnode)
|
||||
drives.push_back(devnode);
|
||||
udev_device_unref(device);
|
||||
}
|
||||
udev_enumerate_unref(enumerate);
|
||||
}
|
||||
udev_unref(udev_context);
|
||||
|
||||
return drives;
|
||||
}
|
||||
|
||||
void GetValidDrive(std::string& drive)
|
||||
{
|
||||
if (!drive.empty()) {
|
||||
int fd = open(drive.c_str(), O_RDONLY | O_NONBLOCK);
|
||||
if (fd != -1) {
|
||||
if (ioctl(fd, CDROM_GET_CAPABILITY, 0) == -1)
|
||||
drive.clear();
|
||||
close(fd);
|
||||
}
|
||||
else {
|
||||
drive.clear();
|
||||
}
|
||||
}
|
||||
if (drive.empty()) {
|
||||
auto drives = GetOpticalDriveList();
|
||||
if (!drives.empty())
|
||||
drive = drives.front();
|
||||
}
|
||||
if (!drive.empty())
|
||||
printf(" * CDVD: Opening drive '%s'...\n", drive.c_str());
|
||||
}
|
|
@ -0,0 +1,216 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2016 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "../CDVDdiscReader.h"
|
||||
|
||||
#include <linux/cdrom.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
|
||||
IOCtlSrc::IOCtlSrc(decltype(m_filename) filename)
|
||||
: m_filename(filename)
|
||||
{
|
||||
if (!Reopen())
|
||||
throw std::runtime_error(" * CDVD: Error opening source.\n");
|
||||
}
|
||||
|
||||
IOCtlSrc::~IOCtlSrc()
|
||||
{
|
||||
if (m_device != -1) {
|
||||
SetSpindleSpeed(true);
|
||||
close(m_device);
|
||||
}
|
||||
}
|
||||
|
||||
bool IOCtlSrc::Reopen()
|
||||
{
|
||||
if (m_device != -1)
|
||||
close(m_device);
|
||||
|
||||
// O_NONBLOCK allows a valid file descriptor to be returned even if the
|
||||
// drive is empty. Probably does other things too.
|
||||
m_device = open(m_filename.c_str(), O_RDONLY | O_NONBLOCK);
|
||||
if (m_device == -1)
|
||||
return false;
|
||||
|
||||
// DVD detection MUST be first on Linux - The TOC ioctls work for both
|
||||
// CDs and DVDs.
|
||||
if (ReadDVDInfo() || ReadCDInfo())
|
||||
SetSpindleSpeed(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IOCtlSrc::SetSpindleSpeed(bool restore_defaults) const
|
||||
{
|
||||
// TODO: CD seems easy enough (CDROM_SELECT_SPEED ioctl), but I'm not sure
|
||||
// about DVD.
|
||||
}
|
||||
|
||||
u32 IOCtlSrc::GetSectorCount() const
|
||||
{
|
||||
return m_sectors;
|
||||
}
|
||||
|
||||
u32 IOCtlSrc::GetLayerBreakAddress() const
|
||||
{
|
||||
return m_layer_break;
|
||||
}
|
||||
|
||||
s32 IOCtlSrc::GetMediaType() const
|
||||
{
|
||||
return m_media_type;
|
||||
}
|
||||
|
||||
const std::vector<toc_entry>& IOCtlSrc::ReadTOC() const
|
||||
{
|
||||
return m_toc;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadSectors2048(u32 sector, u32 count, u8* buffer) const
|
||||
{
|
||||
const ssize_t bytes_to_read = 2048 * count;
|
||||
ssize_t bytes_read = pread(m_device, buffer, bytes_to_read, sector * 2048ULL);
|
||||
if (bytes_read == bytes_to_read)
|
||||
return true;
|
||||
|
||||
if (bytes_read == -1)
|
||||
fprintf(stderr, " * CDVD read sectors %u-%u failed: %s\n",
|
||||
sector, sector + count - 1, strerror(errno));
|
||||
else
|
||||
fprintf(stderr, " * CDVD read sectors %u-%u: %zd bytes read, %zd bytes expected\n",
|
||||
sector, sector + count - 1, bytes_read, bytes_to_read);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadSectors2352(u32 sector, u32 count, u8* buffer) const
|
||||
{
|
||||
union
|
||||
{
|
||||
cdrom_msf msf;
|
||||
char buffer[CD_FRAMESIZE_RAW];
|
||||
} data;
|
||||
|
||||
for (u32 n = 0; n < count; ++n) {
|
||||
u32 lba = sector + n;
|
||||
lba_to_msf(lba, &data.msf.cdmsf_min0, &data.msf.cdmsf_sec0, &data.msf.cdmsf_frame0);
|
||||
if (ioctl(m_device, CDROMREADRAW, &data) == -1) {
|
||||
fprintf(stderr, " * CDVD CDROMREADRAW sector %u failed: %s\n",
|
||||
lba, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
memcpy(buffer, data.buffer, CD_FRAMESIZE_RAW);
|
||||
buffer += CD_FRAMESIZE_RAW;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadDVDInfo()
|
||||
{
|
||||
dvd_struct dvdrs;
|
||||
dvdrs.type = DVD_STRUCT_PHYSICAL;
|
||||
dvdrs.physical.layer_num = 0;
|
||||
|
||||
int ret = ioctl(m_device, DVD_READ_STRUCT, &dvdrs);
|
||||
if (ret == -1)
|
||||
return false;
|
||||
|
||||
u32 start_sector = dvdrs.physical.layer[0].start_sector;
|
||||
u32 end_sector = dvdrs.physical.layer[0].end_sector;
|
||||
|
||||
if (dvdrs.physical.layer[0].nlayers == 0) {
|
||||
// Single layer
|
||||
m_media_type = 0;
|
||||
m_layer_break = 0;
|
||||
m_sectors = end_sector - start_sector + 1;
|
||||
}
|
||||
else if (dvdrs.physical.layer[0].track_path == 0) {
|
||||
// Dual layer, Parallel Track Path
|
||||
dvdrs.physical.layer_num = 1;
|
||||
ret = ioctl(m_device, DVD_READ_STRUCT, &dvdrs);
|
||||
if (ret == -1)
|
||||
return false;
|
||||
u32 layer1_start_sector = dvdrs.physical.layer[1].start_sector;
|
||||
u32 layer1_end_sector = dvdrs.physical.layer[1].end_sector;
|
||||
|
||||
m_media_type = 1;
|
||||
m_layer_break = end_sector - start_sector;
|
||||
m_sectors = end_sector - start_sector + 1 + layer1_end_sector - layer1_start_sector + 1;
|
||||
}
|
||||
else {
|
||||
// Dual layer, Opposite Track Path
|
||||
u32 end_sector_layer0 = dvdrs.physical.layer[0].end_sector_l0;
|
||||
m_media_type = 2;
|
||||
m_layer_break = end_sector_layer0 - start_sector;
|
||||
m_sectors = end_sector_layer0 - start_sector + 1 + end_sector - (~end_sector_layer0 & 0xFFFFFFU) + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadCDInfo()
|
||||
{
|
||||
cdrom_tochdr header;
|
||||
|
||||
if (ioctl(m_device, CDROMREADTOCHDR, &header) == -1)
|
||||
return false;
|
||||
|
||||
cdrom_tocentry entry{};
|
||||
entry.cdte_format = CDROM_LBA;
|
||||
|
||||
m_toc.clear();
|
||||
for (u8 n = header.cdth_trk0; n <= header.cdth_trk1; ++n) {
|
||||
entry.cdte_track = n;
|
||||
if (ioctl(m_device, CDROMREADTOCENTRY, &entry) != -1)
|
||||
m_toc.push_back({ static_cast<u32>(entry.cdte_addr.lba), entry.cdte_track,
|
||||
entry.cdte_adr, entry.cdte_ctrl });
|
||||
}
|
||||
|
||||
// TODO: Do I need a fallback if this doesn't work?
|
||||
entry.cdte_track = 0xAA;
|
||||
if (ioctl(m_device, CDROMREADTOCENTRY, &entry) == -1)
|
||||
return false;
|
||||
|
||||
m_sectors = entry.cdte_addr.lba;
|
||||
m_media_type = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::DiscReady()
|
||||
{
|
||||
if (m_device == -1)
|
||||
return false;
|
||||
|
||||
// CDSL_CURRENT must be used - 0 will cause the drive tray to close.
|
||||
if (ioctl(m_device, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK) {
|
||||
if (!m_sectors)
|
||||
Reopen();
|
||||
}
|
||||
else {
|
||||
m_sectors = 0;
|
||||
m_layer_break = 0;
|
||||
m_media_type = 0;
|
||||
}
|
||||
|
||||
return !!m_sectors;
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
//Copyright (C) 2020 PCSX2 Dev Team
|
||||
//Copyright (c) David Quintana <DavidQuintana@canal21.com>
|
||||
//
|
||||
//This library 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 Foundation; either
|
||||
//version 3.0 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library 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
|
||||
//Lesser General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU Lesser General Public
|
||||
//License along with this library; if not, write to the Free Software
|
||||
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
//
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "../CDVDdiscReader.h"
|
||||
|
||||
std::vector<std::wstring> GetOpticalDriveList()
|
||||
{
|
||||
DWORD size = GetLogicalDriveStrings(0, nullptr);
|
||||
std::vector<wchar_t> drive_strings(size);
|
||||
if (GetLogicalDriveStrings(size, drive_strings.data()) != size - 1)
|
||||
return {};
|
||||
|
||||
std::vector<std::wstring> drives;
|
||||
for (auto p = drive_strings.data(); *p; ++p) {
|
||||
if (GetDriveType(p) == DRIVE_CDROM)
|
||||
drives.push_back(p);
|
||||
while (*p)
|
||||
++p;
|
||||
}
|
||||
return drives;
|
||||
}
|
||||
|
||||
void GetValidDrive(std::wstring& drive)
|
||||
{
|
||||
if (drive.empty() || GetDriveType(drive.c_str()) != DRIVE_CDROM) {
|
||||
auto drives = GetOpticalDriveList();
|
||||
if (drives.empty())
|
||||
{
|
||||
drive = {};
|
||||
}
|
||||
else
|
||||
{
|
||||
drive = drives.front();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int size = WideCharToMultiByte(CP_UTF8, 0, drive.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
||||
std::vector<char> converted_string(size);
|
||||
WideCharToMultiByte(CP_UTF8, 0, drive.c_str(), -1, converted_string.data(), converted_string.size(), nullptr, nullptr);
|
||||
printf(" * CDVD: Opening drive '%s'...\n", converted_string.data());
|
||||
|
||||
// The drive string has the form "X:\", but to open the drive, the string
|
||||
// has to be in the form "\\.\X:"
|
||||
drive.pop_back();
|
||||
drive.insert(0, L"\\\\.\\");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,303 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2016 PCSX2 Dev Team
|
||||
* Copyright (C) 2002-2014 David Quintana [gigaherz]
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "../CDVDdiscReader.h"
|
||||
|
||||
#include <winioctl.h>
|
||||
#include <ntddcdvd.h>
|
||||
#include <ntddcdrm.h>
|
||||
// "typedef ignored" warning will disappear once we move to the Windows 10 SDK.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4091)
|
||||
#include <ntddscsi.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
|
||||
IOCtlSrc::IOCtlSrc(decltype(m_filename) filename)
|
||||
: m_filename(filename)
|
||||
{
|
||||
if (!Reopen())
|
||||
throw std::runtime_error(" * CDVD: Error opening source.\n");
|
||||
}
|
||||
|
||||
IOCtlSrc::~IOCtlSrc()
|
||||
{
|
||||
if (m_device != INVALID_HANDLE_VALUE) {
|
||||
SetSpindleSpeed(true);
|
||||
CloseHandle(m_device);
|
||||
}
|
||||
}
|
||||
|
||||
// If a new disc is inserted, ReadFile will fail unless the device is closed
|
||||
// and reopened.
|
||||
bool IOCtlSrc::Reopen()
|
||||
{
|
||||
if (m_device != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(m_device);
|
||||
|
||||
// SPTI only works if the device is opened with GENERIC_WRITE access.
|
||||
m_device = CreateFile(m_filename.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ, nullptr, OPEN_EXISTING,
|
||||
FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
|
||||
if (m_device == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
DWORD unused;
|
||||
// Required to read from layer 1 of Dual layer DVDs
|
||||
DeviceIoControl(m_device, FSCTL_ALLOW_EXTENDED_DASD_IO, nullptr, 0, nullptr,
|
||||
0, &unused, nullptr);
|
||||
|
||||
if (ReadDVDInfo() || ReadCDInfo())
|
||||
SetSpindleSpeed(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IOCtlSrc::SetSpindleSpeed(bool restore_defaults) const
|
||||
{
|
||||
// IOCTL_CDROM_SET_SPEED issues a SET CD SPEED command. So 0xFFFF should be
|
||||
// equivalent to "optimal performance".
|
||||
// 1x DVD-ROM and CD-ROM speeds are respectively 1385 KB/s and 150KB/s.
|
||||
// The PS2 can do 4x DVD-ROM and 24x CD-ROM speeds (5540KB/s and 3600KB/s).
|
||||
// TODO: What speed? Performance seems smoother with a lower speed (less
|
||||
// time required to get up to speed).
|
||||
const USHORT speed = restore_defaults ? 0xFFFF : GetMediaType() >= 0 ? 5540 : 3600;
|
||||
CDROM_SET_SPEED s{ CdromSetSpeed, speed, speed, CdromDefaultRotation };
|
||||
|
||||
DWORD unused;
|
||||
if (DeviceIoControl(m_device, IOCTL_CDROM_SET_SPEED, &s, sizeof(s),
|
||||
nullptr, 0, &unused, nullptr)) {
|
||||
if (!restore_defaults)
|
||||
printf(" * CDVD: setSpindleSpeed success (%uKB/s)\n", speed);
|
||||
}
|
||||
else {
|
||||
printf(" * CDVD: setSpindleSpeed failed!\n");
|
||||
}
|
||||
}
|
||||
|
||||
u32 IOCtlSrc::GetSectorCount() const
|
||||
{
|
||||
return m_sectors;
|
||||
}
|
||||
|
||||
u32 IOCtlSrc::GetLayerBreakAddress() const
|
||||
{
|
||||
return m_layer_break;
|
||||
}
|
||||
|
||||
s32 IOCtlSrc::GetMediaType() const
|
||||
{
|
||||
return m_media_type;
|
||||
}
|
||||
|
||||
const std::vector<toc_entry>& IOCtlSrc::ReadTOC() const
|
||||
{
|
||||
return m_toc;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadSectors2048(u32 sector, u32 count, u8* buffer) const
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_lock);
|
||||
LARGE_INTEGER offset;
|
||||
offset.QuadPart = sector * 2048ULL;
|
||||
|
||||
if (!SetFilePointerEx(m_device, offset, nullptr, FILE_BEGIN)) {
|
||||
fprintf(stderr, " * CDVD SetFilePointerEx failed: sector %u: error %u\n",
|
||||
sector, GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
const DWORD bytes_to_read = 2048 * count;
|
||||
DWORD bytes_read;
|
||||
if (ReadFile(m_device, buffer, bytes_to_read, &bytes_read, nullptr)) {
|
||||
if (bytes_read == bytes_to_read)
|
||||
return true;
|
||||
fprintf(stderr, " * CDVD ReadFile: sectors %u-%u: %u bytes read, %u bytes expected\n",
|
||||
sector, sector + count - 1, bytes_read, bytes_to_read);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, " * CDVD ReadFile failed: sectors %u-%u: error %u\n",
|
||||
sector, sector + count - 1, GetLastError());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadSectors2352(u32 sector, u32 count, u8* buffer) const
|
||||
{
|
||||
struct sptdinfo
|
||||
{
|
||||
SCSI_PASS_THROUGH_DIRECT info;
|
||||
char sense_buffer[20];
|
||||
} sptd{};
|
||||
|
||||
// READ CD command
|
||||
sptd.info.Cdb[0] = 0xBE;
|
||||
// Don't care about sector type.
|
||||
sptd.info.Cdb[1] = 0;
|
||||
// Number of sectors to read
|
||||
sptd.info.Cdb[6] = 0;
|
||||
sptd.info.Cdb[7] = 0;
|
||||
sptd.info.Cdb[8] = 1;
|
||||
// Sync + all headers + user data + EDC/ECC. Excludes C2 + subchannel
|
||||
sptd.info.Cdb[9] = 0xF8;
|
||||
sptd.info.Cdb[10] = 0;
|
||||
sptd.info.Cdb[11] = 0;
|
||||
|
||||
sptd.info.CdbLength = 12;
|
||||
sptd.info.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
|
||||
sptd.info.DataIn = SCSI_IOCTL_DATA_IN;
|
||||
sptd.info.SenseInfoOffset = offsetof(sptdinfo, sense_buffer);
|
||||
sptd.info.TimeOutValue = 5;
|
||||
|
||||
// Read sectors one by one to avoid reading data from 2 tracks of different
|
||||
// types in the same read (which will fail).
|
||||
for (u32 n = 0; n < count; ++n) {
|
||||
u32 current_sector = sector + n;
|
||||
sptd.info.Cdb[2] = (current_sector >> 24) & 0xFF;
|
||||
sptd.info.Cdb[3] = (current_sector >> 16) & 0xFF;
|
||||
sptd.info.Cdb[4] = (current_sector >> 8) & 0xFF;
|
||||
sptd.info.Cdb[5] = current_sector & 0xFF;
|
||||
sptd.info.DataTransferLength = 2352;
|
||||
sptd.info.DataBuffer = buffer + 2352 * n;
|
||||
sptd.info.SenseInfoLength = sizeof(sptd.sense_buffer);
|
||||
|
||||
DWORD unused;
|
||||
if (DeviceIoControl(m_device, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd,
|
||||
sizeof(sptd), &sptd, sizeof(sptd), &unused, nullptr)) {
|
||||
if (sptd.info.DataTransferLength == 2352)
|
||||
continue;
|
||||
}
|
||||
printf(" * CDVD: SPTI failed reading sector %u; SENSE %u -", current_sector, sptd.info.SenseInfoLength);
|
||||
for (const auto& c : sptd.sense_buffer)
|
||||
printf(" %02X", c);
|
||||
putchar('\n');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadDVDInfo()
|
||||
{
|
||||
DWORD unused;
|
||||
// 4 bytes header + 18 bytes layer descriptor - Technically you only need
|
||||
// to read 17 bytes of the layer descriptor since bytes 17-2047 is for
|
||||
// media specific information. However, Windows requires you to read at
|
||||
// least 18 bytes of the layer descriptor or else the ioctl will fail. The
|
||||
// media specific information seems to be empty, so there's no point reading
|
||||
// any more than that.
|
||||
std::array<u8, 22> buffer;
|
||||
DVD_READ_STRUCTURE dvdrs{ {0}, DvdPhysicalDescriptor, 0, 0 };
|
||||
|
||||
if (!DeviceIoControl(m_device, IOCTL_DVD_READ_STRUCTURE, &dvdrs, sizeof(dvdrs),
|
||||
buffer.data(), buffer.size(), &unused, nullptr))
|
||||
return false;
|
||||
|
||||
auto& layer = *reinterpret_cast<DVD_LAYER_DESCRIPTOR*>(
|
||||
reinterpret_cast<DVD_DESCRIPTOR_HEADER*>(buffer.data())->Data);
|
||||
|
||||
u32 start_sector = _byteswap_ulong(layer.StartingDataSector);
|
||||
u32 end_sector = _byteswap_ulong(layer.EndDataSector);
|
||||
|
||||
if (layer.NumberOfLayers == 0) {
|
||||
// Single layer
|
||||
m_media_type = 0;
|
||||
m_layer_break = 0;
|
||||
m_sectors = end_sector - start_sector + 1;
|
||||
}
|
||||
else if (layer.TrackPath == 0) {
|
||||
// Dual layer, Parallel Track Path
|
||||
dvdrs.LayerNumber = 1;
|
||||
if (!DeviceIoControl(m_device, IOCTL_DVD_READ_STRUCTURE, &dvdrs, sizeof(dvdrs),
|
||||
buffer.data(), buffer.size(), &unused, nullptr))
|
||||
return false;
|
||||
u32 layer1_start_sector = _byteswap_ulong(layer.StartingDataSector);
|
||||
u32 layer1_end_sector = _byteswap_ulong(layer.EndDataSector);
|
||||
|
||||
m_media_type = 1;
|
||||
m_layer_break = end_sector - start_sector;
|
||||
m_sectors = end_sector - start_sector + 1 + layer1_end_sector - layer1_start_sector + 1;
|
||||
}
|
||||
else {
|
||||
// Dual layer, Opposite Track Path
|
||||
u32 end_sector_layer0 = _byteswap_ulong(layer.EndLayerZeroSector);
|
||||
m_media_type = 2;
|
||||
m_layer_break = end_sector_layer0 - start_sector;
|
||||
m_sectors = end_sector_layer0 - start_sector + 1 + end_sector - (~end_sector_layer0 & 0xFFFFFFU) + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadCDInfo()
|
||||
{
|
||||
DWORD unused;
|
||||
CDROM_READ_TOC_EX toc_ex{};
|
||||
toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_TOC;
|
||||
toc_ex.Msf = 0;
|
||||
toc_ex.SessionTrack = 1;
|
||||
|
||||
CDROM_TOC toc;
|
||||
if (!DeviceIoControl(m_device, IOCTL_CDROM_READ_TOC_EX, &toc_ex,
|
||||
sizeof(toc_ex), &toc, sizeof(toc), &unused, nullptr))
|
||||
return false;
|
||||
|
||||
m_toc.clear();
|
||||
size_t track_count = ((toc.Length[0] << 8) + toc.Length[1] - 2) / sizeof(TRACK_DATA);
|
||||
for (size_t n = 0; n < track_count; ++n) {
|
||||
TRACK_DATA& track = toc.TrackData[n];
|
||||
// Exclude the lead-out track descriptor.
|
||||
if (track.TrackNumber == 0xAA)
|
||||
continue;
|
||||
u32 lba = (track.Address[1] << 16) + (track.Address[2] << 8) + track.Address[3];
|
||||
m_toc.push_back({ lba, track.TrackNumber, track.Adr, track.Control });
|
||||
}
|
||||
|
||||
GET_LENGTH_INFORMATION info;
|
||||
if (!DeviceIoControl(m_device, IOCTL_DISK_GET_LENGTH_INFO, nullptr, 0, &info,
|
||||
sizeof(info), &unused, nullptr))
|
||||
return false;
|
||||
|
||||
m_sectors = static_cast<u32>(info.Length.QuadPart / 2048);
|
||||
m_media_type = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::DiscReady()
|
||||
{
|
||||
if (m_device == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
DWORD unused;
|
||||
if (DeviceIoControl(m_device, IOCTL_STORAGE_CHECK_VERIFY, nullptr, 0,
|
||||
nullptr, 0, &unused, nullptr)) {
|
||||
if (!m_sectors)
|
||||
Reopen();
|
||||
}
|
||||
else {
|
||||
m_sectors = 0;
|
||||
m_layer_break = 0;
|
||||
m_media_type = 0;
|
||||
}
|
||||
|
||||
return !!m_sectors;
|
||||
}
|
|
@ -183,6 +183,7 @@ set(pcsx2CDVDSources
|
|||
CDVD/CDVD.cpp
|
||||
CDVD/CDVDdiscReader.cpp
|
||||
CDVD/CDVDisoReader.cpp
|
||||
CDVD/CDVDdiscThread.cpp
|
||||
CDVD/InputIsoFile.cpp
|
||||
CDVD/OutputIsoFile.cpp
|
||||
CDVD/ChunksCache.cpp
|
||||
|
@ -402,6 +403,8 @@ set(pcsx2IPUHeaders
|
|||
|
||||
# Linux sources
|
||||
set(pcsx2LinuxSources
|
||||
CDVD/Unix/DriveUtility.cpp
|
||||
CDVD/Unix/IOCtlSrc.cpp
|
||||
gui/CpuUsageProviderLnx.cpp
|
||||
Linux/LnxConsolePipe.cpp
|
||||
Linux/LnxKeyCodes.cpp
|
||||
|
@ -409,6 +412,8 @@ set(pcsx2LinuxSources
|
|||
)
|
||||
|
||||
set(pcsx2OSXSources
|
||||
CDVD/Unix/DriveUtility.cpp
|
||||
CDVD/Unix/IOCtlSrc.cpp
|
||||
gui/CpuUsageProviderLnx.cpp
|
||||
Linux/LnxConsolePipe.cpp
|
||||
# Linux/LnxKeyCodes.cpp
|
||||
|
@ -515,6 +520,8 @@ set(pcsx2ZipToolsHeaders
|
|||
|
||||
# Windows sources
|
||||
set(pcsx2WindowsSources
|
||||
CDVD/Windows/DriveUtility.cpp
|
||||
CDVD/Windows/IOCtlSrc.cpp
|
||||
gui/CpuUsageProviderMSW.cpp
|
||||
windows/FlatFileReaderWindows.cpp
|
||||
windows/Optimus.cpp
|
||||
|
@ -631,7 +638,12 @@ set(Common
|
|||
if(Linux)
|
||||
set(Platform
|
||||
${pcsx2LinuxSources}
|
||||
${pcsx2LinuxHeaders})
|
||||
${pcsx2LinuxHeaders}
|
||||
)
|
||||
|
||||
set(Platform_Libs
|
||||
${LIBUDEV_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Windows
|
||||
|
@ -646,6 +658,10 @@ if(APPLE)
|
|||
set(Platform
|
||||
${pcsx2OSXSources}
|
||||
${pcsx2LinuxHeaders})
|
||||
|
||||
set(Platform_Libs
|
||||
${LIBUDEV_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" OR ${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
|
||||
|
@ -667,6 +683,7 @@ set(pcsx2FinalLibs
|
|||
${ZLIB_LIBRARIES}
|
||||
${AIO_LIBRARIES}
|
||||
${GCOV_LIBRARIES}
|
||||
${Platform_Libs}
|
||||
)
|
||||
|
||||
if(BUILTIN_GS)
|
||||
|
|
|
@ -24,7 +24,6 @@ enum PluginsEnum_t
|
|||
PluginId_GS = 0,
|
||||
PluginId_PAD,
|
||||
PluginId_SPU2,
|
||||
PluginId_CDVD,
|
||||
PluginId_USB,
|
||||
PluginId_FW,
|
||||
PluginId_DEV9,
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include "GS.h"
|
||||
#include "Gif.h"
|
||||
#include "CDVD/CDVDisoReader.h"
|
||||
|
||||
#include "Utilities/pxStreams.h"
|
||||
|
||||
|
@ -83,7 +82,6 @@ const PluginInfo tbl_PluginInfo[] =
|
|||
{ "GS", PluginId_GS, PS2E_LT_GS, PS2E_GS_VERSION },
|
||||
{ "PAD", PluginId_PAD, PS2E_LT_PAD, PS2E_PAD_VERSION },
|
||||
{ "SPU2", PluginId_SPU2, PS2E_LT_SPU2, PS2E_SPU2_VERSION },
|
||||
{ "CDVD", PluginId_CDVD, PS2E_LT_CDVD, PS2E_CDVD_VERSION },
|
||||
{ "USB", PluginId_USB, PS2E_LT_USB, PS2E_USB_VERSION },
|
||||
{ "FW", PluginId_FW, PS2E_LT_FW, PS2E_FW_VERSION },
|
||||
{ "DEV9", PluginId_DEV9, PS2E_LT_DEV9, PS2E_DEV9_VERSION },
|
||||
|
@ -447,118 +445,6 @@ static const LegacyApi_OptMethod s_MethMessOpt_PAD[] =
|
|||
{ NULL },
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CDVD Mess!
|
||||
// ----------------------------------------------------------------------------
|
||||
void CALLBACK CDVD_newDiskCB(void (*callback)()) {}
|
||||
|
||||
extern int lastReadSize;
|
||||
extern u32 lastLSN;
|
||||
static s32 CALLBACK CDVD_getBuffer2(u8* buffer)
|
||||
{
|
||||
// TEMP: until I fix all the plugins to use this function style
|
||||
u8* pb = CDVD->getBuffer();
|
||||
if(pb == NULL) return -2;
|
||||
|
||||
memcpy( buffer, pb, lastReadSize );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32 CALLBACK CDVD_readSector(u8* buffer, u32 lsn, int mode)
|
||||
{
|
||||
if(CDVD->readTrack(lsn,mode) < 0)
|
||||
return -1;
|
||||
|
||||
// TEMP: until all the plugins use the new CDVDgetBuffer style
|
||||
switch (mode)
|
||||
{
|
||||
case CDVD_MODE_2352:
|
||||
lastReadSize = 2352;
|
||||
break;
|
||||
case CDVD_MODE_2340:
|
||||
lastReadSize = 2340;
|
||||
break;
|
||||
case CDVD_MODE_2328:
|
||||
lastReadSize = 2328;
|
||||
break;
|
||||
case CDVD_MODE_2048:
|
||||
lastReadSize = 2048;
|
||||
break;
|
||||
}
|
||||
|
||||
lastLSN = lsn;
|
||||
return CDVD->getBuffer2(buffer);
|
||||
}
|
||||
|
||||
static s32 CALLBACK CDVD_getDualInfo(s32* dualType, u32* layer1Start)
|
||||
{
|
||||
u8 toc[2064];
|
||||
|
||||
// if error getting toc, settle for single layer disc ;)
|
||||
if(CDVD->getTOC(toc))
|
||||
return 0;
|
||||
|
||||
if(toc[14] & 0x60)
|
||||
{
|
||||
if(toc[14] & 0x10)
|
||||
{
|
||||
// otp dvd
|
||||
*dualType = 2;
|
||||
*layer1Start = (toc[25]<<16) + (toc[26]<<8) + (toc[27]) - 0x30000 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ptp dvd
|
||||
*dualType = 1;
|
||||
*layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// single layer dvd
|
||||
*dualType = 0;
|
||||
*layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
CDVD_API CDVDapi_Plugin =
|
||||
{
|
||||
// All of these are filled by the plugin manager
|
||||
NULL
|
||||
};
|
||||
|
||||
CDVD_API* CDVD = NULL;
|
||||
|
||||
static const LegacyApi_ReqMethod s_MethMessReq_CDVD[] =
|
||||
{
|
||||
{ "CDVDopen", (vMeth**)&CDVDapi_Plugin.open, NULL },
|
||||
{ "CDVDclose", (vMeth**)&CDVDapi_Plugin.close, NULL },
|
||||
{ "CDVDreadTrack", (vMeth**)&CDVDapi_Plugin.readTrack, NULL },
|
||||
{ "CDVDgetBuffer", (vMeth**)&CDVDapi_Plugin.getBuffer, NULL },
|
||||
{ "CDVDreadSubQ", (vMeth**)&CDVDapi_Plugin.readSubQ, NULL },
|
||||
{ "CDVDgetTN", (vMeth**)&CDVDapi_Plugin.getTN, NULL },
|
||||
{ "CDVDgetTD", (vMeth**)&CDVDapi_Plugin.getTD, NULL },
|
||||
{ "CDVDgetTOC", (vMeth**)&CDVDapi_Plugin.getTOC, NULL },
|
||||
{ "CDVDgetDiskType", (vMeth**)&CDVDapi_Plugin.getDiskType, NULL },
|
||||
{ "CDVDgetTrayStatus",(vMeth**)&CDVDapi_Plugin.getTrayStatus, NULL },
|
||||
{ "CDVDctrlTrayOpen", (vMeth**)&CDVDapi_Plugin.ctrlTrayOpen, NULL },
|
||||
{ "CDVDctrlTrayClose",(vMeth**)&CDVDapi_Plugin.ctrlTrayClose, NULL },
|
||||
{ "CDVDnewDiskCB", (vMeth**)&CDVDapi_Plugin.newDiskCB, (vMeth*)CDVD_newDiskCB },
|
||||
|
||||
{ "CDVDreadSector", (vMeth**)&CDVDapi_Plugin.readSector, (vMeth*)CDVD_readSector },
|
||||
{ "CDVDgetBuffer2", (vMeth**)&CDVDapi_Plugin.getBuffer2, (vMeth*)CDVD_getBuffer2 },
|
||||
{ "CDVDgetDualInfo", (vMeth**)&CDVDapi_Plugin.getDualInfo, (vMeth*)CDVD_getDualInfo },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const LegacyApi_OptMethod s_MethMessOpt_CDVD[] =
|
||||
{
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// SPU2 Mess!
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -671,7 +557,6 @@ static const LegacyApi_ReqMethod* const s_MethMessReq[] =
|
|||
s_MethMessReq_GS,
|
||||
s_MethMessReq_PAD,
|
||||
s_MethMessReq_SPU2,
|
||||
s_MethMessReq_CDVD,
|
||||
s_MethMessReq_USB,
|
||||
s_MethMessReq_FW,
|
||||
s_MethMessReq_DEV9
|
||||
|
@ -682,7 +567,6 @@ static const LegacyApi_OptMethod* const s_MethMessOpt[] =
|
|||
s_MethMessOpt_GS,
|
||||
s_MethMessOpt_PAD,
|
||||
s_MethMessOpt_SPU2,
|
||||
s_MethMessOpt_CDVD,
|
||||
s_MethMessOpt_USB,
|
||||
s_MethMessOpt_FW,
|
||||
s_MethMessOpt_DEV9
|
||||
|
@ -851,9 +735,6 @@ void* StaticLibrary::GetSymbol(const wxString &name)
|
|||
#ifdef BUILTIN_SPU2_PLUGIN
|
||||
RETURN_COMMON_SYMBOL(SPU2);
|
||||
#endif
|
||||
#ifdef BUILTIN_CDVD_PLUGIN
|
||||
RETURN_COMMON_SYMBOL(CDVD);
|
||||
#endif
|
||||
#ifdef BUILTIN_DEV9_PLUGIN
|
||||
RETURN_COMMON_SYMBOL(DEV9);
|
||||
#endif
|
||||
|
@ -921,9 +802,6 @@ SysCorePlugins::PluginStatus_t::PluginStatus_t( PluginsEnum_t _pid, const wxStri
|
|||
#ifdef BUILTIN_SPU2_PLUGIN
|
||||
case PluginId_SPU2:
|
||||
#endif
|
||||
#ifdef BUILTIN_CDVD_PLUGIN
|
||||
case PluginId_CDVD:
|
||||
#endif
|
||||
#ifdef BUILTIN_DEV9_PLUGIN
|
||||
case PluginId_DEV9:
|
||||
#endif
|
||||
|
@ -1105,8 +983,6 @@ void SysCorePlugins::Load( const wxString (&folders)[PluginId_Count] )
|
|||
} while( ++pi, pi->shortname != NULL );
|
||||
indent.LeaveScope();
|
||||
|
||||
CDVDapi_Plugin.newDiskCB( cdvdNewDiskCB );
|
||||
|
||||
// Hack for PAD's stupid parameter passed on Init
|
||||
PADinit = (_PADinit)m_info[PluginId_PAD]->CommonBindings.Init;
|
||||
m_info[PluginId_PAD]->CommonBindings.Init = _hack_PADinit;
|
||||
|
@ -1190,11 +1066,6 @@ extern void spu2DMA4Irq();
|
|||
extern void spu2DMA7Irq();
|
||||
extern void spu2Irq();
|
||||
|
||||
bool SysCorePlugins::OpenPlugin_CDVD()
|
||||
{
|
||||
return DoCDVDopen();
|
||||
}
|
||||
|
||||
bool SysCorePlugins::OpenPlugin_GS()
|
||||
{
|
||||
GetMTGS().Resume();
|
||||
|
@ -1271,7 +1142,6 @@ void SysCorePlugins::Open( PluginsEnum_t pid )
|
|||
{
|
||||
case PluginId_GS: result = OpenPlugin_GS(); break;
|
||||
case PluginId_PAD: result = OpenPlugin_PAD(); break;
|
||||
case PluginId_CDVD: result = OpenPlugin_CDVD(); break;
|
||||
case PluginId_SPU2: result = OpenPlugin_SPU2(); break;
|
||||
case PluginId_USB: result = OpenPlugin_USB(); break;
|
||||
case PluginId_FW: result = OpenPlugin_FW(); break;
|
||||
|
@ -1342,11 +1212,6 @@ void SysCorePlugins::ClosePlugin_GS()
|
|||
}
|
||||
}
|
||||
|
||||
void SysCorePlugins::ClosePlugin_CDVD()
|
||||
{
|
||||
DoCDVDclose();
|
||||
}
|
||||
|
||||
void SysCorePlugins::ClosePlugin_PAD()
|
||||
{
|
||||
_generalclose( PluginId_PAD );
|
||||
|
@ -1391,7 +1256,6 @@ void SysCorePlugins::Close( PluginsEnum_t pid )
|
|||
{
|
||||
case PluginId_GS: ClosePlugin_GS(); break;
|
||||
case PluginId_PAD: ClosePlugin_PAD(); break;
|
||||
case PluginId_CDVD: ClosePlugin_CDVD(); break;
|
||||
case PluginId_SPU2: ClosePlugin_SPU2(); break;
|
||||
case PluginId_USB: ClosePlugin_USB(); break;
|
||||
case PluginId_FW: ClosePlugin_FW(); break;
|
||||
|
|
|
@ -189,7 +189,7 @@ typedef void CALLBACK FnType_SetDir( const char* dir );
|
|||
// Important: Contents of this structure must match the order of the contents of the
|
||||
// s_MethMessCommon[] array defined in Plugins.cpp.
|
||||
//
|
||||
// Note: Open is excluded from this list because the GS and CDVD have custom signatures >_<
|
||||
// Note: Open is excluded from this list because the GS has a custom signatures >_<
|
||||
//
|
||||
struct LegacyPluginAPI_Common
|
||||
{
|
||||
|
@ -401,7 +401,6 @@ protected:
|
|||
virtual bool NeedsUnload() const;
|
||||
|
||||
virtual bool OpenPlugin_GS();
|
||||
virtual bool OpenPlugin_CDVD();
|
||||
virtual bool OpenPlugin_PAD();
|
||||
virtual bool OpenPlugin_SPU2();
|
||||
virtual bool OpenPlugin_DEV9();
|
||||
|
@ -412,7 +411,6 @@ protected:
|
|||
void _generalclose( PluginsEnum_t pid );
|
||||
|
||||
virtual void ClosePlugin_GS();
|
||||
virtual void ClosePlugin_CDVD();
|
||||
virtual void ClosePlugin_PAD();
|
||||
virtual void ClosePlugin_SPU2();
|
||||
virtual void ClosePlugin_DEV9();
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "Utilities/SafeArray.h"
|
||||
#include "Utilities/Threading.h" // to use threading stuff, include the Threading namespace in your file.
|
||||
#include "CDVD/CDVDaccess.h"
|
||||
#include "Plugins.h"
|
||||
|
||||
#include "vtlb.h"
|
||||
|
||||
|
|
|
@ -279,11 +279,13 @@ void SysCoreThread::ExecuteTaskInThread()
|
|||
void SysCoreThread::OnSuspendInThread()
|
||||
{
|
||||
GetCorePlugins().Close();
|
||||
DoCDVDclose();
|
||||
}
|
||||
|
||||
void SysCoreThread::OnResumeInThread( bool isSuspended )
|
||||
{
|
||||
GetCorePlugins().Open();
|
||||
DoCDVDopen();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -100,7 +100,6 @@ enum MenuIdentifiers
|
|||
MenuId_Cdvd_Source,
|
||||
MenuId_DriveSelector,
|
||||
MenuId_Src_Iso,
|
||||
MenuId_Src_Plugin,
|
||||
MenuId_Src_Disc,
|
||||
MenuId_Src_NoDisc,
|
||||
MenuId_Boot_Iso, // Opens submenu with Iso browser, and recent isos.
|
||||
|
@ -804,6 +803,7 @@ extern void ShutdownPlugins();
|
|||
|
||||
extern bool SysHasValidState();
|
||||
extern void SysUpdateIsoSrcFile( const wxString& newIsoFile );
|
||||
extern void SysUpdateDiscSrcDrive( const wxString& newDiscDrive );
|
||||
extern void SysStatus( const wxString& text );
|
||||
|
||||
extern bool HasMainFrame();
|
||||
|
|
|
@ -641,6 +641,7 @@ void AppConfig::LoadSaveRootItems( IniInterface& ini )
|
|||
ini.Entry( L"CurrentIso", res, res, ini.IsLoading() || IsPortable() );
|
||||
CurrentIso = res.GetFullPath();
|
||||
|
||||
IniEntry( CurrentDisc );
|
||||
IniEntry( CurrentBlockdump );
|
||||
IniEntry( CurrentELF );
|
||||
IniEntry( CurrentIRX );
|
||||
|
@ -725,8 +726,9 @@ AppConfig::FolderOptions::FolderOptions()
|
|||
, Cheats ( PathDefs::GetCheats() )
|
||||
, CheatsWS ( PathDefs::GetCheatsWS() )
|
||||
|
||||
, RunIso( PathDefs::GetDocuments() ) // raw default is always the Documents folder.
|
||||
, RunELF( PathDefs::GetDocuments() ) // raw default is always the Documents folder.
|
||||
, RunIso ( PathDefs::GetDocuments() ) // raw default is always the Documents folder.
|
||||
, RunELF ( PathDefs::GetDocuments() ) // raw default is always the Documents folder.
|
||||
, RunDisc ( PathDefs::GetDocuments() )
|
||||
{
|
||||
bitset = 0xffffffff;
|
||||
}
|
||||
|
@ -766,6 +768,7 @@ void AppConfig::FolderOptions::LoadSave( IniInterface& ini )
|
|||
|
||||
IniEntryDirFile( RunIso, rel );
|
||||
IniEntryDirFile( RunELF, rel );
|
||||
IniEntryDirFile( RunDisc, rel );
|
||||
|
||||
if( ini.IsLoading() )
|
||||
{
|
||||
|
@ -1254,7 +1257,14 @@ static void LoadUiSettings()
|
|||
g_Conf->LoadSave( loader );
|
||||
|
||||
if( !wxFile::Exists( g_Conf->CurrentIso ) )
|
||||
{
|
||||
g_Conf->CurrentIso.clear();
|
||||
}
|
||||
|
||||
if( !wxDirExists( g_Conf->CurrentDisc ) )
|
||||
{
|
||||
g_Conf->CurrentDisc.clear();
|
||||
}
|
||||
|
||||
sApp.DispatchUiSettingsEvent( loader );
|
||||
}
|
||||
|
@ -1287,9 +1297,17 @@ void AppLoadSettings()
|
|||
static void SaveUiSettings()
|
||||
{
|
||||
if( !wxFile::Exists( g_Conf->CurrentIso ) )
|
||||
{
|
||||
g_Conf->CurrentIso.clear();
|
||||
}
|
||||
|
||||
if( !wxDirExists( g_Conf->CurrentDisc ) )
|
||||
{
|
||||
g_Conf->CurrentDisc.clear();
|
||||
}
|
||||
|
||||
sApp.GetRecentIsoManager().Add( g_Conf->CurrentIso );
|
||||
//TODO_CDVD Should this be done for CurrentDisc?
|
||||
|
||||
AppIniSaver saver;
|
||||
g_Conf->LoadSave( saver );
|
||||
|
|
|
@ -166,6 +166,7 @@ public:
|
|||
|
||||
wxDirName RunIso; // last used location for Iso loading.
|
||||
wxDirName RunELF; // last used location for ELF loading.
|
||||
wxDirName RunDisc; // last used location for Disc loading.
|
||||
|
||||
FolderOptions();
|
||||
void LoadSave( IniInterface& conf );
|
||||
|
@ -324,6 +325,7 @@ public:
|
|||
bool AskOnBoot;
|
||||
|
||||
wxString CurrentIso;
|
||||
wxString CurrentDisc;
|
||||
wxString CurrentBlockdump;
|
||||
wxString CurrentELF;
|
||||
wxString CurrentIRX;
|
||||
|
|
|
@ -178,7 +178,7 @@ void AppCoreThread::ChangeCdvdSource()
|
|||
// Fast change of the CDVD source only -- a Pause will suffice.
|
||||
|
||||
ScopedCoreThreadPause paused_core;
|
||||
GetCorePlugins().Close( PluginId_CDVD );
|
||||
//TODO_CDVD close CDVDdiscReader here?
|
||||
CDVDsys_ChangeSource( cdvdsrc );
|
||||
paused_core.AllowResume();
|
||||
|
||||
|
@ -541,7 +541,7 @@ void AppCoreThread::OnResumeInThread( bool isSuspended )
|
|||
{
|
||||
if( m_resetCdvd )
|
||||
{
|
||||
GetCorePlugins().Close( PluginId_CDVD );
|
||||
//TODO_CDVD close CDVDdiscReader here?
|
||||
CDVDsys_ChangeSource( g_Conf->CdvdSource );
|
||||
cdvdCtrlTrayOpen();
|
||||
m_resetCdvd = false;
|
||||
|
|
|
@ -229,8 +229,7 @@ void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser )
|
|||
parser.AddOption( wxEmptyString,L"elf", _("executes an ELF image"), wxCMD_LINE_VAL_STRING );
|
||||
parser.AddOption( wxEmptyString,L"irx", _("executes an IRX image"), wxCMD_LINE_VAL_STRING );
|
||||
parser.AddSwitch( wxEmptyString,L"nodisc", _("boots an empty DVD tray; use to enter the PS2 system menu") );
|
||||
//TODO_CDVD update string
|
||||
parser.AddSwitch( wxEmptyString,L"usecd", _("boots from the CDVD plugin (overrides IsoFile parameter)") );
|
||||
parser.AddSwitch( wxEmptyString,L"usecd", _("boots from the disc drive (overrides IsoFile parameter)") );
|
||||
|
||||
parser.AddSwitch( wxEmptyString,L"nohacks", _("disables all speedhacks") );
|
||||
parser.AddOption( wxEmptyString,L"gamefixes", _("use the specified comma or pipe-delimited list of gamefixes.") + fixlist, wxCMD_LINE_VAL_STRING );
|
||||
|
@ -364,8 +363,7 @@ bool Pcsx2App::OnCmdLineParsed( wxCmdLineParser& parser )
|
|||
|
||||
if( parser.Found(L"usecd") )
|
||||
{
|
||||
//TODO_CDVD change plugin to disc
|
||||
Startup.CdvdSource = CDVD_SourceType::Plugin;
|
||||
Startup.CdvdSource = CDVD_SourceType::Disc;
|
||||
Startup.SysAutoRun = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1180,8 +1180,13 @@ void SysStatus( const wxString& text )
|
|||
void SysUpdateIsoSrcFile( const wxString& newIsoFile )
|
||||
{
|
||||
g_Conf->CurrentIso = newIsoFile;
|
||||
sMainFrame.UpdateIsoSrcSelection();
|
||||
sMainFrame.UpdateStatusBar();
|
||||
sMainFrame.UpdateCdvdSrcSelection();
|
||||
}
|
||||
|
||||
void SysUpdateDiscSrcDrive( const wxString& newDiscDrive )
|
||||
{
|
||||
g_Conf->CurrentDisc = newDiscDrive;
|
||||
sMainFrame.UpdateCdvdSrcSelection();
|
||||
}
|
||||
|
||||
bool HasMainFrame()
|
||||
|
|
|
@ -15,35 +15,31 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Dialogs/ModalPopups.h"
|
||||
#include "../CDVD/CDVDdiscReader.h"
|
||||
|
||||
static wxArrayString GetOpticalDriveList()
|
||||
{
|
||||
DWORD size = GetLogicalDriveStrings(0, nullptr);
|
||||
std::vector<wchar_t> drive_strings(size);
|
||||
if (GetLogicalDriveStrings(size, drive_strings.data()) != size - 1)
|
||||
return {};
|
||||
|
||||
wxArrayString drives;
|
||||
for (auto p = drive_strings.data(); *p; ++p) {
|
||||
if (GetDriveType(p) == DRIVE_CDROM)
|
||||
drives.Add(p);
|
||||
while (*p)
|
||||
++p;
|
||||
}
|
||||
return drives;
|
||||
}
|
||||
|
||||
Dialogs::DriveSelectorDialog::DriveSelectorDialog(wxWindow* parent)
|
||||
Dialogs::DriveSelectorDialog::DriveSelectorDialog(wxWindow* parent, wxString curDrive)
|
||||
: wxDialog(parent, wxID_ANY, "")
|
||||
{
|
||||
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
|
||||
wxStaticBoxSizer* staticSizer = new wxStaticBoxSizer(wxVERTICAL, this, "Source drive...");
|
||||
wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
wxArrayString driveList = GetOpticalDriveList();
|
||||
auto drives = GetOpticalDriveList();
|
||||
wxArrayString driveList;
|
||||
|
||||
for (auto i : drives)
|
||||
{
|
||||
driveList.Add(i);
|
||||
}
|
||||
|
||||
choiceDrive = new wxChoice(this, wxID_ANY, wxDefaultPosition, { 240, 40 }, driveList);
|
||||
|
||||
int driveIndex = choiceDrive->FindString(curDrive);
|
||||
if (driveIndex != wxNOT_FOUND)
|
||||
{
|
||||
choiceDrive->SetSelection(driveIndex);
|
||||
}
|
||||
|
||||
wxButton* btnOk = new wxButton(this, wxID_OK);
|
||||
wxButton* btnCancel = new wxButton(this, wxID_CANCEL);
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace Dialogs
|
|||
class DriveSelectorDialog : public wxDialog
|
||||
{
|
||||
public:
|
||||
DriveSelectorDialog( wxWindow* parent );
|
||||
DriveSelectorDialog( wxWindow* parent, wxString curDrive );
|
||||
wxString GetSelectedDrive();
|
||||
private:
|
||||
wxChoice* choiceDrive;
|
||||
|
|
|
@ -229,7 +229,6 @@ void MainEmuFrame::ConnectMenus()
|
|||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_IsoClear_Click, this, MenuId_IsoClear);
|
||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_CdvdSource_Click, this, MenuId_Src_Iso);
|
||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_DiscBrowse_Click, this, MenuId_DriveSelector);
|
||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_CdvdSource_Click, this, MenuId_Src_Disc);
|
||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_DriveSelector_Click, this, MenuId_DriveSelector);
|
||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_CdvdSource_Click, this, MenuId_Src_Disc);
|
||||
Bind(wxEVT_MENU, &MainEmuFrame::Menu_CdvdSource_Click, this, MenuId_Src_NoDisc);
|
||||
|
|
|
@ -144,7 +144,7 @@ public:
|
|||
void OnLogBoxHidden();
|
||||
|
||||
bool IsPaused() const { return GetMenuBar()->IsChecked( MenuId_Sys_SuspendResume ); }
|
||||
void UpdateIsoSrcSelection();
|
||||
void UpdateCdvdSrcSelection();
|
||||
void RemoveCdvdMenu();
|
||||
void EnableMenuItem( int id, bool enable );
|
||||
void CheckMenuItem(int id, bool checked);
|
||||
|
@ -189,7 +189,7 @@ protected:
|
|||
|
||||
void Menu_IsoBrowse_Click(wxCommandEvent &event);
|
||||
void Menu_IsoClear_Click(wxCommandEvent &event);
|
||||
void Menu_DriveSelector_Click(wxCommandEvent &event);
|
||||
void Menu_DiscBrowse_Click(wxCommandEvent &event);
|
||||
void Menu_EnableBackupStates_Click(wxCommandEvent &event);
|
||||
void Menu_EnablePatches_Click(wxCommandEvent &event);
|
||||
void Menu_EnableCheats_Click(wxCommandEvent &event);
|
||||
|
@ -249,6 +249,7 @@ protected:
|
|||
void _DoBootCdvd();
|
||||
bool _DoSelectIsoBrowser( wxString& dest );
|
||||
bool _DoSelectELFBrowser();
|
||||
bool _DoSelectDiscBrowser( wxString& driveLetter );
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// MainEmuFram Internal API for Populating Main Menu Contents
|
||||
|
|
|
@ -174,7 +174,54 @@ wxWindowID SwapOrReset_Iso( wxWindow* owner, IScopedCoreThread& core_control, co
|
|||
core_control.AllowResume();
|
||||
}
|
||||
|
||||
GetMainFrame().EnableCdvdPluginSubmenu( g_Conf->CdvdSource == CDVD_SourceType::Plugin);
|
||||
//TODO_CDVD enable/disable disc selector menu item
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return values:
|
||||
// wxID_CANCEL - User canceled the action outright.
|
||||
// wxID_RESET - User wants to reset the emu in addition to swap discs
|
||||
// (anything else) - Standard swap, no reset. (hotswap!)
|
||||
wxWindowID SwapOrReset_Disc( wxWindow* owner, IScopedCoreThread& core, const wxString driveLetter)
|
||||
{
|
||||
wxWindowID result = wxID_CANCEL;
|
||||
|
||||
if ((g_Conf->CdvdSource == CDVD_SourceType::Disc) && (driveLetter == g_Conf->CurrentDisc))
|
||||
{
|
||||
core.AllowResume();
|
||||
return result;
|
||||
}
|
||||
|
||||
if (SysHasValidState())
|
||||
{
|
||||
core.DisallowResume();
|
||||
wxDialogWithHelpers dialog(owner, _("Confirm disc change"));
|
||||
|
||||
dialog += dialog.Heading("New drive selected: " + driveLetter);
|
||||
dialog += dialog.GetCharHeight();
|
||||
dialog += dialog.Heading(_("Do you want to swap discs or boot the new disc (via system reset)?"));
|
||||
|
||||
result = pxIssueConfirmation(dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap"));
|
||||
if (result == wxID_CANCEL)
|
||||
{
|
||||
core.AllowResume();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
g_Conf->CdvdSource = CDVD_SourceType::Disc;
|
||||
SysUpdateDiscSrcDrive(driveLetter);
|
||||
if (result == wxID_RESET)
|
||||
{
|
||||
core.DisallowResume();
|
||||
sApp.SysExecute(CDVD_SourceType::Disc);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Indent().WriteLn("Hot swapping to new disc!");
|
||||
core.AllowResume();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -202,7 +249,7 @@ wxWindowID SwapOrReset_CdvdSrc( wxWindow* owner, CDVD_SourceType newsrc )
|
|||
if( result == wxID_CANCEL )
|
||||
{
|
||||
core.AllowResume();
|
||||
sMainFrame.UpdateIsoSrcSelection();
|
||||
sMainFrame.UpdateCdvdSrcSelection();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +263,7 @@ wxWindowID SwapOrReset_CdvdSrc( wxWindow* owner, CDVD_SourceType newsrc )
|
|||
WX_STR(wxString(CDVD_SourceLabels[enum_cast(oldsrc)])),
|
||||
WX_STR(wxString(CDVD_SourceLabels[enum_cast(newsrc)])));
|
||||
//CoreThread.ChangeCdvdSource();
|
||||
sMainFrame.UpdateIsoSrcSelection();
|
||||
sMainFrame.UpdateCdvdSrcSelection();
|
||||
core.AllowResume();
|
||||
}
|
||||
else
|
||||
|
@ -225,7 +272,7 @@ wxWindowID SwapOrReset_CdvdSrc( wxWindow* owner, CDVD_SourceType newsrc )
|
|||
sApp.SysExecute( g_Conf->CdvdSource );
|
||||
}
|
||||
|
||||
GetMainFrame().EnableCdvdPluginSubmenu( g_Conf->CdvdSource == CDVD_SourceType::Plugin );
|
||||
//TODO_CDVD enable/disable disc selector menu item
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -311,6 +358,20 @@ bool MainEmuFrame::_DoSelectELFBrowser()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool MainEmuFrame::_DoSelectDiscBrowser(wxString& driveLetter)
|
||||
{
|
||||
DriveSelectorDialog driveDialog(this, g_Conf->Folders.RunDisc.ToString());
|
||||
|
||||
if (driveDialog.ShowModal() != wxID_CANCEL)
|
||||
{
|
||||
driveLetter = driveDialog.GetSelectedDrive();
|
||||
g_Conf->Folders.RunDisc = wxDirName(driveLetter);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainEmuFrame::_DoBootCdvd()
|
||||
{
|
||||
ScopedCoreThreadPause paused_core;
|
||||
|
@ -347,6 +408,37 @@ void MainEmuFrame::_DoBootCdvd()
|
|||
SysUpdateIsoSrcFile( result );
|
||||
}
|
||||
}
|
||||
else if( g_Conf->CdvdSource == CDVD_SourceType::Disc )
|
||||
{
|
||||
bool selector = g_Conf->CurrentDisc.IsEmpty();
|
||||
|
||||
if( !selector && !wxDirExists(g_Conf->CurrentDisc) )
|
||||
{
|
||||
// The previous mounted disc isn't mounted anymore
|
||||
|
||||
wxDialogWithHelpers dialog( this, _("Drive not mounted!") );
|
||||
dialog += dialog.Heading(
|
||||
_("An error occured while trying to read drive: ") + g_Conf->CurrentDisc + L"\n\n" +
|
||||
_("Error: The configured drive does not exist. Click OK to select a new drive for CDVD.")
|
||||
);
|
||||
|
||||
pxIssueConfirmation( dialog, MsgButtons().OK() );
|
||||
|
||||
selector = true;
|
||||
}
|
||||
|
||||
if( selector || g_Conf->AskOnBoot )
|
||||
{
|
||||
wxString driveLetter;
|
||||
if( !_DoSelectDiscBrowser( driveLetter ) )
|
||||
{
|
||||
paused_core.AllowResume();
|
||||
return;
|
||||
}
|
||||
|
||||
SysUpdateDiscSrcDrive( driveLetter );
|
||||
}
|
||||
}
|
||||
|
||||
if( SysHasValidState() )
|
||||
{
|
||||
|
@ -364,21 +456,6 @@ void MainEmuFrame::_DoBootCdvd()
|
|||
sApp.SysExecute( g_Conf->CdvdSource );
|
||||
}
|
||||
|
||||
void MainEmuFrame::Menu_DriveSelector_Click(wxCommandEvent& event)
|
||||
{
|
||||
DriveSelectorDialog driveDialog(this);
|
||||
if (driveDialog.ShowModal() == wxID_OK)
|
||||
{
|
||||
wxString driveLetter = driveDialog.GetSelectedDrive();
|
||||
//TODO_CDVD send driveLetter to CDVDdiscReader
|
||||
}
|
||||
}
|
||||
|
||||
void MainEmuFrame::EnableCdvdPluginSubmenu(bool isEnable)
|
||||
{
|
||||
EnableMenuItem( GetPluginMenuId_Settings(PluginId_CDVD), isEnable );
|
||||
}
|
||||
|
||||
void MainEmuFrame::Menu_CdvdSource_Click( wxCommandEvent &event )
|
||||
{
|
||||
CDVD_SourceType newsrc = CDVD_SourceType::NoDisc;
|
||||
|
@ -386,7 +463,6 @@ void MainEmuFrame::Menu_CdvdSource_Click( wxCommandEvent &event )
|
|||
switch( event.GetId() )
|
||||
{
|
||||
case MenuId_Src_Iso: newsrc = CDVD_SourceType::Iso; break;
|
||||
case MenuId_Src_Plugin: newsrc = CDVD_SourceType::Plugin; break;
|
||||
case MenuId_Src_Disc: newsrc = CDVD_SourceType::Disc; break;
|
||||
case MenuId_Src_NoDisc: newsrc = CDVD_SourceType::NoDisc; break;
|
||||
jNO_DEFAULT
|
||||
|
@ -409,6 +485,21 @@ void MainEmuFrame::Menu_FastBoot_Click( wxCommandEvent &event )
|
|||
UpdateStatusBar();
|
||||
}
|
||||
|
||||
void MainEmuFrame::Menu_DiscBrowse_Click(wxCommandEvent& event)
|
||||
{
|
||||
ScopedCoreThreadPopup core;
|
||||
wxString driveLetter;
|
||||
|
||||
if ( !_DoSelectDiscBrowser(driveLetter) )
|
||||
{
|
||||
core.AllowResume();
|
||||
return;
|
||||
}
|
||||
|
||||
SwapOrReset_Disc(this, core, driveLetter);
|
||||
AppSaveSettings();
|
||||
}
|
||||
|
||||
wxString GetMsg_IsoImageChanged()
|
||||
{
|
||||
return _("You have selected the following ISO image into PCSX2:\n\n");
|
||||
|
|
|
@ -264,7 +264,6 @@ static const std::unique_ptr<BaseSavestateEntry> SavestateEntries[] = {
|
|||
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_GS )),
|
||||
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_PAD )),
|
||||
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_SPU2 )),
|
||||
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_CDVD )),
|
||||
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_USB )),
|
||||
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_FW )),
|
||||
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_DEV9 ))
|
||||
|
|
|
@ -148,11 +148,28 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="..\..\CDVD\BlockdumpFileReader.cpp" />
|
||||
<ClCompile Include="..\..\CDVD\CDVDdiscReader.cpp" />
|
||||
<ClCompile Include="..\..\CDVD\CDVDdiscThread.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Devel|Win32'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\CDVD\ChunksCache.cpp" />
|
||||
<ClCompile Include="..\..\CDVD\CompressedFileReader.cpp" />
|
||||
<ClCompile Include="..\..\CDVD\CsoFileReader.cpp" />
|
||||
<ClCompile Include="..\..\CDVD\GzippedFileReader.cpp" />
|
||||
<ClCompile Include="..\..\CDVD\OutputIsoFile.cpp" />
|
||||
<ClCompile Include="..\..\CDVD\Unix\DriveUtility.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Devel|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\CDVD\Unix\IOCtlSrc.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Devel|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\CDVD\Windows\DriveUtility.cpp" />
|
||||
<ClCompile Include="..\..\CDVD\Windows\IOCtlSrc.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\Breakpoints.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\DebugInterface.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\DisassemblyManager.cpp" />
|
||||
|
|
|
@ -148,6 +148,12 @@
|
|||
<Filter Include="Recording\gui">
|
||||
<UniqueIdentifier>{93e36831-627f-4529-b709-1f4bad398512}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\Ps2\Iop\CDVD\Windows">
|
||||
<UniqueIdentifier>{be861049-a142-4650-85a5-a2fdd4eef011}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\Ps2\Iop\CDVD\Unix">
|
||||
<UniqueIdentifier>{a5904fb6-e846-4cbf-940c-ca1c604140a0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\Utilities\folderdesc.txt">
|
||||
|
@ -867,6 +873,21 @@
|
|||
<ClCompile Include="..\..\gui\Dialogs\DriveSelectorDialog.cpp">
|
||||
<Filter>AppHost\Dialogs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\CDVD\CDVDdiscThread.cpp">
|
||||
<Filter>System\Ps2\Iop\CDVD</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\CDVD\Windows\DriveUtility.cpp">
|
||||
<Filter>System\Ps2\Iop\CDVD\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\CDVD\Windows\IOCtlSrc.cpp">
|
||||
<Filter>System\Ps2\Iop\CDVD\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\CDVD\Unix\IOCtlSrc.cpp">
|
||||
<Filter>System\Ps2\Iop\CDVD\Unix</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\CDVD\Unix\DriveUtility.cpp">
|
||||
<Filter>System\Ps2\Iop\CDVD\Unix</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\Patch.h">
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
/* CDVDnull
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "CDVD.h"
|
||||
#include "svnrev.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf sprintf_s
|
||||
#endif
|
||||
static char libraryName[256];
|
||||
|
||||
const unsigned char version = PS2E_CDVD_VERSION;
|
||||
const unsigned char revision = 0;
|
||||
const unsigned char build = 6;
|
||||
|
||||
EXPORT_C_(const char *)
|
||||
PS2EgetLibName()
|
||||
{
|
||||
snprintf(libraryName, 255, "CDVDnull Driver %lld%s", SVN_REV, SVN_MODS ? "m" : "");
|
||||
return libraryName;
|
||||
}
|
||||
|
||||
EXPORT_C_(u32)
|
||||
PS2EgetLibType()
|
||||
{
|
||||
return PS2E_LT_CDVD;
|
||||
}
|
||||
|
||||
EXPORT_C_(u32)
|
||||
CALLBACK PS2EgetLibVersion2(u32 type)
|
||||
{
|
||||
return (version << 16) | (revision << 8) | build;
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDinit()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDopen(const char *pTitle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(void)
|
||||
CDVDclose()
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT_C_(void)
|
||||
CDVDshutdown()
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDreadTrack(u32 lsn, int mode)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// return can be NULL (for async modes)
|
||||
EXPORT_C_(u8 *)
|
||||
CDVDgetBuffer()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDreadSubQ(u32 lsn, cdvdSubQ *subq)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDgetTN(cdvdTN *Buffer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDgetTD(u8 Track, cdvdTD *Buffer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDgetTOC(void *toc)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDgetDiskType()
|
||||
{
|
||||
return CDVD_TYPE_NODISC;
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDgetTrayStatus()
|
||||
{
|
||||
return CDVD_TRAY_CLOSE;
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDctrlTrayOpen()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDctrlTrayClose()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(void)
|
||||
CDVDconfigure()
|
||||
{
|
||||
SysMessage("Nothing to Configure");
|
||||
}
|
||||
|
||||
EXPORT_C_(void)
|
||||
CDVDabout()
|
||||
{
|
||||
SysMessage("%s %d.%d", "CDVDnull Driver", revision, build);
|
||||
}
|
||||
|
||||
EXPORT_C_(s32)
|
||||
CDVDtest()
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/* CDVDnull
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __CDVD_H__
|
||||
#define __CDVD_H__
|
||||
|
||||
#define CDVDdefs
|
||||
#include "PS2Edefs.h"
|
||||
#include "PS2Eext.h"
|
||||
|
||||
/*#ifdef _MSC_VER
|
||||
#define EXPORT_C_(type) extern "C" __declspec(dllexport) type CALLBACK
|
||||
#else
|
||||
#define EXPORT_C_(type) extern "C" type
|
||||
#endif*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define EXPORT_C_(type) extern "C" type CALLBACK
|
||||
#else
|
||||
#define EXPORT_C_(type) extern "C" __attribute__((stdcall, externally_visible, visibility("default"))) type
|
||||
#endif
|
||||
|
||||
extern const unsigned char version;
|
||||
extern const unsigned char revision;
|
||||
extern const unsigned char build;
|
||||
extern const unsigned int minor;
|
||||
|
||||
extern void SysMessage(const char *fmt, ...);
|
||||
#endif /* __CDVD_H__ */
|
|
@ -1,44 +0,0 @@
|
|||
# Check that people use the good file
|
||||
if(NOT TOP_CMAKE_WAS_SOURCED)
|
||||
message(FATAL_ERROR "
|
||||
You did not 'cmake' the good CMakeLists.txt file. Use the one in the top dir.
|
||||
It is advice to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt")
|
||||
endif()
|
||||
|
||||
|
||||
# plugin name
|
||||
set(Output CDVDnull)
|
||||
|
||||
set(CDVDnullFinalFlags
|
||||
-fvisibility=hidden
|
||||
-Wall
|
||||
-Wno-parentheses
|
||||
)
|
||||
|
||||
# CDVDnull sources
|
||||
set(CDVDnullSources
|
||||
CDVD.cpp)
|
||||
|
||||
# CDVDnull headers
|
||||
set(CDVDnullHeaders
|
||||
CDVD.h)
|
||||
|
||||
# CDVDnull Windows sources
|
||||
set(CDVDnullWindowsSources
|
||||
Windows/CDVDnull.def
|
||||
Windows/plugin.def)
|
||||
|
||||
# CDVDnull Windows headers
|
||||
set(CDVDnullWindowsHeaders
|
||||
)
|
||||
|
||||
set(CDVDnullFinalSources
|
||||
${CDVDnullSources}
|
||||
${CDVDnullHeaders}
|
||||
)
|
||||
|
||||
set(CDVDnullFinalLibs
|
||||
${GTK2_LIBRARIES}
|
||||
)
|
||||
|
||||
add_pcsx2_plugin(${Output} "${CDVDnullFinalSources}" "${CDVDnullFinalLibs}" "${CDVDnullFinalFlags}")
|
|
@ -1,39 +0,0 @@
|
|||
CDVDnull v0.6
|
||||
---------------
|
||||
|
||||
This is an extension to use with playstation2 emulators
|
||||
as PCSX2 (only one right now).
|
||||
The plugin is free open source code.
|
||||
|
||||
Using:
|
||||
-----
|
||||
Place the file "CDVDnull.dll" at the Plugins directory
|
||||
of the Emulator to use it.
|
||||
|
||||
Changes:
|
||||
-------
|
||||
v0.6:
|
||||
* added vsnet2003 project files.
|
||||
* added support for functions in new plugin version
|
||||
|
||||
v0.5:
|
||||
* added vsnet2005beta1 project files. 64bit plugin should be okay now (Not tested!)
|
||||
|
||||
v0.4:
|
||||
* updated to 0.4.3 specifications
|
||||
|
||||
v0.3:
|
||||
* updated to 0.4.0 specifications
|
||||
|
||||
v0.2:
|
||||
* add the 0.2.9 specifications
|
||||
* CDVDopen refixed
|
||||
|
||||
v0.1:
|
||||
* First Release
|
||||
* Tested with Pcsx2
|
||||
|
||||
Authors:
|
||||
-------
|
||||
<linuzappz@hotmail.com>
|
||||
<shadowpcsx2@yahoo.gr>
|
|
@ -1,29 +0,0 @@
|
|||
; CDVDnull.def : Declares the module parameters for the DLL.
|
||||
|
||||
;LIBRARY "CDVDnull"
|
||||
;DESCRIPTION 'CDVD Null Driver'
|
||||
|
||||
EXPORTS
|
||||
; Explicit exports can go here
|
||||
PS2EgetLibType @2
|
||||
PS2EgetLibName @3
|
||||
PS2EgetLibVersion2 @4
|
||||
CDVDinit @5
|
||||
CDVDshutdown @6
|
||||
CDVDopen @7
|
||||
CDVDclose @8
|
||||
CDVDreadTrack @9
|
||||
CDVDgetBuffer @10
|
||||
CDVDreadSubQ @11
|
||||
CDVDgetTN @12
|
||||
CDVDgetTD @13
|
||||
CDVDgetTOC @14
|
||||
CDVDgetDiskType @15
|
||||
CDVDgetTrayStatus @16
|
||||
CDVDctrlTrayOpen @17
|
||||
CDVDctrlTrayClose @18
|
||||
|
||||
CDVDconfigure @19
|
||||
CDVDtest @20
|
||||
CDVDabout @21
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectName>CDVDnull</ProjectName>
|
||||
<ProjectGuid>{F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}</ProjectGuid>
|
||||
<RootNamespace>CDVDnull</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="..\..\..\common\vsprops\plugin_svnroot.props" />
|
||||
<Import Project="ProjectRootDir.props" />
|
||||
<Import Project="..\..\..\common\vsprops\BaseProperties.props" />
|
||||
<Import Project="..\..\..\common\vsprops\CodeGen_Release.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="..\..\..\common\vsprops\plugin_svnroot.props" />
|
||||
<Import Project="ProjectRootDir.props" />
|
||||
<Import Project="..\..\..\common\vsprops\BaseProperties.props" />
|
||||
<Import Project="..\..\..\common\vsprops\IncrementalLinking.props" />
|
||||
<Import Project="..\..\..\common\vsprops\CodeGen_Debug.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MkTypLibCompatible>true</MkTypLibCompatible>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<TargetEnvironment>Win32</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;_USRDLL;CDVDNULL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x2c0a</Culture>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<ModuleDefinitionFile>.\CDVDnull.def</ModuleDefinitionFile>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_USRDLL;CDVDNULL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<ModuleDefinitionFile>CDVDnull.def</ModuleDefinitionFile>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention></DataExecutionPrevention>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\CDVD.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\CDVD.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CDVDnull.def" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,24 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4a528d75-fc57-4a25-8f63-9efd961ebaac}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\CDVD.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\CDVD.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CDVDnull.def">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,15 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="UserMacros">
|
||||
<SvnRootDir>$(ProjectRootDir)\..\..</SvnRootDir>
|
||||
<SvnCommonDir>$(SvnRootDir)\common</SvnCommonDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30128.1</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<BuildMacro Include="SvnRootDir">
|
||||
<Value>$(SvnRootDir)</Value>
|
||||
</BuildMacro>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,21 +0,0 @@
|
|||
EXPORTS
|
||||
PS2EgetLibType = PS2EgetLibType@0 @2
|
||||
PS2EgetLibName = PS2EgetLibName@0 @3
|
||||
PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @4
|
||||
CDVDinit = CDVDinit@0 @5
|
||||
CDVDshutdown = CDVDshutdown@0 @6
|
||||
CDVDopen = CDVDopen@0 @7
|
||||
CDVDclose = CDVDclose@0 @8
|
||||
CDVDreadTrack = CDVDreadTrack@8 @9
|
||||
CDVDgetBuffer = CDVDgetBuffer@0 @10
|
||||
CDVDreadSubQ = CDVDreadSubQ@8 @11
|
||||
CDVDgetTN = CDVDgetTN@4 @12
|
||||
CDVDgetTD = CDVDgetTD@8 @13
|
||||
CDVDgetTOC = CDVDgetTOC@4 @14
|
||||
CDVDgetDiskType = CDVDgetDiskType@0 @15
|
||||
CDVDgetTrayStatus = CDVDgetTrayStatus@0 @16
|
||||
CDVDctrlTrayOpen = CDVDctrlTrayOpen@0 @17
|
||||
CDVDctrlTrayClose = CDVDctrlTrayClose@0 @18
|
||||
CDVDconfigure = CDVDconfigure@0 @19
|
||||
CDVDtest = CDVDtest@0 @20
|
||||
CDVDabout = CDVDabout@0 @21
|
|
@ -6,14 +6,6 @@ if(NOT TOP_CMAKE_WAS_SOURCED)
|
|||
endif()
|
||||
|
||||
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/cdvdGigaherz" AND cdvdGigaherz)
|
||||
add_subdirectory(cdvdGigaherz/src)
|
||||
endif()
|
||||
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/CDVDnull" AND CDVDnull)
|
||||
add_subdirectory(CDVDnull)
|
||||
endif()
|
||||
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/plugins/dev9null" AND dev9null)
|
||||
add_subdirectory(dev9null)
|
||||
endif()
|
||||
|
|
|
@ -1,516 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2014 David Quintana [gigaherz]
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "CDVD.h"
|
||||
#include <cstdio>
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
#include "svnrev.h"
|
||||
|
||||
Settings g_settings;
|
||||
static std::string s_config_file{"inis/cdvdGigaherz.ini"};
|
||||
|
||||
void (*newDiscCB)();
|
||||
|
||||
static std::mutex s_keepalive_lock;
|
||||
static std::condition_variable s_keepalive_cv;
|
||||
static std::thread s_keepalive_thread;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// State Information //
|
||||
|
||||
u8 strack;
|
||||
u8 etrack;
|
||||
track tracks[100];
|
||||
|
||||
int curDiskType;
|
||||
int curTrayStatus;
|
||||
|
||||
static u32 csector;
|
||||
int cmode;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Plugin Interface //
|
||||
|
||||
#ifndef PCSX2_DEBUG
|
||||
static std::string s_libname("cdvdGigaherz " + std::to_string(SVN_REV));
|
||||
#else
|
||||
static std::string s_libname("cdvdGigaherz Debug " + std::to_string(SVN_REV));
|
||||
#endif
|
||||
|
||||
const unsigned char version = PS2E_CDVD_VERSION;
|
||||
const unsigned char revision = 0;
|
||||
const unsigned char build = 11;
|
||||
|
||||
EXPORT const char *CALLBACK PS2EgetLibName()
|
||||
{
|
||||
return s_libname.c_str();
|
||||
}
|
||||
|
||||
EXPORT u32 CALLBACK PS2EgetLibType()
|
||||
{
|
||||
return PS2E_LT_CDVD;
|
||||
}
|
||||
|
||||
EXPORT u32 CALLBACK PS2EgetLibVersion2(u32 type)
|
||||
{
|
||||
return (version << 16) | (revision << 8) | build;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Utility Functions //
|
||||
|
||||
inline u8 dec_to_bcd(u8 dec)
|
||||
{
|
||||
return ((dec / 10) << 4) | (dec % 10);
|
||||
}
|
||||
|
||||
inline void lsn_to_msf(u8 *minute, u8 *second, u8 *frame, u32 lsn)
|
||||
{
|
||||
*frame = dec_to_bcd(lsn % 75);
|
||||
lsn /= 75;
|
||||
*second = dec_to_bcd(lsn % 60);
|
||||
lsn /= 60;
|
||||
*minute = dec_to_bcd(lsn % 100);
|
||||
}
|
||||
|
||||
void ReadSettings()
|
||||
{
|
||||
g_settings.Load(s_config_file);
|
||||
}
|
||||
|
||||
void WriteSettings()
|
||||
{
|
||||
g_settings.Save(s_config_file);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CDVD processing functions //
|
||||
|
||||
std::atomic<bool> s_keepalive_is_open;
|
||||
bool disc_has_changed = false;
|
||||
bool weAreInNewDiskCB = false;
|
||||
|
||||
std::unique_ptr<IOCtlSrc> src;
|
||||
|
||||
extern u32 g_last_sector_block_lsn;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// keepAliveThread throws a read event regularly to prevent drive spin down //
|
||||
|
||||
void keepAliveThread()
|
||||
{
|
||||
u8 throwaway[2352];
|
||||
|
||||
printf(" * CDVD: KeepAlive thread started...\n");
|
||||
std::unique_lock<std::mutex> guard(s_keepalive_lock);
|
||||
|
||||
while (!s_keepalive_cv.wait_for(guard, std::chrono::seconds(30),
|
||||
[]() { return !s_keepalive_is_open; })) {
|
||||
|
||||
//printf(" * keepAliveThread: polling drive.\n");
|
||||
if (src->GetMediaType() >= 0)
|
||||
src->ReadSectors2048(g_last_sector_block_lsn, 1, throwaway);
|
||||
else
|
||||
src->ReadSectors2352(g_last_sector_block_lsn, 1, throwaway);
|
||||
}
|
||||
|
||||
printf(" * CDVD: KeepAlive thread finished.\n");
|
||||
}
|
||||
|
||||
bool StartKeepAliveThread()
|
||||
{
|
||||
s_keepalive_is_open = true;
|
||||
try {
|
||||
s_keepalive_thread = std::thread(keepAliveThread);
|
||||
} catch (std::system_error &) {
|
||||
s_keepalive_is_open = false;
|
||||
}
|
||||
|
||||
return s_keepalive_is_open;
|
||||
}
|
||||
|
||||
void StopKeepAliveThread()
|
||||
{
|
||||
if (!s_keepalive_thread.joinable())
|
||||
return;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_keepalive_lock);
|
||||
s_keepalive_is_open = false;
|
||||
}
|
||||
s_keepalive_cv.notify_one();
|
||||
s_keepalive_thread.join();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CDVD Pluin Interface //
|
||||
|
||||
EXPORT void CALLBACK CDVDsetSettingsDir(const char *dir)
|
||||
{
|
||||
s_config_file = std::string(dir ? dir : "inis") + "/cdvdGigaherz.ini";
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDinit()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDopen(const char *pTitleFilename)
|
||||
{
|
||||
ReadSettings();
|
||||
|
||||
auto drive = GetValidDrive();
|
||||
if (drive.empty())
|
||||
return -1;
|
||||
|
||||
// open device file
|
||||
try {
|
||||
src = std::unique_ptr<IOCtlSrc>(new IOCtlSrc(drive));
|
||||
} catch (std::runtime_error &ex) {
|
||||
fputs(ex.what(), stdout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//setup threading manager
|
||||
if (!cdvdStartThread()) {
|
||||
src.reset();
|
||||
return -1;
|
||||
}
|
||||
StartKeepAliveThread();
|
||||
|
||||
return cdvdRefreshData();
|
||||
}
|
||||
|
||||
EXPORT void CALLBACK CDVDclose()
|
||||
{
|
||||
StopKeepAliveThread();
|
||||
cdvdStopThread();
|
||||
//close device
|
||||
src.reset();
|
||||
}
|
||||
|
||||
EXPORT void CALLBACK CDVDshutdown()
|
||||
{
|
||||
//nothing to do here
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDgetDualInfo(s32 *dualType, u32 *_layer1start)
|
||||
{
|
||||
switch (src->GetMediaType()) {
|
||||
case 1:
|
||||
*dualType = 1;
|
||||
*_layer1start = src->GetLayerBreakAddress() + 1;
|
||||
return 0;
|
||||
case 2:
|
||||
*dualType = 2;
|
||||
*_layer1start = src->GetLayerBreakAddress() + 1;
|
||||
return 0;
|
||||
case 0:
|
||||
*dualType = 0;
|
||||
*_layer1start = 0;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lastReadInNewDiskCB = 0;
|
||||
u8 directReadSectorBuffer[2448];
|
||||
|
||||
EXPORT s32 CALLBACK CDVDreadSector(u8 *buffer, u32 lsn, int mode)
|
||||
{
|
||||
return cdvdDirectReadSector(lsn, mode, buffer);
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDreadTrack(u32 lsn, int mode)
|
||||
{
|
||||
csector = lsn;
|
||||
cmode = mode;
|
||||
|
||||
if (weAreInNewDiskCB) {
|
||||
int ret = cdvdDirectReadSector(lsn, mode, directReadSectorBuffer);
|
||||
if (ret == 0)
|
||||
lastReadInNewDiskCB = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
cdvdRequestSector(lsn, mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return can be NULL (for async modes)
|
||||
EXPORT u8 *CALLBACK CDVDgetBuffer()
|
||||
{
|
||||
if (lastReadInNewDiskCB) {
|
||||
lastReadInNewDiskCB = 0;
|
||||
return directReadSectorBuffer;
|
||||
}
|
||||
|
||||
return cdvdGetSector(csector, cmode);
|
||||
}
|
||||
|
||||
// return can be NULL (for async modes)
|
||||
EXPORT int CALLBACK CDVDgetBuffer2(u8 *dest)
|
||||
{
|
||||
// Do nothing for out of bounds disc sector reads. It prevents some games
|
||||
// from hanging (All-Star Baseball 2005, Hello Kitty: Roller Rescue,
|
||||
// Hot Wheels: Beat That! (NTSC), Ratchet & Clank 3 (PAL),
|
||||
// Test Drive: Eve of Destruction, etc.).
|
||||
if (csector >= src->GetSectorCount())
|
||||
return 0;
|
||||
|
||||
int csize = 2352;
|
||||
switch (cmode) {
|
||||
case CDVD_MODE_2048:
|
||||
csize = 2048;
|
||||
break;
|
||||
case CDVD_MODE_2328:
|
||||
csize = 2328;
|
||||
break;
|
||||
case CDVD_MODE_2340:
|
||||
csize = 2340;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lastReadInNewDiskCB) {
|
||||
lastReadInNewDiskCB = 0;
|
||||
|
||||
memcpy(dest, directReadSectorBuffer, csize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(dest, cdvdGetSector(csector, cmode), csize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ *subq)
|
||||
{
|
||||
// the formatted subq command returns: control/adr, track, index, trk min, trk sec, trk frm, 0x00, abs min, abs sec, abs frm
|
||||
|
||||
if (lsn >= src->GetSectorCount())
|
||||
return -1;
|
||||
|
||||
memset(subq, 0, sizeof(cdvdSubQ));
|
||||
|
||||
lsn_to_msf(&subq->discM, &subq->discS, &subq->discF, lsn + 150);
|
||||
|
||||
u8 i = strack;
|
||||
while (i < etrack && lsn >= tracks[i + 1].start_lba)
|
||||
++i;
|
||||
|
||||
lsn -= tracks[i].start_lba;
|
||||
|
||||
lsn_to_msf(&subq->trackM, &subq->trackS, &subq->trackF, lsn);
|
||||
|
||||
subq->mode = 1;
|
||||
subq->ctrl = tracks[i].type;
|
||||
subq->trackNum = i;
|
||||
subq->trackIndex = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDgetTN(cdvdTN *Buffer)
|
||||
{
|
||||
Buffer->strack = strack;
|
||||
Buffer->etrack = etrack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer)
|
||||
{
|
||||
if (Track == 0) {
|
||||
Buffer->lsn = src->GetSectorCount();
|
||||
Buffer->type = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Track < strack)
|
||||
return -1;
|
||||
if (Track > etrack)
|
||||
return -1;
|
||||
|
||||
Buffer->lsn = tracks[Track].start_lba;
|
||||
Buffer->type = tracks[Track].type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDgetTOC(void *toc)
|
||||
{
|
||||
u8 *tocBuff = static_cast<u8 *>(toc);
|
||||
if (curDiskType == CDVD_TYPE_NODISC)
|
||||
return -1;
|
||||
|
||||
if (curDiskType == CDVD_TYPE_DETCTDVDS || curDiskType == CDVD_TYPE_DETCTDVDD) {
|
||||
memset(tocBuff, 0, 2048);
|
||||
|
||||
s32 mt = src->GetMediaType();
|
||||
|
||||
if (mt < 0)
|
||||
return -1;
|
||||
|
||||
if (mt == 0) { //single layer
|
||||
// fake it
|
||||
tocBuff[0] = 0x04;
|
||||
tocBuff[1] = 0x02;
|
||||
tocBuff[2] = 0xF2;
|
||||
tocBuff[3] = 0x00;
|
||||
tocBuff[4] = 0x86;
|
||||
tocBuff[5] = 0x72;
|
||||
|
||||
tocBuff[16] = 0x00; // first sector for layer 0
|
||||
tocBuff[17] = 0x03;
|
||||
tocBuff[18] = 0x00;
|
||||
tocBuff[19] = 0x00;
|
||||
} else if (mt == 1) { //PTP
|
||||
u32 layer1start = src->GetLayerBreakAddress() + 0x30000;
|
||||
|
||||
// dual sided
|
||||
tocBuff[0] = 0x24;
|
||||
tocBuff[1] = 0x02;
|
||||
tocBuff[2] = 0xF2;
|
||||
tocBuff[3] = 0x00;
|
||||
tocBuff[4] = 0x41;
|
||||
tocBuff[5] = 0x95;
|
||||
|
||||
tocBuff[14] = 0x61; // PTP
|
||||
|
||||
tocBuff[16] = 0x00;
|
||||
tocBuff[17] = 0x03;
|
||||
tocBuff[18] = 0x00;
|
||||
tocBuff[19] = 0x00;
|
||||
|
||||
tocBuff[20] = (layer1start >> 24);
|
||||
tocBuff[21] = (layer1start >> 16) & 0xff;
|
||||
tocBuff[22] = (layer1start >> 8) & 0xff;
|
||||
tocBuff[23] = (layer1start >> 0) & 0xff;
|
||||
} else { //OTP
|
||||
u32 layer1start = src->GetLayerBreakAddress() + 0x30000;
|
||||
|
||||
// dual sided
|
||||
tocBuff[0] = 0x24;
|
||||
tocBuff[1] = 0x02;
|
||||
tocBuff[2] = 0xF2;
|
||||
tocBuff[3] = 0x00;
|
||||
tocBuff[4] = 0x41;
|
||||
tocBuff[5] = 0x95;
|
||||
|
||||
tocBuff[14] = 0x71; // OTP
|
||||
|
||||
tocBuff[16] = 0x00;
|
||||
tocBuff[17] = 0x03;
|
||||
tocBuff[18] = 0x00;
|
||||
tocBuff[19] = 0x00;
|
||||
|
||||
tocBuff[24] = (layer1start >> 24);
|
||||
tocBuff[25] = (layer1start >> 16) & 0xff;
|
||||
tocBuff[26] = (layer1start >> 8) & 0xff;
|
||||
tocBuff[27] = (layer1start >> 0) & 0xff;
|
||||
}
|
||||
} else if (curDiskType == CDVD_TYPE_DETCTCD) {
|
||||
// cd toc
|
||||
// (could be replaced by 1 command that reads the full toc)
|
||||
u8 min, sec, frm, i;
|
||||
s32 err;
|
||||
cdvdTN diskInfo;
|
||||
cdvdTD trackInfo;
|
||||
memset(tocBuff, 0, 1024);
|
||||
if (CDVDgetTN(&diskInfo) == -1) {
|
||||
diskInfo.etrack = 0;
|
||||
diskInfo.strack = 1;
|
||||
}
|
||||
if (CDVDgetTD(0, &trackInfo) == -1)
|
||||
trackInfo.lsn = 0;
|
||||
|
||||
tocBuff[0] = 0x41;
|
||||
tocBuff[1] = 0x00;
|
||||
|
||||
//Number of FirstTrack
|
||||
tocBuff[2] = 0xA0;
|
||||
tocBuff[7] = dec_to_bcd(diskInfo.strack);
|
||||
|
||||
//Number of LastTrack
|
||||
tocBuff[12] = 0xA1;
|
||||
tocBuff[17] = dec_to_bcd(diskInfo.etrack);
|
||||
|
||||
//DiskLength
|
||||
lba_to_msf(trackInfo.lsn, &min, &sec, &frm);
|
||||
tocBuff[22] = 0xA2;
|
||||
tocBuff[27] = dec_to_bcd(min);
|
||||
tocBuff[28] = dec_to_bcd(sec);
|
||||
tocBuff[29] = dec_to_bcd(frm);
|
||||
|
||||
fprintf(stderr, "Track 0: %u mins %u secs %u frames\n", min, sec, frm);
|
||||
|
||||
for (i = diskInfo.strack; i <= diskInfo.etrack; i++) {
|
||||
err = CDVDgetTD(i, &trackInfo);
|
||||
lba_to_msf(trackInfo.lsn, &min, &sec, &frm);
|
||||
tocBuff[i * 10 + 30] = trackInfo.type;
|
||||
tocBuff[i * 10 + 32] = err == -1 ? 0 : dec_to_bcd(i); //number
|
||||
tocBuff[i * 10 + 37] = dec_to_bcd(min);
|
||||
tocBuff[i * 10 + 38] = dec_to_bcd(sec);
|
||||
tocBuff[i * 10 + 39] = dec_to_bcd(frm);
|
||||
fprintf(stderr, "Track %u: %u mins %u secs %u frames\n", i, min, sec, frm);
|
||||
}
|
||||
} else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDgetDiskType()
|
||||
{
|
||||
return curDiskType;
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDgetTrayStatus()
|
||||
{
|
||||
return curTrayStatus;
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDctrlTrayOpen()
|
||||
{
|
||||
curTrayStatus = CDVD_TRAY_OPEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDctrlTrayClose()
|
||||
{
|
||||
curTrayStatus = CDVD_TRAY_CLOSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT void CALLBACK CDVDnewDiskCB(void (*callback)())
|
||||
{
|
||||
newDiscCB = callback;
|
||||
}
|
||||
|
||||
EXPORT void CALLBACK CDVDconfigure()
|
||||
{
|
||||
configure();
|
||||
}
|
||||
|
||||
EXPORT s32 CALLBACK CDVDtest()
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2014 David Quintana [gigaherz]
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CDVD_H__
|
||||
#define __CDVD_H__
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define CDVDdefs
|
||||
#include <PS2Edefs.h>
|
||||
#include "Settings.h"
|
||||
|
||||
struct track
|
||||
{
|
||||
u32 start_lba;
|
||||
u8 type;
|
||||
};
|
||||
|
||||
extern u8 strack;
|
||||
extern u8 etrack;
|
||||
extern track tracks[100];
|
||||
|
||||
extern int curDiskType;
|
||||
extern int curTrayStatus;
|
||||
|
||||
struct toc_entry
|
||||
{
|
||||
u32 lba;
|
||||
u8 track;
|
||||
u8 adr : 4;
|
||||
u8 control : 4;
|
||||
};
|
||||
|
||||
class IOCtlSrc
|
||||
{
|
||||
IOCtlSrc(const IOCtlSrc &) = delete;
|
||||
IOCtlSrc &operator=(const IOCtlSrc &) = delete;
|
||||
|
||||
#if defined(_WIN32)
|
||||
HANDLE m_device = INVALID_HANDLE_VALUE;
|
||||
std::wstring m_filename;
|
||||
mutable std::mutex m_lock;
|
||||
#else
|
||||
int m_device = -1;
|
||||
std::string m_filename;
|
||||
#endif
|
||||
|
||||
s32 m_media_type = 0;
|
||||
u32 m_sectors = 0;
|
||||
u32 m_layer_break = 0;
|
||||
std::vector<toc_entry> m_toc;
|
||||
|
||||
bool ReadDVDInfo();
|
||||
bool ReadCDInfo();
|
||||
bool Reopen();
|
||||
|
||||
public:
|
||||
IOCtlSrc(decltype(m_filename) filename);
|
||||
~IOCtlSrc();
|
||||
|
||||
u32 GetSectorCount() const;
|
||||
const std::vector<toc_entry> &ReadTOC() const;
|
||||
bool ReadSectors2048(u32 sector, u32 count, u8 *buffer) const;
|
||||
bool ReadSectors2352(u32 sector, u32 count, u8 *buffer) const;
|
||||
u32 GetLayerBreakAddress() const;
|
||||
s32 GetMediaType() const;
|
||||
void SetSpindleSpeed(bool restore_defaults) const;
|
||||
bool DiscReady();
|
||||
};
|
||||
|
||||
extern std::unique_ptr<IOCtlSrc> src;
|
||||
|
||||
void configure();
|
||||
|
||||
void ReadSettings();
|
||||
void WriteSettings();
|
||||
#if defined(_WIN32)
|
||||
std::wstring GetValidDrive();
|
||||
#else
|
||||
std::string GetValidDrive();
|
||||
#endif
|
||||
|
||||
extern Settings g_settings;
|
||||
|
||||
extern bool disc_has_changed;
|
||||
extern bool weAreInNewDiskCB;
|
||||
|
||||
extern void (*newDiscCB)();
|
||||
|
||||
bool cdvdStartThread();
|
||||
void cdvdStopThread();
|
||||
void cdvdRequestSector(u32 sector, s32 mode);
|
||||
u8 *cdvdGetSector(u32 sector, s32 mode);
|
||||
s32 cdvdDirectReadSector(u32 sector, s32 mode, u8 *buffer);
|
||||
s32 cdvdGetMediaType();
|
||||
s32 cdvdRefreshData();
|
||||
void cdvdParseTOC();
|
||||
|
||||
inline void lba_to_msf(s32 lba, u8 *m, u8 *s, u8 *f)
|
||||
{
|
||||
lba += 150;
|
||||
*m = static_cast<u8>(lba / (60 * 75));
|
||||
*s = static_cast<u8>((lba / 75) % 60);
|
||||
*f = static_cast<u8>(lba % 75);
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define EXPORT
|
||||
#else
|
||||
#define EXPORT extern "C" __attribute__((stdcall, externally_visible, visibility("default")))
|
||||
#endif
|
||||
#endif /* __CDVD_H__ */
|
|
@ -1,53 +0,0 @@
|
|||
#Check that people use the good file
|
||||
if (NOT TOP_CMAKE_WAS_SOURCED)
|
||||
message(FATAL_ERROR "
|
||||
You did not 'cmake' the good CMakeLists.txt file. Use the one in the top dir.
|
||||
It is advised to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt")
|
||||
endif()
|
||||
|
||||
#plugin name(no version number to ease future version bump and bisect)
|
||||
set(Output cdvdGigaherz)
|
||||
|
||||
set(FinalFlags
|
||||
-fvisibility=hidden
|
||||
-Wall
|
||||
-Wno-parentheses
|
||||
)
|
||||
|
||||
set(Sources
|
||||
CDVD.cpp
|
||||
ReadThread.cpp
|
||||
Settings.cpp
|
||||
TocStuff.cpp
|
||||
)
|
||||
|
||||
set(Headers
|
||||
CDVD.h
|
||||
Settings.h
|
||||
)
|
||||
|
||||
if(Windows)
|
||||
LIST(APPEND Sources
|
||||
Windows/config.cpp
|
||||
Windows/resource.h
|
||||
)
|
||||
else()
|
||||
LIST(APPEND Sources
|
||||
Unix/GtkGui.cpp
|
||||
Unix/LinuxConfig.cpp
|
||||
Unix/LinuxIOCtlSrc.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(FinalSources
|
||||
${Sources}
|
||||
${Headers}
|
||||
)
|
||||
|
||||
set(FinalLibs
|
||||
${GTK2_LIBRARIES}
|
||||
${LIBC_LIBRARIES}
|
||||
${LIBUDEV_LIBRARIES}
|
||||
)
|
||||
|
||||
add_pcsx2_plugin(${Output} "${FinalSources}" "${FinalLibs}" "${FinalFlags}")
|
|
@ -1,398 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2014 David Quintana [gigaherz]
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "CDVD.h"
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <limits>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
|
||||
const u32 sectors_per_read = 16;
|
||||
|
||||
static_assert(sectors_per_read > 1 && !(sectors_per_read & (sectors_per_read - 1)),
|
||||
"sectors_per_read must by a power of 2");
|
||||
|
||||
struct SectorInfo
|
||||
{
|
||||
u32 lsn;
|
||||
// Sectors are read in blocks, not individually
|
||||
u8 data[2352 * sectors_per_read];
|
||||
};
|
||||
|
||||
u32 g_last_sector_block_lsn;
|
||||
|
||||
static std::thread s_thread;
|
||||
|
||||
static std::mutex s_notify_lock;
|
||||
static std::condition_variable s_notify_cv;
|
||||
static std::mutex s_request_lock;
|
||||
static std::queue<u32> s_request_queue;
|
||||
static std::mutex s_cache_lock;
|
||||
|
||||
static std::atomic<bool> cdvd_is_open;
|
||||
|
||||
//bits: 12 would use 1<<12 entries, or 4096*16 sectors ~ 128MB
|
||||
#define CACHE_SIZE 12
|
||||
|
||||
const u32 CacheSize = 1U << CACHE_SIZE;
|
||||
SectorInfo Cache[CacheSize];
|
||||
|
||||
u32 cdvdSectorHash(u32 lsn)
|
||||
{
|
||||
u32 t = 0;
|
||||
|
||||
int i = 32;
|
||||
u32 m = CacheSize - 1;
|
||||
|
||||
while (i >= 0) {
|
||||
t ^= lsn & m;
|
||||
lsn >>= CACHE_SIZE;
|
||||
i -= CACHE_SIZE;
|
||||
}
|
||||
|
||||
return t & m;
|
||||
}
|
||||
|
||||
void cdvdCacheUpdate(u32 lsn, u8 *data)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_cache_lock);
|
||||
u32 entry = cdvdSectorHash(lsn);
|
||||
|
||||
memcpy(Cache[entry].data, data, 2352 * sectors_per_read);
|
||||
Cache[entry].lsn = lsn;
|
||||
}
|
||||
|
||||
bool cdvdCacheCheck(u32 lsn)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_cache_lock);
|
||||
u32 entry = cdvdSectorHash(lsn);
|
||||
|
||||
return Cache[entry].lsn == lsn;
|
||||
}
|
||||
|
||||
bool cdvdCacheFetch(u32 lsn, u8 *data)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_cache_lock);
|
||||
u32 entry = cdvdSectorHash(lsn);
|
||||
|
||||
if (Cache[entry].lsn == lsn) {
|
||||
memcpy(data, Cache[entry].data, 2352 * sectors_per_read);
|
||||
return true;
|
||||
}
|
||||
//printf("NOT IN CACHE\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
void cdvdCacheReset()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_cache_lock);
|
||||
for (u32 i = 0; i < CacheSize; i++) {
|
||||
Cache[i].lsn = std::numeric_limits<u32>::max();
|
||||
}
|
||||
}
|
||||
|
||||
bool cdvdReadBlockOfSectors(u32 sector, u8 *data)
|
||||
{
|
||||
u32 count = std::min(sectors_per_read, src->GetSectorCount() - sector);
|
||||
const s32 media = src->GetMediaType();
|
||||
|
||||
// TODO: Is it really necessary to retry if it fails? I'm not sure the
|
||||
// second time is really going to be any better.
|
||||
for (int tries = 0; tries < 2; ++tries) {
|
||||
if (media >= 0) {
|
||||
if (src->ReadSectors2048(sector, count, data))
|
||||
return true;
|
||||
} else {
|
||||
if (src->ReadSectors2352(sector, count, data))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cdvdCallNewDiscCB()
|
||||
{
|
||||
weAreInNewDiskCB = true;
|
||||
newDiscCB();
|
||||
weAreInNewDiskCB = false;
|
||||
}
|
||||
|
||||
bool cdvdUpdateDiscStatus()
|
||||
{
|
||||
bool ready = src->DiscReady();
|
||||
|
||||
if (!ready) {
|
||||
if (!disc_has_changed) {
|
||||
disc_has_changed = true;
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
curTrayStatus = CDVD_TRAY_OPEN;
|
||||
cdvdCallNewDiscCB();
|
||||
}
|
||||
} else {
|
||||
if (disc_has_changed) {
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
curTrayStatus = CDVD_TRAY_CLOSE;
|
||||
|
||||
disc_has_changed = false;
|
||||
cdvdRefreshData();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> request_guard(s_request_lock);
|
||||
s_request_queue = decltype(s_request_queue)();
|
||||
}
|
||||
|
||||
cdvdCallNewDiscCB();
|
||||
}
|
||||
}
|
||||
return !ready;
|
||||
}
|
||||
|
||||
void cdvdThread()
|
||||
{
|
||||
u8 buffer[2352 * sectors_per_read];
|
||||
u32 prefetches_left = 0;
|
||||
|
||||
printf(" * CDVD: IO thread started...\n");
|
||||
std::unique_lock<std::mutex> guard(s_notify_lock);
|
||||
|
||||
while (cdvd_is_open) {
|
||||
if (cdvdUpdateDiscStatus()) {
|
||||
// Need to sleep some to avoid an aggressive spin that sucks the cpu dry.
|
||||
s_notify_cv.wait_for(guard, std::chrono::milliseconds(10));
|
||||
prefetches_left = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefetches_left == 0)
|
||||
s_notify_cv.wait_for(guard, std::chrono::milliseconds(250));
|
||||
|
||||
// check again to make sure we're not done here...
|
||||
if (!cdvd_is_open)
|
||||
break;
|
||||
|
||||
// Read request
|
||||
bool handling_request = false;
|
||||
u32 request_lsn;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> request_guard(s_request_lock);
|
||||
if (!s_request_queue.empty()) {
|
||||
request_lsn = s_request_queue.front();
|
||||
s_request_queue.pop();
|
||||
handling_request = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!handling_request) {
|
||||
if (prefetches_left == 0)
|
||||
continue;
|
||||
|
||||
--prefetches_left;
|
||||
|
||||
u32 next_prefetch_lsn = g_last_sector_block_lsn + sectors_per_read;
|
||||
request_lsn = next_prefetch_lsn;
|
||||
}
|
||||
|
||||
// Handle request
|
||||
if (!cdvdCacheCheck(request_lsn)) {
|
||||
if (cdvdReadBlockOfSectors(request_lsn, buffer)) {
|
||||
cdvdCacheUpdate(request_lsn, buffer);
|
||||
} else {
|
||||
// If the read fails, further reads are likely to fail too.
|
||||
prefetches_left = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
g_last_sector_block_lsn = request_lsn;
|
||||
|
||||
if (!handling_request)
|
||||
continue;
|
||||
|
||||
// Prefetch
|
||||
u32 next_prefetch_lsn = g_last_sector_block_lsn + sectors_per_read;
|
||||
if (next_prefetch_lsn >= src->GetSectorCount()) {
|
||||
prefetches_left = 0;
|
||||
} else {
|
||||
const u32 max_prefetches = 16;
|
||||
u32 remaining = src->GetSectorCount() - next_prefetch_lsn;
|
||||
prefetches_left = std::min((remaining + sectors_per_read - 1) / sectors_per_read, max_prefetches);
|
||||
}
|
||||
}
|
||||
printf(" * CDVD: IO thread finished.\n");
|
||||
}
|
||||
|
||||
bool cdvdStartThread()
|
||||
{
|
||||
cdvd_is_open = true;
|
||||
try {
|
||||
s_thread = std::thread(cdvdThread);
|
||||
} catch (std::system_error &) {
|
||||
cdvd_is_open = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
cdvdCacheReset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cdvdStopThread()
|
||||
{
|
||||
cdvd_is_open = false;
|
||||
s_notify_cv.notify_one();
|
||||
s_thread.join();
|
||||
}
|
||||
|
||||
void cdvdRequestSector(u32 sector, s32 mode)
|
||||
{
|
||||
if (sector >= src->GetSectorCount())
|
||||
return;
|
||||
|
||||
// Align to cache block
|
||||
sector &= ~(sectors_per_read - 1);
|
||||
|
||||
if (cdvdCacheCheck(sector))
|
||||
return;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_request_lock);
|
||||
s_request_queue.push(sector);
|
||||
}
|
||||
|
||||
s_notify_cv.notify_one();
|
||||
}
|
||||
|
||||
u8 *cdvdGetSector(u32 sector, s32 mode)
|
||||
{
|
||||
static u8 buffer[2352 * sectors_per_read];
|
||||
|
||||
// Align to cache block
|
||||
u32 sector_block = sector & ~(sectors_per_read - 1);
|
||||
|
||||
if (!cdvdCacheFetch(sector_block, buffer))
|
||||
if (cdvdReadBlockOfSectors(sector_block, buffer))
|
||||
cdvdCacheUpdate(sector_block, buffer);
|
||||
|
||||
if (src->GetMediaType() >= 0) {
|
||||
u32 offset = 2048 * (sector - sector_block);
|
||||
return buffer + offset;
|
||||
}
|
||||
|
||||
u32 offset = 2352 * (sector - sector_block);
|
||||
u8 *data = buffer + offset;
|
||||
|
||||
switch (mode) {
|
||||
case CDVD_MODE_2048:
|
||||
// Data location depends on CD mode
|
||||
return (data[15] & 3) == 2 ? data + 24 : data + 16;
|
||||
case CDVD_MODE_2328:
|
||||
return data + 24;
|
||||
case CDVD_MODE_2340:
|
||||
return data + 12;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
s32 cdvdDirectReadSector(u32 sector, s32 mode, u8 *buffer)
|
||||
{
|
||||
static u8 data[2352 * sectors_per_read];
|
||||
|
||||
if (sector >= src->GetSectorCount())
|
||||
return -1;
|
||||
|
||||
// Align to cache block
|
||||
u32 sector_block = sector & ~(sectors_per_read - 1);
|
||||
|
||||
if (!cdvdCacheFetch(sector_block, data)) {
|
||||
if (cdvdReadBlockOfSectors(sector_block, data))
|
||||
cdvdCacheUpdate(sector_block, data);
|
||||
}
|
||||
|
||||
if (src->GetMediaType() >= 0) {
|
||||
u32 offset = 2048 * (sector - sector_block);
|
||||
memcpy(buffer, data + offset, 2048);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 offset = 2352 * (sector - sector_block);
|
||||
u8 *bfr = data + offset;
|
||||
|
||||
switch (mode) {
|
||||
case CDVD_MODE_2048:
|
||||
// Data location depends on CD mode
|
||||
std::memcpy(buffer, (bfr[15] & 3) == 2 ? bfr + 24 : bfr + 16, 2048);
|
||||
return 0;
|
||||
case CDVD_MODE_2328:
|
||||
memcpy(buffer, bfr + 24, 2328);
|
||||
return 0;
|
||||
case CDVD_MODE_2340:
|
||||
memcpy(buffer, bfr + 12, 2340);
|
||||
return 0;
|
||||
default:
|
||||
memcpy(buffer, bfr, 2352);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
s32 cdvdGetMediaType()
|
||||
{
|
||||
return src->GetMediaType();
|
||||
}
|
||||
|
||||
s32 cdvdRefreshData()
|
||||
{
|
||||
const char *diskTypeName = "Unknown";
|
||||
|
||||
//read TOC from device
|
||||
cdvdParseTOC();
|
||||
|
||||
if ((etrack == 0) || (strack > etrack)) {
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
} else {
|
||||
s32 mt = cdvdGetMediaType();
|
||||
|
||||
if (mt < 0)
|
||||
curDiskType = CDVD_TYPE_DETCTCD;
|
||||
else if (mt == 0)
|
||||
curDiskType = CDVD_TYPE_DETCTDVDS;
|
||||
else
|
||||
curDiskType = CDVD_TYPE_DETCTDVDD;
|
||||
}
|
||||
|
||||
curTrayStatus = CDVD_TRAY_CLOSE;
|
||||
|
||||
switch (curDiskType) {
|
||||
case CDVD_TYPE_DETCTDVDD:
|
||||
diskTypeName = "Double-Layer DVD";
|
||||
break;
|
||||
case CDVD_TYPE_DETCTDVDS:
|
||||
diskTypeName = "Single-Layer DVD";
|
||||
break;
|
||||
case CDVD_TYPE_DETCTCD:
|
||||
diskTypeName = "CD-ROM";
|
||||
break;
|
||||
case CDVD_TYPE_NODISC:
|
||||
diskTypeName = "No Disc";
|
||||
break;
|
||||
}
|
||||
|
||||
printf(" * CDVD: Disk Type: %s\n", diskTypeName);
|
||||
|
||||
cdvdCacheReset();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2016 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Settings.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
#endif
|
||||
#include <fstream>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
#include <PluginCompatibility.h>
|
||||
|
||||
Settings::Settings()
|
||||
{
|
||||
}
|
||||
|
||||
Settings::Settings(std::map<std::string, std::string> data)
|
||||
: m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
void Settings::TrimWhitespace(std::string &str) const
|
||||
{
|
||||
// Leading whitespace
|
||||
str.erase(0, str.find_first_not_of(" \r\t"));
|
||||
// Trailing whitespace
|
||||
auto pos = str.find_last_not_of(" \r\t");
|
||||
if (pos != std::string::npos && pos != str.size() - 1)
|
||||
str.erase(pos + 1);
|
||||
}
|
||||
|
||||
void Settings::Load(const std::string &filename)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
std::ifstream file(convert_utf8_to_utf16(filename));
|
||||
#else
|
||||
std::ifstream file(filename);
|
||||
#endif
|
||||
if (!file.is_open())
|
||||
return;
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
auto separator = line.find('=');
|
||||
if (separator == std::string::npos)
|
||||
continue;
|
||||
|
||||
std::string key = line.substr(0, separator);
|
||||
// Trim leading and trailing whitespace
|
||||
TrimWhitespace(key);
|
||||
if (key.empty())
|
||||
continue;
|
||||
|
||||
std::string value = line.substr(separator + 1);
|
||||
TrimWhitespace(value);
|
||||
|
||||
Set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void Settings::Save(const std::string &filename) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
std::ofstream file(convert_utf8_to_utf16(filename), std::ios::trunc);
|
||||
#else
|
||||
std::ofstream file(filename, std::ios::trunc);
|
||||
#endif
|
||||
if (!file.is_open())
|
||||
return;
|
||||
|
||||
for (const auto &pair : m_data)
|
||||
file << pair.first << '=' << pair.second << '\n';
|
||||
}
|
||||
|
||||
void Settings::Set(std::string key, std::string value)
|
||||
{
|
||||
m_data[key] = value;
|
||||
}
|
||||
|
||||
bool Settings::Get(const std::string &key, std::string &data) const
|
||||
{
|
||||
auto it = m_data.find(key);
|
||||
if (it == m_data.end())
|
||||
return false;
|
||||
|
||||
data = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
void Settings::Set(std::string key, std::wstring value)
|
||||
{
|
||||
int size = WideCharToMultiByte(CP_UTF8, 0, value.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
||||
std::vector<char> converted_string(size);
|
||||
WideCharToMultiByte(CP_UTF8, 0, value.c_str(), -1, converted_string.data(), converted_string.size(), nullptr, nullptr);
|
||||
m_data[key] = converted_string.data();
|
||||
}
|
||||
|
||||
bool Settings::Get(const std::string &key, std::wstring &data) const
|
||||
{
|
||||
auto it = m_data.find(key);
|
||||
if (it == m_data.end())
|
||||
return false;
|
||||
|
||||
int size = MultiByteToWideChar(CP_UTF8, 0, it->second.c_str(), -1, nullptr, 0);
|
||||
std::vector<wchar_t> converted_string(size);
|
||||
MultiByteToWideChar(CP_UTF8, 0, it->second.c_str(), -1, converted_string.data(), converted_string.size());
|
||||
data = converted_string.data();
|
||||
return true;
|
||||
}
|
||||
#endif
|
|
@ -1,41 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2016 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class Settings
|
||||
{
|
||||
private:
|
||||
std::map<std::string, std::string> m_data;
|
||||
|
||||
void TrimWhitespace(std::string &str) const;
|
||||
|
||||
public:
|
||||
Settings();
|
||||
Settings(std::map<std::string, std::string> data);
|
||||
|
||||
void Load(const std::string &filename);
|
||||
void Save(const std::string &filename) const;
|
||||
|
||||
void Set(std::string key, std::string value);
|
||||
bool Get(const std::string &key, std::string &data) const;
|
||||
#if defined(_WIN32)
|
||||
void Set(std::string key, std::wstring value);
|
||||
bool Get(const std::string &key, std::wstring &data) const;
|
||||
#endif
|
||||
};
|
|
@ -1,62 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2014 David Quintana [gigaherz]
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "CDVD.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
void cdvdParseTOC()
|
||||
{
|
||||
tracks[1].start_lba = 0;
|
||||
|
||||
if (!src->GetSectorCount()) {
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
strack = 1;
|
||||
etrack = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (src->GetMediaType() >= 0) {
|
||||
tracks[1].type = CDVD_MODE1_TRACK;
|
||||
|
||||
strack = 1;
|
||||
etrack = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
strack = 0xFF;
|
||||
etrack = 0;
|
||||
|
||||
for (auto &entry : src->ReadTOC()) {
|
||||
if (entry.track < 1 || entry.track > 99)
|
||||
continue;
|
||||
strack = std::min(strack, entry.track);
|
||||
etrack = std::max(etrack, entry.track);
|
||||
tracks[entry.track].start_lba = entry.lba;
|
||||
if ((entry.control & 0x0C) == 0x04) {
|
||||
std::array<u8, 2352> buffer;
|
||||
// Byte 15 of a raw CD data sector determines the track mode
|
||||
if (src->ReadSectors2352(entry.lba, 1, buffer.data()) && (buffer[15] & 3) == 2) {
|
||||
tracks[entry.track].type = CDVD_MODE2_TRACK;
|
||||
} else {
|
||||
tracks[entry.track].type = CDVD_MODE1_TRACK;
|
||||
}
|
||||
} else {
|
||||
tracks[entry.track].type = CDVD_AUDIO_TRACK;
|
||||
}
|
||||
fprintf(stderr, "Track %u start sector: %u\n", entry.track, entry.lba);
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2016 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "CDVD.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
std::vector<std::string> GetOpticalDriveList();
|
||||
|
||||
void configure()
|
||||
{
|
||||
ReadSettings();
|
||||
|
||||
GtkDialogFlags flags = static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT);
|
||||
GtkWidget *dialog = gtk_dialog_new_with_buttons("Config", nullptr,
|
||||
flags,
|
||||
"Cancel", GTK_RESPONSE_REJECT,
|
||||
"Ok", GTK_RESPONSE_ACCEPT,
|
||||
nullptr);
|
||||
|
||||
GtkWidget *label = gtk_label_new("Device:");
|
||||
GtkWidget *combobox = gtk_combo_box_text_new();
|
||||
|
||||
auto drives = GetOpticalDriveList();
|
||||
std::string drive;
|
||||
g_settings.Get("drive", drive);
|
||||
for (size_t n = 0; n < drives.size(); ++n) {
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combobox), drives[n].c_str());
|
||||
if (drive == drives[n])
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), n);
|
||||
}
|
||||
|
||||
GtkContainer *content_area = GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
|
||||
gtk_container_add(content_area, label);
|
||||
gtk_container_add(content_area, combobox);
|
||||
|
||||
gtk_widget_show_all(dialog);
|
||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
if (const char *selected_drive = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combobox))) {
|
||||
g_settings.Set("drive", selected_drive);
|
||||
WriteSettings();
|
||||
}
|
||||
}
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2016 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "CDVD.h"
|
||||
#include <libudev.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/cdrom.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
std::vector<std::string> GetOpticalDriveList()
|
||||
{
|
||||
udev *udev_context = udev_new();
|
||||
if (!udev_context)
|
||||
return {};
|
||||
|
||||
std::vector<std::string> drives;
|
||||
udev_enumerate *enumerate = udev_enumerate_new(udev_context);
|
||||
if (enumerate) {
|
||||
udev_enumerate_add_match_subsystem(enumerate, "block");
|
||||
udev_enumerate_add_match_property(enumerate, "ID_CDROM_DVD", "1");
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
|
||||
|
||||
udev_list_entry *dev_list_entry;
|
||||
udev_list_entry_foreach(dev_list_entry, devices)
|
||||
{
|
||||
const char *path = udev_list_entry_get_name(dev_list_entry);
|
||||
udev_device *device = udev_device_new_from_syspath(udev_context, path);
|
||||
const char *devnode = udev_device_get_devnode(device);
|
||||
if (devnode)
|
||||
drives.push_back(devnode);
|
||||
udev_device_unref(device);
|
||||
}
|
||||
udev_enumerate_unref(enumerate);
|
||||
}
|
||||
udev_unref(udev_context);
|
||||
|
||||
return drives;
|
||||
}
|
||||
|
||||
std::string GetValidDrive()
|
||||
{
|
||||
std::string drive;
|
||||
g_settings.Get("drive", drive);
|
||||
if (!drive.empty()) {
|
||||
int fd = open(drive.c_str(), O_RDONLY | O_NONBLOCK);
|
||||
if (fd != -1) {
|
||||
if (ioctl(fd, CDROM_GET_CAPABILITY, 0) == -1)
|
||||
drive.clear();
|
||||
close(fd);
|
||||
} else {
|
||||
drive.clear();
|
||||
}
|
||||
}
|
||||
if (drive.empty()) {
|
||||
auto drives = GetOpticalDriveList();
|
||||
if (!drives.empty())
|
||||
drive = drives.front();
|
||||
}
|
||||
if (!drive.empty())
|
||||
printf(" * CDVD: Opening drive '%s'...\n", drive.c_str());
|
||||
|
||||
return drive;
|
||||
}
|
|
@ -1,212 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2016 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../CDVD.h"
|
||||
|
||||
#include <linux/cdrom.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
|
||||
IOCtlSrc::IOCtlSrc(decltype(m_filename) filename)
|
||||
: m_filename(filename)
|
||||
{
|
||||
if (!Reopen())
|
||||
throw std::runtime_error(" * CDVD: Error opening source.\n");
|
||||
}
|
||||
|
||||
IOCtlSrc::~IOCtlSrc()
|
||||
{
|
||||
if (m_device != -1) {
|
||||
SetSpindleSpeed(true);
|
||||
close(m_device);
|
||||
}
|
||||
}
|
||||
|
||||
bool IOCtlSrc::Reopen()
|
||||
{
|
||||
if (m_device != -1)
|
||||
close(m_device);
|
||||
|
||||
// O_NONBLOCK allows a valid file descriptor to be returned even if the
|
||||
// drive is empty. Probably does other things too.
|
||||
m_device = open(m_filename.c_str(), O_RDONLY | O_NONBLOCK);
|
||||
if (m_device == -1)
|
||||
return false;
|
||||
|
||||
// DVD detection MUST be first on Linux - The TOC ioctls work for both
|
||||
// CDs and DVDs.
|
||||
if (ReadDVDInfo() || ReadCDInfo())
|
||||
SetSpindleSpeed(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IOCtlSrc::SetSpindleSpeed(bool restore_defaults) const
|
||||
{
|
||||
// TODO: CD seems easy enough (CDROM_SELECT_SPEED ioctl), but I'm not sure
|
||||
// about DVD.
|
||||
}
|
||||
|
||||
u32 IOCtlSrc::GetSectorCount() const
|
||||
{
|
||||
return m_sectors;
|
||||
}
|
||||
|
||||
u32 IOCtlSrc::GetLayerBreakAddress() const
|
||||
{
|
||||
return m_layer_break;
|
||||
}
|
||||
|
||||
s32 IOCtlSrc::GetMediaType() const
|
||||
{
|
||||
return m_media_type;
|
||||
}
|
||||
|
||||
const std::vector<toc_entry> &IOCtlSrc::ReadTOC() const
|
||||
{
|
||||
return m_toc;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadSectors2048(u32 sector, u32 count, u8 *buffer) const
|
||||
{
|
||||
const ssize_t bytes_to_read = 2048 * count;
|
||||
ssize_t bytes_read = pread(m_device, buffer, bytes_to_read, sector * 2048ULL);
|
||||
if (bytes_read == bytes_to_read)
|
||||
return true;
|
||||
|
||||
if (bytes_read == -1)
|
||||
fprintf(stderr, " * CDVD read sectors %u-%u failed: %s\n",
|
||||
sector, sector + count - 1, strerror(errno));
|
||||
else
|
||||
fprintf(stderr, " * CDVD read sectors %u-%u: %zd bytes read, %zd bytes expected\n",
|
||||
sector, sector + count - 1, bytes_read, bytes_to_read);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadSectors2352(u32 sector, u32 count, u8 *buffer) const
|
||||
{
|
||||
union
|
||||
{
|
||||
cdrom_msf msf;
|
||||
char buffer[CD_FRAMESIZE_RAW];
|
||||
} data;
|
||||
|
||||
for (u32 n = 0; n < count; ++n) {
|
||||
u32 lba = sector + n;
|
||||
lba_to_msf(lba, &data.msf.cdmsf_min0, &data.msf.cdmsf_sec0, &data.msf.cdmsf_frame0);
|
||||
if (ioctl(m_device, CDROMREADRAW, &data) == -1) {
|
||||
fprintf(stderr, " * CDVD CDROMREADRAW sector %u failed: %s\n",
|
||||
lba, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
memcpy(buffer, data.buffer, CD_FRAMESIZE_RAW);
|
||||
buffer += CD_FRAMESIZE_RAW;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadDVDInfo()
|
||||
{
|
||||
dvd_struct dvdrs;
|
||||
dvdrs.type = DVD_STRUCT_PHYSICAL;
|
||||
dvdrs.physical.layer_num = 0;
|
||||
|
||||
int ret = ioctl(m_device, DVD_READ_STRUCT, &dvdrs);
|
||||
if (ret == -1)
|
||||
return false;
|
||||
|
||||
u32 start_sector = dvdrs.physical.layer[0].start_sector;
|
||||
u32 end_sector = dvdrs.physical.layer[0].end_sector;
|
||||
|
||||
if (dvdrs.physical.layer[0].nlayers == 0) {
|
||||
// Single layer
|
||||
m_media_type = 0;
|
||||
m_layer_break = 0;
|
||||
m_sectors = end_sector - start_sector + 1;
|
||||
} else if (dvdrs.physical.layer[0].track_path == 0) {
|
||||
// Dual layer, Parallel Track Path
|
||||
dvdrs.physical.layer_num = 1;
|
||||
ret = ioctl(m_device, DVD_READ_STRUCT, &dvdrs);
|
||||
if (ret == -1)
|
||||
return false;
|
||||
u32 layer1_start_sector = dvdrs.physical.layer[1].start_sector;
|
||||
u32 layer1_end_sector = dvdrs.physical.layer[1].end_sector;
|
||||
|
||||
m_media_type = 1;
|
||||
m_layer_break = end_sector - start_sector;
|
||||
m_sectors = end_sector - start_sector + 1 + layer1_end_sector - layer1_start_sector + 1;
|
||||
} else {
|
||||
// Dual layer, Opposite Track Path
|
||||
u32 end_sector_layer0 = dvdrs.physical.layer[0].end_sector_l0;
|
||||
m_media_type = 2;
|
||||
m_layer_break = end_sector_layer0 - start_sector;
|
||||
m_sectors = end_sector_layer0 - start_sector + 1 + end_sector - (~end_sector_layer0 & 0xFFFFFFU) + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadCDInfo()
|
||||
{
|
||||
cdrom_tochdr header;
|
||||
|
||||
if (ioctl(m_device, CDROMREADTOCHDR, &header) == -1)
|
||||
return false;
|
||||
|
||||
cdrom_tocentry entry{};
|
||||
entry.cdte_format = CDROM_LBA;
|
||||
|
||||
m_toc.clear();
|
||||
for (u8 n = header.cdth_trk0; n <= header.cdth_trk1; ++n) {
|
||||
entry.cdte_track = n;
|
||||
if (ioctl(m_device, CDROMREADTOCENTRY, &entry) != -1)
|
||||
m_toc.push_back({static_cast<u32>(entry.cdte_addr.lba), entry.cdte_track,
|
||||
entry.cdte_adr, entry.cdte_ctrl});
|
||||
}
|
||||
|
||||
// TODO: Do I need a fallback if this doesn't work?
|
||||
entry.cdte_track = 0xAA;
|
||||
if (ioctl(m_device, CDROMREADTOCENTRY, &entry) == -1)
|
||||
return false;
|
||||
|
||||
m_sectors = entry.cdte_addr.lba;
|
||||
m_media_type = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::DiscReady()
|
||||
{
|
||||
if (m_device == -1)
|
||||
return false;
|
||||
|
||||
// CDSL_CURRENT must be used - 0 will cause the drive tray to close.
|
||||
if (ioctl(m_device, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK) {
|
||||
if (!m_sectors)
|
||||
Reopen();
|
||||
} else {
|
||||
m_sectors = 0;
|
||||
m_layer_break = 0;
|
||||
m_media_type = 0;
|
||||
}
|
||||
|
||||
return !!m_sectors;
|
||||
}
|
|
@ -1,298 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2016 PCSX2 Dev Team
|
||||
* Copyright (C) 2002-2014 David Quintana [gigaherz]
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../CDVD.h"
|
||||
|
||||
#include <winioctl.h>
|
||||
#include <ntddcdvd.h>
|
||||
#include <ntddcdrm.h>
|
||||
// "typedef ignored" warning will disappear once we move to the Windows 10 SDK.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4091)
|
||||
#include <ntddscsi.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
|
||||
IOCtlSrc::IOCtlSrc(decltype(m_filename) filename)
|
||||
: m_filename(filename)
|
||||
{
|
||||
if (!Reopen())
|
||||
throw std::runtime_error(" * CDVD: Error opening source.\n");
|
||||
}
|
||||
|
||||
IOCtlSrc::~IOCtlSrc()
|
||||
{
|
||||
if (m_device != INVALID_HANDLE_VALUE) {
|
||||
SetSpindleSpeed(true);
|
||||
CloseHandle(m_device);
|
||||
}
|
||||
}
|
||||
|
||||
// If a new disc is inserted, ReadFile will fail unless the device is closed
|
||||
// and reopened.
|
||||
bool IOCtlSrc::Reopen()
|
||||
{
|
||||
if (m_device != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(m_device);
|
||||
|
||||
// SPTI only works if the device is opened with GENERIC_WRITE access.
|
||||
m_device = CreateFile(m_filename.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ, nullptr, OPEN_EXISTING,
|
||||
FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
|
||||
if (m_device == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
DWORD unused;
|
||||
// Required to read from layer 1 of Dual layer DVDs
|
||||
DeviceIoControl(m_device, FSCTL_ALLOW_EXTENDED_DASD_IO, nullptr, 0, nullptr,
|
||||
0, &unused, nullptr);
|
||||
|
||||
if (ReadDVDInfo() || ReadCDInfo())
|
||||
SetSpindleSpeed(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IOCtlSrc::SetSpindleSpeed(bool restore_defaults) const
|
||||
{
|
||||
// IOCTL_CDROM_SET_SPEED issues a SET CD SPEED command. So 0xFFFF should be
|
||||
// equivalent to "optimal performance".
|
||||
// 1x DVD-ROM and CD-ROM speeds are respectively 1385 KB/s and 150KB/s.
|
||||
// The PS2 can do 4x DVD-ROM and 24x CD-ROM speeds (5540KB/s and 3600KB/s).
|
||||
// TODO: What speed? Performance seems smoother with a lower speed (less
|
||||
// time required to get up to speed).
|
||||
const USHORT speed = restore_defaults ? 0xFFFF : GetMediaType() >= 0 ? 5540 : 3600;
|
||||
CDROM_SET_SPEED s{CdromSetSpeed, speed, speed, CdromDefaultRotation};
|
||||
|
||||
DWORD unused;
|
||||
if (DeviceIoControl(m_device, IOCTL_CDROM_SET_SPEED, &s, sizeof(s),
|
||||
nullptr, 0, &unused, nullptr)) {
|
||||
if (!restore_defaults)
|
||||
printf(" * CDVD: setSpindleSpeed success (%uKB/s)\n", speed);
|
||||
} else {
|
||||
printf(" * CDVD: setSpindleSpeed failed!\n");
|
||||
}
|
||||
}
|
||||
|
||||
u32 IOCtlSrc::GetSectorCount() const
|
||||
{
|
||||
return m_sectors;
|
||||
}
|
||||
|
||||
u32 IOCtlSrc::GetLayerBreakAddress() const
|
||||
{
|
||||
return m_layer_break;
|
||||
}
|
||||
|
||||
s32 IOCtlSrc::GetMediaType() const
|
||||
{
|
||||
return m_media_type;
|
||||
}
|
||||
|
||||
const std::vector<toc_entry> &IOCtlSrc::ReadTOC() const
|
||||
{
|
||||
return m_toc;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadSectors2048(u32 sector, u32 count, u8 *buffer) const
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_lock);
|
||||
LARGE_INTEGER offset;
|
||||
offset.QuadPart = sector * 2048ULL;
|
||||
|
||||
if (!SetFilePointerEx(m_device, offset, nullptr, FILE_BEGIN)) {
|
||||
fprintf(stderr, " * CDVD SetFilePointerEx failed: sector %u: error %u\n",
|
||||
sector, GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
const DWORD bytes_to_read = 2048 * count;
|
||||
DWORD bytes_read;
|
||||
if (ReadFile(m_device, buffer, bytes_to_read, &bytes_read, nullptr)) {
|
||||
if (bytes_read == bytes_to_read)
|
||||
return true;
|
||||
fprintf(stderr, " * CDVD ReadFile: sectors %u-%u: %u bytes read, %u bytes expected\n",
|
||||
sector, sector + count - 1, bytes_read, bytes_to_read);
|
||||
} else {
|
||||
fprintf(stderr, " * CDVD ReadFile failed: sectors %u-%u: error %u\n",
|
||||
sector, sector + count - 1, GetLastError());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadSectors2352(u32 sector, u32 count, u8 *buffer) const
|
||||
{
|
||||
struct sptdinfo
|
||||
{
|
||||
SCSI_PASS_THROUGH_DIRECT info;
|
||||
char sense_buffer[20];
|
||||
} sptd{};
|
||||
|
||||
// READ CD command
|
||||
sptd.info.Cdb[0] = 0xBE;
|
||||
// Don't care about sector type.
|
||||
sptd.info.Cdb[1] = 0;
|
||||
// Number of sectors to read
|
||||
sptd.info.Cdb[6] = 0;
|
||||
sptd.info.Cdb[7] = 0;
|
||||
sptd.info.Cdb[8] = 1;
|
||||
// Sync + all headers + user data + EDC/ECC. Excludes C2 + subchannel
|
||||
sptd.info.Cdb[9] = 0xF8;
|
||||
sptd.info.Cdb[10] = 0;
|
||||
sptd.info.Cdb[11] = 0;
|
||||
|
||||
sptd.info.CdbLength = 12;
|
||||
sptd.info.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
|
||||
sptd.info.DataIn = SCSI_IOCTL_DATA_IN;
|
||||
sptd.info.SenseInfoOffset = offsetof(sptdinfo, sense_buffer);
|
||||
sptd.info.TimeOutValue = 5;
|
||||
|
||||
// Read sectors one by one to avoid reading data from 2 tracks of different
|
||||
// types in the same read (which will fail).
|
||||
for (u32 n = 0; n < count; ++n) {
|
||||
u32 current_sector = sector + n;
|
||||
sptd.info.Cdb[2] = (current_sector >> 24) & 0xFF;
|
||||
sptd.info.Cdb[3] = (current_sector >> 16) & 0xFF;
|
||||
sptd.info.Cdb[4] = (current_sector >> 8) & 0xFF;
|
||||
sptd.info.Cdb[5] = current_sector & 0xFF;
|
||||
sptd.info.DataTransferLength = 2352;
|
||||
sptd.info.DataBuffer = buffer + 2352 * n;
|
||||
sptd.info.SenseInfoLength = sizeof(sptd.sense_buffer);
|
||||
|
||||
DWORD unused;
|
||||
if (DeviceIoControl(m_device, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd,
|
||||
sizeof(sptd), &sptd, sizeof(sptd), &unused, nullptr)) {
|
||||
if (sptd.info.DataTransferLength == 2352)
|
||||
continue;
|
||||
}
|
||||
printf(" * CDVD: SPTI failed reading sector %u; SENSE %u -", current_sector, sptd.info.SenseInfoLength);
|
||||
for (const auto &c : sptd.sense_buffer)
|
||||
printf(" %02X", c);
|
||||
putchar('\n');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadDVDInfo()
|
||||
{
|
||||
DWORD unused;
|
||||
// 4 bytes header + 18 bytes layer descriptor - Technically you only need
|
||||
// to read 17 bytes of the layer descriptor since bytes 17-2047 is for
|
||||
// media specific information. However, Windows requires you to read at
|
||||
// least 18 bytes of the layer descriptor or else the ioctl will fail. The
|
||||
// media specific information seems to be empty, so there's no point reading
|
||||
// any more than that.
|
||||
std::array<u8, 22> buffer;
|
||||
DVD_READ_STRUCTURE dvdrs{{0}, DvdPhysicalDescriptor, 0, 0};
|
||||
|
||||
if (!DeviceIoControl(m_device, IOCTL_DVD_READ_STRUCTURE, &dvdrs, sizeof(dvdrs),
|
||||
buffer.data(), buffer.size(), &unused, nullptr))
|
||||
return false;
|
||||
|
||||
auto &layer = *reinterpret_cast<DVD_LAYER_DESCRIPTOR *>(
|
||||
reinterpret_cast<DVD_DESCRIPTOR_HEADER *>(buffer.data())->Data);
|
||||
|
||||
u32 start_sector = _byteswap_ulong(layer.StartingDataSector);
|
||||
u32 end_sector = _byteswap_ulong(layer.EndDataSector);
|
||||
|
||||
if (layer.NumberOfLayers == 0) {
|
||||
// Single layer
|
||||
m_media_type = 0;
|
||||
m_layer_break = 0;
|
||||
m_sectors = end_sector - start_sector + 1;
|
||||
} else if (layer.TrackPath == 0) {
|
||||
// Dual layer, Parallel Track Path
|
||||
dvdrs.LayerNumber = 1;
|
||||
if (!DeviceIoControl(m_device, IOCTL_DVD_READ_STRUCTURE, &dvdrs, sizeof(dvdrs),
|
||||
buffer.data(), buffer.size(), &unused, nullptr))
|
||||
return false;
|
||||
u32 layer1_start_sector = _byteswap_ulong(layer.StartingDataSector);
|
||||
u32 layer1_end_sector = _byteswap_ulong(layer.EndDataSector);
|
||||
|
||||
m_media_type = 1;
|
||||
m_layer_break = end_sector - start_sector;
|
||||
m_sectors = end_sector - start_sector + 1 + layer1_end_sector - layer1_start_sector + 1;
|
||||
} else {
|
||||
// Dual layer, Opposite Track Path
|
||||
u32 end_sector_layer0 = _byteswap_ulong(layer.EndLayerZeroSector);
|
||||
m_media_type = 2;
|
||||
m_layer_break = end_sector_layer0 - start_sector;
|
||||
m_sectors = end_sector_layer0 - start_sector + 1 + end_sector - (~end_sector_layer0 & 0xFFFFFFU) + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::ReadCDInfo()
|
||||
{
|
||||
DWORD unused;
|
||||
CDROM_READ_TOC_EX toc_ex{};
|
||||
toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_TOC;
|
||||
toc_ex.Msf = 0;
|
||||
toc_ex.SessionTrack = 1;
|
||||
|
||||
CDROM_TOC toc;
|
||||
if (!DeviceIoControl(m_device, IOCTL_CDROM_READ_TOC_EX, &toc_ex,
|
||||
sizeof(toc_ex), &toc, sizeof(toc), &unused, nullptr))
|
||||
return false;
|
||||
|
||||
m_toc.clear();
|
||||
size_t track_count = ((toc.Length[0] << 8) + toc.Length[1] - 2) / sizeof(TRACK_DATA);
|
||||
for (size_t n = 0; n < track_count; ++n) {
|
||||
TRACK_DATA &track = toc.TrackData[n];
|
||||
// Exclude the lead-out track descriptor.
|
||||
if (track.TrackNumber == 0xAA)
|
||||
continue;
|
||||
u32 lba = (track.Address[1] << 16) + (track.Address[2] << 8) + track.Address[3];
|
||||
m_toc.push_back({lba, track.TrackNumber, track.Adr, track.Control});
|
||||
}
|
||||
|
||||
GET_LENGTH_INFORMATION info;
|
||||
if (!DeviceIoControl(m_device, IOCTL_DISK_GET_LENGTH_INFO, nullptr, 0, &info,
|
||||
sizeof(info), &unused, nullptr))
|
||||
return false;
|
||||
|
||||
m_sectors = static_cast<u32>(info.Length.QuadPart / 2048);
|
||||
m_media_type = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOCtlSrc::DiscReady()
|
||||
{
|
||||
if (m_device == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
DWORD unused;
|
||||
if (DeviceIoControl(m_device, IOCTL_STORAGE_CHECK_VERIFY, nullptr, 0,
|
||||
nullptr, 0, &unused, nullptr)) {
|
||||
if (!m_sectors)
|
||||
Reopen();
|
||||
} else {
|
||||
m_sectors = 0;
|
||||
m_layer_break = 0;
|
||||
m_media_type = 0;
|
||||
}
|
||||
|
||||
return !!m_sectors;
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "windows.h"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Spanish resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESN)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_CONFIG DIALOGEX 0, 0, 184, 77
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "cdvdGigaherz"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,75,59,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,129,59,50,14
|
||||
COMBOBOX IDC_DRIVE,15,20,160,64,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
GROUPBOX "Source drive...",IDC_STATIC,7,7,172,48
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_CONFIG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 179
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 73
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Spanish resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<Import Project="$(SolutionDir)common\vsprops\WinSDK.props" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{5CF88D5F-64DD-4EDC-9F1A-436BD502940A}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization Condition="$(Configuration.Contains(Release))">true</WholeProgramOptimization>
|
||||
<UseDebugLibraries Condition="$(Configuration.Contains(Debug))">true</UseDebugLibraries>
|
||||
<UseDebugLibraries Condition="!$(Configuration.Contains(Debug))">false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="..\..\..\..\common\vsprops\plugin_svnroot.props" />
|
||||
<Import Project="..\..\..\..\common\vsprops\BaseProperties.props" />
|
||||
<Import Project="..\..\..\..\common\vsprops\3rdpartyDeps.props" />
|
||||
<Import Condition="$(Configuration.Contains(Debug))" Project="..\..\..\..\common\vsprops\CodeGen_Debug.props" />
|
||||
<Import Condition="$(Configuration.Contains(Release))" Project="..\..\..\..\common\vsprops\CodeGen_Release.props" />
|
||||
<Import Condition="!$(Configuration.Contains(Release))" Project="..\..\..\..\common\vsprops\IncrementalLinking.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<ModuleDefinitionFile>.\plugin.def</ModuleDefinitionFile>
|
||||
<TargetMachine Condition="'$(Platform)'=='Win32'">MachineX86</TargetMachine>
|
||||
<TargetMachine Condition="'$(Platform)'=='x64'">MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\CDVD.cpp" />
|
||||
<ClCompile Include="..\Settings.cpp" />
|
||||
<ClCompile Include="..\Unix\GtkGui.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Unix\LinuxConfig.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Unix\LinuxIOCtlSrc.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="config.cpp" />
|
||||
<ClCompile Include="IOCtlSrc.cpp" />
|
||||
<ClCompile Include="..\ReadThread.cpp" />
|
||||
<ClCompile Include="..\TocStuff.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\CDVD.h" />
|
||||
<ClInclude Include="..\Settings.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="cdvdGigaherz.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="plugin.def" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
|
@ -1,76 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{c03fe088-95f7-4235-a796-5fe044914fb5}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{6c12b075-7b05-42ce-8628-c668f325f4ce}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{a80698fd-3734-41c4-b7e8-6b96b34633e0}</UniqueIdentifier>
|
||||
<Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Windows">
|
||||
<UniqueIdentifier>{a0a8deec-63fd-4ef5-b815-d6c9ff3d80e1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Linux">
|
||||
<UniqueIdentifier>{102507ff-fef0-4989-9bcb-4fa14a0b7595}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\GTK">
|
||||
<UniqueIdentifier>{2054202d-299a-4cbf-8f4f-282bfe79a98e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\CDVD.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\ReadThread.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\TocStuff.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Settings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Unix\LinuxIOCtlSrc.cpp">
|
||||
<Filter>Source Files\Linux</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IOCtlSrc.cpp">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="config.cpp">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Unix\LinuxConfig.cpp">
|
||||
<Filter>Source Files\Linux</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Unix\GtkGui.cpp">
|
||||
<Filter>Source Files\GTK</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\CDVD.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Settings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="cdvdGigaherz.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="plugin.def">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,127 +0,0 @@
|
|||
//Copyright (C) 2016 PCSX2 Dev Team
|
||||
//Copyright (c) David Quintana <DavidQuintana@canal21.com>
|
||||
//
|
||||
//This library 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 Foundation; either
|
||||
//version 3.0 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library 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
|
||||
//Lesser General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU Lesser General Public
|
||||
//License along with this library; if not, write to the Free Software
|
||||
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
//
|
||||
|
||||
#include "../CDVD.h"
|
||||
#include <Windows.h>
|
||||
#include <commctrl.h>
|
||||
#include "resource.h"
|
||||
|
||||
static HINSTANCE s_hinstance;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstance, DWORD reason, LPVOID reserved)
|
||||
{
|
||||
if (reason == DLL_PROCESS_ATTACH)
|
||||
s_hinstance = hinstance;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg) {
|
||||
case WM_INITDIALOG: {
|
||||
std::vector<std::wstring> &drives =
|
||||
*reinterpret_cast<std::vector<std::wstring> *>(lParam);
|
||||
HWND combobox = GetDlgItem(hWnd, IDC_DRIVE);
|
||||
std::wstring drive;
|
||||
g_settings.Get("drive", drive);
|
||||
for (size_t n = 0; n < drives.size(); ++n) {
|
||||
SendMessage(combobox, CB_ADDSTRING, 0,
|
||||
reinterpret_cast<LPARAM>(drives[n].c_str()));
|
||||
if (drive == drives[n])
|
||||
SendMessage(combobox, CB_SETCURSEL, n, 0);
|
||||
}
|
||||
} break;
|
||||
case WM_COMMAND:
|
||||
// Parse the menu selections:
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDOK: {
|
||||
HWND combobox = GetDlgItem(hWnd, IDC_DRIVE);
|
||||
LRESULT index = SendMessage(combobox, CB_GETCURSEL, 0, 0);
|
||||
if (index != CB_ERR) {
|
||||
LRESULT length = SendMessage(combobox, CB_GETLBTEXTLEN,
|
||||
index, 0);
|
||||
std::vector<wchar_t> drive(length + 1);
|
||||
SendMessage(combobox, CB_GETLBTEXT, index,
|
||||
reinterpret_cast<LPARAM>(drive.data()));
|
||||
g_settings.Set("drive", std::wstring(drive.data()));
|
||||
WriteSettings();
|
||||
}
|
||||
EndDialog(hWnd, 0);
|
||||
} break;
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static std::vector<std::wstring> GetOpticalDriveList()
|
||||
{
|
||||
DWORD size = GetLogicalDriveStrings(0, nullptr);
|
||||
std::vector<wchar_t> drive_strings(size);
|
||||
if (GetLogicalDriveStrings(size, drive_strings.data()) != size - 1)
|
||||
return {};
|
||||
|
||||
std::vector<std::wstring> drives;
|
||||
for (auto p = drive_strings.data(); *p; ++p) {
|
||||
if (GetDriveType(p) == DRIVE_CDROM)
|
||||
drives.push_back(p);
|
||||
while (*p)
|
||||
++p;
|
||||
}
|
||||
return drives;
|
||||
}
|
||||
|
||||
std::wstring GetValidDrive()
|
||||
{
|
||||
std::wstring drive;
|
||||
g_settings.Get("drive", drive);
|
||||
if (drive.empty() || GetDriveType(drive.c_str()) != DRIVE_CDROM) {
|
||||
auto drives = GetOpticalDriveList();
|
||||
if (drives.empty())
|
||||
return {};
|
||||
drive = drives.front();
|
||||
}
|
||||
|
||||
int size = WideCharToMultiByte(CP_UTF8, 0, drive.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
||||
std::vector<char> converted_string(size);
|
||||
WideCharToMultiByte(CP_UTF8, 0, drive.c_str(), -1, converted_string.data(), converted_string.size(), nullptr, nullptr);
|
||||
printf(" * CDVD: Opening drive '%s'...\n", converted_string.data());
|
||||
|
||||
// The drive string has the form "X:\", but to open the drive, the string
|
||||
// has to be in the form "\\.\X:"
|
||||
drive.pop_back();
|
||||
drive.insert(0, L"\\\\.\\");
|
||||
return drive;
|
||||
}
|
||||
|
||||
void configure()
|
||||
{
|
||||
ReadSettings();
|
||||
auto drives = GetOpticalDriveList();
|
||||
DialogBoxParam(s_hinstance, MAKEINTRESOURCE(IDD_CONFIG), GetActiveWindow(),
|
||||
ConfigProc, reinterpret_cast<LPARAM>(&drives));
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
EXPORTS
|
||||
PS2EgetLibType @2
|
||||
PS2EgetLibName @3
|
||||
PS2EgetLibVersion2 @4
|
||||
CDVDinit @5
|
||||
CDVDshutdown @6
|
||||
CDVDopen @7
|
||||
CDVDclose @8
|
||||
CDVDreadTrack @9
|
||||
CDVDgetBuffer @10
|
||||
CDVDreadSubQ @11
|
||||
CDVDgetTN @12
|
||||
CDVDgetTD @13
|
||||
CDVDgetTOC @14
|
||||
CDVDgetDiskType @15
|
||||
CDVDgetTrayStatus @16
|
||||
CDVDctrlTrayOpen @17
|
||||
CDVDctrlTrayClose @18
|
||||
CDVDconfigure @19
|
||||
CDVDtest @20
|
||||
CDVDnewDiskCB @22
|
||||
CDVDgetBuffer2 @23
|
||||
CDVDreadSector @24
|
||||
CDVDgetDualInfo @25
|
||||
CDVDsetSettingsDir @26
|
|
@ -1,42 +0,0 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by cdvd.rc
|
||||
//
|
||||
|
||||
#ifndef IDC_STATIC
|
||||
#define IDC_STATIC -1
|
||||
#endif
|
||||
|
||||
#define IDD_CONFIG 101
|
||||
#define IDC_PLUGINS 1000
|
||||
#define IDC_CONFIGURE 1001
|
||||
#define IDC_TEST 1002
|
||||
#define IDC_ABOUT 1003
|
||||
#define IDC_IMAGE_BROWSE 1004
|
||||
#define IDC_USEISO 1005
|
||||
#define IDC_NOCD 1006
|
||||
#define IDC_PLUGIN 1007
|
||||
#define IDC_IMAGE 1008
|
||||
#define IDC_IMAGE_FILE 1009
|
||||
#define IDC_NOSUB 1010
|
||||
#define IDC_FAKE 1011
|
||||
#define IDC_SAME 1012
|
||||
#define IDC_DRIVE 1012
|
||||
#define IDC_SUB_FILE 1014
|
||||
#define IDC_ABOUT3 1015
|
||||
#define IDC_SUB_BROWSE 1015
|
||||
#define IDC_FILE 1016
|
||||
#define IDC_NODUMP 1020
|
||||
#define IDC_DUMP_ISO 1021
|
||||
#define IDC_DUMP_BDV2 1022
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1011
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
Loading…
Reference in New Issue