⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rio.cpp

📁 一个简单漂亮的C++编写的mp3播放器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
///////////////////////////////////////////////////////////////////////////////
//
//	rio.cpp
//
//	v1.01 14/01/99	Initial launch.
//
//	v1.02 18/01/99	Additional debug added for ioperm() call.
//
//	v1.03 25/01/99	Added download support.
//					Added delete support.
//					Progress callback for upload/download file.
//					Boland Turbo C++ v1.01 supported.
//
//	v1.04 27/01/99	Win NT v4.0 supported, using RIOIO driver provided.
//
//	v1.05 29/01/99	Added version field in dir header to be compatible
//					with later Rio Manager v1.01 software.
//					Added CheckPresent() member function.
//					Support for Alpha platform.
//
//	v1.06 11/03/99	Added support for external flash ram.
//					Added initialization with bad block check.
//					Added file re-ordering support.
//
//	v1.07 10/06/99	Added support for FreeBSD.
//					Added support for BSDI.
//					Added support for OS/2.
//					Added support for Rio 64M SE (Special Edition).
//					Improved detection of device, using manufacturer ID.
//					Selectable IO delays.
//
///////////////////////////////////////////////////////////////////////////////
#include	<stdio.h>
#include	<string.h>
#include	<stdarg.h>
#include	<time.h>
#include	<errno.h>
#include	<sys/stat.h>

#include	"rio.h"
#include	"binary.h"

// platform dependencies
#if defined(_WINNT)
	// MS VC++ v5.0 for WinNT v4
	#include	<windows.h>
	#include	<winioctl.h>
	#include	"rioioctl.h"
	#define		OUTPORT( p, v )			WinNTOutPort( p, v )
	#define		INPORT( p )				WinNTInPort( p )
	#define		CLOCK_SECOND			CLOCKS_PER_SEC
	#define		DELETEARRAY				delete[]
	#define		ID_DRIVER_VERSION		101

#elif defined(_WIN32)
	// MS VC++ v5.0 for Win9x
	#include	<conio.h>
	#define		OUTPORT( p, v )			_outp( p, v )
	#define		INPORT( p )				_inp( p )
	#define		CLOCK_SECOND			CLOCKS_PER_SEC
	#define		DELETEARRAY				delete[]

#elif defined(__linux__)
	// linux g++
	#include	<unistd.h>
	#include	<sys/io.h>
	#include	<asm/io.h>
	#define		OUTPORT(p,v)			outb( v, p )
	#define		INPORT(p)				inb( p )
	#define		CLOCK_SECOND			CLOCKS_PER_SEC
	#define		DELETEARRAY				delete[]

#elif defined(__FreeBSD__)
	// FreeBSD g++
	#include	<fcntl.h>
	#include	<unistd.h>
	#include	<machine/cpufunc.h>
	#define		OUTPORT(p,v)			outb( p, v )
	#define		INPORT(p)				inb( p )
	#define		CLOCK_SECOND			CLOCKS_PER_SEC
	#define		DELETEARRAY				delete[]

#elif defined(__bsdi__)
	// BSD/OS g++
	#include	<unistd.h>
	#include	<machine/inline.h>
	#define		OUTPORT(p,v)			outb( p, v )
	#define		INPORT(p)				inb( p )
	#define		CLOCK_SECOND			CLOCKS_PER_SEC
	#define		DELETEARRAY				delete[]

#elif defined(__OS2__)
	// OS/2 VisualAge C++ v. 3
	#include	"iopl32.h"
	#define		OUTPORT(p,v)			WPORT( p, v )
	#define		INPORT(p)				((UCHAR)RPORT( p ))
	#define		CLOCK_SECOND			CLOCKS_PER_SEC
	#define		DELETEARRAY				delete[]

#elif defined(__TURBOC__)
	// turboc v1.01
	#include	<dos.h>
	#define		OUTPORT( p, v )			outp( p, v )
	#define		INPORT( p )				inp( p )
	#define		CLOCK_SECOND			((int)CLOCKS_PER_SEC)
	#define		DELETEARRAY				delete

#else
	// not supported
	#error ! ! compiler/platform not supported ! !
#endif

// port offset constants
#define		OFFSET_PORT_DATA		0
#define		OFFSET_PORT_STATUS		1
#define		OFFSET_PORT_CONTROL		2

