/
erlang.spawn
/
fallout2-ce
Обзор
Документация
Войти
/
erlang.spawn
/
fallout2-ce
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
continious
src/input.cc
1 137 строк
27 KB
Mike Klaas
Use in-game gamma when generating screenshots (#469)
26 май 2026, 19:23
Не верифицирован
26 май 2026, 19:23
8afe4b3
Код
Авторство
О чём код?
#include "input.h" #include <SDL.h> #include <lodepng.h> #include "audio_engine.h" #include "color.h" #include "delay.h" #include "dinput.h" #include "draw.h" #include "game.h" #include "kb.h" #include "memory.h" #include "mouse.h" #include "sfall_kb_helpers.h" #include "sfall_script_hooks.h" #include "svga.h" #include "text_font.h" #include "touch.h" #include "win32.h" namespace fallout { typedef struct InputEvent { // This is either logical key or input event id, which can be either // character code pressed or some other numbers used throughout the // game interface. int logicalKey; int mouseX; int mouseY; } InputEvent; typedef struct RepeatInfo { // Time when appropriate key was pressed down or -1 if it's up. int tick; int repeatCount; } RepeatInfo; typedef struct TickerListNode { int flags; TickerProc* proc; struct TickerListNode* next; } TickerListNode; static int dequeueInputEvent(); static void screenshotBlitter(unsigned char* src, int src_pitch, int a3, int x, int y, int width, int height, int dest_x, int dest_y); static void buildNormalizedQwertyKeys(); static void _GNW95_process_key(KeyboardData* data); static int inputGetHookMouseButton(int sdlButton); static void inputHandleMouseClickHook(int sdlButton, bool pressed); // 0x51E23C GNW95_repeat_rate static int gKeyboardKeyRepeatRate = 80; // 0x51E240 GNW95_repeat_delay static int gKeyboardKeyRepeatDelay = 500; // A map of SDL_SCANCODE_* constants normalized for QWERTY keyboard. // // 0x6ABC70 GNW95_key_map static int gNormalizedQwertyKeys[SDL_NUM_SCANCODES]; // Ring buffer of input events. // // Looks like this buffer does not support overwriting of values. Once the // buffer is full it will not overwrite values until they are dequeued. // // 0x6ABD70 input_buffer static InputEvent gInputEventQueue[40]; // 0x6ABF50 GNW95_key_time_stamps static RepeatInfo _GNW95_key_time_stamps[SDL_NUM_SCANCODES]; // 0x6AC750 input_mx static int _input_mx; // 0x6AC754 input_my static int _input_my; // 0x6AC760 screendump_key static int gScreenshotKeyCode; // 0x6AC76C screendump_func static ScreenshotHandler* gScreenshotHandler; // 0x6AC770 input_get static int gInputEventQueueReadIndex; // 0x6AC774 screendump_buf static unsigned char* gScreenshotBuffer; // 0x6AC77C input_put static int gInputEventQueueWriteIndex; // 0x6AC780 bk_disabled static bool gRunLoopDisabled; // 0x6AC784 bk_list static TickerListNode* gTickerListHead; // 0x6AC788 bk_process_time static unsigned int gTickerLastTimestamp; // global for inventoryOpenUseItemOn inventory to prevent click through bug bool gBlockMouseUpEvent = false; static int inputGetHookMouseButton(int sdlButton) { switch (sdlButton) { case SDL_BUTTON_LEFT: return 0; case SDL_BUTTON_RIGHT: return 1; case SDL_BUTTON_MIDDLE: return 2; case SDL_BUTTON_X1: return 3; case SDL_BUTTON_X2: return 4; default: if (sdlButton >= 6 && sdlButton <= 8) { return sdlButton - 1; } return -1; } } static void inputHandleMouseClickHook(int sdlButton, bool pressed) { if (!gGameLoaded) return; int hookButton = inputGetHookMouseButton(sdlButton); if (hookButton == -1) return; ScriptHookCall(HOOK_MOUSECLICK, 0, { pressed ? 1 : 0, hookButton }).call(); } // 0x4C8A70 int inputInit() { if (!directInputInit()) { return -1; } if (keyboardInit() == -1) { return -1; } if (mouseInit() == -1) { return -1; } if (_GNW95_input_init() == -1) { return -1; } buildNormalizedQwertyKeys(); _GNW95_clear_time_stamps(); gInputEventQueueWriteIndex = 0; gInputEventQueueReadIndex = -1; _input_mx = -1; _input_my = -1; gRunLoopDisabled = 0; gScreenshotHandler = screenshotHandlerDefaultImpl; gTickerListHead = nullptr; gScreenshotKeyCode = KEY_ALT_C; return 0; } // 0x4C8B40 void inputExit() { _GNW95_input_init(); mouseFree(); keyboardFree(); directInputFree(); TickerListNode* curr = gTickerListHead; while (curr != nullptr) { TickerListNode* next = curr->next; internal_free(curr); curr = next; } } // 0x4C8B78 int inputGetInput() { int v3; _GNW95_process_message(); if (!gProgramIsActive) { _GNW95_lost_focus(); } _process_bk(); v3 = dequeueInputEvent(); if (v3 == -1 && mouseGetEvent() & 0x33) { mouseGetPosition(&_input_mx, &_input_my); return -2; } else { return _GNW_check_menu_bars(v3); } return -1; } // 0x4C8BC8 void get_input_position(int* x, int* y) { *x = _input_mx; *y = _input_my; } // 0x4C8BDC void _process_bk() { int v1; tickersExecute(); _mouse_info(); v1 = _win_check_all_buttons(); if (v1 != -1) { enqueueInputEvent(v1); return; } v1 = _kb_getch(); if (v1 != -1) { enqueueInputEvent(v1); return; } } // 0x4C8C04 void enqueueInputEvent(int logicalKey) { if (logicalKey == -1) { return; } if (logicalKey == gScreenshotKeyCode) { takeScreenshot(); return; } if (gInputEventQueueWriteIndex == gInputEventQueueReadIndex) { return; } InputEvent* inputEvent = &(gInputEventQueue[gInputEventQueueWriteIndex]); inputEvent->logicalKey = logicalKey; mouseGetPosition(&(inputEvent->mouseX), &(inputEvent->mouseY)); gInputEventQueueWriteIndex++; if (gInputEventQueueWriteIndex == 40) { gInputEventQueueWriteIndex = 0; return; } if (gInputEventQueueReadIndex == -1) { gInputEventQueueReadIndex = 0; } } // 0x4C8C9C static int dequeueInputEvent() { if (gInputEventQueueReadIndex == -1) { return -1; } InputEvent* inputEvent = &(gInputEventQueue[gInputEventQueueReadIndex]); int eventCode = inputEvent->logicalKey; _input_mx = inputEvent->mouseX; _input_my = inputEvent->mouseY; gInputEventQueueReadIndex++; if (gInputEventQueueReadIndex == 40) { gInputEventQueueReadIndex = 0; } if (gInputEventQueueReadIndex == gInputEventQueueWriteIndex) { gInputEventQueueReadIndex = -1; gInputEventQueueWriteIndex = 0; } return eventCode; } // 0x4C8D04 void inputEventQueueReset() { gInputEventQueueReadIndex = -1; gInputEventQueueWriteIndex = 0; SDL_Event e; while (SDL_PollEvent(&e)) { } // Clear all input events sfall_kb_clear_synthetic_key_events(); } // 0x4C8D1C void tickersExecute() { if (gRunLoopDisabled) { return; } gTickerLastTimestamp = SDL_GetTicks(); TickerListNode* curr = gTickerListHead; TickerListNode** currPtr = &(gTickerListHead); while (curr != nullptr) { TickerListNode* next = curr->next; if (curr->flags & 1) { *currPtr = next; internal_free(curr); } else { curr->proc(); currPtr = &(curr->next); } curr = next; } } // 0x4C8D74 void tickersAdd(TickerProc* proc) { TickerListNode* curr = gTickerListHead; while (curr != nullptr) { if (curr->proc == proc) { if ((curr->flags & 0x01) != 0) { curr->flags &= ~0x01; return; } } curr = curr->next; } curr = (TickerListNode*)internal_malloc(sizeof(*curr)); curr->flags = 0; curr->proc = proc; curr->next = gTickerListHead; gTickerListHead = curr; } // 0x4C8DC4 void tickersRemove(TickerProc* proc) { TickerListNode* curr = gTickerListHead; while (curr != nullptr) { if (curr->proc == proc) { curr->flags |= 0x01; return; } curr = curr->next; } } // 0x4C8DE4 void tickersEnable() { gRunLoopDisabled = false; } // 0x4C8DF0 void tickersDisable() { gRunLoopDisabled = true; } // 0x4C8F4C void takeScreenshot() { int width = _scr_size.right - _scr_size.left + 1; int height = _scr_size.bottom - _scr_size.top + 1; gScreenshotBuffer = (unsigned char*)internal_malloc(width * height); if (gScreenshotBuffer == nullptr) { return; } WINDOWDRAWINGPROC old_src = _scr_blit; _scr_blit = screenshotBlitter; WINDOWDRAWINGPROC old_mouse = _mouse_blit; _mouse_blit = screenshotBlitter; WindowDrawingProc2* old_mouse_trans = _mouse_blit_trans; _mouse_blit_trans = nullptr; windowRefreshAll(&_scr_size); _mouse_blit_trans = old_mouse_trans; _mouse_blit = old_mouse; _scr_blit = old_src; // Save screenshots with the palette currently presented on screen so the // exported colors match brightness-adjusted rendering. unsigned char* palette = gSdlSurface != nullptr ? directDrawGetPalette() : _getSystemPalette(); gScreenshotHandler(width, height, gScreenshotBuffer, palette); internal_free(gScreenshotBuffer); } // 0x4C8FF0 static void screenshotBlitter(unsigned char* src, int srcPitch, int _, int srcX, int srcY, int width, int height, int destX, int destY) { int destWidth = _scr_size.right - _scr_size.left + 1; blitBufferToBuffer(src + srcPitch * srcY + srcX, width, height, srcPitch, gScreenshotBuffer + destWidth * destY + destX, destWidth); } // 0x4C9048 int screenshotHandlerDefaultImpl(int width, int height, unsigned char* data, unsigned char* palette) { char fileName[16]; FILE* stream; int index; unsigned int intValue; unsigned short shortValue; for (index = 0; index < 100000; index++) { snprintf(fileName, sizeof(fileName), "scr%.5d.bmp", index); stream = compat_fopen(fileName, "rb"); if (stream == nullptr) { break; } fclose(stream); } if (index == 100000) { return -1; } stream = compat_fopen(fileName, "wb"); if (stream == nullptr) { return -1; } // bfType shortValue = 0x4D42; fwrite(&shortValue, sizeof(shortValue), 1, stream); // bfSize // 14 - sizeof(BITMAPFILEHEADER) // 40 - sizeof(BITMAPINFOHEADER) // 1024 - sizeof(RGBQUAD) * 256 intValue = width * height + 14 + 40 + 1024; fwrite(&intValue, sizeof(intValue), 1, stream); // bfReserved1 shortValue = 0; fwrite(&shortValue, sizeof(shortValue), 1, stream); // bfReserved2 shortValue = 0; fwrite(&shortValue, sizeof(shortValue), 1, stream); // bfOffBits intValue = 14 + 40 + 1024; fwrite(&intValue, sizeof(intValue), 1, stream); // biSize intValue = 40; fwrite(&intValue, sizeof(intValue), 1, stream); // biWidth intValue = width; fwrite(&intValue, sizeof(intValue), 1, stream); // biHeight intValue = height; fwrite(&intValue, sizeof(intValue), 1, stream); // biPlanes shortValue = 1; fwrite(&shortValue, sizeof(shortValue), 1, stream); // biBitCount shortValue = 8; fwrite(&shortValue, sizeof(shortValue), 1, stream); // biCompression intValue = 0; fwrite(&intValue, sizeof(intValue), 1, stream); // biSizeImage intValue = 0; fwrite(&intValue, sizeof(intValue), 1, stream); // biXPelsPerMeter intValue = 0; fwrite(&intValue, sizeof(intValue), 1, stream); // biYPelsPerMeter intValue = 0; fwrite(&intValue, sizeof(intValue), 1, stream); // biClrUsed intValue = 0; fwrite(&intValue, sizeof(intValue), 1, stream); // biClrImportant intValue = 0; fwrite(&intValue, sizeof(intValue), 1, stream); for (int index = 0; index < 256; index++) { unsigned char rgbReserved = 0; unsigned char rgbRed = palette[index * 3] << 2; unsigned char rgbGreen = palette[index * 3 + 1] << 2; unsigned char rgbBlue = palette[index * 3 + 2] << 2; fwrite(&rgbBlue, sizeof(rgbBlue), 1, stream); fwrite(&rgbGreen, sizeof(rgbGreen), 1, stream); fwrite(&rgbRed, sizeof(rgbRed), 1, stream); fwrite(&rgbReserved, sizeof(rgbReserved), 1, stream); } for (int y = height - 1; y >= 0; y--) { unsigned char* dataPtr = data + y * width; fwrite(dataPtr, 1, width, stream); } fflush(stream); fclose(stream); return 0; } int screenshotHandlerPngImpl(int width, int height, unsigned char* data, unsigned char* palette) { char fileName[16]; FILE* stream; int fileIndex; for (fileIndex = 0; fileIndex < 100000; fileIndex++) { snprintf(fileName, sizeof(fileName), "scr%.5d.png", fileIndex); stream = compat_fopen(fileName, "rb"); if (stream == nullptr) { break; } fclose(stream); } if (fileIndex == 100000) { return -1; } stream = compat_fopen(fileName, "wb"); if (stream == nullptr) { return -1; } fclose(stream); int imgLen = width * height; std::vector<unsigned char> image(imgLen * 3); for (size_t i = 0; i < imgLen; i++) { image[i * 3] = palette[data[i] * 3] << 2; image[i * 3 + 1] = palette[data[i] * 3 + 1] << 2; image[i * 3 + 2] = palette[data[i] * 3 + 2] << 2; } unsigned error = lodepng::encode(fileName, image, width, height, LCT_RGB, 8); if (error) { return -1; } return 0; } // 0x4C9358 void screenshotHandlerConfigure(int keyCode, ScreenshotHandler* handler) { gScreenshotKeyCode = keyCode; if (handler == nullptr) { handler = screenshotHandlerDefaultImpl; } gScreenshotHandler = handler; } // 0x4C9370 unsigned int getTicks() { return SDL_GetTicks(); } // 0x4C937C void inputPauseForTocks(unsigned int delay) { // NOTE: Uninline. unsigned int start = getTicks(); unsigned int end = getTicks(); // NOTE: Uninline. unsigned int diff = getTicksBetween(end, start); while (diff < delay) { _process_bk(); end = getTicks(); // NOTE: Uninline. diff = getTicksBetween(end, start); } } // 0x4C93B8 void inputBlockForTocks(unsigned int ms) { delay_ms(ms); } // 0x4C93E0 unsigned int getTicksSince(unsigned int start) { unsigned int end = SDL_GetTicks(); // NOTE: Uninline. return getTicksBetween(end, start); } // 0x4C9400 unsigned int getTicksBetween(unsigned int end, unsigned int start) { if (start > end) { return INT_MAX; } else { return end - start; } } // 0x4C9410 unsigned int _get_bk_time() { return gTickerLastTimestamp; } // 0x4C9490 static void buildNormalizedQwertyKeys() { int* keys = gNormalizedQwertyKeys; int k; keys[SDL_SCANCODE_ESCAPE] = SDL_SCANCODE_ESCAPE; keys[SDL_SCANCODE_1] = SDL_SCANCODE_1; keys[SDL_SCANCODE_2] = SDL_SCANCODE_2; keys[SDL_SCANCODE_3] = SDL_SCANCODE_3; keys[SDL_SCANCODE_4] = SDL_SCANCODE_4; keys[SDL_SCANCODE_5] = SDL_SCANCODE_5; keys[SDL_SCANCODE_6] = SDL_SCANCODE_6; keys[SDL_SCANCODE_7] = SDL_SCANCODE_7; keys[SDL_SCANCODE_8] = SDL_SCANCODE_8; keys[SDL_SCANCODE_9] = SDL_SCANCODE_9; keys[SDL_SCANCODE_0] = SDL_SCANCODE_0; switch (gKeyboardLayout) { case 0: k = SDL_SCANCODE_MINUS; break; case 1: k = SDL_SCANCODE_6; break; default: k = SDL_SCANCODE_SLASH; break; } keys[SDL_SCANCODE_MINUS] = k; switch (gKeyboardLayout) { case 1: k = SDL_SCANCODE_0; break; default: k = SDL_SCANCODE_EQUALS; break; } keys[SDL_SCANCODE_EQUALS] = k; keys[SDL_SCANCODE_BACKSPACE] = SDL_SCANCODE_BACKSPACE; keys[SDL_SCANCODE_TAB] = SDL_SCANCODE_TAB; switch (gKeyboardLayout) { case 1: k = SDL_SCANCODE_A; break; default: k = SDL_SCANCODE_Q; break; } keys[SDL_SCANCODE_Q] = k; switch (gKeyboardLayout) { case 1: k = SDL_SCANCODE_Z; break; default: k = SDL_SCANCODE_W; break; } keys[SDL_SCANCODE_W] = k; keys[SDL_SCANCODE_E] = SDL_SCANCODE_E; keys[SDL_SCANCODE_R] = SDL_SCANCODE_R; keys[SDL_SCANCODE_T] = SDL_SCANCODE_T; switch (gKeyboardLayout) { case 0: case 1: case 3: case 4: k = SDL_SCANCODE_Y; break; default: k = SDL_SCANCODE_Z; break; } keys[SDL_SCANCODE_Y] = k; keys[SDL_SCANCODE_U] = SDL_SCANCODE_U; keys[SDL_SCANCODE_I] = SDL_SCANCODE_I; keys[SDL_SCANCODE_O] = SDL_SCANCODE_O; keys[SDL_SCANCODE_P] = SDL_SCANCODE_P; switch (gKeyboardLayout) { case 0: case 3: case 4: k = SDL_SCANCODE_LEFTBRACKET; break; case 1: k = SDL_SCANCODE_5; break; default: k = SDL_SCANCODE_8; break; } keys[SDL_SCANCODE_LEFTBRACKET] = k; switch (gKeyboardLayout) { case 0: case 3: case 4: k = SDL_SCANCODE_RIGHTBRACKET; break; case 1: k = SDL_SCANCODE_MINUS; break; default: k = SDL_SCANCODE_9; break; } keys[SDL_SCANCODE_RIGHTBRACKET] = k; keys[SDL_SCANCODE_RETURN] = SDL_SCANCODE_RETURN; keys[SDL_SCANCODE_LCTRL] = SDL_SCANCODE_LCTRL; switch (gKeyboardLayout) { case 1: k = SDL_SCANCODE_Q; break; default: k = SDL_SCANCODE_A; break; } keys[SDL_SCANCODE_A] = k; keys[SDL_SCANCODE_S] = SDL_SCANCODE_S; keys[SDL_SCANCODE_D] = SDL_SCANCODE_D; keys[SDL_SCANCODE_F] = SDL_SCANCODE_F; keys[SDL_SCANCODE_G] = SDL_SCANCODE_G; keys[SDL_SCANCODE_H] = SDL_SCANCODE_H; keys[SDL_SCANCODE_J] = SDL_SCANCODE_J; keys[SDL_SCANCODE_K] = SDL_SCANCODE_K; keys[SDL_SCANCODE_L] = SDL_SCANCODE_L; switch (gKeyboardLayout) { case 0: k = SDL_SCANCODE_SEMICOLON; break; default: k = SDL_SCANCODE_COMMA; break; } keys[SDL_SCANCODE_SEMICOLON] = k; switch (gKeyboardLayout) { case 0: k = SDL_SCANCODE_APOSTROPHE; break; case 1: k = SDL_SCANCODE_4; break; default: k = SDL_SCANCODE_MINUS; break; } keys[SDL_SCANCODE_APOSTROPHE] = k; switch (gKeyboardLayout) { case 0: k = SDL_SCANCODE_GRAVE; break; case 1: k = SDL_SCANCODE_2; break; case 3: case 4: k = 0; break; default: k = SDL_SCANCODE_RIGHTBRACKET; break; } keys[SDL_SCANCODE_GRAVE] = k; keys[SDL_SCANCODE_LSHIFT] = SDL_SCANCODE_LSHIFT; switch (gKeyboardLayout) { case 0: k = SDL_SCANCODE_BACKSLASH; break; case 1: k = SDL_SCANCODE_8; break; case 3: case 4: k = SDL_SCANCODE_GRAVE; break; default: k = SDL_SCANCODE_Y; break; } keys[SDL_SCANCODE_BACKSLASH] = k; switch (gKeyboardLayout) { case 0: case 3: case 4: k = SDL_SCANCODE_Z; break; case 1: k = SDL_SCANCODE_W; break; default: k = SDL_SCANCODE_Y; break; } keys[SDL_SCANCODE_Z] = k; keys[SDL_SCANCODE_X] = SDL_SCANCODE_X; keys[SDL_SCANCODE_C] = SDL_SCANCODE_C; keys[SDL_SCANCODE_V] = SDL_SCANCODE_V; keys[SDL_SCANCODE_B] = SDL_SCANCODE_B; keys[SDL_SCANCODE_N] = SDL_SCANCODE_N; switch (gKeyboardLayout) { case 1: k = SDL_SCANCODE_SEMICOLON; break; default: k = SDL_SCANCODE_M; break; } keys[SDL_SCANCODE_M] = k; switch (gKeyboardLayout) { case 1: k = SDL_SCANCODE_M; break; default: k = SDL_SCANCODE_COMMA; break; } keys[SDL_SCANCODE_COMMA] = k; switch (gKeyboardLayout) { case 1: k = SDL_SCANCODE_COMMA; break; default: k = SDL_SCANCODE_PERIOD; break; } keys[SDL_SCANCODE_PERIOD] = k; switch (gKeyboardLayout) { case 0: k = SDL_SCANCODE_SLASH; break; case 1: k = SDL_SCANCODE_PERIOD; break; default: k = SDL_SCANCODE_7; break; } keys[SDL_SCANCODE_SLASH] = k; keys[SDL_SCANCODE_RSHIFT] = SDL_SCANCODE_RSHIFT; keys[SDL_SCANCODE_KP_MULTIPLY] = SDL_SCANCODE_KP_MULTIPLY; keys[SDL_SCANCODE_SPACE] = SDL_SCANCODE_SPACE; keys[SDL_SCANCODE_LALT] = SDL_SCANCODE_LALT; keys[SDL_SCANCODE_CAPSLOCK] = SDL_SCANCODE_CAPSLOCK; keys[SDL_SCANCODE_F1] = SDL_SCANCODE_F1; keys[SDL_SCANCODE_F2] = SDL_SCANCODE_F2; keys[SDL_SCANCODE_F3] = SDL_SCANCODE_F3; keys[SDL_SCANCODE_F4] = SDL_SCANCODE_F4; keys[SDL_SCANCODE_F5] = SDL_SCANCODE_F5; keys[SDL_SCANCODE_F6] = SDL_SCANCODE_F6; keys[SDL_SCANCODE_F7] = SDL_SCANCODE_F7; keys[SDL_SCANCODE_F8] = SDL_SCANCODE_F8; keys[SDL_SCANCODE_F9] = SDL_SCANCODE_F9; keys[SDL_SCANCODE_F10] = SDL_SCANCODE_F10; keys[SDL_SCANCODE_NUMLOCKCLEAR] = SDL_SCANCODE_NUMLOCKCLEAR; keys[SDL_SCANCODE_SCROLLLOCK] = SDL_SCANCODE_SCROLLLOCK; keys[SDL_SCANCODE_KP_7] = SDL_SCANCODE_KP_7; keys[SDL_SCANCODE_KP_9] = SDL_SCANCODE_KP_9; keys[SDL_SCANCODE_KP_8] = SDL_SCANCODE_KP_8; keys[SDL_SCANCODE_KP_MINUS] = SDL_SCANCODE_KP_MINUS; keys[SDL_SCANCODE_KP_4] = SDL_SCANCODE_KP_4; keys[SDL_SCANCODE_KP_5] = SDL_SCANCODE_KP_5; keys[SDL_SCANCODE_KP_6] = SDL_SCANCODE_KP_6; keys[SDL_SCANCODE_KP_PLUS] = SDL_SCANCODE_KP_PLUS; keys[SDL_SCANCODE_KP_1] = SDL_SCANCODE_KP_1; keys[SDL_SCANCODE_KP_2] = SDL_SCANCODE_KP_2; keys[SDL_SCANCODE_KP_3] = SDL_SCANCODE_KP_3; keys[SDL_SCANCODE_KP_0] = SDL_SCANCODE_KP_0; keys[SDL_SCANCODE_KP_DECIMAL] = SDL_SCANCODE_KP_DECIMAL; keys[SDL_SCANCODE_F11] = SDL_SCANCODE_F11; keys[SDL_SCANCODE_F12] = SDL_SCANCODE_F12; keys[SDL_SCANCODE_F13] = -1; keys[SDL_SCANCODE_F14] = -1; keys[SDL_SCANCODE_F15] = -1; // keys[DIK_KANA] = -1; // keys[DIK_CONVERT] = -1; // keys[DIK_NOCONVERT] = -1; // keys[DIK_YEN] = -1; keys[SDL_SCANCODE_KP_EQUALS] = -1; // keys[DIK_PREVTRACK] = -1; // keys[DIK_AT] = -1; // keys[DIK_COLON] = -1; // keys[DIK_UNDERLINE] = -1; // keys[DIK_KANJI] = -1; keys[SDL_SCANCODE_STOP] = -1; // keys[DIK_AX] = -1; // keys[DIK_UNLABELED] = -1; keys[SDL_SCANCODE_KP_ENTER] = SDL_SCANCODE_KP_ENTER; keys[SDL_SCANCODE_RCTRL] = SDL_SCANCODE_RCTRL; keys[SDL_SCANCODE_KP_COMMA] = -1; keys[SDL_SCANCODE_KP_DIVIDE] = SDL_SCANCODE_KP_DIVIDE; // keys[DIK_SYSRQ] = 84; keys[SDL_SCANCODE_RALT] = SDL_SCANCODE_RALT; keys[SDL_SCANCODE_HOME] = SDL_SCANCODE_HOME; keys[SDL_SCANCODE_UP] = SDL_SCANCODE_UP; keys[SDL_SCANCODE_PRIOR] = SDL_SCANCODE_PRIOR; keys[SDL_SCANCODE_LEFT] = SDL_SCANCODE_LEFT; keys[SDL_SCANCODE_RIGHT] = SDL_SCANCODE_RIGHT; keys[SDL_SCANCODE_END] = SDL_SCANCODE_END; keys[SDL_SCANCODE_DOWN] = SDL_SCANCODE_DOWN; keys[SDL_SCANCODE_PAGEUP] = SDL_SCANCODE_PAGEUP; keys[SDL_SCANCODE_PAGEDOWN] = SDL_SCANCODE_PAGEDOWN; keys[SDL_SCANCODE_INSERT] = SDL_SCANCODE_INSERT; keys[SDL_SCANCODE_DELETE] = SDL_SCANCODE_DELETE; keys[SDL_SCANCODE_LGUI] = -1; keys[SDL_SCANCODE_RGUI] = -1; keys[SDL_SCANCODE_APPLICATION] = -1; } // 0x4C9C20 int _GNW95_input_init() { return 0; } // 0x4C9CF0 void _GNW95_process_message() { // We need to process event loop even if program is not active or keyboard // is disabled, because if we ignore it, we'll never be able to reactivate // it again. KeyboardData keyboardData; SDL_Event e; while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_MOUSEMOTION: case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: case SDL_MOUSEWHEEL: if (e.type == SDL_MOUSEBUTTONDOWN || e.type == SDL_MOUSEBUTTONUP) { inputHandleMouseClickHook(e.button.button, e.type == SDL_MOUSEBUTTONDOWN); } handleMouseEvent(&e); break; case SDL_FINGERDOWN: touch_handle_start(&(e.tfinger)); break; case SDL_FINGERMOTION: touch_handle_move(&(e.tfinger)); break; case SDL_FINGERUP: touch_handle_end(&(e.tfinger)); break; case SDL_KEYDOWN: case SDL_KEYUP: { keyboardData.key = e.key.keysym.scancode; keyboardData.down = (e.key.state & SDL_PRESSED) != 0; bool syntheticSfallKey = sfall_kb_consume_synthetic_key_event(keyboardData.key, keyboardData.down); if (!keyboardIsDisabled()) { if (!e.key.repeat && !syntheticSfallKey) { int keyOverride = sfall_kb_handle_key_pressed(keyboardData.key, keyboardData.down); if (keyOverride != SDL_SCANCODE_UNKNOWN) { keyboardData.key = keyOverride; } } _GNW95_process_key(&keyboardData); } break; } case SDL_WINDOWEVENT: switch (e.window.event) { case SDL_WINDOWEVENT_EXPOSED: windowRefreshAll(&_scr_size); break; case SDL_WINDOWEVENT_SIZE_CHANGED: handleWindowSizeChanged(); break; case SDL_WINDOWEVENT_FOCUS_GAINED: gProgramIsActive = true; windowRefreshAll(&_scr_size); audioEngineResume(); break; case SDL_WINDOWEVENT_FOCUS_LOST: gProgramIsActive = false; audioEnginePause(); break; } break; case SDL_QUIT: exit(EXIT_SUCCESS); break; } } touch_process_gesture(); if (gProgramIsActive && !keyboardIsDisabled()) { // NOTE: Uninline int tick = getTicks(); for (int key = 0; key < SDL_NUM_SCANCODES; key++) { RepeatInfo* ptr = &(_GNW95_key_time_stamps[key]); if (ptr->tick != -1) { int elapsedTime = ptr->tick > tick ? INT_MAX : tick - ptr->tick; int delay = ptr->repeatCount == 0 ? gKeyboardKeyRepeatDelay : gKeyboardKeyRepeatRate; if (elapsedTime > delay) { keyboardData.key = key; keyboardData.down = 1; _GNW95_process_key(&keyboardData); ptr->tick = tick; ptr->repeatCount++; } } } } } // 0x4C9DF0 void _GNW95_clear_time_stamps() { for (int index = 0; index < SDL_NUM_SCANCODES; index++) { _GNW95_key_time_stamps[index].tick = -1; _GNW95_key_time_stamps[index].repeatCount = 0; } } // 0x4C9E14 static void _GNW95_process_key(KeyboardData* data) { // Use originally pressed scancode, not qwerty-remapped one, for tracking // timestamps, see usage from |_GNW95_process_message|. int scanCode = data->key; data->key = gNormalizedQwertyKeys[data->key]; RepeatInfo* ptr = &(_GNW95_key_time_stamps[scanCode]); if (data->down == 1) { ptr->tick = getTicks(); ptr->repeatCount = 0; } else { ptr->tick = -1; } // Ignore keys which were remapped to -1. if (data->key == -1) { return; } _kb_simulate_key(data); } // 0x4C9EEC void _GNW95_lost_focus() { while (!gProgramIsActive) { _GNW95_process_message(); SDL_Delay(125); } } void beginTextInput() { SDL_StartTextInput(); } void endTextInput() { SDL_StopTextInput(); } } // namespace fallout