[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Plextor commands for DVD scanning



Hi all,

I have discussed with Alexander Noe, who has done some reverse engineering to find the plextor commands for DVD scanning. He gave me some code, which he allowed me to disperse so that software developers can add DVD scan support to their software.

It contains the proprietary commands for the Plextor drives, probably for PX-[57]xx series.

I hope you will find useful things, and sorry if you already had these information.

What we have:
-PIE
-PIF
-Jitter
-Beta

What is missing:
- TA. Alexander is working on TA on his new PX716A.

Eric

// plexstuff.cpp : Definiert den Einsprungpunkt für die Konsolenanwendung.
//

#include "stdafx.h"

#include "windows.h"
#include "memory.h"
#include "stdlib.h"
#include "wnaspi32.h"
#include "scsidefs.h"
#include "math.h"

#pragma pack(1)

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

int debug = 0;

const int DISC_DVDminusR  = 0x01;
const int DISC_DVDminusRW = 0x02;
const int DISC_DVDplusR   = 0x03;
const int DISC_DVDplusRW  = 0x04;
const int DISC_DVDplusRDL = 0x05;
const int DISC_DVDROM     = 0x06;

/*
typedef struct {
	int     data[8];
	int     position;


} RINGLIST;
*/

typedef struct
{
	char		vendor_ID[9];
	char		product_ID[17];
	char		product_revision[5];
	BYTE		haID;
	BYTE		Target;
	BYTE		Lun;
//	DRIVE_CAPS	caps;
} DRIVE_INFO;


/* Global Variables */
HINSTANCE hWNASPI32; // Handle to ASPI for Win32

/* Function Prototypes for WNASPI32.DLL */

DWORD (*GetASPI32SupportInfo)(void);
DWORD (*SendASPI32Command)(LPSRB);
BOOL (*GetASPI32Buffer)( void* );
BOOL (*FreeASPI32Buffer)( void* );
BOOL (*TranslateASPI32Address)( PDWORD, PDWORD );

// Then, inside your Main/WinMain function:

/* Load Real ASPI Layer, WNASPI32.DLL */

DWORD round(double x)
{
if ((x-(DWORD)x)>0.5) {
		return (DWORD)x+1;
	}
	else
	{
		return (DWORD)x;
	}
}

const int COMMAND_FAILED = -0x01;

int ExecSCSICmd(DWORD dwFlag,DRIVE_INFO* drive,SRB_ExecSCSICmd* lpsrbExec,void* lpData,DWORD dwDataLen,
								BYTE cmdlen,BYTE cmd0 = 0,BYTE cmd1 = 0,BYTE cmd2 = 0,
								BYTE cmd3 = 0,BYTE cmd4 = 0,BYTE cmd5 = 0,BYTE cmd6 = 0,
								BYTE cmd7 = 0,BYTE cmd8 = 0, BYTE cmd9 = 0,BYTE cmd10 = 0,
								BYTE cmd11 = 0,BYTE cmd12 = 0)
{
	HANDLE heventSRB;
	DWORD	dwASPIStatus;

	memset(lpsrbExec, 0, sizeof(SRB_ExecSCSICmd) );
	heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );

	lpsrbExec->SRB_Cmd = SC_EXEC_SCSI_CMD;
	lpsrbExec->SRB_Flags = (BYTE)(dwFlag | SRB_EVENT_NOTIFY);
	lpsrbExec->SRB_Target = drive->Target;
	lpsrbExec->SRB_Lun = drive->Lun;
	lpsrbExec->SRB_HaId = drive->haID;
	lpsrbExec->SRB_BufLen = dwDataLen;
		
	lpsrbExec->SRB_BufPointer = (unsigned char*)lpData;
	lpsrbExec->SRB_SenseLen = SENSE_LEN;
	lpsrbExec->SRB_CDBLen = cmdlen;
	lpsrbExec->SRB_PostProc = (LPVOID)heventSRB;
	lpsrbExec->CDBByte[0] = cmd0;
	lpsrbExec->CDBByte[1] = cmd1;
	lpsrbExec->CDBByte[2] = cmd2;
	lpsrbExec->CDBByte[3] = cmd3;
	lpsrbExec->CDBByte[4] = cmd4;
	lpsrbExec->CDBByte[5] = cmd5;
	lpsrbExec->CDBByte[6] = cmd6;
	lpsrbExec->CDBByte[7] = cmd7;
	lpsrbExec->CDBByte[8] = cmd8;
	lpsrbExec->CDBByte[9] = cmd9;
	lpsrbExec->CDBByte[10] = cmd10;
	lpsrbExec->CDBByte[11] = cmd11;
	lpsrbExec->CDBByte[12] = cmd12;
		
	ResetEvent( heventSRB );
	dwASPIStatus = SendASPI32Command( lpsrbExec );
	if( dwASPIStatus == SS_PENDING )
	{
		WaitForSingleObject( heventSRB, INFINITE );
	}
//	DispStat(lpsrbExec);

	if (lpsrbExec->SRB_TargStat==STATUS_CHKCOND)
	{
		if (lpsrbExec->SenseArea[2]==KEY_UNITATT)
		{
			return ExecSCSICmd(dwFlag,drive,lpsrbExec,lpData,dwDataLen,cmdlen,cmd0,cmd1,cmd2,cmd3,cmd4,cmd5,
				cmd6,cmd7,cmd8,cmd9,cmd10,cmd11,cmd12);
} else /*if (lpsrbExec->SenseArea[2]==KEY_MEDIUMERR)
		{
			printf("medium error\n");

		} else
		*/
		
		{
		/*	printf("error: sense code: %02X,  ASC: %02X,  ASCQ: %02X\n", (DWORD)lpsrbExec->SenseArea[2],
				(DWORD)lpsrbExec->SenseArea[12],(DWORD)lpsrbExec->SenseArea[13]);*/
if (debug) { printf(" command failed: (%d) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
					cmdlen,cmd0,cmd1,cmd2,cmd3,cmd4,cmd5,
cmd6,cmd7,cmd8,cmd9,cmd10,cmd11,cmd12); } else {
				printf("    command failed\n");
			}
			
			if (dwDataLen && debug && (dwDataLen < 8192)) {
				if (dwFlag == SRB_DIR_IN) printf("    answer:\n      ");
				if (dwFlag == SRB_DIR_OUT) printf("    input :\n      ");
				for (int i=0;i<(int)dwDataLen;i++) {
					printf("%02X ", ((unsigned char*)lpData)[i]);
					if (((i+1) % 16) == 0) printf("\n      ");
				}
				printf("\n");
			}
			return COMMAND_FAILED;

		}
	} else {
		if (debug) {
			printf("    command succeeded: (%d) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
			cmdlen,cmd0,cmd1,cmd2,cmd3,cmd4,cmd5,
			cmd6,cmd7,cmd8,cmd9,cmd10,cmd11,cmd12);
				if (dwDataLen && dwDataLen < 8192) {
					if (dwFlag == SRB_DIR_IN) printf("    answer:\n      ");
					if (dwFlag == SRB_DIR_OUT) printf("    input :\n      ");
					for (int i=0;i<(int)dwDataLen;i++) {
						printf("%02X ", ((unsigned char*)lpData)[i]);
						if (((i+1) % 16) == 0) printf("\n      ");
					}
					printf("\n");
				}
		}
	}

	return 0;

}

