示例#1
0
void EmuScreen::processAxis(const AxisInput &axis, int direction) {
	std::vector<int> results;
	KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, direction, &results);
	std::vector<int> resultsOpposite;
	KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, -direction, &resultsOpposite);

	for (size_t i = 0; i < results.size(); i++) {
		int result = results[i];
		switch (result) {
		case VIRTKEY_AXIS_X_MIN:
			__CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_LEFT);
			break;
		case VIRTKEY_AXIS_X_MAX:
			__CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_LEFT);
			break;
		case VIRTKEY_AXIS_Y_MIN:
			__CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_LEFT);
			break;
		case VIRTKEY_AXIS_Y_MAX:
			__CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_LEFT);
			break;

		case VIRTKEY_AXIS_RIGHT_X_MIN:
			__CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_RIGHT);
			break;
		case VIRTKEY_AXIS_RIGHT_X_MAX:
			__CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_RIGHT);
			break;
		case VIRTKEY_AXIS_RIGHT_Y_MIN:
			__CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_RIGHT);
			break;
		case VIRTKEY_AXIS_RIGHT_Y_MAX:
			__CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_RIGHT);
			break;

		default:
			if (axis.value >= AXIS_BIND_THRESHOLD || axis.value <= -AXIS_BIND_THRESHOLD) {
				pspKey(result, KEY_DOWN);

				// Also unpress the other direction.
				std::vector<int> opposite;
				KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, axis.value >= 0 ? -1 : 1, &opposite);
				for (size_t i = 0; i < opposite.size(); i++) {
					pspKey(opposite[i], KEY_UP);
				}
				// Hm, why do we use a different way below?
			} else {
				// Release both directions, trying to deal with some erratic controllers that can cause it to stick.
				pspKey(result, KEY_UP);
				for (size_t i = 0; i < resultsOpposite.size(); i++) {
					pspKey(resultsOpposite[i], KEY_UP);
				}
			}
		}
	}
}
示例#2
0
void EmuScreen::onVKeyDown(int virtualKeyCode) {
	I18NCategory *s = GetI18NCategory("Screen"); 

	switch (virtualKeyCode) {
	case VIRTKEY_SPEED_TOGGLE:
		if (PSP_CoreParameter().fpsLimit == 0) {
			PSP_CoreParameter().fpsLimit = 1;
			osm.Show(s->T("fixed", "Speed: fixed"), 1.0);
		}
		else if (PSP_CoreParameter().fpsLimit == 1) {
			PSP_CoreParameter().fpsLimit = 0;
			osm.Show(s->T("standard", "Speed: standard"), 1.0);
		}
		break;

	// On Android, this is take care of in update() using input.buttons & back
	// Should get rid of that but not now.
#ifndef ANDROID
	case VIRTKEY_PAUSE:
		screenManager()->push(new PauseScreen());
		break;
#endif

	case VIRTKEY_AXIS_X_MIN:
		__CtrlSetAnalogX(-1.0f, CTRL_STICK_LEFT);
		break;
	case VIRTKEY_AXIS_X_MAX:
		__CtrlSetAnalogX(1.0f, CTRL_STICK_LEFT);
		break;
	case VIRTKEY_AXIS_Y_MIN:
		__CtrlSetAnalogY(-1.0f, CTRL_STICK_LEFT);
		break;
	case VIRTKEY_AXIS_Y_MAX:
		__CtrlSetAnalogY(1.0f, CTRL_STICK_LEFT);
		break;

	case VIRTKEY_AXIS_RIGHT_X_MIN:
		__CtrlSetAnalogX(-1.0f, CTRL_STICK_RIGHT);
		break;
	case VIRTKEY_AXIS_RIGHT_X_MAX:
		__CtrlSetAnalogX(1.0f, CTRL_STICK_RIGHT);
		break;
	case VIRTKEY_AXIS_RIGHT_Y_MIN:
		__CtrlSetAnalogY(-1.0f, CTRL_STICK_RIGHT);
		break;
	case VIRTKEY_AXIS_RIGHT_Y_MAX:
		__CtrlSetAnalogY(1.0f, CTRL_STICK_RIGHT);
		break;
	}
}
示例#3
0
void EmuScreen::processAxis(const AxisInput &axis, int direction) {
	int result = KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, direction);
	int resultOpposite = KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, -direction);

	if (result == KEYMAP_ERROR_UNKNOWN_KEY)
		return;

	switch (result) {
	case VIRTKEY_AXIS_X_MIN:
		__CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_LEFT);
		break;
	case VIRTKEY_AXIS_X_MAX:
		__CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_LEFT);
		break;
	case VIRTKEY_AXIS_Y_MIN:
		__CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_LEFT);
		break;
	case VIRTKEY_AXIS_Y_MAX:
		__CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_LEFT);
		break;

	case VIRTKEY_AXIS_RIGHT_X_MIN:
		__CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_RIGHT);
		break;
	case VIRTKEY_AXIS_RIGHT_X_MAX:
		__CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_RIGHT);
		break;
	case VIRTKEY_AXIS_RIGHT_Y_MIN:
		__CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_RIGHT);
		break;
	case VIRTKEY_AXIS_RIGHT_Y_MAX:
		__CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_RIGHT);
		break;

	default:
		if (axis.value >= AXIS_BIND_THRESHOLD || axis.value <= -AXIS_BIND_THRESHOLD) {
			pspKey(result, KEY_DOWN);

			// Also unpress the other direction.
			result = KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, axis.value >= 0 ? -1 : 1);
			if (result != KEYMAP_ERROR_UNKNOWN_KEY)
				pspKey(result, KEY_UP);
		} else {
			// Release both directions, trying to deal with some erratic controllers that can cause it to stick.
			pspKey(result, KEY_UP);
			pspKey(resultOpposite, KEY_UP);
		}
	}
}
示例#4
0
void EmuScreen::update(InputState &input) {
	if (!booted_)
		bootGame(gamePath_);

	UIScreen::update(input);

	// Simply forcibily update to the current screen size every frame. Doesn't cost much.
	PSP_CoreParameter().outputWidth = dp_xres;
	PSP_CoreParameter().outputHeight = dp_yres;
	PSP_CoreParameter().pixelWidth = pixel_xres;
	PSP_CoreParameter().pixelHeight = pixel_yres;

	UpdateUIState(UISTATE_INGAME);
	
	if (errorMessage_.size()) {
		I18NCategory *g = GetI18NCategory("Error");
		std::string errLoadingFile = g->T("Error loading file");
		errLoadingFile.append(" ");
		errLoadingFile.append(g->T(errorMessage_.c_str()));

		screenManager()->push(new PromptScreen(
			errLoadingFile, "OK", ""));
		errorMessage_ = "";
		return;
	}

	if (invalid_)
		return;

	float leftstick_x = 0.0f;
	float leftstick_y = 0.0f;
	float rightstick_x = 0.0f;
	float rightstick_y = 0.0f;

	// Virtual keys.
	__CtrlSetRapidFire(virtKeys[VIRTKEY_RAPID_FIRE - VIRTKEY_FIRST]);

	// Apply tilt to left stick
	// TODO: Make into an axis
#ifdef USING_GLES2
	if (g_Config.bAccelerometerToAnalogHoriz) {
		// TODO: Deadzone, etc.
		leftstick_x += clamp1(curve1(input.acc.y) * 2.0f) * g_Config.iTiltSensitivity / 100;
		__CtrlSetAnalogX(clamp1(leftstick_x), CTRL_STICK_LEFT);
	}
#endif

	// Make sure fpsLimit starts at 0
	if (PSP_CoreParameter().fpsLimit != 0 && PSP_CoreParameter().fpsLimit != 1) {
		PSP_CoreParameter().fpsLimit = 0;
	}

	// This is here to support the iOS on screen back button.
	if (pauseTrigger_) {
		pauseTrigger_ = false;
		screenManager()->push(new GamePauseScreen(gamePath_));
	}
}
示例#5
0
void EmuScreen::axis(const AxisInput &axis) {
	int result = KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, axis.value >= 0 ? 1 : -1);
	if (result == KEYMAP_ERROR_UNKNOWN_KEY)
		return;

	switch (result) {
	case VIRTKEY_AXIS_X_MIN:
		__CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_LEFT);
		break;
	case VIRTKEY_AXIS_X_MAX:
		__CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_LEFT);
		break;
	case VIRTKEY_AXIS_Y_MIN:
		__CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_LEFT);
		break;
	case VIRTKEY_AXIS_Y_MAX:
		__CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_LEFT);
		break;

	case VIRTKEY_AXIS_RIGHT_X_MIN:
		__CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_RIGHT);
		break;
	case VIRTKEY_AXIS_RIGHT_X_MAX:
		__CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_RIGHT);
		break;
	case VIRTKEY_AXIS_RIGHT_Y_MIN:
		__CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_RIGHT);
		break;
	case VIRTKEY_AXIS_RIGHT_Y_MAX:
		__CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_RIGHT);
		break;

	default:
		if (axis.value >= AXIS_BIND_THRESHOLD || axis.value <= -AXIS_BIND_THRESHOLD) {
			pspKey(result, KEY_DOWN);

			// Also unpress the other direction.
			result = KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, axis.value >= 0 ? -1 : 1);
			if (result != KEYMAP_ERROR_UNKNOWN_KEY)
				pspKey(result, KEY_UP);
		} else {
			pspKey(result, KEY_UP);
		}
	}
}
示例#6
0
inline void EmuScreen::setVKeyAnalogX(int stick, int virtualKeyMin, int virtualKeyMax) {
	float axis = 0.0f;
	// The down events can repeat, so just trust the virtKeys array.
	if (virtKeys[virtualKeyMin - VIRTKEY_FIRST])
		axis -= 1.0f;
	if (virtKeys[virtualKeyMax - VIRTKEY_FIRST])
		axis += 1.0f;
	__CtrlSetAnalogX(axis, stick);
}
示例#7
0
inline void EmuScreen::setVKeyAnalogX(int stick, int virtualKeyMin, int virtualKeyMax) {
	const float value = virtKeys[VIRTKEY_ANALOG_LIGHTLY - VIRTKEY_FIRST] ? 0.5f : 1.0f;
	float axis = 0.0f;
	// The down events can repeat, so just trust the virtKeys array.
	if (virtKeys[virtualKeyMin - VIRTKEY_FIRST])
		axis -= value;
	if (virtKeys[virtualKeyMax - VIRTKEY_FIRST])
		axis += value;
	__CtrlSetAnalogX(axis, stick);
}
示例#8
0
void EmuScreen::update(InputState &input) {
	if (!booted_)
		bootGame(gamePath_);

	UIScreen::update(input);

	// Simply forcibily update to the current screen size every frame. Doesn't cost much.
	PSP_CoreParameter().outputWidth = dp_xres;
	PSP_CoreParameter().outputHeight = dp_yres;
	PSP_CoreParameter().pixelWidth = pixel_xres;
	PSP_CoreParameter().pixelHeight = pixel_yres;

	globalUIState = UISTATE_INGAME;
	if (errorMessage_.size()) {
		screenManager()->push(new PromptScreen(
			"Error loading file: " + errorMessage_, "OK", ""));
		errorMessage_ = "";
		return;
	}

	if (invalid_)
		return;

	float leftstick_x = 0.0f;
	float leftstick_y = 0.0f;
	float rightstick_x = 0.0f;
	float rightstick_y = 0.0f;

	// Virtual keys.
	__CtrlSetRapidFire(virtKeys[VIRTKEY_RAPID_FIRE - VIRTKEY_FIRST]);

	// Apply tilt to left stick
	if (g_Config.bAccelerometerToAnalogHoriz) {
		// TODO: Deadzone, etc.
		leftstick_x += clamp1(curve1(input.acc.y) * 2.0f);
		__CtrlSetAnalogX(clamp1(leftstick_x), CTRL_STICK_LEFT);
	}

	// Make sure fpsLimit starts at 0
	if (PSP_CoreParameter().fpsLimit != 0 && PSP_CoreParameter().fpsLimit != 1) {
		PSP_CoreParameter().fpsLimit = 0;
	}

	// This is here to support the iOS on screen back button.
	if (pauseTrigger_) {
		pauseTrigger_ = false;
		if (g_Config.bNewUI) {
			screenManager()->push(new GamePauseScreen(gamePath_));
		} else {
			screenManager()->push(new PauseScreen());
		}
	}
}
示例#9
0
void EmuScreen::onVKeyUp(int virtualKeyCode) {
	switch (virtualKeyCode) {
	case VIRTKEY_AXIS_X_MIN:
	case VIRTKEY_AXIS_X_MAX:
		__CtrlSetAnalogX(0.0f, CTRL_STICK_LEFT);
		break;
	case VIRTKEY_AXIS_Y_MIN:
	case VIRTKEY_AXIS_Y_MAX:
		__CtrlSetAnalogY(0.0f, CTRL_STICK_LEFT);
		break;

	case VIRTKEY_AXIS_RIGHT_X_MIN:
	case VIRTKEY_AXIS_RIGHT_X_MAX:
		__CtrlSetAnalogX(0.0f, CTRL_STICK_RIGHT);
		break;
	case VIRTKEY_AXIS_RIGHT_Y_MIN:
	case VIRTKEY_AXIS_RIGHT_Y_MAX:
		__CtrlSetAnalogY(0.0f, CTRL_STICK_RIGHT);
		break;
	default:
		break;
	}
}
示例#10
0
void EmuScreen::update(InputState &input) {
	globalUIState = UISTATE_INGAME;
	if (errorMessage_.size()) {
		screenManager()->push(new ErrorScreen(
			"Error loading file",
			errorMessage_));
		errorMessage_ = "";
		return;
	}

	if (invalid_)
		return;

	float leftstick_x = 0.0f;
	float leftstick_y = 0.0f;
	float rightstick_x = 0.0f;
	float rightstick_y = 0.0f;

	// Virtual keys.
	__CtrlSetRapidFire(virtKeys[VIRTKEY_RAPID_FIRE - VIRTKEY_FIRST]);

	// First translate touches into native pad input.
	// Do this no matter the value of g_Config.bShowTouchControls, some people
	// like to use invisible controls...
	// Don't force on platforms that likely don't have a touchscreen, like Win32, OSX, and Linux...
	// TODO: What are good ifdefs for OSX and Linux, without breaking other mobile platforms?
#ifdef _WIN32
	if(g_Config.bShowTouchControls) {
#endif
		// TODO: Make new better touch buttons so we don't have to do this crap.

		// Copy over the mouse data from the real inputstate.
		fakeInputState.mouse_valid = input.mouse_valid;
		fakeInputState.pad_last_buttons = fakeInputState.pad_buttons;
		fakeInputState.pad_buttons = input.pad_buttons;
		memcpy(fakeInputState.pointer_down, input.pointer_down, sizeof(input.pointer_down));
		memcpy(fakeInputState.pointer_x, input.pointer_x, sizeof(input.pointer_x));
		memcpy(fakeInputState.pointer_y, input.pointer_y, sizeof(input.pointer_y));
		fakeInputState.pad_lstick_x = 0.0f;
		fakeInputState.pad_lstick_y = 0.0f;
		fakeInputState.pad_rstick_x = 0.0f;
		fakeInputState.pad_rstick_y = 0.0f;
		UpdateGamepad(fakeInputState);
		UpdateInputState(&fakeInputState);

		for (size_t i = 0; i < ARRAY_SIZE(legacy_touch_mapping); i++) {
			if (fakeInputState.pad_buttons_down & legacy_touch_mapping[i].from)
				__CtrlButtonDown(legacy_touch_mapping[i].to);
			if (fakeInputState.pad_buttons_up & legacy_touch_mapping[i].from)
				__CtrlButtonUp(legacy_touch_mapping[i].to);
		}
		leftstick_x += fakeInputState.pad_lstick_x;
		leftstick_y += fakeInputState.pad_lstick_y;
		rightstick_x += fakeInputState.pad_rstick_x;
		rightstick_y += fakeInputState.pad_rstick_y;

		if (g_Config.bShowAnalogStick) {
			__CtrlSetAnalogX(clamp1(leftstick_x), CTRL_STICK_LEFT);
			__CtrlSetAnalogY(clamp1(leftstick_y), CTRL_STICK_LEFT);
		}
		__CtrlSetAnalogX(clamp1(rightstick_x), CTRL_STICK_RIGHT);
		__CtrlSetAnalogY(clamp1(rightstick_y), CTRL_STICK_RIGHT);

		// Also send the special buttons to input, since that's where they're handled.
		input.pad_buttons_down |= fakeInputState.pad_buttons_down & (PAD_BUTTON_MENU | PAD_BUTTON_BACK | PAD_BUTTON_RIGHT_THUMB | PAD_BUTTON_LEFT_THUMB);
		input.pad_buttons_up |= fakeInputState.pad_buttons_up & (PAD_BUTTON_MENU | PAD_BUTTON_BACK | PAD_BUTTON_RIGHT_THUMB | PAD_BUTTON_LEFT_THUMB);
		input.pad_buttons = fakeInputState.pad_buttons;
#ifdef _WIN32
	}
#endif

	// Still checking input.pad_buttons here to support the onscreen throttle button.
	PSP_CoreParameter().unthrottle = virtKeys[VIRTKEY_UNTHROTTLE - VIRTKEY_FIRST] ||
		(input.pad_buttons & PAD_BUTTON_UNTHROTTLE) != 0;

	// Apply tilt to left stick
	if (g_Config.bAccelerometerToAnalogHoriz) {
		// TODO: Deadzone, etc.
		leftstick_x += clamp1(curve1(input.acc.y) * 2.0f);
		__CtrlSetAnalogX(clamp1(leftstick_x), CTRL_STICK_LEFT);
	}

	// Make sure fpsLimit starts at 0
	if (PSP_CoreParameter().fpsLimit != 0 && PSP_CoreParameter().fpsLimit != 1) {
		PSP_CoreParameter().fpsLimit = 0;
	}

	// This is still here to support the iOS on screen back button.
	if (input.pad_buttons_down & (PAD_BUTTON_BACK)) {
		screenManager()->push(new PauseScreen());
	}
}
示例#11
0
void EmuScreen::update(InputState &input) {
	if (!booted_)
		bootGame(gamePath_);

	UIScreen::update(input);

	// Simply forcibily update to the current screen size every frame. Doesn't cost much.
	PSP_CoreParameter().outputWidth = dp_xres;
	PSP_CoreParameter().outputHeight = dp_yres;
	PSP_CoreParameter().pixelWidth = pixel_xres;
	PSP_CoreParameter().pixelHeight = pixel_yres;

	UpdateUIState(UISTATE_INGAME);

	if (errorMessage_.size()) {
		// Special handling for ZIP files. It's not very robust to check an error message but meh,
		// at least it's pre-translation.
		if (errorMessage_.find("ZIP") != std::string::npos) {
			screenManager()->push(new InstallZipScreen(gamePath_));
			errorMessage_ = "";
			return;
		}
		I18NCategory *g = GetI18NCategory("Error");
		std::string errLoadingFile = g->T("Error loading file", "Could not load game");

		errLoadingFile.append(" ");
		errLoadingFile.append(g->T(errorMessage_.c_str()));

		screenManager()->push(new PromptScreen(errLoadingFile, "OK", ""));
		errorMessage_ = "";
		return;
	}

	if (invalid_)
		return;

	float leftstick_x = 0.0f;
	float leftstick_y = 0.0f;
	float rightstick_x = 0.0f;
	float rightstick_y = 0.0f;

	// Virtual keys.
	__CtrlSetRapidFire(virtKeys[VIRTKEY_RAPID_FIRE - VIRTKEY_FIRST]);

	// Apply tilt to left stick
	// TODO: Make into an axis
#ifdef USING_GLES2
	if (g_Config.bAccelerometerToAnalogHoriz) {
		// Get the "base" coordinate system which is setup by the calibration system
		float base_x = g_Config.fTiltBaseX;
		float base_y = g_Config.fTiltBaseY;

		//convert the current input into base coordinates and normalize
		//TODO: check if all phones give values between [-50, 50]. I'm not sure how iOS works.
		float normalized_input_x = (input.acc.y - base_x) / 50.0 ;
		float normalized_input_y = (input.acc.x - base_y) / 50.0 ;

		//TODO: need a better name for computed x and y.
		float delta_x =  tiltInputCurve(normalized_input_x * 2.0 * (g_Config.iTiltSensitivityX)) ;

		//if the invert is enabled, invert the motion
		if (g_Config.bInvertTiltX) {
			delta_x *= -1;
		}

		float delta_y =  tiltInputCurve(normalized_input_y * 2.0 * (g_Config.iTiltSensitivityY)) ;
		
		if (g_Config.bInvertTiltY) {
			delta_y *= -1;
		}

		//clamp the delta between [-1, 1]
		leftstick_x += clamp1(delta_x);
		__CtrlSetAnalogX(clamp1(leftstick_x), CTRL_STICK_LEFT);

		
		leftstick_y += clamp1(delta_y);
		__CtrlSetAnalogY(clamp1(leftstick_y), CTRL_STICK_LEFT);
	}
#endif

	// Make sure fpsLimit starts at 0
	if (PSP_CoreParameter().fpsLimit != 0 && PSP_CoreParameter().fpsLimit != 1) {
		PSP_CoreParameter().fpsLimit = 0;
	}

	// This is here to support the iOS on screen back button.
	if (pauseTrigger_) {
		pauseTrigger_ = false;
		screenManager()->push(new GamePauseScreen(gamePath_));
	}
}
示例#12
0
void EmuScreen::processAxis(const AxisInput &axis, int direction) {
	// Sanity check
	if (axis.axisId < 0 || axis.axisId >= JOYSTICK_AXIS_MAX) {
		return;
	}

	std::vector<int> results;
	KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, direction, &results);
	for (size_t i = 0; i < results.size(); i++) {
		int result = results[i];
		switch (result) {
		case VIRTKEY_AXIS_X_MIN:
			__CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_LEFT);
			break;
		case VIRTKEY_AXIS_X_MAX:
			__CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_LEFT);
			break;
		case VIRTKEY_AXIS_Y_MIN:
			__CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_LEFT);
			break;
		case VIRTKEY_AXIS_Y_MAX:
			__CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_LEFT);
			break;

		case VIRTKEY_AXIS_RIGHT_X_MIN:
			__CtrlSetAnalogX(-fabs(axis.value), CTRL_STICK_RIGHT);
			break;
		case VIRTKEY_AXIS_RIGHT_X_MAX:
			__CtrlSetAnalogX(fabs(axis.value), CTRL_STICK_RIGHT);
			break;
		case VIRTKEY_AXIS_RIGHT_Y_MIN:
			__CtrlSetAnalogY(-fabs(axis.value), CTRL_STICK_RIGHT);
			break;
		case VIRTKEY_AXIS_RIGHT_Y_MAX:
			__CtrlSetAnalogY(fabs(axis.value), CTRL_STICK_RIGHT);
			break;
		}
	}

	std::vector<int> resultsOpposite;
	KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, -direction, &resultsOpposite);

	int axisState = 0;
	if ((direction == 1 && axis.value >= AXIS_BIND_THRESHOLD)) {
		axisState = 1;
	} else if (direction == -1 && axis.value <= -AXIS_BIND_THRESHOLD) {
		axisState = -1;
	} else {
		axisState = 0;
	}

	if (axisState != axisState_[axis.axisId]) {
		axisState_[axis.axisId] = axisState;
		if (axisState != 0) {
			for (size_t i = 0; i < results.size(); i++) {
				if (!IsAnalogStickKey(results[i]))
					pspKey(results[i], KEY_DOWN);
			}
			// Also unpress the other direction.
			for (size_t i = 0; i < resultsOpposite.size(); i++) {
				if (!IsAnalogStickKey(resultsOpposite[i]))
					pspKey(resultsOpposite[i], KEY_UP);
			}
		} else if (axisState == 0) {
			// Release both directions, trying to deal with some erratic controllers that can cause it to stick.
			for (size_t i = 0; i < results.size(); i++) {
				if (!IsAnalogStickKey(results[i]))
					pspKey(results[i], KEY_UP);
			}
			for (size_t i = 0; i < resultsOpposite.size(); i++) {
				if (!IsAnalogStickKey(resultsOpposite[i]))
					pspKey(resultsOpposite[i], KEY_UP);
			}
		}
	}
}