// max tx/rx block retry
#define		MAX_RETRY				3

// flash ram bank pos
#define		POS_BANK_EXTERNALFLASH	4

// delay's
#define		IODELAY(c)				{ for( long _lA=0; _lA<c; ++_lA ) INPORT(m_iPortStatus); }
#define		DELAY(t)				{ long _lTime=clock()+t; while( _lTime > clock() ) ; }

// new, delete
#define		NEWBLOCK( p )			{ p = new UCHAR[ CRIO_SIZE_32KBLOCK ]; if ( !p ) { LogError( CRIO_ERROR_ALLOC, "new failed" ); return FALSE; } }
#define		ZERONEWBLOCK( p )		{ NEWBLOCK(p); memset(p, 0, CRIO_SIZE_32KBLOCK); }
#define		DELETEBLOCK( p )		{ if ( p ) { DELETEARRAY p; p = NULL; } }

// command out
#define		COMMANDOUT(v1, v2, v3)	{ OUTPORT(m_iPortData, v1); OUTPORT(m_iPortControl, v2); OUTPORT(m_iPortControl, v3); }
// wait for reply
#define		WAITNIBBLE( v1 )		{ if (!WaitInput(v1)) return FALSE; }
#define		WAITACK()				{ if (!WaitAck()) return FALSE; }

///////////////////////////////////////////////////////////////////////////////
// if WinNT
#if defined(_WINNT)

	// handle
	static HANDLE m_hDriver;

	// WinNT out port
	void WinNTOutPort( int iPort, int iValue )
	{
		DWORD dwSizeReturn;
		ULONG ulInput = ((ULONG)iPort-0x378) | ((ULONG)iValue << 16);
		DeviceIoControl( m_hDriver, RIOIO_IOCTL_WRITE, &ulInput,
			sizeof(long), NULL, 0, &dwSizeReturn, NULL );
	}

	// WinNT in port
	int WinNTInPort( int iPort )
	{
		DWORD dwSizeReturn;
		ULONG ulPort = iPort - 0x378;
		ULONG ulData = 0;
		DeviceIoControl( m_hDriver, RIOIO_IOCTL_READ, &ulPort, sizeof(ulPort),
			&ulData, sizeof(char), &dwSizeReturn, NULL );
		return (int)ulData;
	}

#endif

///////////////////////////////////////////////////////////////////////////////
// if DOS
#if defined(__TURBOC__)
	// get clock ticks
	long clock( void )
	{
		return (long) (*(int far*)MK_FP( 0x40, 0x6c ));
	}
#endif

///////////////////////////////////////////////////////////////////////////////
// return file only
static const char* GetFile( const char* pszPathFile )
{
	int iLength = strlen( pszPathFile );
	if ( !iLength )
		return pszPathFile;

	const char* pc = pszPathFile + iLength - 1;
	while( *pc != '\\' && *pc != '/' && *pc != ':' )
	{
		if ( pc == pszPathFile )
			return pc;
		--pc;
	}
	++pc;

	return pc;
}

///////////////////////////////////////////////////////////////////////////////
// set/unset, constructors and destructors
void CRio::Unset( void )
{
	// if WinNT
	#if defined(_WINNT)
		// close device file
		if ( m_hDriver )
		{
			CloseHandle( m_hDriver );
			m_hDriver = NULL;
		}
	#endif
}