int TestUnitReady (DRIVE_INFO* drive)
{
	SRB_ExecSCSICmd srbExec;

	int j = ExecSCSICmd(0,drive,&srbExec,NULL,0,6,0);

	if (j != COMMAND_FAILED) return 1;
	return 0;
}

int swap4(char* c) {
	char d[4];
	d[0]=c[3];
	d[1]=c[2];
	d[2]=c[1];
	d[3]=c[0];
	return *(int*)d;
}

short int swap2(char* c) {
	char d[2];
	d[0]=c[1];
	d[1]=c[0];
	return *(short int*)d;
}

int swap4(int c_) {
	char* c = (char*)&c_;
	char d[4];
	d[0]=c[3];
	d[1]=c[2];
	d[2]=c[1];
	d[3]=c[0];
	return *(int*)d;
}

void print_gigarec_value(int i)
{
	switch (i & 0xFF) {
		case 0x00: printf("gigarec off\n"); break;
		case 0x01: printf("gigarec 1.2x\n"); break;
		case 0x02: printf("gigarec 1.3x\n"); break;
		case 0x03: printf("gigarec 1.4x\n"); break;
		case 0x81: printf("gigarec 0.8x\n"); break;
		case 0x82: printf("gigarec 0.7x\n"); break;
		case 0x83: printf("gigarec 0.6x\n"); break;
	}
}

int plextor_set_gigarec(DRIVE_INFO* drive, int i)
{
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	printf("  applying gigarec setting       : ");
	print_gigarec_value(i);

	char data[] = { 0x00, 0x00, 0x00, 0, 0,0,0,0 };
	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,data,8,12,0xE9,0x10,0x04,
		0x00,i,0x00,0x00,0x00,0x00,0x00,0x08);

	return 1;
}

int plextor_read_gigarec(DRIVE_INFO* drive, int* i)
{
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	char data[] = { 0x00,0x00,0,0,0,0,0,0 };
	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,data,8,12,0xE9,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08);

	printf("  reading current gigarec setting: ");

	print_gigarec_value(data[3]);

	return 1;
}

int plextor_start_pisum8(DRIVE_INFO* drive)
{
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,NULL,0,12,0xEA,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10);

	if (j != COMMAND_FAILED) return 1;
	return 0;
}

int plextor_start_pif(DRIVE_INFO* drive)
{
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,NULL,0,12,0xEA,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x12);

	if (j != COMMAND_FAILED) return 1;
	return 0;
}

int plextor_start_jitterbeta(DRIVE_INFO* drive)
{
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,NULL,0,10,0xEA,0x15,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00);

	if (j != COMMAND_FAILED) return 1;
	return 0;
}

int plextor_end_pi(DRIVE_INFO* drive)
{
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,NULL,0,12,0xEA,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);

	if (j != COMMAND_FAILED) return 1;
	return 0;
}

