示例#1
0
// Done
bool WriteCartNorm(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{
	if (!Cart->bHasRam)
	{
		DebugWriteA("RAM write: no RAM\n");
		return true;
	}

	if (Cart->RomData[0x149] == 1) { // Whoops... Only 1/4 of the RAM space is used.
		if ((dwAddress >= 0xA000) && (dwAddress <= 0xA7FF)) { // Write to RAM
			DebugWriteA("RAM write: Unbanked\n");
			CopyMemory(&Cart->RamData[dwAddress - 0xA000], Data, 32);
		}
		else
		{
			DebugWriteA("RAM write: Unbanked (out of range!)\n");
		}
	} else {
		if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) { // Write to RAM
			DebugWriteA("RAM write: Unbanked\n");
			CopyMemory(&Cart->RamData[dwAddress - 0xA000], Data, 32);
		}
	}
	return true;
}
示例#2
0
// Done
bool WriteCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{
	if ((dwAddress >= 0x0000) && (dwAddress <= 0x1FFF)) // RAM enable
	{
		Cart->bRamEnableState = (Data[0] == 0x0A);
		DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState);
	}
	else if ((dwAddress >= 0x2000) && (dwAddress <= 0x3FFF)) // ROM bank select
	{
		Cart->iCurrentRomBankNo &= 0x60;	// keep MSB
		Cart->iCurrentRomBankNo |= Data[0] & 0x1F;

		// emulate quirk: 0x00 -> 0x01, 0x20 -> 0x21, 0x40->0x41, 0x60 -> 0x61
		if ((Cart->iCurrentRomBankNo & 0x1F) == 0) 
		{
			Cart->iCurrentRomBankNo |= 0x01;
		}
		DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo);
	}
	else if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM bank select
	{
		if (Cart->bMBC1RAMbanking)	
		{
			Cart->iCurrentRamBankNo = Data[0] & 0x03;
			DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo);
		}
		else 
		{
			Cart->iCurrentRomBankNo &= 0x1F;
			Cart->iCurrentRomBankNo |= ((Data[0] & 0x03) << 5); // set bits 5 and 6 of ROM bank
			DebugWriteA("Set ROM Bank MSB, ROM bank now: %02X\n", Cart->iCurrentRomBankNo);
		}
	}
	else if ((dwAddress >= 0x6000) && (dwAddress <= 0x7FFF)) // MBC1 mode select
	{
		// this is overly complicated, but it keeps us from having to do bitwise math later
		// Basically we shuffle the 2 "magic bits" between iCurrentRomBankNo and iCurrentRamBankNo as necessary.
		if (Cart->bMBC1RAMbanking != (Data[0] & 0x01))
		{
			// we should only alter the ROM and RAM bank numbers if we have changed modes
			Cart->bMBC1RAMbanking = Data[0] & 0x01;
			if (Cart->bMBC1RAMbanking)
			{
				Cart->iCurrentRamBankNo = Cart->iCurrentRomBankNo >> 5;	// set the ram bank to the "magic bits"
				Cart->iCurrentRomBankNo &= 0x1F; // zero out bits 5 and 6 to keep consistency
			}
			else
			{
示例#3
0
HRESULT WriteAdaptoidPak( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, DWORD addr, LPBYTE data )
{
    DIEFFESCAPE esc;
    struct
    {
        DWORD addr;
        BYTE data[32];
    } buf;

    buf.addr = addr;
    CopyMemory( buf.data, data, 32 );

    esc.dwSize = sizeof(esc);
    esc.dwCommand = ADAPT_WRITEPAK;   // Write 32 bytes to pak
    esc.lpvInBuffer = &buf;
    esc.cbInBuffer = 36;
    esc.lpvOutBuffer = NULL;   
    esc.cbOutBuffer = 0;
	
	HRESULT hr = lpDirectInputDevice->Escape(&esc);

#ifdef _DEBUG
	LPCSTR suc = (SUCCEEDED(hr)) ? "OK" : "FAILED";

	DebugWriteA( "Direct Adaptoid WritePak(Addr:%04X): %s (RC:%08X)\n", addr, suc, hr );
#endif // #ifdef _DEBUG

    return hr;
}
示例#4
0
/******************************************************************
  Function: GetKeys
  Purpose:  To get the current state of the controllers buttons.
  input:    - Controller Number (0 to 3)
            - A pointer to a BUTTONS structure to be filled with 
			the controller state.
  output:   none
*******************************************************************/  	
EXPORT void CALL GetKeys(int Control, BUTTONS * Keys )
{
#ifdef ENABLE_RAWPAK_DEBUG
	DebugWriteA("CALLED: GetKeys\n");
#endif
	if( g_bConfiguring )
		Keys->Value = 0;
	else
	{
		EnterCriticalSection( &g_critical );
		
		if( g_pcControllers[Control].fPlugged ) {
			if (Control == g_iFirstController )
			{
				GetDeviceDatas();
				CheckShortcuts();
			}
			if( g_pcControllers[Control].xiController.bConnected && g_pcControllers[Control].fXInput )	// reads the xinput controller keys, if connected --tecnicors
				GetXInputControllerKeys( &g_pcControllers[Control].xiController, &Keys->Value );
			else
				GetNControllerInput( Control, &Keys->Value );
		}
		LeaveCriticalSection( &g_critical );
	}
	return;
}
示例#5
0
/******************************************************************
  Function: RomClosed
  Purpose:  This function is called when a rom is closed.
  input:    none
  output:   none
*******************************************************************/ 
EXPORT void CALL RomClosed(void)
{
	int i;

	XInputEnable( FALSE );	// disables xinput --tecnicors

	DebugWriteA("CALLED: RomClosed\n");
	EnterCriticalSection( &g_critical );

	if (g_sysMouse.didHandle)
		g_sysMouse.didHandle->SetCooperativeLevel(g_strEmuInfo.hMainWindow, DIB_KEYBOARD); // unlock the mouse, just in case

	for( i = 0; i < ARRAYSIZE(g_pcControllers); ++i )
	{
		if( g_pcControllers[i].pPakData )
		{
			SaveControllerPak( i );
			CloseControllerPak( i );
		}
		// freePakData( &g_pcControllers[i] ); already done by CloseControllerPak --rabid
		// DON'T free the modifiers!
//		ZeroMemory( &g_pcControllers[i], sizeof(CONTROLLER) );
	}

	for( i = 0; i < ARRAYSIZE( g_apdiEffect ); ++i )
		ReleaseEffect( g_apdiEffect[i] );
	ZeroMemory( g_apdiEffect, sizeof(g_apdiEffect) );

	g_bRunning = false;
	LeaveCriticalSection( &g_critical );
	
	return;
}
示例#6
0
// Use string table refs to generate and throw an error message with title IDS_ERR_TITLE (see string table in resources)
// Also if compiled with DEBUG, will log the message with DebugWrite
// uID			the string table ref to display
// dwError		if nonzero, will display a Windows error message using FormatMessage (for use when an API function fails)
// fUserChoose	if true, display buttons Retry and Cancel.  if false, display single button OK.
//		for fUserChoose==true; ErrorMessage returns true if user selects Retry, and false if user selects Cancel.
//		for fUserChoose==false; ErrorMessage always returns false.
bool ErrorMessage( UINT uID, DWORD dwError, bool fUserChoose )
{
	TCHAR pszFirstLine[DEFAULT_BUFFER];

	bool fReturn = false;
	int iBytes;
	TCHAR szError[512];
	TCHAR tszErrorTitle[DEFAULT_BUFFER];

	LoadString( g_hResourceDLL, uID, pszFirstLine, DEFAULT_BUFFER );
	LoadString( g_hResourceDLL, IDS_ERR_TITLE, tszErrorTitle, DEFAULT_BUFFER );

	if( dwError )
	{
		iBytes = wsprintf( szError, _T("%s\n\n Error description: "), pszFirstLine );
		FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError , 0, &szError[iBytes], sizeof(szError) - iBytes, NULL );
	}
	else
		lstrcpyn( szError, pszFirstLine, 512 );
	
	DebugWrite(_T("ErrorMessage! ID:%d "), uID);
	DebugFlush();

	if( fUserChoose )
		fReturn = MessageBox( g_strEmuInfo.hMainWindow, szError, tszErrorTitle, MB_RETRYCANCEL | MB_ICONERROR ) == IDRETRY;
	else
		MessageBox( g_strEmuInfo.hMainWindow, szError, tszErrorTitle, MB_OK | MB_ICONERROR );

	DebugWriteA(fReturn ? "(user: retry)\n" : "(user: acknowledge)\n");
	return fReturn;
}
示例#7
0
// Post a message box, using string resource uTextID and MessageBox style uType
int WarningMessage( UINT uTextID, UINT uType )
{
	DebugWriteA("WarningMessage: ID:%d Type:%d\n", uTextID, uType);
	DebugFlush();

	TCHAR tszTitle[DEFAULT_BUFFER], tszText[DEFAULT_BUFFER];

	LoadString( g_hResourceDLL, uTextID, tszText, DEFAULT_BUFFER );
	LoadString( g_hResourceDLL, IDS_DLG_WARN_TITLE, tszTitle, DEFAULT_BUFFER );

	return MessageBox( g_strEmuInfo.hMainWindow, tszText, tszTitle, uType );
}
示例#8
0
/******************************************************************
  Function: GetDllInfo
  Purpose:  This function allows the emulator to gather information
            about the dll by filling in the PluginInfo structure.
  input:    a pointer to a PLUGIN_INFO stucture that needs to be
            filled by the function. (see def above)
  output:   none
*******************************************************************/ 
EXPORT void CALL GetDllInfo ( PLUGIN_INFO* PluginInfo )
{
	DebugWriteA("CALLED: GetDllInfo\n");
	strncpy(PluginInfo->Name, STRING_PLUGINNAME " " VERSIONNUMBER
#ifndef _UNICODE
		"-ANSI"
#endif
#ifdef _DEBUG
		"-Debugbuild"
#endif
		, sizeof(PluginInfo->Name));
	PluginInfo->Type = PLUGIN_TYPE_CONTROLLER;
	PluginInfo->Version = SPECS_VERSION;
}
示例#9
0
// Done
bool ReadCartNorm(LPGBCART Cart, WORD dwAddress, BYTE *Data) // For all non-MBC carts; fixed 0x8000 ROM; fixed, optional 0x2000 RAM
{
	switch (dwAddress >> 13) // hack: examine highest 3 bits
	{
	case 0:
	case 1:
	case 2:
	case 3:	//	if ((dwAddress >= 0) && (dwAddress <= 0x7FFF))
		CopyMemory(Data, &Cart->RomData[dwAddress], 32);
		DebugWriteA("Nonbanked ROM read - RAW\n");
		break;
	case 5:
		if (Cart->bHasRam)	// no MBC, so no enable state to check
		{
			if (Cart->RomData[0x149] == 1 && (dwAddress - 0xA000) / 0x0800 ) // Only 1/4 of the RAM space is used, and we're out of bounds
			{
				DebugWriteA("Failed RAM read: Unbanked (out of bounds)");
				ZeroMemory(Data, 32);
			}
			else
			{
				CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000], 32);
				DebugWriteA("RAM read: Unbanked\n");
			}
		}
		else
		{
			ZeroMemory(Data, 32);
			DebugWriteA("Failed RAM read: Unbanked (RAM not present)\n");
		}
		break;
	default:
		DebugWriteA("Bad read from RAW cart, address %04X\n", dwAddress);
	}

	return true;
}
示例#10
0
// Done
bool ReadCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data)
{
	if ((dwAddress >= 0) && (dwAddress <= 0x3FFF))
	{
		CopyMemory(Data, &Cart->RomData[dwAddress], 32);
		DebugWriteA("Nonbanked ROM read - MBC1\n");
	}
	else if ((dwAddress >= 0x4000) && (dwAddress <= 0x7FFF))
	{
		if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks)
		{
			ZeroMemory(Data, 32);
			DebugWriteA("Banked ROM read: (Banking Error) Bank %02X\n", Cart->iCurrentRomBankNo);
		}
		else
		{
			// for (i=0; i<32; i++) Data[i] = Cart->RomData[(dwAddress - 0x4000) + i + (Cart->iCurrentRomBankNo * 0x4000)];
			CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo << 14)], 32);
			DebugWriteA("Banked ROM read: Bank %02X\n", Cart->iCurrentRomBankNo);
		}
	}
	else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF))
	{
		if (Cart->bHasRam/* && Cart->bRamEnableState)*/)
		{
			if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks)
			{
				ZeroMemory(Data, 32);
				DebugWriteA("Failed RAM read: (Banking Error) %02X\n", Cart->iCurrentRamBankNo);
			}
			else
			{
				CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], 32);
				DebugWriteA("RAM read: Bank %02X\n", Cart->iCurrentRamBankNo);
			}
		}
		else
		{
			ZeroMemory(Data, 32);
			DebugWriteA("Failed RAM read: (RAM not present)\n");
		}
	}
	else
	{
		DebugWriteA("Bad read from MBC1 cart, address %04X\n", dwAddress);
	}

	return true;
}
示例#11
0
/******************************************************************
  Function: CloseDLL
  Purpose:  This function is called when the emulator is closing
            down allowing the dll to de-initialise.
  input:    none
  output:   none
*******************************************************************/ 
EXPORT void CALL CloseDLL (void)
{										// HACK: THIS IS BROKEN IN PJ64 1.6 (it calls CloseDLL too often)
	DebugWriteA("CALLED: CloseDLL\n");
	if( g_bRunning )
		RomClosed();
	for( int i = 0; i < 4; i++ )
	{
		freePakData( &g_pcControllers[i] );
		freeModifiers( &g_pcControllers[i] );
	}

	// ZeroMemory( g_pcControllers, sizeof(g_pcControllers) ); // why zero the memory if we're just going to close down?
	
	FreeDirectInput();

	return;
}
示例#12
0
/******************************************************************
  Function: RomOpen
  Purpose:  This function is called when a rom is open. (from the 
            emulation thread)
  input:    none
  output:   none
*******************************************************************/ 
EXPORT void CALL RomOpen (void)
{
	DebugWriteA("CALLED: RomOpen\n");

	XInputEnable( TRUE );	// enables xinput --tecnicors

	if( !g_strEmuInfo.fInitialisedPlugin )
	{
		ErrorMessage(IDS_ERR_NOINIT, 0, false);
		return;
	}
	
	EnterCriticalSection( &g_critical );
	// re-init our paks and shortcuts
	InitiatePaks( true );
	// LoadShortcuts( &g_scShortcuts ); WHY are we loading shortcuts again?? Should already be loaded!
	LeaveCriticalSection( &g_critical );
	g_bRunning = true;
	return;
}
示例#13
0
HRESULT ReadAdaptoidPak( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, DWORD addr, LPBYTE data )
{
    DIEFFESCAPE esc;

    esc.dwSize = sizeof(esc);
    esc.dwCommand = ADAPT_READPAK;   // Read 32 bytes from pak
    esc.lpvInBuffer = &addr;
    esc.cbInBuffer = 4;
    esc.lpvOutBuffer = data;   
    esc.cbOutBuffer = 32;

	HRESULT hr = lpDirectInputDevice->Escape(&esc);

#ifdef _DEBUG
	LPCSTR suc = (SUCCEEDED(hr)) ? "OK" : "FAILED";

	DebugWriteA( "Direct Adaptoid ReadPak(Addr:%04X): %s (RC:%08X)\n", addr, suc, hr );
#endif // #ifdef _DEBUG

    return hr;
}
示例#14
0
/******************************************************************
  Function: DllAbout
  Purpose:  This function is optional function that is provided
            to give further information about the DLL.
  input:    a handle to the window that calls this function
  output:   none
*******************************************************************/ 
EXPORT void CALL DllAbout ( HWND hParent )
{
	DebugWriteA("CALLED: DllAbout\n");
	TCHAR tszTitle[DEFAULT_BUFFER], tszTranslator[DEFAULT_BUFFER];

	LoadString( g_hResourceDLL, IDS_DLG_ABOUT_TITLE, tszTitle, DEFAULT_BUFFER );

	TCHAR szText[DEFAULT_BUFFER * 4] = _T(STRING_PLUGINNAME) _T("\n\n") \
		_T("Visit my site for support:  >>http://go.to/nrage<<\n\n") \
		_T("Version ") VERSIONINFO _T(" (") _T(__DATE__) _T(")\n") \
		_T("Done by N-Rage\n") \
		_T("\n") \
		_T(" - - - - -\n") \
		_T("Transferpak emulation done by MadManMarkAu\n") \
		_T("Cleanup, tweaks, and language support by RabidDeity\n");

	LoadString( g_hResourceDLL, IDS_DLG_ABOUT, tszTranslator, DEFAULT_BUFFER );

	_tcscat(szText, tszTranslator);

	MessageBox( hParent, szText, tszTitle, MB_OK | MB_ICONINFORMATION);
	return;
}
示例#15
0
void UpdateRTC(LPGBCART Cart) {
	time_t now, dif;
	int days;

	now = time(NULL);
	dif = now - Cart->timerLastUpdate;

	Cart->TimerData[0] += (BYTE)(dif % 60);
	dif /= 60;
	Cart->TimerData[1] += (BYTE)(dif % 60);
	dif /= 60;
	Cart->TimerData[2] += (BYTE)(dif % 24);
	dif /= 24;

	days = Cart->TimerData[3] + ((Cart->TimerData[4] & 1) << 8) + (int)dif;
	Cart->TimerData[3] = (days & 0xFF);

	if(days > 255) {
		if(days > 511) {
			days &= 511;
			Cart->TimerData[4] |= 0x80;
		}
		if (days > 255)
		Cart->TimerData[4] = (Cart->TimerData[4] & 0xFE) | (days > 255 ? 1 : 0);
	}

	Cart->timerLastUpdate = now;

	DebugWriteA("Update RTC: ");
	DebugWriteByteA(Cart->TimerData[0]);
	DebugWriteA(":");
	DebugWriteByteA(Cart->TimerData[1]);
	DebugWriteA(":");
	DebugWriteByteA(Cart->TimerData[2]);
	DebugWriteA(":");
	DebugWriteByteA(Cart->TimerData[3]);
	DebugWriteA(":");
	DebugWriteByteA(Cart->TimerData[4]);
	DebugWriteA("\n");
}
示例#16
0
/******************************************************************
  Function: InitiateControllers
  Purpose:  This function initialises how each of the controllers 
            should be handled.
  input:    - A controller structure that needs to be filled for 
			  the emulator to know how to handle each controller.
  output:   none
*******************************************************************/  
EXPORT void CALL InitiateControllers (CONTROL_INFO ControlInfo)

