void EmuScreen::update(InputState &input) {
globalUIState = UISTATE_INGAME;
if (errorMessage_.size()) {
screenManager()->push(new ErrorScreen(
"Error loading file",
errorMessage_));
errorMessage_ = "";
return;
}
if (invalid_)
return;
// 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
UpdateGamepad(input);
UpdateInputState(&input);
#ifdef _WIN32
}
#endif
// Then translate pad input into PSP pad input. Also, add in tilt.
static const int mapping[12][2] = {
{PAD_BUTTON_A, CTRL_CROSS},
{PAD_BUTTON_B, CTRL_CIRCLE},
{PAD_BUTTON_X, CTRL_SQUARE},
{PAD_BUTTON_Y, CTRL_TRIANGLE},
{PAD_BUTTON_UP, CTRL_UP},
{PAD_BUTTON_DOWN, CTRL_DOWN},
{PAD_BUTTON_LEFT, CTRL_LEFT},
{PAD_BUTTON_RIGHT, CTRL_RIGHT},
{PAD_BUTTON_LBUMPER, CTRL_LTRIGGER},
{PAD_BUTTON_RBUMPER, CTRL_RTRIGGER},
{PAD_BUTTON_START, CTRL_START},
{PAD_BUTTON_SELECT, CTRL_SELECT},
};
for (int i = 0; i < 12; i++) {
if (input.pad_buttons_down & mapping[i][0]) {
__CtrlButtonDown(mapping[i][1]);
}
if (input.pad_buttons_up & mapping[i][0]) {
__CtrlButtonUp(mapping[i][1]);
}
}
float stick_x = input.pad_lstick_x;
float stick_y = input.pad_lstick_y;
float rightstick_x = input.pad_rstick_x;
float rightstick_y = input.pad_rstick_y;
I18NCategory *s = GetI18NCategory("Screen");
// Apply tilt to left stick
if (g_Config.bAccelerometerToAnalogHoriz) {
// TODO: Deadzone, etc.
stick_x += clamp1(curve1(input.acc.y) * 2.0f);
stick_x = clamp1(stick_x);
}
__CtrlSetAnalog(stick_x, stick_y, 0);
__CtrlSetAnalog(rightstick_x, rightstick_x, 1);
if (PSP_CoreParameter().fpsLimit != 2) {
// Don't really need to show these, it's pretty obvious what unthrottle does,
// in contrast to the three state toggle
/*
if (input.pad_buttons_down & PAD_BUTTON_UNTHROTTLE) {
osm.Show(s->T("unlimited", "Speed: unlimited!"), 1.0, 0x50E0FF);
}
if (input.pad_buttons_up & PAD_BUTTON_UNTHROTTLE) {
osm.Show(s->T("standard", "Speed: standard"), 1.0);
}*/
}
if (input.pad_buttons & PAD_BUTTON_UNTHROTTLE) {
PSP_CoreParameter().unthrottle = true;
} else {
PSP_CoreParameter().unthrottle = false;
}
// Make sure fpsLimit starts at 0
if (PSP_CoreParameter().fpsLimit != 0 && PSP_CoreParameter().fpsLimit != 1 && PSP_CoreParameter().fpsLimit != 2) {
PSP_CoreParameter().fpsLimit = 0;
}
//Toggle between 3 different states of fpsLimit
if (input.pad_buttons_down & PAD_BUTTON_LEFT_THUMB) {
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 = 2;
osm.Show(s->T("unlimited", "Speed: unlimited!"), 1.0, 0x50E0FF);
//.........这里部分代码省略.........
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.
// If bounds is set to be smaller than the actual pixel resolution of the display, respect that.
// TODO: Should be able to use g_dpi_scale here instead. Might want to store the dpi scale in the UI context too.
const Bounds &bounds = screenManager()->getUIContext()->GetBounds();
PSP_CoreParameter().pixelWidth = pixel_xres * bounds.w / dp_xres;
PSP_CoreParameter().pixelHeight = pixel_yres * bounds.h / dp_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_ = "";
quit_ = true;
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_ = "";
quit_ = true;
return;
}
if (invalid_)
return;
// Virtual keys.
__CtrlSetRapidFire(virtKeys[VIRTKEY_RAPID_FIRE - VIRTKEY_FIRST]);
// Apply tilt to left stick
// TODO: Make into an axis
#ifdef MOBILE_DEVICE
/*
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_));
}
}
bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_message) {
*error_message = "ok";
hWnd = window;
GLuint PixelFormat;
// TODO: Change to use WGL_ARB_pixel_format instead
static const PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
24, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
8, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // At least a 16Bit Z-Buffer (Depth Buffer)
8, // 8-bit Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
hDC = GetDC(hWnd);
if (!hDC) {
*error_message = "Failed to get a device context.";
return false; // Return FALSE
}
if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) {
*error_message = "Can't find a suitable PixelFormat.";
return false;
}
if (!SetPixelFormat(hDC, PixelFormat, &pfd)) {
*error_message = "Can't set the PixelFormat.";
return false;
}
if (!(hRC = wglCreateContext(hDC))) {
*error_message = "Can't create a GL rendering context.";
return false;
}
if (!wglMakeCurrent(hDC, hRC)) {
*error_message = "Can't activate the GL rendering context.";
return false;
}
// Check for really old OpenGL drivers and refuse to run really early in some cases.
// TODO: Also either tell the user to give up or point the user to the right websites. Here's some collected
// information about a system that will not work:
// GL_VERSION GL_VENDOR GL_RENDERER
// "1.4.0 - Build 8.14.10.2364" "intel" intel Pineview Platform
I18NCategory *err = GetI18NCategory("Error");
std::string glVersion = (const char *)glGetString(GL_VERSION);
std::string glRenderer = (const char *)glGetString(GL_RENDERER);
const std::string openGL_1 = "1.";
if (glRenderer == "GDI Generic" || glVersion.substr(0, openGL_1.size()) == openGL_1) {
//The error may come from 16-bit colour mode
//Check Colour depth
HDC dc = GetDC(NULL);
u32 colour_depth = GetDeviceCaps(dc, BITSPIXEL);
ReleaseDC(NULL, dc);
if (colour_depth != 32){
MessageBox(0, L"Please switch your display to 32-bit colour mode", L"OpenGL Error", MB_OK);
ExitProcess(1);
}
const char *defaultError = "Insufficient OpenGL driver support detected!\n\n"
"Your GPU reports that it does not support OpenGL 2.0. Would you like to try using DirectX 9 instead?\n\n"
"DirectX is currently compatible with less games, but on your GPU it may be the only choice.\n\n"
"Visit the forums at http://forums.ppsspp.org for more information.\n\n";
std::wstring versionDetected = ConvertUTF8ToWString(glVersion + "\n\n");
std::wstring error = ConvertUTF8ToWString(err->T("InsufficientOpenGLDriver", defaultError));
std::wstring title = ConvertUTF8ToWString(err->T("OpenGLDriverError", "OpenGL driver error"));
std::wstring combined = versionDetected + error;
bool yes = IDYES == MessageBox(hWnd, combined.c_str(), title.c_str(), MB_ICONERROR | MB_YESNO);
if (yes) {
// Change the config to D3D and restart.
g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D9;
g_Config.Save();
W32Util::ExitAndRestart();
}
// Avoid further error messages. Let's just bail, it's safe, and we can't continue.
ExitProcess(1);
}
//.........这里部分代码省略.........
bool DirectoryFileHandle::Open(std::string &basePath, std::string &fileName, FileAccess access, u32 &error)
{
error = 0;
#if HOST_IS_CASE_SENSITIVE
if (access & (FILEACCESS_APPEND|FILEACCESS_CREATE|FILEACCESS_WRITE))
{
DEBUG_LOG(FILESYS, "Checking case for path %s", fileName.c_str());
if ( ! FixPathCase(basePath, fileName, FPC_PATH_MUST_EXIST) )
return false; // or go on and attempt (for a better error code than just 0?)
}
// else we try fopen first (in case we're lucky) before simulating case insensitivity
#endif
std::string fullName = GetLocalPath(basePath,fileName);
DEBUG_LOG(FILESYS,"Actually opening %s", fullName.c_str());
// On the PSP, truncating doesn't lose data. If you seek later, you'll recover it.
// This is abnormal, so we deviate from the PSP's behavior and truncate on write/close.
// This means it's incorrectly not truncated before the write.
if (access & FILEACCESS_TRUNCATE) {
needsTrunc_ = 0;
}
//TODO: tests, should append seek to end of file? seeking in a file opened for append?
#ifdef _WIN32
// Convert parameters to Windows permissions and access
DWORD desired = 0;
DWORD sharemode = 0;
DWORD openmode = 0;
if (access & FILEACCESS_READ) {
desired |= GENERIC_READ;
sharemode |= FILE_SHARE_READ;
}
if (access & FILEACCESS_WRITE) {
desired |= GENERIC_WRITE;
sharemode |= FILE_SHARE_WRITE;
}
if (access & FILEACCESS_CREATE) {
openmode = OPEN_ALWAYS;
} else {
openmode = OPEN_EXISTING;
}
//Let's do it!
hFile = CreateFile(ConvertUTF8ToWString(fullName).c_str(), desired, sharemode, 0, openmode, 0, 0);
bool success = hFile != INVALID_HANDLE_VALUE;
if (!success) {
DWORD w32err = GetLastError();
if (w32err == ERROR_DISK_FULL || w32err == ERROR_NOT_ENOUGH_QUOTA) {
// This is returned when the disk is full.
I18NCategory *err = GetI18NCategory("Error");
osm.Show(err->T("Disk full while writing data"));
error = SCE_KERNEL_ERROR_ERRNO_NO_PERM;
}
}
#else
int flags = 0;
if (access & FILEACCESS_APPEND) {
flags |= O_APPEND;
}
if ((access & FILEACCESS_READ) && (access & FILEACCESS_WRITE)) {
flags |= O_RDWR;
} else if (access & FILEACCESS_READ) {
flags |= O_RDONLY;
} else if (access & FILEACCESS_WRITE) {
flags |= O_WRONLY;
}
if (access & FILEACCESS_CREATE) {
flags |= O_CREAT;
}
hFile = open(fullName.c_str(), flags, 0666);
bool success = hFile != -1;
#endif
#if HOST_IS_CASE_SENSITIVE
if (!success && !(access & FILEACCESS_CREATE)) {
if ( ! FixPathCase(basePath,fileName, FPC_PATH_MUST_EXIST) )
return 0; // or go on and attempt (for a better error code than just 0?)
fullName = GetLocalPath(basePath,fileName);
const char *fullNameC = fullName.c_str();
DEBUG_LOG(FILESYS, "Case may have been incorrect, second try opening %s (%s)", fullNameC, fileName.c_str());
// And try again with the correct case this time
#ifdef _WIN32
hFile = CreateFile(fullNameC, desired, sharemode, 0, openmode, 0, 0);
success = hFile != INVALID_HANDLE_VALUE;
#else
hFile = open(fullNameC, flags, 0666);
success = hFile != -1;
#endif
}
#endif
#ifndef _WIN32
if (success) {
struct stat st;
if (fstat(hFile, &st) == 0 && S_ISDIR(st.st_mode)) {
close(hFile);
//.........这里部分代码省略.........
请发表评论