int read_one_ecc_block(DRIVE_INFO* drive, void* pBuffer, int lba) {
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,pBuffer,32768,10,0x28,0x00,(lba>>24) & 0xFF,
		(lba>>16) & 0xFF, (lba>>8) & 0xFF, lba & 0xFF, 0x00,0x00,0x10,0x00);

	if (j != COMMAND_FAILED) return 1;


	

	return 0;
}

int plextor_read_pi_info(DRIVE_INFO* drive, void* pBuffer)
{
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,pBuffer,0x34,12,0xEA,0x16,
		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x00);

	if (j != COMMAND_FAILED) return 1;
	return 0;
}

int plextor_read_jb_info(DRIVE_INFO* drive, void* pBuffer)
{
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,pBuffer,0x10,12,0xEA,0x16,
		0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00);

	if (j != COMMAND_FAILED) return 1;
	return 0;
}

int plextor_pisum8_do_eight_ecc_blocks(DRIVE_INFO* drive, void* pBuffer, int lba, int* pError_count)
{
	char data[0x34]; memset(data, 0, 0x34);

	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	for (int i=0;i<8;i++) {
		read_one_ecc_block(drive, pBuffer, lba);
		lba += 16;
	}

	plextor_read_pi_info(drive, data);

	*pError_count = swap4(data+0x24);
	
	return 1;
}

int plextor_jitterbeta_do_16_ecc_blocks(DRIVE_INFO* drive, void* pBuffer, int lba, int* jitter,
										short int* beta)
{
	char data[0x34]; memset(data, 0, 0x34);
	short int*  i16_beta;
	char c;

	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	for (int i=0;i<16;i++) {
		read_one_ecc_block(drive, pBuffer, lba);
		lba += 16;
	}

	plextor_read_jb_info(drive, data);

	c = data[10]; data[10] = data[11]; data[11] = c;
	i16_beta = (short int*)(data+10);
	*beta = *i16_beta;

	*jitter = swap2(data+12);
	
	return 1;
}

int plextor_pif_do_one_ecc_block(DRIVE_INFO* drive, void* pBuffer, int lba, int* pError_count)
{
	char data[0x34]; memset(data, 0, 0x34);

	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	read_one_ecc_block(drive, pBuffer, lba);
	lba += 16;

	plextor_read_pi_info(drive, data);

	*pError_count = swap4(data+0x24);
	
	return 1;
}

int read_capacity(DRIVE_INFO* drive, int* pCapacity)
{
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
	char data[8]; memset(data, 0, 8);

	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,data,8,10,0x25);
	
	*pCapacity = swap4(data);
	if ((*pCapacity % 16) != 0) {
		*pCapacity = ((*pCapacity) / 16 * 16) + 16;
	}

	return 1;
}

int eval_dvd_struct_0e(void* pData)
{
	char* cData = (char*)pData;

	cData[27]=0;
	cData[35]=0;
	cData[43]=0;

	printf("manufacturer ID: ");
	printf(cData+21);
	printf(cData+29);
	printf("\n");

	return 1;
}

int eval_dvd_struct_11_dvdplus(void* pData)
{
	char* cData = (char*)pData;

//	cData[34]=0;
	cData[0] = cData[31];
	cData[31] = 0;

	if (cData[23]) {
		printf("manufacturer ID: ");
		printf(cData+23);
		printf("-");
		cData[31] = cData[0];
		cData[0] = cData[34];
		cData[34] = 0;
		printf(cData+31);
		printf("-");
		printf("%c%c", (unsigned int)(cData[0] >> 4)+48, (unsigned int)(cData[0] & 0x0F)+48);
		printf("\n");
	}


	return 1;
}
/*
int get_read_speed(DRIVE_INFO* drive, int* speed)
{
	unsigned char data[40]; memset(data, 0, 40);

	char* perf_data_length = (char*)&data[0];
	char* start_lba = (char*)&data[8];
	char* start_perf = (char*)&data[12];
	char* end_lba = (char*)&data[16];
	char* end_perf = (char*)&data[20];

	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,data,40,12,0xAC,0x00,0,0,0,0,0,0,0,2,0,0);

	printf("get_read_speed:\n");
	printf("  pd     len= %d\n", swap4(perf_data_length));
	printf("  start_lba = %06X\n", swap4(start_lba));
	printf("  start_perf= %6d\n", swap4(start_perf));
	printf("  end  _lba = %06X\n", swap4(end_lba));
	printf("  end  _perf= %6d\n", swap4(end_perf));

	return 1;
}
*/

int get_feature(DRIVE_INFO* drive, int feature_number, char* pDest, int pDest_len, int* current = NULL)
{
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
	if (current) *current = 0;

	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,pDest,32,10,0x46,0x02,(feature_number >> 8) & 0xFF,
		feature_number & 0xFF,0,0,0,32);

	if (j == COMMAND_FAILED) return 0;

	char* data_length = (char*)&pDest[0];
	char* current_profile = (char*)&pDest[6];

	if (current) *current = pDest[10] & 0x01;
	if (swap4(data_length) < 8) return 0;

	return 1;
}

int read_dvd_structure(DRIVE_INFO* drive, int format, char* pDest)
{
	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,pDest,2056,10,0xAD,0,0,0,0,0,0,format,
		8,8,0);

	return 1;
}