#endif // SPECS_VERSION
{
	DebugWriteA("CALLED: InitiateControllers\n");
	if( !prepareHeap())
		return;

#if SPECS_VERSION == 0x0100
	g_strEmuInfo.hMainWindow = hMainWindow;
//	g_strEmuInfo.HEADER = NULL;
#elif SPECS_VERSION >= 0x0101
	g_strEmuInfo.hMainWindow = ControlInfo.hMainWindow;
//	g_strEmuInfo.MemoryBswaped = ControlInfo.MemoryBswaped;
//	g_strEmuInfo.HEADER = ControlInfo.HEADER;
	// UNDONE: Instead of just storing the header, figure out what ROM we're running and save that information somewhere
#endif // SPECS_VERSION

	// The emulator expects us to tell what controllers are plugged in and what their paks are at this point.

	if( !g_pDIHandle ) // if we don't have a directinput handle, we need to make one, attach it to the main window (so it will die if our emulator dies), and enumerate devices
	{
		if( InitDirectInput( g_strEmuInfo.hMainWindow ))
		{
			EnterCriticalSection ( &g_critical );
			InitMouse();
			g_pDIHandle->EnumDevices( DI8DEVCLASS_ALL, EnumMakeDeviceList, NULL, DIEDFL_ATTACHEDONLY );
			LeaveCriticalSection ( &g_critical );
			DebugWriteA("InitDirectInput run in InitiateControllers, g_nDevices=%d\n", g_nDevices);
		}
		else
			return;
	}

	int iDevice;

	EnterCriticalSection( &g_critical );

	// ZeroMemory( g_apFFDevice, sizeof(g_apFFDevice) ); // NO, we'll reinit the existing reference if it's already loaded
	// ZeroMemory( g_apdiEffect, sizeof(g_apdiEffect) ); // NO, we'll release it with CloseControllerPak

	for( int i = 3; i >= 0; i-- )
	{
		SaveControllerPak( i );
		CloseControllerPak( i );
		// freePakData( &g_pcControllers[i] ); // already called by CloseControllerPak
		freeModifiers( &g_pcControllers[i] );
		SetControllerDefaults( &g_pcControllers[i] );
	}

	g_pcControllers[0].fPlugged = true;

	if (! LoadConfigFromINI() )
	{
		DebugWriteA("\tINI load failed, loading defaults from resource\n");
		for ( int i = 0; i < 4; i++ )
			LoadProfileFromResource( i, false );
		LoadShortcutsFromResource(false);
	}

	for( int i = 0; i < 4; i++)	// initiate xinput controller and plug then if connected --tecnicors
	{
		InitiateXInputController( &g_pcControllers[i].xiController, i );
		if( g_pcControllers[i].xiController.bConnected )
		{
			g_pcControllers[i].fPlugged = true;
			g_pcControllers[i].fGamePad = true;
		}
	}	// END

	// Init: Find force-feedback devices and init 
	for( int i = 3; i >= 0; i-- )
	{
		DebugWriteA("Controller %d: ", i+1);
		if( g_pcControllers[i].xiController.bConnected && g_pcControllers[i].fXInput)	// if xinput connected, we don't need other config --tecnicors
			continue;

		if( g_pcControllers[i].fPlugged )
		{
			// Search for right Controller
			iDevice = FindDeviceinList( g_pcControllers[i].guidFFDevice );
			if( iDevice != -1 && g_devList[iDevice].bEffType )
			{
				DebugWriteA("rumble device set, ");
			}
			else // we couldn't find the device specified in the INI file, or it was already null
			{
				g_pcControllers[i].guidFFDevice = GUID_NULL;
				DebugWriteA("no rumble device/effect type set, ");
			}

			if( g_pcControllers[i].nModifiers > 0)
				SetModifier( &g_pcControllers[i] );
			g_iFirstController = i;
			DebugWriteA("plugged in, with paktype %d, ", g_pcControllers[i].PakType);
			DebugWriteA("RawMode is %d\n", g_pcControllers[i].fRawData);
		}
		else
		{
			DebugWriteA("unplugged\n");
			freePakData( &g_pcControllers[i] );	// we don't need to do this again, but there's not much overhead so I'll leave it --rabid
			freeModifiers( &g_pcControllers[i] );
		}
	}

	PrepareInputDevices();

	if( g_bExclusiveMouse ) {
		// g_sysMouse.didHandle->Unacquire();
		// g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_MOUSE ); // PrepareInputDevices does this.
		g_sysMouse.didHandle->Acquire();
	}

	InitiatePaks( true );

	g_strEmuInfo.fInitialisedPlugin = true;

	LeaveCriticalSection( &g_critical );

#if SPECS_VERSION == 0x0100
	FillControls(Controls);
#elif SPECS_VERSION >= 0x0101
	FillControls(ControlInfo.Controls);
#endif // SPECS_VERSION

	return;
} // end InitiateControllers
示例#17
0
/******************************************************************
  Function: DllTest
  Purpose:  This function is optional function that is provided
            to allow the user to test the dll
  input:    a handle to the window that calls this function
  output:   none
*******************************************************************/ 
EXPORT void CALL DllTest ( HWND hParent )
{
	DebugWriteA("CALLED: DllTest\n");
	return;
}
示例#18
0
/******************************************************************
  Function: DllConfig
  Purpose:  This function is optional function that is provided
            to allow the user to configure the dll
  input:    a handle to the window that calls this function
  output:   none
*******************************************************************/ 
EXPORT void CALL DllConfig ( HWND hParent )
{
	DebugWriteA("CALLED: DllConfig\n");
	static bool bInitCC = false;
	if( !prepareHeap())
		return;

	if( !g_pDIHandle )
	{
		if( InitDirectInput( hParent ))
		{
			EnterCriticalSection ( &g_critical );
			InitMouse();
			g_pDIHandle->EnumDevices( DI8DEVCLASS_ALL, EnumMakeDeviceList, NULL, DIEDFL_ATTACHEDONLY );
			LeaveCriticalSection ( &g_critical );
			DebugWriteA("InitDirectInput run in DllConfig, g_nDevices=%d\n", g_nDevices);
		}
	}

	if( g_pDIHandle && !g_bConfiguring )
	{	
		g_bConfiguring = true;
		if( !bInitCC )
		{
			INITCOMMONCONTROLSEX ccCtrls =	{	sizeof(INITCOMMONCONTROLSEX), 
											ICC_BAR_CLASSES | ICC_TAB_CLASSES | ICC_LISTVIEW_CLASSES };
			InitCommonControlsEx( &ccCtrls ); // needed for TrackBars & Tabs
		}
		
		EnterCriticalSection( &g_critical );
		if( g_sysMouse.didHandle ) { // unlock mouse while configuring
			g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_DEVICE );
			g_sysMouse.didHandle->Acquire();
		}
		LeaveCriticalSection( &g_critical );

		int iOK = DialogBox( g_hResourceDLL, MAKEINTRESOURCE( IDD_MAINCFGDIALOG ), hParent, MainDlgProc );

		// If we go into the dialog box, and the user navigates to the Rumble window, our FF device can get unacquired.
		// So let's reinit them now if we're running, just to be safe --rabid
		if( g_bRunning )
		{
			EnterCriticalSection( &g_critical );
			// PrepareInputDevices resets g_bExclusiveMouse to false if no mouse keys are bound, and the only way to
			// re-enable exclusive mouse is with a shortcut.
			// This is undesirable behavior, but it beats the alternative (and we REALLY need to re-init FF devices here)
			PrepareInputDevices();
			if (iOK)
			{
				InitiatePaks( false );	// only re-init the mempaks and such if the user clicked Save or Use
			}
			
			if( g_sysMouse.didHandle ) {
				if ( g_bExclusiveMouse ) { // if we have exclusive mouse, we need to relock mouse after closing the config
					g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_MOUSE );
					g_sysMouse.didHandle->Acquire();
					if (g_strEmuInfo.fDisplayShortPop)
					{
						LoadString( g_hResourceDLL, IDS_POP_MOUSELOCKED, g_pszThreadMessage, ARRAYSIZE(g_pszThreadMessage) );
						// HWND hMessage = CreateWindowEx( WS_EX_NOPARENTNOTIFY | WS_EX_STATICEDGE | WS_EX_TOPMOST, _T("STATIC"), pszMessage, WS_CHILD | WS_VISIBLE, 10, 10, 200, 30, g_strEmuInfo.hMainWindow, NULL, g_strEmuInfo.hinst, NULL );
						// SetTimer( hMessage, TIMER_MESSAGEWINDOW, 2000, MessageTimer );
						CreateThread(NULL, 0, MsgThreadFunction, g_pszThreadMessage, 0, NULL);
					}
				}
				else {
					g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_KEYBOARD );
					g_sysMouse.didHandle->Acquire();
				}
			}
			LeaveCriticalSection( &g_critical );
		}

		g_bConfiguring = false;
	}
	return;
}
示例#19
0
// Create a force feedback effect handle and downloads the effect.  Parameters are self-explanatory.
bool CreateEffectHandle( HWND hWnd, LPDIRECTINPUTDEVICE8 lpDirectInputDevice, LPDIRECTINPUTEFFECT &pDIEffect, BYTE bRumbleTyp, long lStrength )
{
	if( pDIEffect )
		ReleaseEffect( pDIEffect );

	if( !lpDirectInputDevice || bRumbleTyp == RUMBLE_DIRECT )
		return false;	

	DWORD nAxes = 0;
	DWORD rgdwAxes[] = { DIJOFS_X, DIJOFS_Y };

	HRESULT hResult;

	// count the FF - axes of the joystick
	lpDirectInputDevice->EnumObjects( EnumCountFFAxes, &nAxes, DIDFT_FFACTUATOR | DIDFT_AXIS );

	if( nAxes == 0 )
		return false;
	nAxes = min( nAxes, 2 );


	// Must be unaquired for setting stuff like Co-op Level
	hResult = lpDirectInputDevice->Unacquire();
	//FF Requires EXCLUSIVE LEVEL, took me hours to find the reason why it wasnt working
	hResult = lpDirectInputDevice->SetCooperativeLevel( hWnd, DIB_FF );

	// fail if we can't set coop level --rabid
	if (hResult != DI_OK)
	{
		DebugWriteA("CreateEffectHandle: couldn't set coop level: %08X\n", hResult);
		return false;
	}

    // Since we will be playing force feedback effects, we should disable the
    // auto-centering spring.
	DIPROPDWORD dipdw;
    dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    dipdw.diph.dwObj        = 0;
    dipdw.diph.dwHow        = DIPH_DEVICE;
    dipdw.dwData            = FALSE;
	
	hResult = lpDirectInputDevice->SetProperty( DIPROP_AUTOCENTER, &dipdw.diph );

	long rglDirection[] = { 1, 1 };
	LPGUID EffectGuid;
    DIEFFECT eff;
    ZeroMemory( &eff, sizeof(eff) );

	eff.dwSize                  = sizeof(DIEFFECT);
	eff.dwFlags                 = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
	eff.dwGain                  = lStrength * 100;
    eff.dwTriggerButton         = DIEB_NOTRIGGER;
    eff.dwTriggerRepeatInterval = 0;
    eff.cAxes                   = nAxes; //Number of Axes
    eff.rgdwAxes                = rgdwAxes;
    eff.rglDirection            = rglDirection;
    eff.lpEnvelope              = NULL;
	eff.dwStartDelay            = 0;

	DICONSTANTFORCE cf;
	DIRAMPFORCE rf;
	DIPERIODIC pf;

	switch( bRumbleTyp )
	{
	case RUMBLE_CONSTANT:
		EffectGuid = (GUID*)&GUID_ConstantForce;

		eff.dwDuration              = 150000; // microseconds
		eff.dwSamplePeriod          = 0;
		eff.cbTypeSpecificParams    = sizeof(DICONSTANTFORCE);
		eff.lpvTypeSpecificParams   = &cf;

		cf.lMagnitude = 10000;
		break;
	case RUMBLE_RAMP:
		EffectGuid = (GUID*)&GUID_RampForce;
		
		eff.dwDuration              = 300000; // microseconds
		eff.dwSamplePeriod          = 0;
		eff.cbTypeSpecificParams    = sizeof(DIRAMPFORCE);
		eff.lpvTypeSpecificParams   = &rf;

		rf.lStart = 10000;
		rf.lEnd = 2000;
		break;
	
	case RUMBLE_CONDITION:
	case RUMBLE_PERIODIC:
		EffectGuid = (GUID*)&GUID_Sine;

		eff.dwDuration              = 150000; // microseconds
		eff.dwSamplePeriod          = 0;
		eff.cbTypeSpecificParams    = sizeof(DIPERIODIC);
		eff.lpvTypeSpecificParams   = &pf;

		pf.dwMagnitude = 10000;
		pf.lOffset = 0;
		pf.dwPhase = 0;
		pf.dwPeriod = 2000;
		break;

	case RUMBLE_NONE:
	case RUMBLE_CUSTOM:
	default:
		return false;
	}

	hResult = lpDirectInputDevice->CreateEffect( *EffectGuid, &eff, &pDIEffect, NULL );

	if (hResult == DI_OK)
	{
		hResult = lpDirectInputDevice->Acquire();
		hResult = pDIEffect->Download();
	}
	else
	{
		DebugWriteA("CreateEffectHandle: didn't CreateEffect: %08X\n", hResult);
	}
	return SUCCEEDED( hResult );
}
示例#20
0
// **if passed an existing DirectInputDevice which matches gGuid
//		unacquires it, and sets its cooperative level (reinitialize)
// **if the existing device does not match the passed gGuid, the existing device is released
// **if no device was passed or gGuid did not match
//		searches for the controller matching gGuid in connected and available devices
//		creates a DirectInputDevice
//		sets its data format
//		sets its cooperative level
//		for joysticks, calls EnumSetObjectsAxis for each axis
// GetInputDevice always leaves the returned device in an UNACQUIRED state.
bool GetInputDevice( HWND hWnd, LPDIRECTINPUTDEVICE8 &lpDirectInputDevice, GUID gGuid, DWORD dwDevType, DWORD dwCooperativeLevel )
{
	DebugWriteA("GetInputDevice: gGuid is {%08.8lX-%04.4hX-%04.4hX-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}\n", gGuid.Data1, gGuid.Data2, gGuid.Data3, gGuid.Data4[0], gGuid.Data4[1], gGuid.Data4[2], gGuid.Data4[3], gGuid.Data4[4], gGuid.Data4[5], gGuid.Data4[6], gGuid.Data4[7]);
	if( lpDirectInputDevice != NULL)
	{
		DIDEVICEINSTANCE didDev;
		didDev.dwSize = sizeof(DIDEVICEINSTANCE);
		lpDirectInputDevice->GetDeviceInfo( &didDev );

		if( didDev.guidInstance == gGuid )
		{	// we've already gotten this device; unacquire it and initialize
			DebugWriteA("GetInputDevice: already created, attempting to reinit\n");
			lpDirectInputDevice->Unacquire();
			lpDirectInputDevice->SetCooperativeLevel( hWnd, dwCooperativeLevel );
			return true;
		}
		else
			ReleaseDevice( lpDirectInputDevice );
	}

	HRESULT hResult;
	
	LPCDIDATAFORMAT ppDiDataFormat = NULL;
	bool Success = false;

	switch( LOBYTE(dwDevType) )
	{
	case DI8DEVTYPE_KEYBOARD:
		ppDiDataFormat = &c_dfDIKeyboard;
		break;

	case DI8DEVTYPE_MOUSE:
		ppDiDataFormat = &c_dfDIMouse2;
		break;

	//case DI8DEVTYPE_GAMEPAD:
	//case DI8DEVTYPE_JOYSTICK:
	//case DI8DEVTYPE_DRIVING:
	//case DI8DEVTYPE_1STPERSON:
	//case DI8DEVTYPE_FLIGHT:
	default: // assume everything else is a gamepad; probably not the best idea but it works
		ppDiDataFormat = &c_dfDIJoystick;
		break;
	}

	bool bDeviceAvailable = false;
		
	VOID* aRef[2] = { &gGuid, &bDeviceAvailable };
		
	// for each available device in our dwDevType category, run EnumIsDeviceAvailable with params "aRef"
	g_pDIHandle->EnumDevices( DI8DEVCLASS_ALL, EnumIsDeviceAvailable, (LPVOID)aRef, DIEDFL_ATTACHEDONLY );
		
	if( !bDeviceAvailable )
	{
		DebugWriteA("GetInputDevice: Device does not appear available\n");
		return false;
	}
		
	hResult = g_pDIHandle->CreateDevice( gGuid, &lpDirectInputDevice, NULL );
	
	if( SUCCEEDED( hResult ))
	{
		hResult = lpDirectInputDevice->SetDataFormat( ppDiDataFormat );
		hResult = lpDirectInputDevice->SetCooperativeLevel( hWnd, dwCooperativeLevel );
		
		Success = SUCCEEDED( hResult );
		if (!Success)
		{
			DebugWriteA("GetInputDevice: SetCooperativeLevel failed\n");
		}
	}
	else
		DebugWriteA("GetInputDevice: CreateDevice failed\n");

	if( Success && ( ppDiDataFormat == &c_dfDIJoystick ))
		lpDirectInputDevice->EnumObjects( EnumSetObjectsAxis, lpDirectInputDevice, DIDFT_AXIS );

	return Success;
}
示例#21
0
/******************************************************************
  Function: ReadController
  Purpose:  To process the raw data in the pif ram that is about to
            be read.
  input:    - Controller Number (0 to 3) and -1 signalling end of 
              processing the pif ram.
			- Pointer of data to be processed.
  output:   none  
  note:     This function is only needed if the DLL is allowing raw
            data.
*******************************************************************/
EXPORT void CALL ReadController( int Control, BYTE * Command )
{
#ifdef ENABLE_RAWPAK_DEBUG
	DebugWriteA("CALLED: ReadController\n");
#endif
	if( Control == -1 )
		return;

	EnterCriticalSection( &g_critical );

	if( !g_pcControllers[Control].fPlugged )
	{
		Command[1] |= RD_ERROR;
		LeaveCriticalSection( &g_critical );
		return;
	}

	
	switch( Command[2] )
	{
	case RD_RESETCONTROLLER:
		WriteDatasA( "ResetController-PreProcessing", Control, Command, 0);
	case RD_GETSTATUS:
		// expected: controller gets 1 byte (command), controller sends back 3 bytes
		// should be:	Command[0] == 0x01
		//				Command[1] == 0x03
#ifdef ENABLE_RAWPAK_DEBUG
		WriteDatasA( "GetStatus-PreProcessing", Control, Command, 0);
#endif
		Command[3] = RD_GAMEPAD | RD_ABSOLUTE;
		Command[4] = RD_NOEEPROM;

		if( g_pcControllers[Control].fPakInitialized && g_pcControllers[Control].pPakData )
		{
			if( *(BYTE*)g_pcControllers[Control].pPakData == PAK_ADAPTOID )
			{
				Command[5] = GetAdaptoidStatus( Control );

				if( Command[5] & RD_NOTINITIALIZED )
					((ADAPTOIDPAK*)g_pcControllers[Control].pPakData)->fRumblePak = true;
			}
			else
			{
				Command[5] = ( *(BYTE*)g_pcControllers[Control].pPakData != PAK_NONE ) ? RD_PLUGIN : RD_NOPLUGIN;
				if( g_pcControllers[Control].fPakCRCError )
				{
					Command[5] = Command[5] | RD_ADDRCRCERR;
					g_pcControllers[Control].fPakCRCError = false;
				}
			}
		}
		else
		{
			if( !g_bConfiguring && InitControllerPak( Control ) && g_pcControllers[Control].pPakData )
			{
				g_pcControllers[Control].fPakInitialized = true;

				if( *(BYTE*)g_pcControllers[Control].pPakData == PAK_ADAPTOID )
					Command[5] = GetAdaptoidStatus( Control );
				else
				{
					Command[5] = ( *(BYTE*)g_pcControllers[Control].pPakData ) ? RD_PLUGIN : RD_NOPLUGIN;
					Command[5] = Command[5] | ( g_pcControllers[Control].fPakCRCError ? RD_ADDRCRCERR : 0 );
				}
			}
			else
				Command[5] = RD_NOPLUGIN | RD_NOTINITIALIZED;
		}

		if( g_pcControllers[Control].fPakCRCError )
		{
			Command[5] = Command[5] | RD_ADDRCRCERR;
			g_pcControllers[Control].fPakCRCError = false;
		}

#ifdef ENABLE_RAWPAK_DEBUG
		WriteDatasA( "GetStatus-PostProcessing", Control, Command, 0);
		DebugWriteA( NULL );
#endif
		break;

	case RD_READKEYS:
		// expected: controller gets 1 byte (command), controller sends back 4 bytes
		// should be:	Command[0] == 0x01
		//				Command[1] == 0x04
		if( g_bConfiguring )
			Command[3] = Command[4] = Command[5] = Command[6] = 0;
		else
		{
			if (Control == g_iFirstController )
			{
				GetDeviceDatas();
				CheckShortcuts();
			}
			if( g_pcControllers[Control].xiController.bConnected && g_pcControllers[Control].fXInput )	// reads xinput controller kesy, if connected --tecnicors
				GetXInputControllerKeys( &g_pcControllers[Control].xiController, (LPDWORD)&Command[3] );
			else
				GetNControllerInput( Control, (DWORD*)&Command[3] );
		}
		break;
		

	case RD_READPAK:
#ifdef ENABLE_RAWPAK_DEBUG
		WriteDatasA( "ReadPak-PreProcessing", Control, Command, 0);
#endif
		if( g_pcControllers[Control].fPakInitialized )
			//Command[1] = Command[1] | ReadControllerPak( Control, &Command[3] );
			ReadControllerPak( Control, &Command[3] );
		else
		{
			DebugWriteA("Tried to read, but pak wasn't initialized!!\n");
			// InitControllerPak( Control );
			Command[1] |= RD_ERROR;
			//ZeroMemory( &Command[5], 32 );
		}
#ifdef ENABLE_RAWPAK_DEBUG
		WriteDatasA( "ReadPak-PostProcessing", Control, Command, 0);
		DebugWriteA( NULL );
#endif
		break;

	case RD_WRITEPAK:
#ifdef ENABLE_RAWPAK_DEBUG
		WriteDatasA( "WritePak-PreProcessing", Control, Command, 0);
#endif
		if( g_pcControllers[Control].fPakInitialized )
			//Command[1] = Command[1] | WriteControllerPak( Control, &Command[3] );
			WriteControllerPak( Control, &Command[3] );
		else
		{
			DebugWriteA("Tried to write, but pak wasn't initialized! (paktype was %u)\n", g_pcControllers[Control].PakType);
			// InitControllerPak( Control );
			Command[1] |= RD_ERROR;
		}
#ifdef ENABLE_PAK_WRITES_DEBUG
		WriteDatasA( "WritePak-PostProcessing", Control, Command, 0);
		DebugWriteA( NULL );
#endif
		break;

	case RD_READEEPROM:
		// Should be handled by the Emulator
		WriteDatasA( "ReadEeprom-PreProcessing", Control, Command, 0);
		WriteDatasA( "ReadEeprom-PostProcessing", Control, Command, 0);
		DebugWriteA( NULL );
		break;
	case RD_WRITEEPROM:
		// Should be handled by the Emulator
		WriteDatasA( "WriteEeprom-PreProcessing", Control, Command, 0);
		WriteDatasA( "WriteEeprom-PostProcessing", Control, Command, 0);
		DebugWriteA( NULL );
		break;

	default:
		// only accessible if the Emulator has bugs.. or maybe the Rom is flawed
		WriteDatasA( "ReadController: Bad read", Control, Command, 0);
		DebugWriteA( NULL );
		Command[1] = Command[1] | RD_ERROR;
	}

	LeaveCriticalSection( &g_critical );
	return;
}
示例#22
0
// Direct Adaptoid debugging stuff.
void _debugAd( LPCSTR szMessage, HRESULT res )
{
	LPCSTR suc = (SUCCEEDED(res)) ? "OK" : "FAILED";

	DebugWriteA( "%s: %s (RC:%08X)\n", szMessage, suc, res );
}
示例#23
0
// Fill in button states and axis states for controller indexController, into the struct pdwData.
// pdwData is a pointer to a 4 byte BUTTONS union, if anyone cares
bool GetNControllerInput ( const int indexController, LPDWORD pdwData )
{
	*pdwData = 0;
	WORD w_Buttons = 0;
	// WORD w_Axes = 0;

	LPCONTROLLER pcController = &g_pcControllers[indexController]; // still needs to be here, but not as important --rabid

	bool b_Value;
	long l_Value = 0;

	long lAxisValueX = ZEROVALUE;
	long lAxisValueY = ZEROVALUE;

	// take this info from the N64 controller struct, regardless of input devices
	float d_ModifierX = (float)pcController->bStickRange / 100.0f;
	float d_ModifierY = (float)pcController->bStickRange / 100.0f;

	int i;

	// do N64-Buttons / modifiers
	for (i = 0; i < pcController->nModifiers; i++ )
	{
		BUTTON btnButton = pcController->pModifiers[i].btnButton;

		b_Value = IsBtnPressed( btnButton );

		bool fChangeMod = false;

		if( pcController->pModifiers[i].bModType == MDT_CONFIG )
		{ // Config-Type
			if( pcController->pModifiers[i].fToggle )
			{
				if( b_Value && !btnButton.fPrevPressed)
				{
					pcController->pModifiers[i].fStatus = !pcController->pModifiers[i].fStatus;
					fChangeMod = true;
				}
			}
			else
			{
				if(	b_Value != (bool)(btnButton.fPrevPressed))
					fChangeMod = true;
			}
		}
		else
		{ // Move / Macro Type
			if( pcController->pModifiers[i].fToggle )
			{
				if( b_Value && !btnButton.fPrevPressed )
					pcController->pModifiers[i].fStatus = !pcController->pModifiers[i].fStatus;
				fChangeMod = ( pcController->pModifiers[i].fStatus != 0 );
			}
			else
			{
				fChangeMod = b_Value;
			}
		}

		if( fChangeMod )
		{
			switch( pcController->pModifiers[i].bModType )
			{
			case MDT_MOVE:
			{
				LPMODSPEC_MOVE args = (LPMODSPEC_MOVE)&pcController->pModifiers[i].dwSpecific;
				d_ModifierX *= args->XModification / 100.0f;
				d_ModifierY *= args->YModification / 100.0f;	
			}
				break;
			case MDT_MACRO:
			{
				LPMODSPEC_MACRO args = (LPMODSPEC_MACRO)&pcController->pModifiers[i].dwSpecific;

				if (args->fRapidFire) // w00t! Rapid Fire here
				{
					if ((unsigned) b_Value != btnButton.fPrevPressed) // New macro pressed
					{
						args->fPrevFireState = 0;
						args->fPrevFireState2 = 0;
					}
					if(!args->fPrevFireState) // This round, a firing is needed
					{
						w_Buttons |= args->aButtons;
						if( args->fAnalogRight )
							lAxisValueX += MAXAXISVALUE;
						else if( args->fAnalogLeft )
							lAxisValueX -= MAXAXISVALUE;

						if( args->fAnalogDown )
							lAxisValueY -= MAXAXISVALUE;
						else if( args->fAnalogUp ) // up
								lAxisValueY += MAXAXISVALUE;
					}

					// Ok, update the firing counters here
					if (args->fRapidFireRate) // Do the rapid fire slowly
					{ // Note that this updates State2 before State... Makes a nice slower square-wave type pulse for the update
						args->fPrevFireState2 = (args->fPrevFireState2 + 1) & 1;
						if (!args->fPrevFireState2)
						{
							args->fPrevFireState = (args->fPrevFireState + 1) & 1;
							DebugWriteA("Slow Rapid Fire - Mark 2\n");
						}
					}
					else // Do a fast rapid fire
					{
						args->fPrevFireState = (args->fPrevFireState + 1) & 1;
						DebugWriteA("Fast Rapid Fire\n");
					}
				}
				else
				{
					w_Buttons |= args->aButtons; // Note this: It lets you push buttons as well as the macro buttons
					if( args->fAnalogRight )
						lAxisValueX += MAXAXISVALUE;
					else if( args->fAnalogLeft )
						lAxisValueX -= MAXAXISVALUE;

					if( args->fAnalogDown )
						lAxisValueY -= MAXAXISVALUE;
					else if( args->fAnalogUp ) // up
						lAxisValueY += MAXAXISVALUE;

					args->fPrevFireState = 0;
				}
			}
				break;
			case MDT_CONFIG:
			{
				LPMODSPEC_CONFIG args = (LPMODSPEC_CONFIG)&pcController->pModifiers[i].dwSpecific;

				if( args->fChangeAnalogConfig )
				{
					BYTE bConfig = (BYTE)args->fAnalogStickMode;
					if( bConfig < PF_AXESETS )
						pcController->bAxisSet = bConfig;
					else
					{
						if( pcController->bAxisSet == PF_AXESETS-1 )
							pcController->bAxisSet = 0;
						else
							++pcController->bAxisSet;
					}

				}
				if( args->fChangeMouseXAxis )
					if (pcController->bMouseMoveX == MM_BUFF)
						pcController->bMouseMoveX = MM_ABS;
					else if (pcController->bMouseMoveX == MM_ABS)
						pcController->bMouseMoveX = MM_BUFF;
				if( args->fChangeMouseYAxis )
					if (pcController->bMouseMoveY == MM_BUFF)
						pcController->bMouseMoveY = MM_ABS;
					else if (pcController->bMouseMoveY == MM_ABS)
						pcController->bMouseMoveY = MM_BUFF;

				if( args->fChangeKeyboardXAxis )
					pcController->fKeyAbsoluteX = !pcController->fKeyAbsoluteX;
				if( args->fChangeKeyboardYAxis )
					pcController->fKeyAbsoluteY = !pcController->fKeyAbsoluteY;
			}
				break;
			}
		}

		btnButton.fPrevPressed = b_Value;
		pcController->pModifiers[i].btnButton = btnButton;
	} // END N64 MODIFIERS for

	// do N64-Buttons / modifiers
	for( i = 0; i < PF_APADR; i++ )
	{
		BUTTON btnButton = pcController->aButton[i];

		b_Value = IsBtnPressed( btnButton );

		w_Buttons |= (((WORD)b_Value) << i);
	} // END N64 BUTTONS for

	long lDeadZoneValue = pcController->bPadDeadZone * RANGERELATIVE / 100;
	float fDeadZoneRelation	= (float)RANGERELATIVE  / (float)( RANGERELATIVE - lDeadZoneValue );

	// do N64 joystick axes
	for ( i = 0; i < 4; i++ )
	{
		//	0 : right
		//	1 : left
		//	2 : down
		//	3 : up

		bool fNegInput = (( i == 1 ) || ( i == 2 )); // Input has to be negated

		BUTTON btnButton = pcController->aButton[PF_APADR + pcController->bAxisSet * 4 + i];
		LPLONG plRawState = (LPLONG)&btnButton.parentDevice->stateAs.joyState;
		
		switch( btnButton.bBtnType )
		{
		case DT_JOYBUTTON:
			l_Value = MAXAXISVALUE;
			b_Value = ( btnButton.parentDevice->stateAs.joyState.rgbButtons[btnButton.bOffset] & 0x80 ) != 0;
			break;

		case DT_JOYSLIDER:
		case DT_JOYAXE:
			l_Value = plRawState[btnButton.bOffset] - ZEROVALUE;

			if( btnButton.bAxisID ) // negative Range
			{
				fNegInput = !fNegInput;

				b_Value = ( l_Value <= -lDeadZoneValue );
				if( b_Value )
					l_Value = (long) ((float)(l_Value + lDeadZoneValue ) * fDeadZoneRelation );
			}
			else
			{
				b_Value = ( l_Value >= lDeadZoneValue );
				if( b_Value )
					l_Value = (long) ((float)(l_Value - lDeadZoneValue ) * fDeadZoneRelation );
			}	
			break;

		case DT_JOYPOV:
			l_Value = MAXAXISVALUE;
			b_Value = GetJoyPadPOV( (PDWORD)&plRawState[btnButton.bOffset] , btnButton.bAxisID );
			break;

		case DT_KEYBUTTON:
			if( btnButton.parentDevice->stateAs.rgbButtons[btnButton.bOffset] & 0x80 )
			{
				b_Value = true;

				if(( pcController->fKeyAbsoluteX && i < 2 )
					|| ( pcController->fKeyAbsoluteY &&  i > 1 ))
				{
					if( pcController->wAxeBuffer[i] < MAXAXISVALUE )
					{
						l_Value = pcController->wAxeBuffer[i] = min(( pcController->wAxeBuffer[i] + N64DIVIDER*3), MAXAXISVALUE );
					}
					else
						l_Value = MAXAXISVALUE;
				}
				else
				{
					if( pcController->wAxeBuffer[i] < MAXAXISVALUE )
					{
						l_Value = pcController->wAxeBuffer[i] = min(( pcController->wAxeBuffer[i] * 2 + N64DIVIDER*5 ), MAXAXISVALUE );
					}
					else
						l_Value = MAXAXISVALUE;
				}
			}
			else
			{
				if(( pcController->fKeyAbsoluteX && i < 2 )
					|| ( pcController->fKeyAbsoluteY && i > 1 ))
				{
					l_Value = pcController->wAxeBuffer[i];
					b_Value = true;
				}
				else
				{
					if( pcController->wAxeBuffer[i] > N64DIVIDER )
					{
						b_Value = true;
						l_Value = pcController->wAxeBuffer[i] = pcController->wAxeBuffer[i] / 2 ;
					}
					else
						b_Value = false;
				}
			}
			break;

		case DT_MOUSEBUTTON:
			l_Value = MAXAXISVALUE;
			b_Value = ( btnButton.parentDevice->stateAs.mouseState.rgbButtons[btnButton.bOffset] & 0x80 ) != 0;
			break;

		case DT_MOUSEAXE:
			if( i < 2 )
				pcController->wAxeBuffer[i] += plRawState[btnButton.bOffset] * pcController->wMouseSensitivityX * MOUSESCALEVALUE;	// l_Value = btnButton.parentDevice->stateAs.mouseState[btnButton.bOffset];
			else
				pcController->wAxeBuffer[i] += plRawState[btnButton.bOffset] * pcController->wMouseSensitivityY * MOUSESCALEVALUE;	// l_Value = btnButton.parentDevice->stateAs.mouseState[btnButton.bOffset];

			l_Value = pcController->wAxeBuffer[i];

			// wAxeBuffer is positive for axes 0 and 3 if buffer remains, else zero
			// wAxeBuffer is negative for axes 1 and 2 if buffer remains, else zero

			if(( pcController->bMouseMoveX == MM_ABS && i < 2 ) || ( pcController->bMouseMoveY == MM_ABS &&  i > 1 ))
				pcController->wAxeBuffer[i] = min( max( MINAXISVALUE, pcController->wAxeBuffer[i]) , MAXAXISVALUE);
			else if (( pcController->bMouseMoveX == MM_BUFF && i < 2 ) || ( pcController->bMouseMoveY == MM_BUFF &&  i > 1 ))
				pcController->wAxeBuffer[i] = pcController->wAxeBuffer[i] * MOUSEBUFFERDECAY / 100;
			else // "deadpan" mouse
			{
				pcController->wAxeBuffer[i] = 0;
			}

			if( btnButton.bAxisID == AI_AXE_N) // the mouse axis has the '-' flag set
			{
				fNegInput = !fNegInput;

				b_Value = ( l_Value < ZEROVALUE );
			}
			else
			{
				b_Value = ( l_Value > ZEROVALUE );
			}

			break;
		
		case DT_UNASSIGNED:
		default:
			b_Value = false;
		}

		if ( b_Value )
		{
			if ( fNegInput )
				l_Value = -l_Value;
			
			if( i < 2 )
				lAxisValueX += l_Value;
			else
				lAxisValueY += l_Value;
		}
	}

	if( pcController->fKeyboard )
	{
		if( pcController->fKeyAbsoluteX )
		{
			if( pcController->wAxeBuffer[0] > pcController->wAxeBuffer[1] )
			{
				pcController->wAxeBuffer[0] -= pcController->wAxeBuffer[1];
				pcController->wAxeBuffer[1] = 0;
			}
			else
			{
				pcController->wAxeBuffer[1] -= pcController->wAxeBuffer[0];
				pcController->wAxeBuffer[0] = 0;
			}
		}
		if( pcController->fKeyAbsoluteY )
		{
			if( pcController->wAxeBuffer[2] > pcController->wAxeBuffer[3] )
			{
				pcController->wAxeBuffer[2] -= pcController->wAxeBuffer[3];
				pcController->wAxeBuffer[3] = 0;
			}
			else
			{
				pcController->wAxeBuffer[3] -= pcController->wAxeBuffer[2];
				pcController->wAxeBuffer[2] = 0;
			}
		}
	}


	if (pcController->bRapidFireEnabled)
	{
		if (pcController->bRapidFireCounter >= pcController->bRapidFireRate)
		{
			w_Buttons = (w_Buttons & 0xFF1F);
			pcController->bRapidFireCounter = 0;
		}
		else
		{
			pcController->bRapidFireCounter = pcController->bRapidFireCounter + 1;
		}
	}

	if( pcController->fRealN64Range && ( lAxisValueX || lAxisValueY ))
	{
		long lAbsoluteX = ( lAxisValueX > 0 ) ? lAxisValueX : -lAxisValueX;
		long lAbsoluteY = ( lAxisValueY > 0 ) ? lAxisValueY : -lAxisValueY;

		long lRangeX;
		long lRangeY;

		if(	lAbsoluteX > lAbsoluteY )
		{
			lRangeX = MAXAXISVALUE;
			lRangeY = lRangeX * lAbsoluteY / lAbsoluteX;
		}
		else
		{
			lRangeY = MAXAXISVALUE;
			lRangeX = lRangeY * lAbsoluteX / lAbsoluteY;
		}

		// TODO: optimize this --rabid
		double dRangeDiagonal = sqrt((double)(lRangeX * lRangeX + lRangeY * lRangeY));
//		__asm{
//			fld fRangeDiagonal
//			fsqrt
//			fstp fRangeDiagonal
//			fwait
//		}
		double dRel = MAXAXISVALUE / dRangeDiagonal;

		*pdwData = MAKELONG(w_Buttons,
							MAKEWORD(	(BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueX * d_ModifierX * dRel )), MAXAXISVALUE) / N64DIVIDER ),
										(BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueY * d_ModifierY * dRel )), MAXAXISVALUE) / N64DIVIDER )));
	}
	else
	{
		*pdwData = MAKELONG(w_Buttons,
							MAKEWORD(	(BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueX * d_ModifierX )), MAXAXISVALUE) / N64DIVIDER ),
										(BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueY * d_ModifierY )), MAXAXISVALUE) / N64DIVIDER )));
	}

	return true;
}
示例#24
0
BOOL APIENTRY DllMain( HINSTANCE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{
	switch ( ul_reason_for_call )
	{
	case DLL_PROCESS_ATTACH:
		DisableThreadLibraryCalls( hModule );
		if( !prepareHeap())
			return FALSE;
		DebugWriteA("*** DLL Attach (" VERSIONNUMBER "-Debugbuild | built on " __DATE__ " at " __TIME__")\n");
		ZeroMemory( &g_strEmuInfo, sizeof(g_strEmuInfo) );
		ZeroMemory( g_devList, sizeof(g_devList) );
		ZeroMemory( &g_sysMouse, sizeof(g_sysMouse) );
		ZeroMemory( g_aszDefFolders, sizeof(g_aszDefFolders) );
		ZeroMemory( g_aszLastBrowse, sizeof(g_aszLastBrowse) );
		g_strEmuInfo.hinst = hModule;
		g_strEmuInfo.fDisplayShortPop = true;	// display pak switching message windows by default
#ifdef _UNICODE
		{
			g_strEmuInfo.Language = GetLanguageFromINI();
			if ( g_strEmuInfo.Language == 0 )
			{
				g_strEmuInfo.Language = DetectLanguage();
				DebugWriteA("Autoselect language: %d\n", g_strEmuInfo.Language);
			}
			g_hResourceDLL = LoadLanguageDLL(g_strEmuInfo.Language); // HACK: it's theoretically not safe to call LoadLibraryEx from DllMain... --rabid
			if( g_hResourceDLL == NULL )
			{
				g_strEmuInfo.Language = 0;
				g_hResourceDLL = hModule;
				DebugWriteA("couldn't load language DLL, falling back to defaults\n");
			}
		}
#else
		DebugWriteA("  (compiled in ANSI mode, language detection DISABLED.)\n");
		g_strEmuInfo.Language = 0;
		g_hResourceDLL = hModule;
#endif // #ifndef _UNICODE
		InitializeCriticalSection( &g_critical );
		break;

	case DLL_THREAD_ATTACH:
		break;

	case DLL_THREAD_DETACH:
		break;

	case DLL_PROCESS_DETACH:
		//CloseDLL();
		if (g_hResourceDLL != g_strEmuInfo.hinst)
			FreeLibrary(g_hResourceDLL); // HACK: it's not safe to call FreeLibrary from DllMain... but screw it

		DebugWriteA("*** DLL Detach\n");

		CloseDebugFile(); // Moved here from CloseDll
		DeleteCriticalSection( &g_critical );

		// Moved here from CloseDll... Heap is created from DllMain,
		// and now it's destroyed by DllMain... just safer code --rabid
		if( g_hHeap != NULL )
		{
			HeapDestroy( g_hHeap );
			g_hHeap = NULL;
		}
		break;
	}
    return TRUE;
}
示例#25
0
// returns true if the ROM was loaded OK
bool LoadCart(LPGBCART Cart, LPCTSTR RomFileName, LPCTSTR RamFileName, LPCTSTR TdfFileName)
{
	HANDLE hTemp;
	DWORD dwFilesize;
	DWORD NumQuarterBlocks = 0;

	UnloadCart(Cart);	// first, make sure any previous carts have been unloaded

	Cart->iCurrentRamBankNo = 0;
	Cart->iCurrentRomBankNo = 1;
	Cart->bRamEnableState = 0;
	Cart->bMBC1RAMbanking = 0;

	// Attempt to load the ROM file.
	hTemp = CreateFile(RomFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	if (hTemp != INVALID_HANDLE_VALUE && (Cart->hRomFile = CreateFileMapping(hTemp, NULL, PAGE_READONLY, 0, 0, NULL) ) )
	{
		// if the first case fails, the file doesn't exist. The second case can fail if the file size is zero.
		dwFilesize = GetFileSize(hTemp, NULL);
		CloseHandle(hTemp);
		Cart->RomData = (LPCBYTE)MapViewOfFile( Cart->hRomFile, FILE_MAP_READ, 0, 0, 0 );
	} else {
		DebugWriteA("Couldn't load the ROM file, GetLastError returned %08x\n", GetLastError());
		if (hTemp != INVALID_HANDLE_VALUE)
			CloseHandle(hTemp);	// if file size was zero, make sure we don't leak the handle

		ErrorMessage(IDS_ERR_GBROM, 0, false);
		return false;
	}

	if (dwFilesize < 0x8000) // a Rom file has to be at least 32kb
	{
		DebugWriteA("ROM file wasn't big enough to be a GB ROM!\n");
		ErrorMessage(IDS_ERR_GBROM, 0, false);

		UnloadCart(Cart);
		return false;
	}

	DebugWriteA(" Cartridge Type #:");
	DebugWriteByteA(Cart->RomData[0x147]);
	DebugWriteA("\n");
	switch (Cart->RomData[0x147]) {	// if we hadn't checked the file size before, this might have caused an access violation
	case 0x00:
		Cart->iCartType = GB_NORM;
		Cart->bHasRam = false;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x01:
		Cart->iCartType = GB_MBC1;
		Cart->bHasRam = false;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x02:
		Cart->iCartType = GB_MBC1;
		Cart->bHasRam = true;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x03:
		Cart->iCartType = GB_MBC1;
		Cart->bHasRam = true;
		Cart->bHasBattery = true;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x05:
		Cart->iCartType = GB_MBC2;
		Cart->bHasRam = false;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x06:
		Cart->iCartType = GB_MBC2;
		Cart->bHasRam = false;
		Cart->bHasBattery = true;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x08:
		Cart->iCartType = GB_NORM;
		Cart->bHasRam = true;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x09:
		Cart->iCartType = GB_NORM;
		Cart->bHasRam = true;
		Cart->bHasBattery = true;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x0B:
		Cart->iCartType = GB_MMMO1;
		Cart->bHasRam = false;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x0C:
		Cart->iCartType = GB_MMMO1;
		Cart->bHasRam = true;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x0D:
		Cart->iCartType = GB_MMMO1;
		Cart->bHasRam = true;
		Cart->bHasBattery = true;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x0F:
		Cart->iCartType = GB_MBC3;
		Cart->bHasRam = false;
		Cart->bHasBattery = true;
		Cart->bHasTimer = true;
		Cart->bHasRumble = false;
		break;
	case 0x10:
		Cart->iCartType = GB_MBC3;
		Cart->bHasRam = true;
		Cart->bHasBattery = true;
		Cart->bHasTimer = true;
		Cart->bHasRumble = false;
		break;
	case 0x11:
		Cart->iCartType = GB_MBC3;
		Cart->bHasRam = false;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x12:
		Cart->iCartType = GB_MBC3;
		Cart->bHasRam = true;
		Cart->bHasBattery = true;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x13:
		Cart->iCartType = GB_MBC3;
		Cart->bHasRam = true;
		Cart->bHasBattery = true;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x19:
		Cart->iCartType = GB_MBC5;
		Cart->bHasRam = false;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x1A:
		Cart->iCartType = GB_MBC5;
		Cart->bHasRam = true;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x1B:
		Cart->iCartType = GB_MBC5;
		Cart->bHasRam = true;
		Cart->bHasBattery = true;
		Cart->bHasTimer = false;
		Cart->bHasRumble = false;
		break;
	case 0x1C:
		Cart->iCartType = GB_MBC5;
		Cart->bHasRam = false;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = true;
		break;
	case 0x1D:
		Cart->iCartType = GB_MBC5;
		Cart->bHasRam = true;
		Cart->bHasBattery = false;
		Cart->bHasTimer = false;
		Cart->bHasRumble = true;
		break;
	case 0x1E:
		Cart->iCartType = GB_MBC5;
		Cart->bHasRam = true;
		Cart->bHasBattery = true;
		Cart->bHasTimer = false;
		Cart->bHasRumble = true;
		break;
	default:
		WarningMessage( IDS_ERR_GBROM, MB_OK | MB_ICONWARNING);
		DebugWriteA("TPak: unsupported paktype\n");
		UnloadCart(Cart);
		return false;
	}

	// assign read/write handlers
	switch (Cart->iCartType) {
	case GB_NORM: // Raw cartridge
		Cart->ptrfnReadCart = &ReadCartNorm;
		Cart->ptrfnWriteCart = &WriteCartNorm;
		break;
	case GB_MBC1:
		Cart->ptrfnReadCart =  &ReadCartMBC1;
		Cart->ptrfnWriteCart = &WriteCartMBC1;
		break;
	case GB_MBC2:
		Cart->ptrfnReadCart =  &ReadCartMBC2;
		Cart->ptrfnWriteCart = &WriteCartMBC2;
		break;
	case GB_MBC3:
		Cart->ptrfnReadCart =  &ReadCartMBC3;
		Cart->ptrfnWriteCart = &WriteCartMBC3;
		break;
	case GB_MBC5:
		Cart->ptrfnReadCart =  &ReadCartMBC5;
		Cart->ptrfnWriteCart = &WriteCartMBC5;
		break;
	default: // Don't pretend we know how to handle carts we don't support
		Cart->ptrfnReadCart = NULL;
		Cart->ptrfnWriteCart = NULL;
		DebugWriteA("Unsupported paktype: can't read/write cart type %02X\n", Cart->iCartType);
		UnloadCart(Cart);
		return false;
	}

	// Determine ROM size for paging checks
	Cart->iNumRomBanks = 2;
	switch (Cart->RomData[0x148]) {
	case 0x01:
		Cart->iNumRomBanks = 4;
		break;
	case 0x02:
		Cart->iNumRomBanks = 8;
		break;
	case 0x03:
		Cart->iNumRomBanks = 16;
		break;
	case 0x04:
		Cart->iNumRomBanks = 32;
		break;
	case 0x05:
		Cart->iNumRomBanks = 64;
		break;
	case 0x06:
		Cart->iNumRomBanks = 128;
		break;
	case 0x52:
		Cart->iNumRomBanks = 72;
		break;
	case 0x53:
		Cart->iNumRomBanks = 80;
		break;
	case 0x54:
		Cart->iNumRomBanks = 96;
		break;
	}

	if (dwFilesize != 0x4000 * Cart->iNumRomBanks) // Now that we know how big the ROM is supposed to be, check it again
	{
		ErrorMessage(IDS_ERR_GBROM, 0, false);

		UnloadCart(Cart);
		return false;
	}

	// Determine RAM size for paging checks
	Cart->iNumRamBanks = 0;
	switch (Cart->RomData[0x149]) {
	case 0x01:
		Cart->iNumRamBanks = 1;
		NumQuarterBlocks = 1;
		break;
	case 0x02:
		Cart->iNumRamBanks = 1;
		NumQuarterBlocks = 4;
		break;
	case 0x03:
		Cart->iNumRamBanks = 4;
		NumQuarterBlocks = 16;
		break;
	case 0x04:
		Cart->iNumRamBanks = 16;
		NumQuarterBlocks = 64;
		break;
	case 0x05:
		Cart->iNumRamBanks = 8;
		NumQuarterBlocks = 32;
		break;
	}

	DebugWriteA("GB cart has %d ROM banks, %d RAM quarter banks\n", Cart->iNumRomBanks, NumQuarterBlocks);
	if (Cart->bHasTimer)
	{
		DebugWriteA("GB cart timer present\n");
	}

	// Attempt to load the SRAM file, but only if RAM is supposed to be present.
	// For saving back to a file, if we map too much it will expand the file.
	if (Cart->bHasRam)
	{
		if (Cart->bHasBattery)
		{
			hTemp = CreateFile( RamFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL );
			if( hTemp == INVALID_HANDLE_VALUE )
			{// test if Read-only access is possible
				hTemp = CreateFile( RamFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL );
				if (Cart->bHasTimer && Cart->bHasBattery) {
					Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC));
					ClearData(Cart->RamData, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC));
				}
				else {
					Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800);
					ClearData(Cart->RamData, NumQuarterBlocks * 0x0800);
				}

				if( hTemp != INVALID_HANDLE_VALUE )
				{
					DWORD dwBytesRead;

					if (Cart->bHasTimer && Cart->bHasBattery)
						ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC), &dwBytesRead, NULL);
					else
						ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800, &dwBytesRead, NULL);
					WarningMessage( IDS_DLG_TPAK_READONLY, MB_OK | MB_ICONWARNING);
				}
				else
				{
					WarningMessage( IDS_ERR_GBSRAMERR, MB_OK | MB_ICONWARNING);
					return true;
				}
			} else { // file is OK, use a mapping
				if (Cart->bHasTimer && Cart->bHasBattery)
					Cart->hRamFile = CreateFileMapping( hTemp, NULL, PAGE_READWRITE, 0, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC), NULL);
				else
					Cart->hRamFile = CreateFileMapping( hTemp, NULL, PAGE_READWRITE, 0, NumQuarterBlocks * 0x0800, NULL);

				if (Cart->hRamFile != NULL)
				{
					Cart->RamData = (LPBYTE)MapViewOfFile( Cart->hRamFile, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
				} else { // could happen, if the file isn't big enough AND can't be grown to fit
					DWORD dwBytesRead;
					if (Cart->bHasTimer && Cart->bHasBattery) {
						Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC));
						ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC), &dwBytesRead, NULL);
					} else {
						Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800);
						ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800, &dwBytesRead, NULL);
					}
					if (dwBytesRead < NumQuarterBlocks * 0x0800 + ((Cart->bHasTimer && Cart->bHasBattery) ? sizeof(gbCartRTC) : 0))
					{
						ClearData(Cart->RamData, NumQuarterBlocks * 0x0800 + ((Cart->bHasTimer && Cart->bHasBattery) ? sizeof(gbCartRTC) : 0));
						WarningMessage( IDS_ERR_GBSRAMERR, MB_OK | MB_ICONWARNING);
					}
					else
					{
						WarningMessage( IDS_DLG_TPAK_READONLY, MB_OK | MB_ICONWARNING);
					}
				}
			}

			if (Cart->bHasTimer && Cart->bHasBattery) {
				dwFilesize = GetFileSize(hTemp, 0);
				if (dwFilesize >= (NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC) ) ) {
					// Looks like there is extra data in the SAV file than just RAM data... assume it is RTC data.
					gbCartRTC RTCTimer;
					CopyMemory( &RTCTimer, &Cart->RamData[NumQuarterBlocks * 0x0800], sizeof(RTCTimer) );
					Cart->TimerData[0] = (BYTE)RTCTimer.mapperSeconds;
					Cart->TimerData[1] = (BYTE)RTCTimer.mapperMinutes;
					Cart->TimerData[2] = (BYTE)RTCTimer.mapperHours;
					Cart->TimerData[3] = (BYTE)RTCTimer.mapperDays;
					Cart->TimerData[4] = (BYTE)RTCTimer.mapperControl;
					Cart->LatchedTimerData[0] = (BYTE)RTCTimer.mapperLSeconds;
					Cart->LatchedTimerData[1] = (BYTE)RTCTimer.mapperLMinutes;
					Cart->LatchedTimerData[2] = (BYTE)RTCTimer.mapperLHours;
					Cart->LatchedTimerData[3] = (BYTE)RTCTimer.mapperLDays;
					Cart->LatchedTimerData[4] = (BYTE)RTCTimer.mapperLControl;
					Cart->timerLastUpdate = RTCTimer.mapperLastTime;
					UpdateRTC(Cart);
				}
				else {
					ReadTDF(Cart);	// try to open TDF format, clear/init Cart->TimerData if that fails
				}
			}

			CloseHandle(hTemp);
		} else {
			// no battery; just allocate some RAM
			Cart->RamData = (LPBYTE)P_malloc(Cart->iNumRamBanks * 0x2000);
		}
	}

	Cart->TimerDataLatched = false;

	return true;
}
示例#26
0
// Executes the shortcut iShortcut on controller iController
// Special case: if iPlayer is -1, run the mouselock shortcut
void DoShortcut( int iControl, int iShortcut )
{
	DebugWriteA("Shortcut: %d %d\n", iControl, iShortcut);
	TCHAR pszMessage[DEFAULT_BUFFER / 2] = TEXT("");
	bool bEjectFirst = false;

	if (iControl == -1)
	{
		EnterCriticalSection( &g_critical );
		if( g_sysMouse.didHandle )
		{
			g_sysMouse.didHandle->Unacquire();
			if( g_bExclusiveMouse )
			{
				g_sysMouse.didHandle->Unacquire();
				g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_KEYBOARD );
				g_sysMouse.didHandle->Acquire();
				LoadString( g_hResourceDLL, IDS_POP_MOUSEUNLOCKED, pszMessage, ARRAYSIZE(pszMessage) );
			}
			else
			{
				g_sysMouse.didHandle->Unacquire();
				g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_MOUSE );
				g_sysMouse.didHandle->Acquire();
				LoadString( g_hResourceDLL, IDS_POP_MOUSELOCKED, pszMessage, ARRAYSIZE(pszMessage) );
			}
			g_sysMouse.didHandle->Acquire();
			g_bExclusiveMouse = !g_bExclusiveMouse;
		}
		LeaveCriticalSection( &g_critical );
	}
	else if( g_pcControllers[iControl].fPlugged )
	{
		if( g_pcControllers[iControl].pPakData )
		{
			SaveControllerPak( iControl );
			CloseControllerPak( iControl );
		}

		switch (iShortcut)
		{
		case SC_NOPAK:
			EnterCriticalSection( &g_critical );
			g_pcControllers[iControl].PakType = PAK_NONE;
			g_pcControllers[iControl].fPakInitialized = false;
			LoadString( g_hResourceDLL, IDS_P_NONE, pszMessage, ARRAYSIZE(pszMessage) );
			LeaveCriticalSection( &g_critical );
			break;

		case SC_MEMPAK:
			if (PAK_NONE == g_pcControllers[iControl].PakType)
			{
				EnterCriticalSection( &g_critical );
				g_pcControllers[iControl].PakType = PAK_MEM;
				g_pcControllers[iControl].fPakInitialized = false;
				LoadString( g_hResourceDLL, IDS_P_MEMPAK, pszMessage, ARRAYSIZE(pszMessage) );
				LeaveCriticalSection( &g_critical );
			}
			else
			{
				bEjectFirst = true;
			}
			break;
		
		case SC_RUMBPAK:
			if (PAK_NONE == g_pcControllers[iControl].PakType)
			{
				EnterCriticalSection( &g_critical );
				g_pcControllers[iControl].PakType = PAK_RUMBLE;
				g_pcControllers[iControl].fPakInitialized = false;

				if( g_pcControllers[iControl].fRawData )
					if (CreateEffectHandle( iControl, g_pcControllers[iControl].bRumbleTyp, g_pcControllers[iControl].bRumbleStrength ) )
					{
						DebugWriteA("CreateEffectHandle for shortcut switch: OK\n");
					}
					else
					{
						DebugWriteA("Couldn't CreateEffectHandle for shortcut switch.\n");
					}

				LoadString( g_hResourceDLL, IDS_P_RUMBLEPAK, pszMessage, ARRAYSIZE(pszMessage) );
				LeaveCriticalSection( &g_critical );
			}
			else
			{
				bEjectFirst = true;
			}
			break;
		
		case SC_TRANSPAK:
			if (PAK_NONE == g_pcControllers[iControl].PakType)
			{
				EnterCriticalSection( &g_critical );
				g_pcControllers[iControl].PakType = PAK_TRANSFER;
				g_pcControllers[iControl].fPakInitialized = false;

				LoadString( g_hResourceDLL, IDS_P_TRANSFERPAK, pszMessage, ARRAYSIZE(pszMessage) );
				LeaveCriticalSection( &g_critical );
			}
			else
			{
				bEjectFirst = true;
			}
			break;
		
		case SC_VOICEPAK:
			if (PAK_NONE == g_pcControllers[iControl].PakType)
			{
				EnterCriticalSection( &g_critical );
				g_pcControllers[iControl].PakType = PAK_VOICE;
				g_pcControllers[iControl].fPakInitialized = false;

				LoadString( g_hResourceDLL, IDS_P_VOICEPAK, pszMessage, ARRAYSIZE(pszMessage) );
				LeaveCriticalSection( &g_critical );
			}
			else
			{
				bEjectFirst = true;
			}
			break;

		case SC_ADAPTPAK:
			if (PAK_NONE == g_pcControllers[iControl].PakType)
			{
				EnterCriticalSection( &g_critical );
				g_pcControllers[iControl].PakType = PAK_ADAPTOID;
				g_pcControllers[iControl].fPakInitialized = false;

				LoadString( g_hResourceDLL, IDS_P_ADAPTOIDPAK, pszMessage, ARRAYSIZE(pszMessage) );
				LeaveCriticalSection( &g_critical );
			}
			else
			{
				bEjectFirst = true;
			}
			break;

		case SC_SWMEMRUMB:
			bEjectFirst = true;
			if( g_pcControllers[iControl].PakType == PAK_MEM )
			{
				iShortcut = PAK_RUMBLE;
			}
			else
			{
				iShortcut = PAK_MEM;
			}
			break;

		case SC_SWMEMADAPT:
			bEjectFirst = true;
			if( g_pcControllers[iControl].PakType == PAK_MEM )
			{
				iShortcut = PAK_ADAPTOID;
			}
			else
			{
				iShortcut = PAK_MEM;
			}
			break;

		default:
			DebugWriteA("Invalid iShortcut passed to DoShortcut\n");
			EnterCriticalSection( &g_critical );
			g_pcControllers[iControl].fPakInitialized = false;
			LeaveCriticalSection( &g_critical );
			return;
		} // switch (iShortcut)
	} // else if

	// let the game code re-init the pak.

	if (bEjectFirst)	// we need to eject the current pack first; then set a DoShortcut to try again in 1 second
	{
		EnterCriticalSection( &g_critical );
		g_pcControllers[iControl].PakType = PAK_NONE;
		g_pcControllers[iControl].fPakInitialized = false;
		LoadString( g_hResourceDLL, IDS_P_SWITCHING, pszMessage, ARRAYSIZE(pszMessage) );
		LeaveCriticalSection( &g_critical );

		LPMSHORTCUT lpmNextShortcut = (LPMSHORTCUT)P_malloc(sizeof(MSHORTCUT));
		if (!lpmNextShortcut)
			return;
		lpmNextShortcut->iControl = iControl;
		lpmNextShortcut->iShortcut = iShortcut;
		CreateThread(NULL, 0, DelayedShortcut, lpmNextShortcut, 0, NULL);
		iControl = -2;	// this is just a hack to get around the check that appends "Changing Pak X to ..."
	}
	
	if( g_strEmuInfo.fDisplayShortPop && _tcslen(pszMessage) > 0 )
	{
		if( iControl >= 0 )
		{
			TCHAR tszNotify[DEFAULT_BUFFER / 2];

			LoadString( g_hResourceDLL, IDS_POP_CHANGEPAK, tszNotify, ARRAYSIZE(tszNotify));
			wsprintf( g_pszThreadMessage, tszNotify, iControl+1, pszMessage );
		}
		else
			lstrcpyn( g_pszThreadMessage, pszMessage, ARRAYSIZE(g_pszThreadMessage) );

		CreateThread(NULL, 0, MsgThreadFunction, g_pszThreadMessage, 0, NULL);
	}
}
示例#27
0
// PrepareInputDevices rewritten --rabid
bool PrepareInputDevices()
{
	bool fKeyboard = false;
	bool fMouse = false;
	bool fGamePad = false;

	for( int i = 0; i < ARRAYSIZE( g_pcControllers ); ++i )
	{
		fGamePad = false;
		if( g_pcControllers[i].fPlugged )
		{
			CountControllerStructDevs( &g_pcControllers[i] );

			fKeyboard = g_pcControllers[i].fKeyboard != 0;
			fMouse = g_pcControllers[i].fMouse != 0;
			fGamePad = ( g_pcControllers[i].fGamePad != 0); // we'll assume for now that there's a gamepad to go with those buttons
		}

		ReleaseEffect( g_apdiEffect[i] );
		if( g_pcControllers[i].guidFFDevice != GUID_NULL && GetInputDevice( g_strEmuInfo.hMainWindow, g_apFFDevice[i], g_pcControllers[i].guidFFDevice, DI8DEVTYPE_JOYSTICK, DIB_FF )) // not necessarily a joystick type device, but we don't use the data anyway
		{
			DIDEVICEINSTANCE diDev;
			diDev.dwSize = sizeof( DIDEVICEINSTANCE );

			g_apFFDevice[i]->GetDeviceInfo( &diDev );

			if( !lstrcmp( diDev.tszProductName, _T( STRING_ADAPTOID )))
			{
				g_pcControllers[i].fIsAdaptoid = true;
				DebugWriteA("FF device on controller %d is of type Adaptoid\n", i+1);
			}
			else
			{
				g_pcControllers[i].fIsAdaptoid = false;
			}

			if ( CreateEffectHandle( i, g_pcControllers[i].bRumbleTyp, g_pcControllers[i].bRumbleStrength ) )
			{
				AcquireDevice( g_apFFDevice[i] );
				DebugWriteA("Got FF device %d\n", i);
			}
			else
				DebugWriteA("Couldn't get FF device: CreateEffectHandle failed!\n");
		}
		else
		{
			g_apFFDevice[i] = NULL;
			DebugWriteA("Didn't get FF device %d\n", i);
		}
	}

	if( fMouse )
	{
		if( !g_sysMouse.didHandle )
		{
			if( GetInputDevice( g_strEmuInfo.hMainWindow, g_sysMouse.didHandle, GUID_SysMouse, DI8DEVTYPE_MOUSE, g_bExclusiveMouse ? DIB_MOUSE : DIB_KEYBOARD ))
			{
				AcquireDevice( g_sysMouse.didHandle );
			}
		}
	}
	else
	{
		g_bExclusiveMouse = false;
	}

	return true;
}