keyboard mapping

This commit is contained in:
Ondřej Novák 2025-01-28 10:21:43 +01:00
parent b6c5658b48
commit bf59962724
7 changed files with 392 additions and 49 deletions

View file

@ -24,34 +24,82 @@ void get_ms_event(MS_EVENT *event)
win_mouseEvent.event=0;
}
*/
char cz_table_1[] = { 0x20, 0x31, 0x21, 0x33, 0x34, 0x35, 0x37, 0xad, 0x39,
0x30, 0x38, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x82, 0x2b, 0x88, 0xa8, 0x87,
0xa9, 0x91, 0x98, 0xa0, 0xa1, 0x5c, 0x22, 0x96, 0x3f, 0x3d, 0x3a, 0x5f,
char cz_table_small_normal[] =
{ 0x20, 0x31, 0x21, 0x33, 0x34, 0x35, 0x37, 0xad,
0x39, 0x30, 0x38, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x82, 0x2b, 0x88, 0xa8,
0x87, 0xa9, 0x91, 0x98, 0xa0, 0xa1, 0x22, 0x96, 0x3f, 0x3d, 0x3a, 0x5f,
0x32, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0xa3, 0x5c, 0x5c, 0x29, 0x36, 0x3d, 0x3b, 0x61, 0x62,
0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
0x2f, 0x7c, 0x28, 0x3b, 0x20 };
char cz_table_2[] = { 0x20, 0x21, 0x5c, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x58, 0x59, 0x5a, 0xa3, 0x5c, 0x29, 0x36, 0x3d, 0x3b, 0x61, 0x62, 0x63,
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x2f,
0x7c, 0x28, 0x3b, 0x20 };
char cz_table_small_carka[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
0x8f, 0x42, 0x43, 0x44, 0x90, 0x46, 0x47, 0x48, 0x8b, 0x4a, 0x4b, 0x8a,
0x4d, 0x4e, 0x95, 0x50, 0x51, 0xab, 0x53, 0x54, 0x97, 0x56, 0x57, 0x58,
0x9d, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0xa0, 0x62, 0x63, 0x64,
0x82, 0x66, 0x67, 0x68, 0xa1, 0x6a, 0x6b, 0x8d, 0x6d, 0x6e, 0xa2, 0x70,
0x71, 0xaa, 0x73, 0x74, 0xa3, 0x76, 0x77, 0x78, 0x98, 0x7a, 0x7b, 0x7c,
0x7d, 0x7e, 0x20 };
char cz_table_small_hacek[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
0x41, 0x42, 0x80, 0x85, 0x89, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x9c,
0x4d, 0xa5, 0xa7, 0x50, 0x51, 0x9e, 0x9b, 0x86, 0xa6, 0x56, 0x57, 0x58,
0x59, 0x92, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x87, 0x83,
0x88, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x8c, 0x6d, 0xa4, 0x93, 0x70,
0x71, 0xa9, 0xa8, 0x9f, 0x96, 0x76, 0x77, 0x78, 0x79, 0x91, 0x7b, 0x7c,
0x7d, 0x7e, 0x20 };
char cz_table_caps_normal[] =
{ 0x20, 0x31, 0x21, 0x33, 0x34, 0x35, 0x37, 0xad,
0x39, 0x30, 0x38, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x90, 0x2b, 0x89, 0x9b, 0x80, 0x9e, 0x92, 0x9d, 0x8f, 0x8b,
0x22, 0x96, 0x3f, 0x3d, 0x3a, 0x5f,
0x32, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0xa3, 0x5c, 0x29, 0x36, 0x3d, 0x3b, 0x41, 0x42, 0x43,
0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x2f,
0x7c, 0x28, 0x3b, 0x20 };
char cz_table_caps_carka[] =
{ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x8f, 0x42, 0x43, 0x44, 0x90, 0x46, 0x47, 0x48, 0x8b, 0x4a, 0x4b,
0x8a, 0x4d, 0x4e, 0x95, 0x50, 0x51, 0xab, 0x53, 0x54, 0x97, 0x56, 0x57,
0x58, 0x9d, 0x5a, 0x5b, 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0xa0, 0x62,
0x63, 0x64, 0x82, 0x66, 0x67, 0x68, 0xa1, 0x6a, 0x6b, 0x8d, 0x6d, 0x6e,
0xa2, 0x70, 0x71, 0xaa, 0x73, 0x74, 0xa3, 0x76, 0x77, 0x78, 0x98, 0x7a,
0x40,
0xa0, 0x62, 0x63, 0x64, 0x82, 0x66, 0x67, 0x68, 0xa1, 0x6a,
0x6b, 0x8d, 0x6d, 0x6e, 0xa2, 0x70, 0x71, 0xaa, 0x73, 0x74,
0xa3, 0x76, 0x77, 0x78, 0x98, 0x7a,
0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
0x8f, 0x42, 0x43, 0x44, 0x90, 0x46, 0x47, 0x48, 0x8b, 0x4a,
0x4b, 0x8a, 0x4d, 0x4e, 0x95, 0x50, 0x51, 0xab, 0x53, 0x54,
0x97, 0x56, 0x57, 0x58, 0x9d, 0x5a,
0x7b, 0x7c, 0x7d, 0x7e, 0x20 };
char cz_table_3[] = { 0x20, 0x21, 0x5c, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x80, 0x85, 0x89, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
0x9c, 0x4d, 0xa5, 0xa7, 0x50, 0x51, 0x9e, 0x9b, 0x86, 0xa6, 0x56, 0x57,
0x58, 0x59, 0x92, 0x5b, 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62,
0x87, 0x83, 0x88, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x8c, 0x6d, 0xa4,
0x93, 0x70, 0x71, 0xa9, 0xa8, 0x9f, 0x96, 0x76, 0x77, 0x78, 0x79, 0x91,
char cz_table_caps_hacek[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
0x61, 0x62, 0x87, 0x83, 0x88, 0x66, 0x67, 0x68, 0x69, 0x6a,
0x6b, 0x8c, 0x6d, 0xa4, 0x93, 0x70, 0x71, 0xa9, 0xa8, 0x9f,
0x96, 0x76, 0x77, 0x78, 0x79, 0x91,
0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
0x41, 0x42, 0x80, 0x85, 0x89, 0x46, 0x47, 0x48, 0x49, 0x4a,
0x4b, 0x9c, 0x4d, 0xa5, 0xa7, 0x50, 0x51, 0x9e, 0x9b, 0x86,
0xa6, 0x56, 0x57, 0x58, 0x59, 0x92,
0x7b, 0x7c, 0x7d, 0x7e, 0x20 };
char *cz_key_tabs[]={cz_table_1,cz_table_2,cz_table_3};
char *cz_key_tabs[]={cz_table_small_normal,cz_table_small_carka,cz_table_small_hacek,
cz_table_caps_normal, cz_table_caps_carka, cz_table_caps_hacek};
void keyboard(EVENT_MSG *msg,void *user_data)
{
@ -71,6 +119,7 @@ void keyboard(EVENT_MSG *msg,void *user_data)
else if (c=='=' && d<55 && !cz_mode) cz_mode=1;
else if (c>32 && c<127 && d<=53)
{
if (get_capslock_state()) cz_mode +=3;
c=cz_key_tabs[cz_mode][c-32];
i=d;
i=(i<<8)+c;

View file

@ -36,6 +36,7 @@ void SetWheelMapping(char up, char down);
char get_control_key_state(void);
char get_shift_key_state(void);
char get_capslock_state(void);
void display_error(const char *text);
int stricmp(const char *a, const char *b);

View file

@ -1,14 +1,25 @@
#include "global_context.h"
#include "input.h"
#include "../platform.h"
char get_control_key_state() {
return 0; //todo
return get_sdl_global_context().get_control_key_state()?1:0;
}
char get_shift_key_state() {
return 0; //todo
return get_sdl_global_context().get_shift_key_state()?1:0;
}
char get_capslock_state() {
return get_sdl_global_context().get_capslock_state()?1:0;
}
uint32_t _bios_keybrd(int mode) {
return 0;
if (mode == _KEYBRD_READY) {
return get_sdl_global_context().is_keyboard_ready()?1:0;
} else if (mode == _KEYBRD_READ) {
return get_sdl_global_context().pop_keyboard_code();
} else {
return 0;
}
}
void SetWheelMapping(char up, char down) { //todo

View file

@ -16,8 +16,11 @@ extern "C" {
#include <devices.h>
char get_control_key_state();
char get_shift_key_state();
char get_control_key_state(void);
char get_shift_key_state(void);
char get_capslock_state(void);
uint32_t _bios_keybrd(int mode);
void SetWheelMapping(char up, char down);
void get_ms_event(MS_EVENT *event);

131
platform/sdl/keyboard_map.h Normal file
View file

@ -0,0 +1,131 @@
#include <cstdint>
struct SDLKey2Bios {
SDL_Scancode scan_code;
uint16_t normal;
uint16_t shift;
uint16_t ctrl;
};
class KeyCodeMap {
public:
template<int n>
constexpr KeyCodeMap(const SDLKey2Bios (&codes)[n]) {
for (const SDLKey2Bios &x: codes) {
int idx = static_cast<int>(x.scan_code);
normal[idx] = x.normal;
w_ctrl[idx] = x.ctrl;
w_shift[idx] = x.shift;
}
}
constexpr uint16_t get_bios_code(SDL_Scancode scan, bool shift, bool control) const {
if (control) return w_ctrl[static_cast<int>(scan)];
if (shift) return w_shift[static_cast<int>(scan)];
return normal[static_cast<int>(scan)];
}
protected:
uint16_t normal[SDL_NUM_SCANCODES] = {};
uint16_t w_shift[SDL_NUM_SCANCODES] = {};
uint16_t w_ctrl[SDL_NUM_SCANCODES] = {};
};
constexpr auto sdl_keycode_map = KeyCodeMap({
{SDL_SCANCODE_A, 0x1E61, 0x1E41, 0x1E01},
{SDL_SCANCODE_B,0x3062,0x3042,0x3002},
{SDL_SCANCODE_C,0x2E63,0x2E42,0x2E03},
{SDL_SCANCODE_D,0x2064,0x2044,0x2004},
{SDL_SCANCODE_E,0x1265,0x1245,0x1205},
{SDL_SCANCODE_F,0x2166,0x2146,0x2106},
{SDL_SCANCODE_G,0x2267,0x2247,0x2207},
{SDL_SCANCODE_H,0x2368,0x2348,0x2308},
{SDL_SCANCODE_I,0x1769,0x1749,0x1709},
{SDL_SCANCODE_J,0x246A,0x244A,0x240A},
{SDL_SCANCODE_K,0x256B,0x254B,0x250B},
{SDL_SCANCODE_L,0x266C,0x264C,0x260C},
{SDL_SCANCODE_M,0x326D,0x324D,0x320D},
{SDL_SCANCODE_N,0x316E,0x314E,0x310E},
{SDL_SCANCODE_O,0x186F,0x184F,0x180F},
{SDL_SCANCODE_P,0x1970,0x1950,0x1910},
{SDL_SCANCODE_Q,0x1071,0x1051,0x1011},
{SDL_SCANCODE_R,0x1372,0x1352,0x1312},
{SDL_SCANCODE_S,0x1F73,0x1F53,0x1F13},
{SDL_SCANCODE_T,0x1474,0x1454,0x1414},
{SDL_SCANCODE_U,0x1675,0x1655,0x1615},
{SDL_SCANCODE_V,0x2F76,0x2F56,0x2F16},
{SDL_SCANCODE_W,0x1177,0x1157,0x1117},
{SDL_SCANCODE_X,0x2D78,0x2D58,0x2D18},
{SDL_SCANCODE_Y,0x1579,0x1559,0x1519},
{SDL_SCANCODE_Z,0x2C7A,0x2C5A,0x2C1A},
{SDL_SCANCODE_1,0x0231,0x0221,0x7800},
{SDL_SCANCODE_2,0x0332,0x0340,0x0300},
{SDL_SCANCODE_3,0x0433,0x0423,0x7A00},
{SDL_SCANCODE_4,0x0534,0x0524,0x7B00},
{SDL_SCANCODE_5,0x0635,0x0625,0x7C00},
{SDL_SCANCODE_6,0x0736,0x075E,0x071E},
{SDL_SCANCODE_7,0x0837,0x0826,0x7E00},
{SDL_SCANCODE_8,0x0938,0x092A,0x7F00},
{SDL_SCANCODE_9,0x0A39,0x0A28,0x8000},
{SDL_SCANCODE_0,0x0B30,0x0B29,0x8100},
{SDL_SCANCODE_MINUS,0x0C2D,0x0C5F,0x0C1F},
{SDL_SCANCODE_EQUALS,0x0D3D,0x0D2B,0x8300},
{SDL_SCANCODE_LEFTBRACKET,0x1A5B,0x1A7B,0x1A1B},
{SDL_SCANCODE_RIGHTBRACKET,0x1B5D,0x1B7D,0x1B1D},
{SDL_SCANCODE_SEMICOLON,0x273B,0x273A,0x2700},
{SDL_SCANCODE_APOSTROPHE,0x2827,0x2822,0},
{SDL_SCANCODE_GRAVE,0x2960,0x297E,0},
{SDL_SCANCODE_BACKSLASH,0x2B5C,0x2B7C,0x2B1C},
{SDL_SCANCODE_COMMA,0x332C,0x333C,0},
{SDL_SCANCODE_PERIOD,0x342E,0x343E,0},
{SDL_SCANCODE_SLASH,0x352F,0x353F,0},
{SDL_SCANCODE_F1 ,0x3B00,0x5400,0x5E00},
{SDL_SCANCODE_F2 ,0x3C00,0x5500,0x5F00},
{SDL_SCANCODE_F3 ,0x3D00,0x5600,0x6000},
{SDL_SCANCODE_F4 ,0x3E00,0x5700,0x6100},
{SDL_SCANCODE_F5 ,0x3F00,0x5800,0x6200},
{SDL_SCANCODE_F6 ,0x4000,0x5900,0x6300},
{SDL_SCANCODE_F7 ,0x4100,0x5A00,0x6400},
{SDL_SCANCODE_F8 ,0x4200,0x5B00,0x6500},
{SDL_SCANCODE_F9 ,0x4300,0x5C00,0x6600},
{SDL_SCANCODE_F10,0x4400,0x5D00,0x6700},
{SDL_SCANCODE_F11,0x8500,0x8700,0x8900},
{SDL_SCANCODE_F12,0x8600,0x8800,0x8A00},
{SDL_SCANCODE_BACKSPACE,0x0E08,0x0E08,0x0E7F},
{SDL_SCANCODE_DELETE,0x5300,0x5300,0x9300},
{SDL_SCANCODE_DOWN,0x5000,0x5000,0x9100},
{SDL_SCANCODE_END,0x4F00,0x4F00,0x7500},
{SDL_SCANCODE_RETURN,0x1C0D,0x1C0D,0x1C0A},
{SDL_SCANCODE_ESCAPE,0x011B,0x011B,0x011B},
{SDL_SCANCODE_HOME,0x4700,0x4700,0x7700},
{SDL_SCANCODE_INSERT,0x5200,0x5200,0x9200},
{SDL_SCANCODE_KP_MULTIPLY,0x372A,0x9600,0x3700},
{SDL_SCANCODE_KP_MINUS,0x4A2D,0x4A2D,0x8E00},
{SDL_SCANCODE_KP_PLUS,0x4E2B,0x4E2B,0x4E00},
{SDL_SCANCODE_KP_DIVIDE,0x352F,0x352F,0x9500},
{SDL_SCANCODE_LEFT,0x4B00,0x4B00,0x7300},
{SDL_SCANCODE_PAGEDOWN,0x5100,0x5100,0x7600},
{SDL_SCANCODE_PAGEUP,0x4900,0x4900,0x8400},
{SDL_SCANCODE_PRINTSCREEN,0x7200,0,0},
{SDL_SCANCODE_RIGHT,0x4D00,0x4D00,0x7400},
{SDL_SCANCODE_SPACE,0x3920,0x3920,0x3920},
{SDL_SCANCODE_TAB,0x0F09,0x0F09,0x9400},
{SDL_SCANCODE_UP,0x4800,0x4800,0x8D00},
{SDL_SCANCODE_KP_1,0x4F31,0x4F00,0x7500},
{SDL_SCANCODE_KP_2,0x5032,0x5000,0x9100},
{SDL_SCANCODE_KP_3,0x5133,0x5100,0x7600},
{SDL_SCANCODE_KP_4,0x4B34,0x4B00,0x7300},
{SDL_SCANCODE_KP_5,0x4C35,0x4C00,0x8F00},
{SDL_SCANCODE_KP_6,0x4D36,0x4D00,0x7400},
{SDL_SCANCODE_KP_7,0x4737,0x4700,0x7700},
{SDL_SCANCODE_KP_8,0x4838,0x4800,0x8D00},
{SDL_SCANCODE_KP_9,0x4939,0x4900,0x8400},
{SDL_SCANCODE_KP_0,0x5230,0x5200,0x9200},
{SDL_SCANCODE_KP_PERIOD,0x532E,0x5300,0x9300}
});

View file

@ -1,9 +1,11 @@
#include "sdl_context.h"
#include "keyboard_map.h"
#include <atomic>
#include <cassert>
#include "../platform.h"
#include <iostream>
#include <stdexcept>
void SDLContext::SDL_Deleter::operator ()(SDL_Window* window) {
SDL_DestroyWindow(window);
@ -83,13 +85,20 @@ void SDLContext::init_screen(DisplayMode mode, const char *title) {
throw std::runtime_error(buff);
}
_renderer.reset(renderer);
// Vytvoření textury pro zobrazení backbufferu
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, 640, 480);
if (!texture) {
snprintf(buff, sizeof(buff), "Chyba při vytváření textury: %s\n", SDL_GetError());
throw std::runtime_error(buff);
}
_texture.reset(texture);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, 640, 480);
if (!texture) {
snprintf(buff, sizeof(buff), "Chyba při vytváření textury: %s\n", SDL_GetError());
throw std::runtime_error(buff);
}
_texture2.reset(texture);
_visible_texture = _texture.get();
_hidden_texture = _texture.get();
} catch (...) {
e = std::current_exception();
err = true;
@ -99,6 +108,7 @@ void SDLContext::init_screen(DisplayMode mode, const char *title) {
SDL_ShowCursor(SDL_DISABLE);
if (!err) event_loop(stp);
_texture.reset();
_texture2.reset();
_renderer.reset();
_window.reset();
});
@ -139,9 +149,19 @@ void SDLContext::event_loop(std::stop_token stp) {
}
if (e.type == SDL_KEYDOWN) {
_key_capslock = e.key.keysym.mod & KMOD_CAPS;
_key_shift =e.key.keysym.mod & KMOD_SHIFT;
_key_control =e.key.keysym.mod & KMOD_CTRL;
if (e.key.keysym.sym == SDLK_RETURN && (e.key.keysym.mod & KMOD_ALT)) {
_fullscreen_mode = !_fullscreen_mode;
SDL_SetWindowFullscreen(_window.get(), _fullscreen_mode ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
} else {
auto code =sdl_keycode_map.get_bios_code(e.key.keysym.scancode,
e.key.keysym.mod & KMOD_SHIFT, e.key.keysym.mod & KMOD_CTRL);
if (code) {
std::lock_guard _(_mx);
_keyboard_queue.push(code);
}
}
} else if (e.type == SDL_MOUSEMOTION) {
int mouseX = e.motion.x;
@ -233,34 +253,112 @@ void SDLContext::present_rect(uint16_t *pixels, unsigned int pitch,
static_cast<int>(y),
static_cast<int>(xs),
static_cast<int>(ys)};
std::vector<short> data;
data.resize(xs*ys);
auto iter = data.begin();
for (unsigned int yp = 0; yp <ys; ++yp) {
iter = std::copy(beg, beg+xs,iter );
beg+=pitch;
}
std::lock_guard _(_mx);
signal_push();
push_update_msg(r, beg, pitch);
}
std::uint16_t SDLContext::pop_keyboard_code() {
std::lock_guard _(_mx);
std::uint16_t out = _keyboard_queue.front();
_keyboard_queue.pop();
return out;
}
bool SDLContext::is_keyboard_ready() const {
std::lock_guard _(_mx);
return !_keyboard_queue.empty();
}
void SDLContext::signal_push() {
if (_display_update_queue.empty()) {
SDL_Event event;
event.type = _update_request_event;
SDL_PushEvent(&event);
}
_display_update_queue.push_back({std::move(r), std::move(data)});
}
void SDLContext::update_screen() {
{
std::lock_guard _(_mx);
for (const UpdateMsg &msg:_display_update_queue) {
SDL_UpdateTexture(_texture.get(), &msg.rc, msg.data.data(), msg.rc.w*2);
QueueIter iter = _display_update_queue.data();
QueueIter end = iter + _display_update_queue.size();
while (iter != end) {
DisplayRequest req;
pop_item(iter, req);
switch (req) {
case DisplayRequest::update: {
SDL_Rect r;
pop_item(iter, r);
std::string_view data = pop_data(iter, r.w*r.h*2);
SDL_UpdateTexture(_texture.get(), &r, data.data(), r.w*2);
}
break;
case DisplayRequest::swap_render_buffers: {
std::swap(_texture,_texture2);
}
break;
case DisplayRequest::swap_visible_buffers: {
std::swap(_visible_texture,_hidden_texture);
}
break;
}
}
_display_update_queue.clear();
}
SDL_RenderClear(_renderer.get());
SDL_RenderCopy(_renderer.get(), _texture.get(), NULL, NULL);
SDL_RenderCopy(_renderer.get(), _visible_texture, NULL, NULL);
SDL_RenderPresent(_renderer.get());
}
template<typename T>
requires(std::is_trivially_copy_constructible_v<T>)
void SDLContext::push_item(const T &item) {
auto b = reinterpret_cast<const char *>(&item);
auto e = b + sizeof(T);
auto sz = _display_update_queue.size();
_display_update_queue.resize(sz + sizeof(T));
std::copy(b, e, _display_update_queue.begin()+sz);
}
void SDLContext::push_item(const std::string_view &item) {
auto sz = _display_update_queue.size();
_display_update_queue.resize(sz + item.size());
std::copy(item.begin(), item.end(), _display_update_queue.begin()+sz);
}
void SDLContext::push_update_msg(const SDL_Rect &rc, const uint16_t *data, int pitch) {
push_item(DisplayRequest::update);
push_item(rc);
for (int yp = 0; yp < rc.h; ++yp) {
push_item(std::string_view(reinterpret_cast<const char *>(data), rc.w*2));
data += pitch;
}
}
template<typename T>
requires(std::is_trivially_copy_constructible_v<T>)
void SDLContext::pop_item(QueueIter &iter, T &item) {
std::copy(iter, iter+sizeof(T), reinterpret_cast<char *>(&item));
iter += sizeof(T);
}
std::string_view SDLContext::pop_data(QueueIter &iter, std::size_t size) {
const char *c = iter;
iter += size;
return std::string_view(c, size);
}
void SDLContext::swap_render_buffers() {
std::lock_guard _(_mx);
signal_push();
push_item(DisplayRequest::swap_render_buffers);
}
void SDLContext::swap_display_buffers() {
std::lock_guard _(_mx);
signal_push();
push_item(DisplayRequest::swap_render_buffers);
}

View file

@ -7,6 +7,8 @@
#include <vector>
#include <mouse.h>
#include <queue>
class SDLContext {
public:
@ -25,6 +27,8 @@ public:
void present_rect(uint16_t *pixels, unsigned int pitch, unsigned int x, unsigned int y, unsigned int xs,unsigned ys);
void swap_render_buffers();
void swap_display_buffers();
MS_EVENT getMsEvent() {
std::lock_guard _(_mx);
@ -33,6 +37,20 @@ public:
return out;
}
bool get_shift_key_state() const {
return _key_shift;
}
bool get_control_key_state() const {
return _key_control;
}
bool get_capslock_state() const {
return _key_capslock;
}
bool is_keyboard_ready() const;
std::uint16_t pop_keyboard_code() ;
protected:
struct SDL_Deleter {
@ -42,30 +60,62 @@ protected:
void operator()(SDL_Texture *);
};
struct UpdateMsg {
SDL_Rect rc;
std::vector<short> data;
};
enum class DisplayRequest {
update,
swap_render_buffers,
swap_visible_buffers,
};
MS_EVENT ms_event;
mutable std::mutex _mx;
std::unique_ptr<SDL_Window, SDL_Deleter> _window;
std::unique_ptr<SDL_Renderer, SDL_Deleter> _renderer;
std::unique_ptr<SDL_Texture, SDL_Deleter> _texture;
std::unique_ptr<SDL_Texture, SDL_Deleter> _texture2;
SDL_Texture *_visible_texture;
SDL_Texture *_hidden_texture;
std::jthread _render_thread;
bool _quit_requested = false;
bool _fullscreen_mode = false;
bool _present = false;
void charge_timer();
std::atomic<bool> _key_control = false;
std::atomic<bool> _key_shift = false;
std::atomic<bool> _key_capslock = false;
void event_loop(std::stop_token stp);
std::mutex _mx;
struct UpdateMsg {
SDL_Rect rc;
std::vector<short> data;
};
std::vector<char> _display_update_queue;
using QueueIter = const char *;
std::queue<uint16_t> _keyboard_queue;
std::vector<UpdateMsg> _display_update_queue;
Uint32 _update_request_event;
void event_loop(std::stop_token stp);
void update_screen();
template<typename T>
requires(std::is_trivially_copy_constructible_v<T>)
void push_item(const T &item);
void push_item(const std::string_view &item);
void push_update_msg(const SDL_Rect &rc, const uint16_t *data, int pitch);
void push_swap_buffers();
template<typename T>
requires(std::is_trivially_copy_constructible_v<T>)
void pop_item(QueueIter &iter, T &item);
std::string_view pop_data(QueueIter &iter, std::size_t size);
void signal_push();
};