int determine_disc_type(DRIVE_INFO* drive, int* disc_type)
{
	bool bDVDminus = false;

	*disc_type = 0;

	char* book_types[] = { "DVD-ROM", "DVD-RAM", "DVD-R", "DVD-RW", "<b0rked>",
		"<b0rked>","<b0rked>","<b0rked>","<b0rked>","DVD+RW", "DVD+R",
		"<b0rked>","<b0rked>","<b0rked>","DVD+R DL", "<b0rked>" };

	char data[2056]; memset(data, 0, 2056); int current = 0;

	if (get_feature(drive, 0x2F, data, 32, &current) && current) {
		printf("disc type: DVD-R/W\n");
		bDVDminus = true;
	} else if (get_feature(drive, 0x2B, data, 32, &current) && current) {
		printf("disc type: DVD+R\n"); *disc_type = DISC_DVDplusR;
	}
	else if (get_feature(drive, 0x2A, data, 32, &current) && current) {
		printf("disc type: DVD+RW\n"); *disc_type = DISC_DVDplusRW;
	}		
	else if (get_feature(drive, 0x3B, data, 32, &current) && current) {
		printf("disc type: DVD+R DL\n"); *disc_type = DISC_DVDplusRDL;
	}
	else if (get_feature(drive, 0x1F, data, 32, &current) && current) {
		printf("disc type: DVD-ROM\n"); *disc_type = DISC_DVDROM;
	}
	else {
		printf("no DVD media found\n");
		return 0;
	}

	read_dvd_structure(drive, 0, data);
	int booktype = ((data[4] & 0xFF) >> 4);

	printf("book type: %s\n", book_types[booktype]);

	if (bDVDminus) {
		if (booktype == 0x02) *disc_type = DISC_DVDminusR;
		if (booktype == 0x03) *disc_type = DISC_DVDminusRW;
	
	}

	return 1;
}

int set_read_speed(DRIVE_INFO* drive, int speed)
{
	unsigned char data[28]; memset(data, 0, 28);

	int* start_lba  = (int*)&data[4];
	int* end_lba    = (int*)&data[8];
	int* read_size  = (int*)&data[12];
	int* read_time  = (int*)&data[16];
	int* write_size = (int*)&data[20];
	int* write_time = (int*)&data[24];

	int capacity; read_capacity(drive, &capacity);

	*start_lba = swap4(0);
	*end_lba = swap4(capacity);
	*read_time = swap4(1000);
	*read_size = swap4(speed);
	*write_time = swap4(1000);
	*write_size = swap4(22000);

	SRB_ExecSCSICmd srbExec;
	memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );

	int j = ExecSCSICmd(SRB_DIR_OUT,drive,&srbExec,data,28,12,0xB6,0,0,0,0,0,0,0,0,0,28);

	if (j == COMMAND_FAILED) return 0;
	return 1;
}

int plextor_scan_pisum8(DRIVE_INFO* drive, int silent, int** result_map = NULL, int capacity = 0,
						int* virtual_file = NULL, HANDLE hSemaphore = NULL)
{
	void*	pBuffer  = malloc(32768);
	__int64 capacity_in_bytes;

	int		scan_start_time;
	int		scan_end_time;
	int		last_update;
	int		produce_map = 0;
//	int     m;

	const int		last_pos_index_max = 8;
	int     k;
	int		last_pos[last_pos_index_max]; memset(last_pos, 0, sizeof(last_pos));
	int		last_pos_index = 0;
int last_time[last_pos_index_max];
	if (!capacity) read_capacity(drive, &capacity);
	capacity_in_bytes = (__int64)(capacity) * 2048;

	printf("\n\nstarting PIsum8 test...\n");
	if (!silent) printf("disc capacity: %d sectors = %d ECC blocks\n\n", capacity, capacity >> 4);
	capacity >>= 7;

	if (result_map) {
		*result_map = (int*)calloc(sizeof(int), capacity+1);
		(*result_map)[0] = capacity;
		produce_map = 1;
	}

	if (virtual_file) {
		*virtual_file++ = capacity;
		ReleaseSemaphore(hSemaphore, 1, NULL);
	}

	int total_error_count = 0;
	int current_error_count = 0;
	int max_error_count = 0;
	int broken_count = 0;

	scan_start_time = GetTickCount();
	last_update = GetTickCount();
	plextor_start_pisum8(drive);

	for (k=0;k<last_pos_index_max;last_time[k++]=scan_start_time-1);

	for (k = 0;k<capacity;k++) {
		plextor_pisum8_do_eight_ecc_blocks(drive, pBuffer, k*16*8, &current_error_count);
		if (produce_map) (*result_map)[k+1] = current_error_count;
		if (max_error_count < current_error_count) max_error_count = current_error_count;
		if (current_error_count > 280) broken_count++;

		if (virtual_file) {
			*virtual_file++ = current_error_count;
			ReleaseSemaphore(hSemaphore, 1, NULL);
		}

		if (GetTickCount() - last_update > 1000 || k==capacity-1) {
			if (!debug) {
				if (!silent) {
					printf("\r");
printf("current speed: %5.2fx, %5.1f%% done, max: %d ", (float)(k-last_pos[last_pos_index])*256/1.385/(GetTickCount()-last_time[last_pos_index]),
						(float)k*100/capacity,max_error_count);
				} else {
					printf("\r");
					printf("%5.1f%%  done", (float)(k+1)*100/capacity);
				}
			}
			last_update += 1000;
			last_time[last_pos_index] = GetTickCount();
			last_pos[last_pos_index++] = k;
			last_pos_index%=last_pos_index_max;
		}
	}

	for (k=0;k<capacity;total_error_count+=(*result_map)[k+++1]);

	if (!silent) {
		printf("\rtotal error count                                   : %8d         \n", total_error_count);
		printf("average nbr of errors per sector                    : %8.2f\n", (float)total_error_count / k / 8);
		printf("PIsum8 max                                          : %8d\n", max_error_count);
		printf("occurences of 8 consecutive blocks with PIsum8 > 280: %8d\n", broken_count);
	} else printf("\n");

	plextor_end_pi(drive);

	scan_end_time = GetTickCount();

	if (!silent) printf("duration                                            : %d seconds\n", (scan_end_time - scan_start_time) / 1000);

	delete pBuffer;

	return 1;
}

