CDVD: merging and removing remnants of plugin

This commit is contained in:
Filjo Abraham 2020-07-01 21:11:42 -05:00 committed by refractionpcsx2
parent a70bfbdaa9
commit 029461c5ae
63 changed files with 1921 additions and 3328 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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!)

View File

@ -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 */

View File

@ -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)
{

View File

@ -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;

View File

@ -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,

View File

@ -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__ */

View File

@ -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;
}

View File

@ -17,7 +17,7 @@
#define __CDROM_H__
#include "IopCommon.h"
#include "PS2Edefs.h"
#include "CDVDaccess.h"
// Not used.
typedef struct {

View File

@ -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());
}

View File

@ -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;
}

View File

@ -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"\\\\.\\");
}
}

View File

@ -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;
}

View File

@ -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)

View File

@ -24,7 +24,6 @@ enum PluginsEnum_t
PluginId_GS = 0,
PluginId_PAD,
PluginId_SPU2,
PluginId_CDVD,
PluginId_USB,
PluginId_FW,
PluginId_DEV9,

View File

@ -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;

View File

@ -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();

View File

@ -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"

View File

@ -279,11 +279,13 @@ void SysCoreThread::ExecuteTaskInThread()
void SysCoreThread::OnSuspendInThread()
{
GetCorePlugins().Close();
DoCDVDclose();
}
void SysCoreThread::OnResumeInThread( bool isSuspended )
{
GetCorePlugins().Open();
DoCDVDopen();
}

View File

@ -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();

View File

@ -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 );

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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()

View File

@ -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);

View File

@ -105,7 +105,7 @@ namespace Dialogs
class DriveSelectorDialog : public wxDialog
{
public:
DriveSelectorDialog( wxWindow* parent );
DriveSelectorDialog( wxWindow* parent, wxString curDrive );
wxString GetSelectedDrive();
private:
wxChoice* choiceDrive;

View File

@ -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);

View File

@ -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

View File

@ -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");

View File

@ -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 ))

View File

@ -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" />

View File

@ -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">

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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}")

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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()

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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}")

View File

@ -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;
}

View File

@ -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

View File

@ -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
};

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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));
}

View File

@ -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

View File

@ -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