Ejemplo n.º 1
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);
	}
}
Ejemplo n.º 2
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;
}