int plextor_scan_pif(DRIVE_INFO* drive, int silent, int** result_map = NULL, int capacity = NULL,
					 int* virtual_file = NULL, HANDLE hSemaphore = NULL)
{
	void*	pBuffer  = malloc(32768);
	__int64 capacity_in_bytes;
	int		scan_start_time;
	int		scan_end_time;
	int     last_update;
	int		k;
	int		produce_map = 0;
	const int		last_pos_index_max = 8;
	int		last_pos[last_pos_index_max]; memset(last_pos, 0, sizeof(last_pos));
	int		last_pos_index = 0;
int last_time[last_pos_index_max];
	if (!capacity) read_capacity(drive, &capacity);
	capacity_in_bytes = (__int64)(capacity) * 2048;

	printf("\n\nstarting PIF test...\n");
	if (!silent) printf("disc capacity: %d sectors = %d ECC blocks\n\n", capacity, capacity >> 4);
	capacity >>= 4;

	if (virtual_file) {
		*virtual_file++ = capacity;
		ReleaseSemaphore(hSemaphore, 1, NULL);
	}

	if (result_map) {
		*result_map = (int*)calloc(sizeof(int), capacity+1);
		(*result_map)[0] = capacity;
		produce_map = 1;
	}

	int total_error_count = 0;
	int current_error_count = 0;
	int max_error_count = 0;
	int broken_count = 0;

	scan_start_time = GetTickCount();
	last_update = GetTickCount();

	plextor_start_pif(drive);

	for (k=0;k<last_pos_index_max;last_time[k++]=scan_start_time-1);
	
	for (k = 0;k<capacity;k++) {
		plextor_pif_do_one_ecc_block(drive, pBuffer, k*16, &current_error_count);
		if (produce_map) (*result_map)[k+1] = current_error_count;
		if (max_error_count < current_error_count) max_error_count = current_error_count;
		if (current_error_count > 4) broken_count++;
		if (virtual_file) {
			*virtual_file++ = current_error_count;
			ReleaseSemaphore(hSemaphore, 1, NULL);
		}

		if (GetTickCount() - last_update > 1000 || k==capacity - 1) {
			if (!debug) {
				if (!silent) {
					printf("\r");
printf("current speed: %5.2fx, %5.1f%% done, max: %d", (float)(k-last_pos[last_pos_index])*32/1.385/(GetTickCount()-last_time[last_pos_index]), (float)k*100/capacity, max_error_count);
				} else {
					printf("\r");
					printf("%5.1f%% ", (float)(k+1)*100/capacity);
				}
			}
			last_update += 1000;
			last_time[last_pos_index] = GetTickCount();
			last_pos[last_pos_index++] = k;
			last_pos_index%=last_pos_index_max;
		}

	}

	for (k=0;k<capacity;total_error_count+=(*result_map)[k+++1]);

	if (!silent) {
		printf("\rtotal error count                          : %8d                      \n", total_error_count);
		printf("average nbr of errors per sector           : %8.2f\n", (float)total_error_count / k / 8);
		printf("PIF max                                    : %8d\n", max_error_count);
		printf("occurences of ECC blocks with PIF    > 4   : %8d\n", broken_count);
	} else printf("\n");

	plextor_end_pi(drive);

	scan_end_time = GetTickCount();

	if (!silent) printf("duration                                   : %d seconds\n", (scan_end_time - scan_start_time) / 1000);

	delete pBuffer;

	return 1;
}