BOOL CRio::Set( int iPortBase )
{
	// cleanup any previous Set()
	Unset();

	// determine ports
	m_iPortBase = iPortBase;
	m_iPortData = m_iPortBase + OFFSET_PORT_DATA;
	m_iPortStatus = m_iPortBase + OFFSET_PORT_STATUS;
	m_iPortControl = m_iPortBase + OFFSET_PORT_CONTROL;

	// if linux
	#if defined(__linux__)
		// request access to required ports
		if ( ioperm(m_iPortBase, 3, 1) )
		{
			LogError( CRIO_ERROR_IOPRERM, "ioperm() failed, reason '%s'", SZERROR );
			return FALSE;
		}
	#endif

	// if FreeBSD
	#if defined(__FreeBSD__)
		// request direct access to memory addresses
		if ( open("/dev/io", O_RDONLY) == -1 )
		{
			LogError( CRIO_ERROR_IOPRERM, "open() failed, reason '%s'\n", SZERROR );
			return FALSE;
		}
	#endif

	// if WinNT
	#if defined(_WINNT)
		// open generic IO device
		m_hDriver = CreateFile( "\\\\.\\RioDev", GENERIC_READ | GENERIC_WRITE,
			FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
		if ( m_hDriver == INVALID_HANDLE_VALUE )
		{
			LogError( CRIO_ERROR_CREATEFILE, "CreateFile() failed, reason %ld\n", GetLastError() );
			return FALSE;
		}
		// check version
		DWORD dwSizeReturn;
		ULONG ulVersion;
		DeviceIoControl( m_hDriver, RIOIO_IOCTL_GETVERSION, NULL,
			0, &ulVersion, sizeof(ulVersion), &dwSizeReturn, NULL );
		if ( ulVersion != ID_DRIVER_VERSION )
		{
			LogError( CRIO_ERROR_DRIVERVERSION, "incorrect RioIO driver version, v%d.%d loaded, v%d.%d expected\n",
				 ulVersion/100, ulVersion%100, ID_DRIVER_VERSION/100, ID_DRIVER_VERSION%100 );
			return FALSE;
		}

	#endif

	return TRUE;
}

CRio::CRio()
{
	// if WinNT
	#if defined(_WINNT)
		m_hDriver = NULL;
	#endif

	// default to use internal flash
	m_bUseExternalFlash = FALSE;

	// default to not using special edition
	m_bSpecialEdition = FALSE;

	// default io delay's
	m_lTimeIODelayInit = CRIO_TIME_IODELAY_INIT;
	m_lTimeIODelayTx = CRIO_TIME_IODELAY_TX;
	m_lTimeIODelayRx = CRIO_TIME_IODELAY_RX;
}

CRio::~CRio()
{
	Unset();
}

///////////////////////////////////////////////////////////////////////////////
// log error
void CRio::LogError( int iIDError, const char* pszFormat, ... )
{
	va_list ArgPtr;
	va_start( ArgPtr, pszFormat );
	vsprintf( m_szError, pszFormat, ArgPtr );
	va_end( ArgPtr );

	m_iIDError = iIDError;
}

// find first free 32K block
UINT CRio::FindFirstFree32KBlock( void )
{
	UINT uiA;
	UCHAR* puc = m_cDirBlock.m_auc32KBlockUsed;
	for( uiA=0; uiA<CRIO_MAX_32KBLOCK; ++uiA, ++puc )
	{
		if ( *puc == CRIO_ID_32KBLOCK_FREE )
			return uiA;
	}
	return 0xffff;
}

// calculate checksum1 (checksum of directory header)
UINT CRio::CalculateChecksum1( void )
{
	USHORT usChecksum = m_cDirBlock.m_cDirHeader.m_usChecksum1;
	USHORT* paus = (USHORT*)&m_cDirBlock.m_cDirHeader;
	for( unsigned int iA=0; iA<(sizeof(CDirHeader)/sizeof(short)); ++iA )
		usChecksum -= *paus++;
	return usChecksum;
}

// calculate checksum2 (checksum of directory entries, used flags and FAT)
UINT CRio::CalculateChecksum2( void )
{
	USHORT usChecksum = 0;
	USHORT* paus = (USHORT*)m_cDirBlock.m_acDirEntry;
	int iSize = ( sizeof(CDirBlock) - sizeof(CDirHeader) ) / sizeof(short);
	for( int iA=0; iA<iSize; ++iA )
		usChecksum -= *paus++;
	return usChecksum;
}

// wait for	requested input from status port
BOOL CRio::WaitInput( int iValue )
{
	long lTime = clock() + CLOCK_SECOND;
	UCHAR ucRx;
	while( lTime > clock() )
	{
		ucRx = INPORT( m_iPortStatus ) & 0xf8;

		if ( ucRx == (int)iValue )
			return TRUE;
	}

	return FALSE;
}

// wait for	ack
BOOL CRio::WaitAck( void )
{
	long lTime = clock() + CLOCK_SECOND;
	while( lTime > clock() )
	{
		UCHAR ucRx = INPORT( m_iPortStatus );
		if ( ucRx & 0x08 )
			return TRUE;
	}

	return FALSE;
}

// get byte from status port
UINT CRio::GetDataByte( void )
{
	// get hi nibble
	OUTPORT( m_iPortControl, B_00000000 );
	IODELAY( m_lTimeIODelayRx );
	UCHAR ucRx = INPORT( m_iPortStatus );
	UCHAR ucIn = ((ucRx & 0xf0) ^ 0x80) >> 4;

	// get lo nibble and combine with previous nibble to make byte
	OUTPORT( m_iPortControl, B_00000100 );
	IODELAY( m_lTimeIODelayRx );
	ucRx = INPORT( m_iPortStatus );
	ucIn |= (ucRx & 0xf0) ^ 0x80;

	// reverse bits in byte
	UCHAR ucReversed = 0;
	for( int iC=0; iC<8; ++iC )
	{
		ucReversed <<= 1;
		ucReversed |= (ucIn & 1);
		ucIn >>= 1;
	}

	return ucReversed;
}

// io intro
BOOL CRio::IOIntro( void )
{
	OUTPORT( m_iPortControl, B_00000100 );

	COMMANDOUT( B_10101000, B_00001100, B_00000100 );

	OUTPORT( m_iPortControl, B_00000000 );
	IODELAY( m_lTimeIODelayInit );

	OUTPORT( m_iPortControl, B_00000100 );
	IODELAY( m_lTimeIODelayInit );

	COMMANDOUT( B_10101101, B_00001100, B_00000100 );
	COMMANDOUT( B_01010101, B_00000000, B_00000100 );
	COMMANDOUT( B_10101110, B_00001100, B_00000100 );
	COMMANDOUT( B_10101010, B_00000000, B_00000100 );
	COMMANDOUT( B_10101000, B_00001100, B_00000100 );

	OUTPORT( m_iPortControl, B_00000000 );
	IODELAY( m_lTimeIODelayInit );

	OUTPORT( m_iPortControl, B_00000100 );
	IODELAY( m_lTimeIODelayInit );

	return TRUE;
}

// io outro
BOOL CRio::IOOutro( void )
{
	COMMANDOUT( B_10101101, B_00001100, B_00000100 );
	COMMANDOUT( B_11111111, B_00000000, B_00000100 );
	OUTPORT( m_iPortData, B_00000000 );
	return TRUE;
}

// tx 32K block retry
BOOL CRio::Tx32KBlockRetry( void* pv, UINT uiPos32KBlock, UINT uiPos32KBlockPrev,
	UINT uiPos32KBlockNext )
{
	ULONG ulPos512ByteBlock;
	ULONG ulPosHi;
	ULONG ulPosMid;
	ULONG ulPosLo;
	unsigned int iA, iB;

	// io intro
	if ( !IOIntro() )
		return FALSE;

	// if internal, blocksize = 8K else if external blocksize = 16K
	int iCount8K = m_bUseExternalFlash ? 2 : 1;

	// prepare all pages in block
	for( iA=0; iA<4; iA+=iCount8K )
	{
		ulPos512ByteBlock = ((ULONG)uiPos32KBlock * 32768 + (ULONG)iA * 8192) / 512;
		ulPosLo = ulPos512ByteBlock & 0xff;

		if ( m_bUseExternalFlash )
		{
			ulPosHi = POS_BANK_EXTERNALFLASH;
			ulPosMid = (ulPos512ByteBlock & 0xff00) >> 8;
		}
		else if ( m_bSpecialEdition )
		{
			ulPosHi	 = ulPos512ByteBlock / 32768;
			ulPosMid = (ulPos512ByteBlock & 0x7f00) >> 8;
		}
		else
		{
			ulPosHi = ulPos512ByteBlock / 16384;
			ulPosMid = (ulPos512ByteBlock & 0x3f00) >> 8;
		}

		COMMANDOUT( B_10101011, B_00001100, B_00000100 );
		COMMANDOUT( ulPosHi, B_00000000, B_00000100 );
		COMMANDOUT( B_10100001, B_00001100, B_00000100 );
		COMMANDOUT( B_01100000, B_00000000, B_00000100 );
		COMMANDOUT( B_10100010, B_00001100, B_00000100 );
		COMMANDOUT( ulPosLo, B_00000000, B_00000100 );
		COMMANDOUT( ulPosMid, B_00000000, B_00000100 );
		COMMANDOUT( B_10100001, B_00001100, B_00000100 );
		COMMANDOUT( B_11010000, B_00000000, B_00000100 );

		WAITACK();

		COMMANDOUT( B_10100001, B_00001100, B_00000100 );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -