2022-10-04 23:23:27 -07:00
|
|
|
#include "input.h"
|
|
|
|
|
|
|
|
#include <SDL.h>
|
|
|
|
|
|
|
|
#include "audio_engine.h"
|
|
|
|
#include "color.h"
|
2022-10-04 23:54:46 -07:00
|
|
|
#include "dinput.h"
|
2022-10-04 23:23:27 -07:00
|
|
|
#include "draw.h"
|
|
|
|
#include "kb.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "mouse.h"
|
2022-10-05 00:35:05 -07:00
|
|
|
#include "svga.h"
|
2022-10-04 23:23:27 -07:00
|
|
|
#include "text_font.h"
|
|
|
|
#include "vcr.h"
|
|
|
|
#include "win32.h"
|
|
|
|
|
|
|
|
namespace fallout {
|
|
|
|
|
2022-10-04 23:54:46 -07:00
|
|
|
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 pauseGame();
|
|
|
|
static int pauseHandlerDefaultImpl();
|
|
|
|
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);
|
|
|
|
|
2022-10-04 23:23:27 -07:00
|
|
|
static void idleImpl();
|
|
|
|
|
|
|
|
// 0x51E234
|
2022-10-04 23:54:46 -07:00
|
|
|
static IdleFunc* _idle_func = NULL;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x51E238
|
2022-10-04 23:54:46 -07:00
|
|
|
static FocusFunc* _focus_func = NULL;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x51E23C
|
2022-10-04 23:54:46 -07:00
|
|
|
static int gKeyboardKeyRepeatRate = 80;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x51E240
|
2022-10-04 23:54:46 -07:00
|
|
|
static int gKeyboardKeyRepeatDelay = 500;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// A map of SDL_SCANCODE_* constants normalized for QWERTY keyboard.
|
|
|
|
//
|
|
|
|
// 0x6ABC70
|
2022-10-04 23:54:46 -07:00
|
|
|
static int gNormalizedQwertyKeys[SDL_NUM_SCANCODES];
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 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
|
2022-10-04 23:54:46 -07:00
|
|
|
static InputEvent gInputEventQueue[40];
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6ABF50
|
2022-10-04 23:54:46 -07:00
|
|
|
static RepeatInfo _GNW95_key_time_stamps[SDL_NUM_SCANCODES];
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC750
|
2022-10-04 23:54:46 -07:00
|
|
|
static int _input_mx;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC754
|
2022-10-04 23:54:46 -07:00
|
|
|
static int _input_my;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC75C
|
2022-10-04 23:54:46 -07:00
|
|
|
static bool gPaused;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC760
|
2022-10-04 23:54:46 -07:00
|
|
|
static int gScreenshotKeyCode;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC764
|
2022-10-04 23:54:46 -07:00
|
|
|
static int _using_msec_timer;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC768
|
2022-10-04 23:54:46 -07:00
|
|
|
static int gPauseKeyCode;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC76C
|
2022-10-04 23:54:46 -07:00
|
|
|
static ScreenshotHandler* gScreenshotHandler;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC770
|
2022-10-04 23:54:46 -07:00
|
|
|
static int gInputEventQueueReadIndex;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC774
|
2022-10-04 23:54:46 -07:00
|
|
|
static unsigned char* gScreenshotBuffer;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC778
|
2022-10-04 23:54:46 -07:00
|
|
|
static PauseHandler* gPauseHandler;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC77C
|
2022-10-04 23:54:46 -07:00
|
|
|
static int gInputEventQueueWriteIndex;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC780
|
2022-10-04 23:54:46 -07:00
|
|
|
static bool gRunLoopDisabled;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC784
|
2022-10-04 23:54:46 -07:00
|
|
|
static TickerListNode* gTickerListHead;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x6AC788
|
2022-10-04 23:54:46 -07:00
|
|
|
static unsigned int gTickerLastTimestamp;
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// 0x4C8A70
|
2022-10-05 00:11:47 -07:00
|
|
|
int inputInit(int a1)
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
|
|
|
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();
|
|
|
|
|
|
|
|
_using_msec_timer = a1;
|
|
|
|
gInputEventQueueWriteIndex = 0;
|
|
|
|
gInputEventQueueReadIndex = -1;
|
|
|
|
_input_mx = -1;
|
|
|
|
_input_my = -1;
|
|
|
|
gRunLoopDisabled = 0;
|
|
|
|
gPaused = false;
|
|
|
|
gPauseKeyCode = KEY_ALT_P;
|
|
|
|
gPauseHandler = pauseHandlerDefaultImpl;
|
|
|
|
gScreenshotHandler = screenshotHandlerDefaultImpl;
|
|
|
|
gTickerListHead = NULL;
|
|
|
|
gScreenshotKeyCode = KEY_ALT_C;
|
|
|
|
|
|
|
|
// SFALL: Set idle function.
|
|
|
|
// CE: Prevents frying CPU when window is not focused.
|
|
|
|
inputSetIdleFunc(idleImpl);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C8B40
|
2022-10-05 00:11:47 -07:00
|
|
|
void inputExit()
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
|
|
|
_GNW95_input_init();
|
|
|
|
mouseFree();
|
|
|
|
keyboardFree();
|
|
|
|
directInputFree();
|
|
|
|
|
|
|
|
TickerListNode* curr = gTickerListHead;
|
|
|
|
while (curr != NULL) {
|
|
|
|
TickerListNode* next = curr->next;
|
|
|
|
internal_free(curr);
|
|
|
|
curr = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C8B78
|
2022-10-05 00:11:47 -07:00
|
|
|
int inputGetInput()
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C8BDC
|
|
|
|
void _process_bk()
|
|
|
|
{
|
|
|
|
int v1;
|
|
|
|
|
|
|
|
tickersExecute();
|
|
|
|
|
|
|
|
if (vcrUpdate() != 3) {
|
|
|
|
_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 a1)
|
|
|
|
{
|
|
|
|
if (a1 == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a1 == gPauseKeyCode) {
|
|
|
|
pauseGame();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a1 == gScreenshotKeyCode) {
|
|
|
|
takeScreenshot();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gInputEventQueueWriteIndex == gInputEventQueueReadIndex) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
InputEvent* inputEvent = &(gInputEventQueue[gInputEventQueueWriteIndex]);
|
|
|
|
inputEvent->logicalKey = a1;
|
|
|
|
|
|
|
|
mouseGetPosition(&(inputEvent->mouseX), &(inputEvent->mouseY));
|
|
|
|
|
|
|
|
gInputEventQueueWriteIndex++;
|
|
|
|
|
|
|
|
if (gInputEventQueueWriteIndex == 40) {
|
|
|
|
gInputEventQueueWriteIndex = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gInputEventQueueReadIndex == -1) {
|
|
|
|
gInputEventQueueReadIndex = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C8C9C
|
2022-10-04 23:54:46 -07:00
|
|
|
static int dequeueInputEvent()
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C8D1C
|
|
|
|
void tickersExecute()
|
|
|
|
{
|
|
|
|
if (gPaused) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gRunLoopDisabled) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gTickerLastTimestamp = SDL_GetTicks();
|
|
|
|
|
|
|
|
TickerListNode* curr = gTickerListHead;
|
|
|
|
TickerListNode** currPtr = &(gTickerListHead);
|
|
|
|
|
|
|
|
while (curr != NULL) {
|
|
|
|
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 != NULL) {
|
|
|
|
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 != NULL) {
|
|
|
|
if (curr->proc == proc) {
|
|
|
|
curr->flags |= 0x01;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
curr = curr->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C8DE4
|
|
|
|
void tickersEnable()
|
|
|
|
{
|
|
|
|
gRunLoopDisabled = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C8DF0
|
|
|
|
void tickersDisable()
|
|
|
|
{
|
|
|
|
gRunLoopDisabled = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C8DFC
|
2022-10-04 23:54:46 -07:00
|
|
|
static void pauseGame()
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
|
|
|
if (!gPaused) {
|
|
|
|
gPaused = true;
|
|
|
|
|
|
|
|
int win = gPauseHandler();
|
|
|
|
|
2022-10-05 00:11:47 -07:00
|
|
|
while (inputGetInput() != KEY_ESCAPE) {
|
2022-10-04 23:23:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
gPaused = false;
|
|
|
|
windowDestroy(win);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C8E38
|
2022-10-04 23:54:46 -07:00
|
|
|
static int pauseHandlerDefaultImpl()
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
|
|
|
int windowWidth = fontGetStringWidth("Paused") + 32;
|
|
|
|
int windowHeight = 3 * fontGetLineHeight() + 16;
|
|
|
|
|
|
|
|
int win = windowCreate((rectGetWidth(&_scr_size) - windowWidth) / 2,
|
|
|
|
(rectGetHeight(&_scr_size) - windowHeight) / 2,
|
|
|
|
windowWidth,
|
|
|
|
windowHeight,
|
|
|
|
256,
|
|
|
|
WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
|
|
|
|
if (win == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
windowDrawBorder(win);
|
|
|
|
|
|
|
|
unsigned char* windowBuffer = windowGetBuffer(win);
|
|
|
|
fontDrawText(windowBuffer + 8 * windowWidth + 16,
|
|
|
|
"Paused",
|
|
|
|
windowWidth,
|
|
|
|
windowWidth,
|
|
|
|
_colorTable[31744]);
|
|
|
|
|
|
|
|
_win_register_text_button(win,
|
|
|
|
(windowWidth - fontGetStringWidth("Done") - 16) / 2,
|
|
|
|
windowHeight - 8 - fontGetLineHeight() - 6,
|
|
|
|
-1,
|
|
|
|
-1,
|
|
|
|
-1,
|
|
|
|
KEY_ESCAPE,
|
|
|
|
"Done",
|
|
|
|
0);
|
|
|
|
|
|
|
|
windowRefresh(win);
|
|
|
|
|
|
|
|
return win;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C8F34
|
|
|
|
void pauseHandlerConfigure(int keyCode, PauseHandler* handler)
|
|
|
|
{
|
|
|
|
gPauseKeyCode = keyCode;
|
|
|
|
|
|
|
|
if (handler == NULL) {
|
|
|
|
handler = pauseHandlerDefaultImpl;
|
|
|
|
}
|
|
|
|
|
|
|
|
gPauseHandler = handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
WINDOWDRAWINGPROC v0 = _scr_blit;
|
|
|
|
_scr_blit = screenshotBlitter;
|
|
|
|
|
|
|
|
WINDOWDRAWINGPROC v2 = _mouse_blit;
|
|
|
|
_mouse_blit = screenshotBlitter;
|
|
|
|
|
|
|
|
WindowDrawingProc2* v1 = _mouse_blit_trans;
|
|
|
|
_mouse_blit_trans = NULL;
|
|
|
|
|
|
|
|
windowRefreshAll(&_scr_size);
|
|
|
|
|
|
|
|
_mouse_blit_trans = v1;
|
|
|
|
_mouse_blit = v2;
|
|
|
|
_scr_blit = v0;
|
|
|
|
|
|
|
|
unsigned char* palette = _getSystemPalette();
|
|
|
|
gScreenshotHandler(width, height, gScreenshotBuffer, palette);
|
|
|
|
internal_free(gScreenshotBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C8FF0
|
2022-10-04 23:54:46 -07:00
|
|
|
static void screenshotBlitter(unsigned char* src, int srcPitch, int a3, int srcX, int srcY, int width, int height, int destX, int destY)
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
|
|
|
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++) {
|
|
|
|
sprintf(fileName, "scr%.5d.bmp", index);
|
|
|
|
|
|
|
|
stream = compat_fopen(fileName, "rb");
|
|
|
|
if (stream == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index == 100000) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
stream = compat_fopen(fileName, "wb");
|
|
|
|
if (stream == NULL) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C9358
|
|
|
|
void screenshotHandlerConfigure(int keyCode, ScreenshotHandler* handler)
|
|
|
|
{
|
|
|
|
gScreenshotKeyCode = keyCode;
|
|
|
|
|
|
|
|
if (handler == NULL) {
|
|
|
|
handler = screenshotHandlerDefaultImpl;
|
|
|
|
}
|
|
|
|
|
|
|
|
gScreenshotHandler = handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C9370
|
2022-10-05 00:11:47 -07:00
|
|
|
unsigned int getTicks()
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
|
|
|
return SDL_GetTicks();
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C937C
|
2022-10-05 00:11:47 -07:00
|
|
|
void inputPauseForTocks(unsigned int delay)
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
|
|
|
// NOTE: Uninline.
|
2022-10-05 00:11:47 -07:00
|
|
|
unsigned int start = getTicks();
|
|
|
|
unsigned int end = getTicks();
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// NOTE: Uninline.
|
|
|
|
unsigned int diff = getTicksBetween(end, start);
|
|
|
|
while (diff < delay) {
|
|
|
|
_process_bk();
|
|
|
|
|
2022-10-05 00:11:47 -07:00
|
|
|
end = getTicks();
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
// NOTE: Uninline.
|
|
|
|
diff = getTicksBetween(end, start);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C93B8
|
2022-10-05 00:11:47 -07:00
|
|
|
void inputBlockForTocks(unsigned int ms)
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
|
|
|
unsigned int start = SDL_GetTicks();
|
|
|
|
unsigned int diff;
|
|
|
|
do {
|
|
|
|
// NOTE: Uninline
|
|
|
|
diff = getTicksSince(start);
|
|
|
|
} while (diff < 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Unused.
|
|
|
|
//
|
|
|
|
// 0x4C9418
|
|
|
|
void inputSetKeyboardKeyRepeatRate(int value)
|
|
|
|
{
|
|
|
|
gKeyboardKeyRepeatRate = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Unused.
|
|
|
|
//
|
|
|
|
// 0x4C9420
|
|
|
|
int inputGetKeyboardKeyRepeatRate()
|
|
|
|
{
|
|
|
|
return gKeyboardKeyRepeatRate;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Unused.
|
|
|
|
//
|
|
|
|
// 0x4C9428
|
|
|
|
void inputSetKeyboardKeyRepeatDelay(int value)
|
|
|
|
{
|
|
|
|
gKeyboardKeyRepeatDelay = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Unused.
|
|
|
|
//
|
|
|
|
// 0x4C9430
|
|
|
|
int inputGetKeyboardKeyRepeatDelay()
|
|
|
|
{
|
|
|
|
return gKeyboardKeyRepeatDelay;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Unused.
|
|
|
|
//
|
|
|
|
// 0x4C9438
|
|
|
|
void inputSetFocusFunc(FocusFunc* func)
|
|
|
|
{
|
|
|
|
_focus_func = func;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Unused.
|
|
|
|
//
|
|
|
|
// 0x4C9440
|
|
|
|
FocusFunc* inputGetFocusFunc()
|
|
|
|
{
|
|
|
|
return _focus_func;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Unused.
|
|
|
|
//
|
|
|
|
// 0x4C9448
|
|
|
|
void inputSetIdleFunc(IdleFunc* func)
|
|
|
|
{
|
|
|
|
_idle_func = func;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Unused.
|
|
|
|
//
|
|
|
|
// 0x4C9450
|
|
|
|
IdleFunc* inputGetIdleFunc()
|
|
|
|
{
|
|
|
|
return _idle_func;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C9490
|
2022-10-04 23:54:46 -07:00
|
|
|
static void buildNormalizedQwertyKeys()
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
|
|
|
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_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:
|
|
|
|
handleMouseEvent(&e);
|
|
|
|
break;
|
|
|
|
case SDL_FINGERDOWN:
|
|
|
|
case SDL_FINGERMOTION:
|
|
|
|
case SDL_FINGERUP:
|
|
|
|
handleTouchEvent(&e);
|
|
|
|
break;
|
|
|
|
case SDL_KEYDOWN:
|
|
|
|
case SDL_KEYUP:
|
|
|
|
if (!keyboardIsDisabled()) {
|
|
|
|
keyboardData.key = e.key.keysym.scancode;
|
|
|
|
keyboardData.down = (e.key.state & SDL_PRESSED) != 0;
|
|
|
|
_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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gProgramIsActive && !keyboardIsDisabled()) {
|
|
|
|
// NOTE: Uninline
|
2022-10-05 00:11:47 -07:00
|
|
|
int tick = getTicks();
|
2022-10-04 23:23:27 -07:00
|
|
|
|
|
|
|
for (int key = 0; key < SDL_NUM_SCANCODES; key++) {
|
2022-10-04 23:54:46 -07:00
|
|
|
RepeatInfo* ptr = &(_GNW95_key_time_stamps[key]);
|
2022-10-04 23:23:27 -07:00
|
|
|
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
|
2022-10-04 23:54:46 -07:00
|
|
|
static void _GNW95_process_key(KeyboardData* data)
|
2022-10-04 23:23:27 -07:00
|
|
|
{
|
2022-10-08 02:32:50 -07:00
|
|
|
// Use originally pressed scancode, not qwerty-remapped one, for tracking
|
|
|
|
// timestamps, see usage from |_GNW95_process_message|.
|
|
|
|
int scanCode = data->key;
|
|
|
|
|
2022-10-04 23:23:27 -07:00
|
|
|
data->key = gNormalizedQwertyKeys[data->key];
|
|
|
|
|
|
|
|
if (gVcrState == VCR_STATE_PLAYING) {
|
|
|
|
if ((gVcrTerminateFlags & VCR_TERMINATE_ON_KEY_PRESS) != 0) {
|
|
|
|
gVcrPlaybackCompletionReason = VCR_PLAYBACK_COMPLETION_REASON_TERMINATED;
|
|
|
|
vcrStop();
|
|
|
|
}
|
|
|
|
} else {
|
2022-10-08 02:32:50 -07:00
|
|
|
RepeatInfo* ptr = &(_GNW95_key_time_stamps[scanCode]);
|
2022-10-04 23:23:27 -07:00
|
|
|
if (data->down == 1) {
|
2022-10-05 00:11:47 -07:00
|
|
|
ptr->tick = getTicks();
|
2022-10-04 23:23:27 -07:00
|
|
|
ptr->repeatCount = 0;
|
|
|
|
} else {
|
|
|
|
ptr->tick = -1;
|
|
|
|
}
|
|
|
|
|
2022-10-08 02:32:50 -07:00
|
|
|
// Ignore keys which were remapped to -1.
|
|
|
|
if (data->key == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-10-04 23:23:27 -07:00
|
|
|
_kb_simulate_key(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4C9EEC
|
|
|
|
void _GNW95_lost_focus()
|
|
|
|
{
|
|
|
|
if (_focus_func != NULL) {
|
|
|
|
_focus_func(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!gProgramIsActive) {
|
|
|
|
_GNW95_process_message();
|
|
|
|
|
|
|
|
if (_idle_func != NULL) {
|
|
|
|
_idle_func();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_focus_func != NULL) {
|
|
|
|
_focus_func(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void idleImpl()
|
|
|
|
{
|
|
|
|
SDL_Delay(125);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace fallout
|