int plextor_scan_jitterbeta(DRIVE_INFO* drive, int silent, int** result_map = NULL, int capacity = NULL,
							int* virtual_file = NULL, HANDLE hSemaphore = NULL)
{
	__int64		 capacity_in_bytes;
	short int	 beta;
	int			 jitter, k;
	unsigned int value;
	int			 produce_map = 0;
	void*		 pBuffer  = malloc(32768);


	if (!capacity) read_capacity(drive, &capacity);
	capacity_in_bytes = (__int64)(capacity) * 2048;

	printf("\n\nstarting J/B test...\n");

	if (!silent) printf("disc capacity: %d sectors = %d ECC blocks\n\n", capacity, capacity >> 4);
	capacity >>= 8;

	plextor_start_jitterbeta(drive);

	if (virtual_file) {
		*virtual_file++ = capacity;
		ReleaseSemaphore(hSemaphore, 1, NULL);
	}

	if (result_map) {
		*result_map = (int*)calloc(sizeof(int), capacity+1);
		(*result_map)[0] = capacity;
		produce_map = 1;
	}

	for (k = 0;k<capacity;k++) {
		plextor_jitterbeta_do_16_ecc_blocks(drive, pBuffer, k*16*16, &jitter, &beta);

		value = (beta) << 16 | (jitter & 0xFFFF);
		if (produce_map) (*result_map)[k+1] = value;

		printf("\rLBA: %06X  jitter: %4d,  beta: %4d", k*16*16, jitter, (int)beta);

		if (virtual_file) {
			*virtual_file++ = value;
			ReleaseSemaphore(hSemaphore, 1, NULL);
		}
	}

	printf("\n");



	plextor_end_pi(drive);
	delete pBuffer;
	return 1;
}

BOOL Init(int argc, char* argv[], int gigarec, int pisum8, int pif, int jb, void** results, int silent, int speed = 2770, int immed_draw = 0)
{
	char	cBuffer[255];
	char	cBuffer2[255];
	int		i,j,k;
	DRIVE_INFO*		drive;
	HANDLE	hMemoryFile = 0;
	HANDLE	hSemaphore = NULL;

	void*	memory_file = NULL;

	hMemoryFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, "pxstuff virtual file");
	if (hMemoryFile) immed_draw = 1;

	if (immed_draw) {
		
		printf("sending data immediately to PxView...\n");
		memory_file = MapViewOfFile(hMemoryFile, FILE_MAP_WRITE,0,0,0);

		hSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, 0, "pxstuff semaphore");
		if (!hSemaphore) {
			printf("Set PxView to capture mode before using draw_immed\n");
			return 0;
		}
	}




	// Symbol für dieses Dialogfeld festlegen. Wird automatisch erledigt
	//  wenn das Hauptfenster der Anwendung kein Dialogfeld ist

	// ZU ERLEDIGEN: Hier zusätzliche Initialisierung einfügen
	HINSTANCE hWNASPI32; // Handle to ASPI for Win32

	hWNASPI32 = LoadLibrary("WNASPI32.DLL");

	if(!hWNASPI32) /* If Load Failed */
	{
		printf(TEXT("LoadLibrary(\"WNASPI32.DLL\") Failed. Install ForceASPI 1.7.\n"));
	    return FALSE;
	}

	GetASPI32SupportInfo = (DWORD (*)(void))
	GetProcAddress(hWNASPI32,"GetASPI32SupportInfo");
	SendASPI32Command = (DWORD (*)(void *)) GetProcAddress(hWNASPI32,"SendASPI32Command");
	GetASPI32Buffer = (BOOL (*)(void *)) GetProcAddress(hWNASPI32,"GetASPI32Buffer");
	FreeASPI32Buffer = (BOOL (*)(void *)) GetProcAddress(hWNASPI32,"FreeASPI32Buffer");
	TranslateASPI32Address = (BOOL (*)(DWORD*,DWORD*)) GetProcAddress(hWNASPI32,"TranslateASPI32Address");

	if( !GetASPI32SupportInfo || !SendASPI32Command )
   {
		printf("Cannot find critical WNASPI32.DLL Functions!\n");
		return FALSE;
   }

	BYTE HACount;
	BYTE ASPIStatus;
	DWORD SupportInfo;
	SupportInfo = GetASPI32SupportInfo();
	HACount = LOBYTE(LOWORD(SupportInfo));
	ASPIStatus = HIBYTE(LOWORD(SupportInfo));
	printf("\nLooking for drives...\n");

	if (!HACount) {
		printf("Broken result received by GetASPI32SupportInfo()\n");
		HACount = 15;
	}
	

	for (i=0;i<HACount;i++)
	{
		SRB_HAInquiry HAInquiry; // Create a data struct for our command.
		memset( &HAInquiry, 0, sizeof(SRB_HAInquiry) ); // Zero out the SRB
		HAInquiry.SRB_Cmd = SC_HA_INQUIRY;
		HAInquiry.SRB_HaId = i;

		for (j=0;j<16;j++)
		{
			for (k=0;k<16;k++)
			{
				DWORD dwASPIStatus;
				SRB_GDEVBlock GDEVBlock;
				HANDLE heventSRB;
				memset( &GDEVBlock, 0, sizeof( SRB_GDEVBlock ));
				GDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE;
				GDEVBlock.SRB_HaId = i; // Host Adapter
				GDEVBlock.SRB_Target = j; // SCSI ID
				GDEVBlock.SRB_Lun = k;
				heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
				if( !heventSRB ) {
					// Couldn't get manual reset event, put error handling code here!
					printf("failed to create event!\n");
				}
				GDEVBlock.SRB_Flags = SRB_EVENT_NOTIFY;

				dwASPIStatus = SendASPI32Command( (LPSRB)&GDEVBlock );
				if( dwASPIStatus == SS_PENDING ) {
					WaitForSingleObject( heventSRB, INFINITE );
				}
				if (dwASPIStatus == SS_BAD_INSTALL) {
					printf("ASPI error: 'Bad Installation'\n");
				}

				if( GDEVBlock.SRB_Status != SS_COMP )
				{ // Handle Error Code
				}
				else // No error*/
				{
					if( GDEVBlock.SRB_DeviceType == DTYPE_CDROM )
					{	
						SRB_ExecSCSICmd srbExec;
						memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
						ZeroMemory(cBuffer,sizeof(cBuffer));
						srbExec.SRB_Cmd = SC_EXEC_SCSI_CMD;
						srbExec.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
						srbExec.SRB_Target = GDEVBlock.SRB_Target;
						srbExec.SRB_Lun = GDEVBlock.SRB_Lun;
						srbExec.SRB_HaId = GDEVBlock.SRB_HaId;
						srbExec.SRB_BufLen = sizeof(cBuffer);
						srbExec.SRB_BufPointer = (unsigned char*)cBuffer;
						srbExec.SRB_SenseLen = SENSE_LEN;
						srbExec.SRB_CDBLen = 6;
						srbExec.SRB_PostProc = (LPVOID)heventSRB;
						srbExec.CDBByte[0] = SCSI_INQUIRY;
						srbExec.CDBByte[4] = sizeof(cBuffer);
						ResetEvent( heventSRB );
						dwASPIStatus = SendASPI32Command( (LPSRB)&srbExec );
						if( dwASPIStatus == SS_PENDING )
						{
							WaitForSingleObject( heventSRB, INFINITE );
						}
						if( srbExec.SRB_Status != SS_COMP )
						{
							// Error processing the SRB, put error handling code here.
						}
						else
						{
							drive = (DRIVE_INFO*)calloc(1,sizeof(DRIVE_INFO));
							lstrcpyn(drive->vendor_ID,&(cBuffer[8]),9);
							lstrcpyn(drive->product_ID,&(cBuffer[16]),17);
							lstrcpyn(drive->product_revision,&(cBuffer[32]),5);
							drive->haID=GDEVBlock.SRB_HaId;
							drive->Target=GDEVBlock.SRB_Target;
							drive->Lun=GDEVBlock.SRB_Lun;

							int plextor = 0;
							int qchk = 0;
							
							if (!strncmp(drive->vendor_ID, "PLEXTOR", 7)) {
								if (!strncmp(drive->product_ID, "DVDR   PX-716",13)) {
									char* c = drive->product_revision + 2;
									plextor=1;
									qchk = 1;
								} else
								if (!strncmp(drive->product_ID, "DVDR   PX-712",13)) {
									char* c = drive->product_revision + 2;
									plextor=1;
									qchk = 1;
								} else
								if (!strncmp(drive->product_ID, "CD-R   PREMIUM",14)) {
									char* c = drive->product_revision + 2;
									plextor=1;
								}
							}

							sprintf(cBuffer2,"Drive %d:%d:%d: %s %s %s \n",GDEVBlock.SRB_HaId,
								GDEVBlock.SRB_Target,GDEVBlock.SRB_Lun,drive->vendor_ID,drive->product_ID,
								drive->product_revision);
							if (plextor) printf(cBuffer2);

							//printf("\n");

							SRB_GetSetTimeouts srbGetSetTimeouts;
							memset( &srbGetSetTimeouts, 0, sizeof(SRB_GetSetTimeouts) );
							srbGetSetTimeouts.SRB_Cmd = SC_GETSET_TIMEOUTS;
							srbGetSetTimeouts.SRB_Flags = SRB_DIR_OUT;
							srbGetSetTimeouts.SRB_Target = drive->Target;
							srbGetSetTimeouts.SRB_Lun = drive->Lun;
							srbGetSetTimeouts.SRB_HaId = drive->haID;
							srbGetSetTimeouts.SRB_Timeout = 10*2;
							SendASPI32Command( (LPSRB)&srbGetSetTimeouts );
							if( srbGetSetTimeouts.SRB_Status != SS_COMP )
							{
								// Error setting timeouts. Put error handling code here.
}
							if (plextor) {
								int i;

								if (!silent) plextor_read_gigarec(drive, &i);
								if (gigarec>-1) {
									plextor_set_gigarec(drive, gigarec);
									if (!silent) plextor_read_gigarec(drive, &i);
								}

								if (qchk && (pisum8 || pif || jb)) {
									int disc_type = -1;

									if (determine_disc_type(drive, &disc_type)) {
										SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
										void* pData = malloc(2056);
										if (disc_type == DISC_DVDminusR || disc_type == DISC_DVDminusRW) {
											read_dvd_structure(drive, 0x0E, (char*)pData);
											eval_dvd_struct_0e(pData);
										} else if (disc_type == DISC_DVDplusR || disc_type == DISC_DVDplusRW
											|| disc_type == DISC_DVDplusRDL) {
											read_dvd_structure(drive, 0x11, (char*)pData);
											eval_dvd_struct_11_dvdplus(pData);
										} else {
											read_dvd_structure(drive, 0x00, (char*)pData);
											eval_dvd_struct_11_dvdplus(pData);
											if (((char*)pData)[23]) {
												printf("DVD-ROM and manufacturer ID detected. Disc might be DVD+R DL (\?\?\?)\n");
											} else {
												read_dvd_structure(drive, 0x0E, (char*)pData);
												eval_dvd_struct_0e(pData);
												if (((char*)pData)[23]) {
													printf("DVD-ROM and manufacturer ID detected. Disc might be bitsetted DVD-R (\?\?\?)\n");
												}
											}
										}
										free(pData);

										printf("trying to set speed to %dx\n", speed/1385);
										set_read_speed(drive, speed);
										int capacity = 0;
										read_capacity(drive, &capacity);
										if (!capacity) {
											printf("reading capacity failed!");
											return 0;
										}

										int scanval = 4*jb + 2*pif + pisum8;
										int* vfile = (int*)memory_file;
										if (vfile) *vfile++ = scanval;

										if (pisum8) {
											plextor_scan_pisum8(drive, silent, (int**)&results[0], capacity,
												vfile, hSemaphore);
											if (vfile) vfile+=1+(capacity>>7);
										}
	
										if (pif) {
											plextor_scan_pif(drive, silent, (int**)&results[1], capacity,
												vfile, hSemaphore);
											if (vfile) vfile+=1+(capacity>>4);
										}

										if (jb) {
											plextor_scan_jitterbeta(drive, silent, (int**)&results[2], capacity,
												vfile, hSemaphore);
										}

									}
								}
							}
						}
					}
				}
			}
		}
	}
	
// TODO:
// If ASPIStatus != SS_COMP and != SS_NO_ADAPTERS, you must handle the error.

// Then, inside your Main/WinMain function:

/* Load Real ASPI Layer, WNASPI32.DLL */


return TRUE; // Geben Sie TRUE zurück, außer ein Steuerelement soll den Fokus erhalten
}

int main(int argc, char* argv[])
{
	int gigarec = -1;
	int pisum8 = 0;
	int pif = 0;
	int jb = 0;
	int silent = 0;
	int immed_draw=0;
	int* results[3] = { NULL, NULL, NULL };
	char destfile[1024]; destfile[0]=0;
	int speed = 2770;

	printf("\nPxScan v1.3, built %s %s\n", __DATE__, __TIME__);

	for (int j=1;j<argc;j++) {
		if (!strcmp(argv[j],"debug")) debug=1; else

		if (!strnicmp(argv[j],"gigarec=",8)) {
			if (!strnicmp(argv[j]+8, "1.2", 3)) {
				gigarec = 0x01;
			}
			if (!strnicmp(argv[j]+8, "1.3", 3)) {
				gigarec = 0x02;
			}
			if (!strnicmp(argv[j]+8, "1.4", 3)) {
				gigarec = 0x03;
			}
			if (!strnicmp(argv[j]+8, "0.6", 3)) {
				gigarec = 0x83;
			}
			if (!strnicmp(argv[j]+8, "0.7", 3)) {
				gigarec = 0x82;
			}
			if (!strnicmp(argv[j]+8, "0.8", 3)) {
				gigarec = 0x81;
			}
		} else

		if (!stricmp(argv[j], "pisum8")) {
			printf(" performing PIsum8 scan\n");
			pisum8 = 1;
		} else
		if (!stricmp(argv[j], "pif")) {
			printf(" performing PIF scan\n");
			pif = 1;
		} else
		if (!stricmp(argv[j], "silent")) {
			silent = 1;
		} else
		if (!stricmp(argv[j], "jitterbeta")) {
			printf(" performing jitter/beta scan\n");
			jb = 1;
		} else
		if (!strnicmp(argv[j], "destfile=", 9)) {
			strcpy(destfile, argv[j]+9);
			printf(" output file for results: %s\n", destfile);
		} else
		if (!strnicmp(argv[j], "speed=", 6)) {
			speed=atoi(argv[j]+6)*1385;
		} else {
			printf(" unknown option: %s\n", argv[j]);
		}

	}



	Init(argc, argv, gigarec, pisum8, pif, jb, (void**)results, silent, speed,
		immed_draw);
	printf("\n");
	if (strlen(destfile) && (pisum8 || pif | jb) && (results[0] || results[1] || results[2])) {
		FILE* f = fopen(destfile, "wb");
		int  present_mask = 0;
		
		if (pisum8) present_mask |= 1;
		if (pif) present_mask |= 2;
		if (jb) present_mask |= (1<<16);

		fwrite(&present_mask, 4, 1, f);

		if (pisum8) {
			printf("writing PIsum8 results (%d values) ...\n", results[0][0]);
			fwrite(&(results[0][0]), 4, 1, f);
			fwrite(&results[0][1], 4, results[0][0], f);
		}

		if (pif) {
			printf("writing PIF    results (%d values) ...\n", results[1][0]);
			fwrite(&(results[1][0]), 4, 1, f);
			fwrite(&results[1][1], 4, results[1][0], f);
		}

		if (jb) {
			printf("writing J/B    results (%d values) ...\n", results[2][0]);
			fwrite(&(results[2][0]), 4, 1, f);
			fwrite(&results[2][1], 4, results[2][0], f);
		}

		fclose(f);

	}

	if (results[0]) delete results[0];
	if (results[1]) delete results[1];
	
	printf("\n\n");
	
	return 0;
}




Reply to: