From 01d0f484e4e9e1444412464da69ac8b6754e23b8 Mon Sep 17 00:00:00 2001 From: Ivan Tatarinov Date: Fri, 3 Feb 2023 20:23:44 +0300 Subject: [PATCH] cores/Spectrum/keymaps: added `dumpkeybmap` and `genkeybmap` tools --- cores/Spectrum/keymaps/.gitignore | 5 + cores/Spectrum/keymaps/Makefile | 64 +++ cores/Spectrum/keymaps/dumpkeybmap.c | 628 +++++++++++++++++++++++++++ cores/Spectrum/keymaps/errors.c | 35 ++ cores/Spectrum/keymaps/errors.h | 19 + cores/Spectrum/keymaps/genkeybmap.c | 336 ++++++++++++++ cores/Spectrum/keymaps/keymap_av.c | 136 ++++++ cores/Spectrum/keymaps/keymap_es.c | 162 +++++++ cores/Spectrum/keymaps/keymap_us.c | 154 +++++++ cores/Spectrum/keymaps/keys_pc.h | 125 ++++++ cores/Spectrum/keymaps/keys_sp.h | 118 +++++ 11 files changed, 1782 insertions(+) create mode 100644 cores/Spectrum/keymaps/.gitignore create mode 100644 cores/Spectrum/keymaps/Makefile create mode 100644 cores/Spectrum/keymaps/dumpkeybmap.c create mode 100644 cores/Spectrum/keymaps/errors.c create mode 100644 cores/Spectrum/keymaps/errors.h create mode 100644 cores/Spectrum/keymaps/genkeybmap.c create mode 100644 cores/Spectrum/keymaps/keymap_av.c create mode 100644 cores/Spectrum/keymaps/keymap_es.c create mode 100644 cores/Spectrum/keymaps/keymap_us.c create mode 100644 cores/Spectrum/keymaps/keys_pc.h create mode 100644 cores/Spectrum/keymaps/keys_sp.h diff --git a/cores/Spectrum/keymaps/.gitignore b/cores/Spectrum/keymaps/.gitignore new file mode 100644 index 00000000..34d968b4 --- /dev/null +++ b/cores/Spectrum/keymaps/.gitignore @@ -0,0 +1,5 @@ +# SPDX-FileType: TEXT +# SPDX-FileCopyrightText: 2023 Ivan Tatarinov +# SPDX-License-Identifier: CC0-1.0 + +build diff --git a/cores/Spectrum/keymaps/Makefile b/cores/Spectrum/keymaps/Makefile new file mode 100644 index 00000000..b0e358ab --- /dev/null +++ b/cores/Spectrum/keymaps/Makefile @@ -0,0 +1,64 @@ +#!/bin/make -f +# +# Supported environments: +# * GNU on Linux, FreeBSD etc. +# * GNU on Windows NT (using MinGW/MSYS/Cygwin/WSL) +# +# SPDX-FileType: SOURCE +# SPDX-FileCopyrightText: 2023 Ivan Tatarinov +# SPDX-License-Identifier: GPL-3.0-or-later + +include ../../../sdk/common.mk + +srcdir = . +MKDIR ?= mkdir +RM ?= rm -f + +BINS=\ + build/dumpkeybmap$(EXESUFFIX)\ + build/genkeybmap$(EXESUFFIX) + +KEYMAPS=\ + build/av.bin\ + build/es.bin\ + build/us.bin\ + +.PHONY: all +all: $(BINS) $(KEYMAPS) + +build: + $(MKDIR) -p $@ + +build/dumpkeybmap$(EXESUFFIX): $(srcdir)/dumpkeybmap.c\ + $(srcdir)/errors.h\ + $(srcdir)/errors.c\ + Makefile | build + $(CC) $(CFLAGS) -std=c99 -Wall -o $@ $< + +build/genkeybmap$(EXESUFFIX): $(srcdir)/genkeybmap.c\ + $(srcdir)/errors.h\ + $(srcdir)/errors.c\ + $(srcdir)/keys_pc.h\ + $(srcdir)/keys_sp.h\ + $(srcdir)/keymap_av.c\ + $(srcdir)/keymap_es.c\ + $(srcdir)/keymap_us.c\ + Makefile | build + $(CC) $(CFLAGS) -std=c99 -Wall -o $@ $< + +build/av.bin: build/genkeybmap$(EXESUFFIX) Makefile | build + ./$< av $@ + +build/es.bin: build/genkeybmap$(EXESUFFIX) Makefile | build + ./$< es $@ + +build/us.bin: build/genkeybmap$(EXESUFFIX) Makefile | build + ./$< us $@ + +.PHONY: clean +clean: + $(RM) $(BINS) $(KEYMAPS) + +.PHONY: distclean +distclean: + $(RM) -r build diff --git a/cores/Spectrum/keymaps/dumpkeybmap.c b/cores/Spectrum/keymaps/dumpkeybmap.c new file mode 100644 index 00000000..a09b8969 --- /dev/null +++ b/cores/Spectrum/keymaps/dumpkeybmap.c @@ -0,0 +1,628 @@ +/* + * dumpkeybmap - dumps ZX Spectrum core's keymap file for ZXUNO/ZXDOS. + * + * Copyright (C) 2023 Ivan Tatarinov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-FileType: SOURCE + * SPDX-FileCopyrightText: 2023 Ivan Tatarinov + * SPDX-FileContributor: 2023 Miguel Angel Rodriguez Jodar + * SPDX-FileContributor: 2023 Antonio Villena + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include +#include + +#define PROGRAM "dumpkeybmap" +#define DESCRIPTION \ +"Dumps ZX Spectrum core's keymap file for ZXUNO/ZXDOS." +#define VERSION "1.0" +#define COPYRIGHT \ +"Copyright (C) 2023 Ivan Tatarinov\n" \ +"Contributors: 2023 Miguel Angel Rodriguez Jodar, Antonio Villena" +#define LICENSE \ +"This program is free software: you can redistribute it and/or modify\n" \ +"it under the terms of the GNU General Public License as published by\n" \ +"the Free Software Foundation, either version 3 of the License, or\n" \ +"(at your option) any later version." +#define HOMEPAGE "https://github.com/ivan-tat/zxuno" + +#define HELP_HINT \ +"Use \"-h\" to get help." + +typedef unsigned char u8; +typedef unsigned short u16; + +/* Options */ +char opt_help=0; +char opt_version=0; +const char *opt_if=NULL; + +/* Length of key's name string */ +#define KEY_LEN 32 + +/* Naming of keys for output */ +#define KEY_PREFIX_PC "PC_" +#define KEY_PREFIX_SP "SP_" + +/* This should be a part of index but is used in key's scan code, limiting + the usage of keys with scan codes above 0x7F */ +#define EXT (1<<7) /* Extended key flag */ + +/* PC key modifiers. Use any combination of these constants as first index to + access `keymap[]' (valid range is 0->7) */ +#define MOD_SHIFT (1<<0) +#define MOD_CTRL (1<<1) +#define MOD_ALT (1<<2) + +/* Aliases for key modifiers used for output */ +#define MOD_SHIFT_STR "MD_SHIFT" +#define MOD_CTRL_STR "MD_CTRL" +#define MOD_ALT_STR "MD_ALT" + +/* Line prefix for output */ +#define LINE_PREFIX " " + +/* Function names used for output */ +#define FUNC_MAP "map" +#define FUNC_MAPALFA "map_alfa" +#define FUNC_MAPALL "map_all" +#define FUNC_MAPXALL "map_xall" + +u8 keymap[8][256][2]; + +/* PS/2 keyboard scan codes (set 2, US). + https://wiki.osdev.org/PS/2_Keyboard + https://techdocs.altium.com/display/FPGA/PS2+Keyboard+Scan+Codes */ +const struct { + char loc; /* 1=localized, 0=standard */ + const char *name; + u8 key; +} pc_keys[]={ /* Key, press scan codes (release scan codes) */ + {0,"ESC", 0x76}, /* ESC, 76 (F076) */ + {0,"F1", 0x05}, /* F1, 05 (F005) */ + {0,"F2", 0x06}, /* F2, 06 (F006) */ + {0,"F3", 0x04}, /* F3, 04 (F004) */ + {0,"F4", 0x0C}, /* F4, 0C (F00C) */ + {0,"F5", 0x03}, /* F5, 03 (F003) */ + {0,"F6", 0x0B}, /* F6, 0B (F00B) */ + {0,"F7", 0x83}, /* F7, 83 (F083) */ + {0,"F8", 0x0A}, /* F8, 0A (F00A) */ + {0,"F9", 0x01}, /* F9, 01 (F001) */ + {0,"F10", 0x09}, /* F10, 09 (F009) */ + {0,"F11", 0x78}, /* F11, 78 (F078) */ + {0,"F12", 0x07}, /* F12, 07 (F007) */ +/*{0,"PRTSCR", ?}, // Prt Scr, E012E07C (E0F07CE0F012) */ + {0,"SCRLOCK", 0x7E}, /* Scroll Lock, 7E (F07E) */ +/*{0,"PAUSE", ?}, // Pause/Break, E11477E1F014E077 (None) */ + {1,"US_GRAVEAC",0x0E}, /* ` ~, 0E (F00E) */ + {0,"1", 0x16}, /* 1, 16 (F016) */ + {0,"2", 0x1E}, /* 2, 1E (F01E) */ + {0,"3", 0x26}, /* 3, 26 (F026) */ + {0,"4", 0x25}, /* 4, 25 (F025) */ + {0,"5", 0x2E}, /* 5, 2E (F02E) */ + {0,"6", 0x36}, /* 6, 36 (F036) */ + {0,"7", 0x3D}, /* 7, 3D (F03D) */ + {0,"8", 0x3E}, /* 8, 3E (F03E) */ + {0,"9", 0x46}, /* 9, 46 (F046) */ + {0,"0", 0x45}, /* 0, 45 (F045) */ + {1,"US_MINUS", 0x4E}, /* - _, 4E (F04E) */ + {1,"US_EQUAL", 0x55}, /* = +, 55 (F055) */ + {0,"BKSPACE", 0x66}, /* Backspace, 66 (F066) */ + {0,"TAB", 0x0D}, /* Tab, 66 (F066) */ + {0,"Q", 0x15}, /* Q, 15 (F015) */ + {0,"W", 0x1D}, /* W, 1D (F01D) */ + {0,"E", 0x24}, /* E, 24 (F024) */ + {0,"R", 0x2D}, /* R, 2D (F02D) */ + {0,"T", 0x2C}, /* T, 2C (F02C) */ + {0,"Y", 0x35}, /* Y, 35 (F035) */ + {0,"U", 0x3C}, /* U, 3C (F03C) */ + {0,"I", 0x43}, /* I, 43 (F043) */ + {0,"O", 0x44}, /* O, 44 (F044) */ + {0,"P", 0x4D}, /* P, 4D (F04D) */ + {1,"US_BRAOPEN",0x54}, /* [ {, 54 (F054) */ + {1,"US_BRACLOS",0x5B}, /* ] }, 5B (F05B) */ + {1,"US_BACKSLA",0x5D}, /* \ |, 5D (F05D) */ + {0,"CPSLOCK", 0x58}, /* Caps Lock, 58 (F058) */ + {0,"A", 0x1C}, /* A, 1C (F01C) */ + {0,"S", 0x1B}, /* S, 1B (F01B) */ + {0,"D", 0x23}, /* D, 23 (F023) */ + {0,"F", 0x2B}, /* F, 2B (F02B) */ + {0,"G", 0x34}, /* G, 34 (F034) */ + {0,"H", 0x33}, /* H, 33 (F033) */ + {0,"J", 0x3B}, /* J, 3B (F03B) */ + {0,"K", 0x42}, /* K, 42 (F042) */ + {0,"L", 0x4B}, /* L, 4B (F04B) */ + {1,"US_SEMICOL",0x4C}, /* ; :, 4C (F04C) */ + {1,"US_APOSTRO",0x52}, /* ' ", 52 (F052) */ + {0,"ENTER", 0x5A}, /* Enter, 52 (F052) */ + {0,"LSHIFT", 0x12}, /* Shift (left), 12 (F012) */ + {0,"Z", 0x1A}, /* Z, 1A (F01A) */ + {0,"X", 0x22}, /* X, 22 (F022) */ + {0,"C", 0x21}, /* C, 21 (F021) */ + {0,"V", 0x2A}, /* V, 2A (F02A) */ + {0,"B", 0x32}, /* B, 32 (F032) */ + {0,"N", 0x31}, /* N, 31 (F031) */ + {0,"M", 0x3A}, /* M, 3A (F03A) */ + {1,"US_COMMA", 0x41}, /* , <, 41 (F041) */ + {1,"US_DOT", 0x49}, /* . >, 49 (F049) */ + {1,"US_SLASH", 0x4A}, /* / ?, 4A (F04A) */ + {0,"RSHIFT", 0x59}, /* Shift (right), 59 (F059) */ + {0,"LCTRL", 0x14}, /* Ctrl (left), 14 (F014) */ + {0,"LWIN", 0x1F|EXT}, /* Windows (left), E01F (E0F01F)*/ + {0,"LALT", 0x11}, /* Alt (left), 11 (F011) */ + {0,"SPACE", 0x29}, /* Spacebar, 29 (F029) */ + {0,"RALT", 0x11|EXT}, /* Alt (right), E011 (E0F011) */ + {0,"RWIN", 0x27|EXT}, /* Windows (right), E027 (E0F027) */ + {0,"APPS", 0x2F|EXT}, /* Menus, E02F (E0F02F) */ + {0,"RCTRL", 0x14|EXT}, /* Ctrl (right), E014 (E0F014) */ + {0,"INSERT", 0x70|EXT}, /* Insert, E070 (E0F070) */ + {0,"HOME", 0x6C|EXT}, /* Home, E06C (E0F06C) */ + {0,"PGUP", 0x7D|EXT}, /* Page Up, E07D (E0F07D) */ + {0,"DELETE", 0x71|EXT}, /* Delete, E071 (E0F071) */ + {0,"END", 0x69|EXT}, /* End, E069 (E0F069) */ + {0,"PGDOWN", 0x7A|EXT}, /* Page Down, E07A (E0F07A) */ + {0,"UP", 0x75|EXT}, /* Up Arrow, E075 (E0F075) */ + {0,"LEFT", 0x6B|EXT}, /* Left Arrow, E06B (E0F06B) */ + {0,"DOWN", 0x72|EXT}, /* Down Arrow, E072 (E0F072) */ + {0,"RIGHT", 0x74|EXT}, /* Right Arrow, E074 (E0F074) */ + /* Keypad */ + {0,"NUMLOCK", 0x77}, /* Num Lock, 77 (F077) */ + {0,"KP_DIVIS", 0x4A|EXT}, /* /, E04A (E0F04A) */ + {0,"KP_MULT", 0x7C}, /* *, 7C (F07C) */ + {0,"KP_MINUS", 0x7B}, /* -, 7B (F07B) */ + {0,"KP_7", 0x6C}, /* 7, 6C (F06C) */ + {0,"KP_8", 0x75}, /* 8, 75 (F075) */ + {0,"KP_9", 0x7D}, /* 9, 7D (F07D) */ + {0,"KP_PLUS", 0x79}, /* +, 79 (F079) */ + {0,"KP_4", 0x6B}, /* 4, 6B (F06B) */ + {0,"KP_5", 0x73}, /* 5, 73 (F073) */ + {0,"KP_6", 0x74}, /* 6, 74 (F074) */ + {0,"KP_1", 0x69}, /* 1, 69 (F069) */ + {0,"KP_2", 0x72}, /* 2, 72 (F072) */ + {0,"KP_3", 0x7A}, /* 3, 7A (F07A) */ + {0,"KP_0", 0x70}, /* 0, 70 (F070) */ + {0,"KP_DOT", 0x71}, /* ., 71 (F071) */ + {0,"KP_ENTER", 0x5A|EXT}, /* Enter, E05A (E0F05A) */ + {0,NULL,0} /* stop mark */ +}; + +/* ZX Spectrum keys ([B7<-B0]=[A2 A1 A0 D4 D3 D2 D1 D0]) + A=semi-row address: 0->3=left half, 4->7=right half + D=bit mask for 5 keys (1=key is pressed) */ +const struct { + const char *name; + u8 key; +} sp_keys[]={ + {"1", 0x61}, /* 1 */ + {"2", 0x62}, /* 2 */ + {"3", 0x64}, /* 3 */ + {"4", 0x68}, /* 4 */ + {"5", 0x70}, /* 5 */ + {"6", 0x90}, /* 6 */ + {"7", 0x88}, /* 7 */ + {"8", 0x84}, /* 8 */ + {"9", 0x82}, /* 9 */ + {"0", 0x81}, /* 0 */ + {"Q", 0x41}, /* Q */ + {"W", 0x42}, /* W */ + {"E", 0x44}, /* E */ + {"R", 0x48}, /* R */ + {"T", 0x50}, /* T */ + {"Y", 0xB0}, /* Y */ + {"U", 0xA8}, /* U */ + {"I", 0xA4}, /* I */ + {"O", 0xA2}, /* O */ + {"P", 0xA1}, /* P */ + {"A", 0x21}, /* A */ + {"S", 0x22}, /* S */ + {"D", 0x24}, /* D */ + {"F", 0x28}, /* F */ + {"G", 0x30}, /* G */ + {"H", 0xD0}, /* H */ + {"J", 0xC8}, /* J */ + {"K", 0xC4}, /* K */ + {"L", 0xC2}, /* L */ + {"ENTER", 0xC1}, /* ENTER */ + {"CAPS", 0x01}, /* CAPS SHIFT */ + {"Z", 0x02}, /* Z */ + {"X", 0x04}, /* X */ + {"C", 0x08}, /* C */ + {"V", 0x10}, /* V */ + {"B", 0xF0}, /* B */ + {"N", 0xE8}, /* N */ + {"M", 0xE4}, /* M */ + {"SYMBOL",0xE2}, /* SYMBOL SHIFT */ + {"SPACE", 0xE1}, /* SPACE */ + {NULL,0} /* stop mark */ +}; + +/* ZX Spectrum 2-keys combinations */ +const struct { + const char *name; + u8 keys[2]; +} sp_keys2[]={ + {"EDIT", {0x01,0x61}}, /* SP_CAPS+SP_1 */ + {"CPSLOCK",{0x01,0x62}}, /* SP_CAPS+SP_2 */ + {"TRUE", {0x01,0x64}}, /* SP_CAPS+SP_3 */ + {"INVERSE",{0x01,0x68}}, /* SP_CAPS+SP_4 */ + {"LEFT", {0x01,0x70}}, /* SP_CAPS+SP_5 */ + {"DOWN", {0x01,0x90}}, /* SP_CAPS+SP_6 */ + {"UP", {0x01,0x88}}, /* SP_CAPS+SP_7 */ + {"RIGHT", {0x01,0x84}}, /* SP_CAPS+SP_8 */ + {"GRAPH", {0x01,0x82}}, /* SP_CAPS+SP_9 */ + {"DELETE", {0x01,0x81}}, /* SP_CAPS+SP_0 */ + {"EXTEND", {0x01,0xE2}}, /* SP_CAPS+SP_SYMBOL */ + {"BREAK", {0x01,0xE1}}, /* SP_CAPS+SP_SPACE */ + {"BANG", {0xE2,0x61}}, /* ! SP_SYMBOL+SP_1 */ + {"AT", {0xE2,0x62}}, /* @ SP_SYMBOL+SP_2 */ + {"HASH", {0xE2,0x64}}, /* # SP_SYMBOL+SP_3 */ + {"DOLLAR", {0xE2,0x68}}, /* $ SP_SYMBOL+SP_4 */ + {"PERCEN", {0xE2,0x70}}, /* % SP_SYMBOL+SP_5 */ + {"AMP", {0xE2,0x90}}, /* & SP_SYMBOL+SP_6 */ + {"APOSTRO",{0xE2,0x88}}, /* ' SP_SYMBOL+SP_7 */ + {"PAROPEN",{0xE2,0x84}}, /* ( SP_SYMBOL+SP_8 */ + {"PARCLOS",{0xE2,0x82}}, /* ) SP_SYMBOL+SP_9 */ + {"UNDERSC",{0xE2,0x81}}, /* _ SP_SYMBOL+SP_0 */ + {"LESSEQ", {0xE2,0x41}}, /* <= SP_SYMBOL+SP_Q */ + {"NOTEQ", {0xE2,0x42}}, /* <> SP_SYMBOL+SP_W */ + {"GREATEQ",{0xE2,0x44}}, /* >= SP_SYMBOL+SP_E */ + {"LESS", {0xE2,0x48}}, /* < SP_SYMBOL+SP_R */ + {"GREATER",{0xE2,0x50}}, /* > SP_SYMBOL+SP_T */ + {"BRAOPEN",{0xE2,0xB0}}, /* [ SP_SYMBOL+SP_Y */ + {"BRACLOS",{0xE2,0xA8}}, /* ] SP_SYMBOL+SP_U */ + {"SEMICOL",{0xE2,0xA2}}, /* ; SP_SYMBOL+SP_O */ + {"QUOTE", {0xE2,0xA1}}, /* " SP_SYMBOL+SP_P */ + {"TILDE", {0xE2,0x21}}, /* ~ SP_SYMBOL+SP_A */ + {"PIPE", {0xE2,0x22}}, /* | SP_SYMBOL+SP_S */ + {"BACKSLA",{0xE2,0x24}}, /* \ SP_SYMBOL+SP_D */ + {"CUROPEN",{0xE2,0x28}}, /* { SP_SYMBOL+SP_F */ + {"CURCLOS",{0xE2,0x30}}, /* } SP_SYMBOL+SP_G */ + {"CARET", {0xE2,0xD0}}, /* ^ SP_SYMBOL+SP_H */ + {"MINUS", {0xE2,0xC8}}, /* - SP_SYMBOL+SP_J */ + {"PLUS", {0xE2,0xC4}}, /* + SP_SYMBOL+SP_K */ + {"EQUAL", {0xE2,0xC2}}, /* = SP_SYMBOL+SP_L */ + {"COLON", {0xE2,0x02}}, /* : SP_SYMBOL+SP_Z */ + {"POUND", {0xE2,0x04}}, /* £ SP_SYMBOL+SP_X */ + {"QUEST", {0xE2,0x08}}, /* ? SP_SYMBOL+SP_C */ + {"SLASH", {0xE2,0x10}}, /* / SP_SYMBOL+SP_V */ + {"STAR", {0xE2,0xF0}}, /* * SP_SYMBOL+SP_B */ + {"COMMA", {0xE2,0xE8}}, /* , SP_SYMBOL+SP_N */ + {"DOT", {0xE2,0xE4}}, /* . SP_SYMBOL+SP_M */ + {NULL,{0,0}} /* stop mark */ +}; + +#include "errors.c" + +void show_version() { + printf( + PROGRAM ", version " VERSION " (built on " __DATE__ " " __TIME__ ")\n" + ); +} + +void show_usage() { + show_version(); + printf( + DESCRIPTION "\n" + COPYRIGHT "\n" + LICENSE "\n" + "Home page: <" HOMEPAGE ">\n" + ); + printf( + "\n" + "Usage:\n" + " " PROGRAM " [options...] | INPUT\n" + "\n" + "Options:\n" + " -h, --help Show this help\n" + " -v, --version Show version\n" + "\n" + "Where:\n" + " INPUT - ZX Spectrum core's keymap file (4 KiB size)\n" + ); +} + +/* 1 if PC key is mapped directly or with any modifier to Spectrum key(s) */ +char is_mapped(u8 pc) { + u8 m; + for(m=0;m<8;m++) if(keymap[m][pc][0]||keymap[m][pc][1]) return 1; + return 0; +} + +/* 1 if PC key is mapped directly and with Shift / CAPS SHIFT modifiers to + Spectrum key(s) */ +char is_mapped_alfa(u8 pc) { + if((keymap[0][pc][0]==0) + && (keymap[0][pc][1]!=0) + && (keymap[1][pc][0]==0x01) + && (keymap[1][pc][1]==keymap[0][pc][1])) { + u8 m; + for(m=2;m<8;m++) if(keymap[m][pc][0]||keymap[m][pc][1]) return 0; + return 1; + } + return 0; +} + +/* 1 if PC key is mapped directly and with all modifiers to Spectrum key(s) */ +char is_mapped_all(u8 pc) { + u8 m; + for(m=1;m<8;m++) + if((keymap[0][pc][0]!=keymap[m][pc][0]) + || (keymap[0][pc][1]!=keymap[m][pc][1])) return 0; + return 1; /* Mapped directly and with all modifiers */ +} + +/* 1 if PC key is mapped not directly but with all modifiers to Spectrum + key(s) */ +char is_mapped_xall(u8 pc) { + if((keymap[0][pc][0]==0)&&(keymap[0][pc][1]==0)) { + /* Not mapped directly */ + u8 m; + for(m=2;m<8;m++) + if((keymap[1][pc][0]!=keymap[m][pc][0]) + || (keymap[1][pc][1]!=keymap[m][pc][1])) return 0; + return 1; /* Not mapped directly but with all modifiers */ + } else return 0; +} + +/* Return index of PC key in `pc_keys' array or -1 if failed */ +int find_pc_key(u8 pc) { + int i; + for(i=0;pc_keys[i].name;i++) if(pc_keys[i].key==pc) return i; + return -1; +} + +void get_pc_name(char *str,size_t size,u8 pc) { + int i=find_pc_key(pc); + if(i>=0) + snprintf(str,size,"%s%s",(char*)KEY_PREFIX_PC,(char*)pc_keys[i].name); + else + snprintf(str,size,"0x%02hhX",(unsigned char)pc); +} + +/* Return index of ZX Spectrum key in `sp_keys' array or -1 if failed */ +int find_sp_key(u8 sp) { + int i; + for(i=0;sp_keys[i].name;i++) if(sp_keys[i].key==sp) return i; + return -1; +} + +void get_sp_name(char *str,size_t size,u8 sp) { + int i=find_sp_key(sp); + if(i>=0) { + snprintf(str,size,KEY_PREFIX_SP "%s",(char*)sp_keys[i].name); + } else { + snprintf(str,size,"0x%02hhX",(unsigned char)sp); + } +} + +/* Return index of ZX Spectrum key in `sp_keys2' array or -1 if failed */ +int find_sp_keys2(u8 sp0,u8 sp1) { + int i; + for(i=0;sp_keys2[i].name;i++) + if(((sp_keys2[i].keys[0]==sp0)&&(sp_keys2[i].keys[1]==sp1)) + || ((sp_keys2[i].keys[0]==sp1)&&(sp_keys2[i].keys[1]==sp0))) return i; + return -1; +} + +void get_sp_name_any(char *str,size_t size,u8 sp0,u8 sp1) { + if(!sp0) { sp0=sp1; sp1=0; } + if(sp0==sp1) sp1=0; + if(sp1) { + /* key 0 + key 1 */ + int i=find_sp_keys2(sp0,sp1); + if(i>=0) { + snprintf(str,size,KEY_PREFIX_SP "%s",(char*)sp_keys2[i].name); + } else { + char spn[2][KEY_LEN]; + get_sp_name(spn[0],KEY_LEN,sp0); + get_sp_name(spn[1],KEY_LEN,sp1); + snprintf(str,size,"(%s<<8)|%s",(char*)spn[0],(char*)spn[1]); + } + } else { + /* key 0 only */ + char spn[KEY_LEN]; + get_sp_name(spn,KEY_LEN,sp0); + snprintf(str,size,"%s",(char*)spn); + } +} + +const char *pc_mods[]={MOD_SHIFT_STR,MOD_CTRL_STR,MOD_ALT_STR}; + +void print_mods(u8 m) { + u8 mask=1<<2,i; + for(i=3;i;i--) { + if(m&mask) printf("%s|",(char*)pc_mods[i-1]); + mask>>=1; + } +} + +/* force=0 to skip unmapped unknown key, otherwise dump it */ +void dump_key(u8 pc,char force) { + char pcn[KEY_LEN]; + get_pc_name(pcn,KEY_LEN,pc); + if(is_mapped(pc)) { + char spn[KEY_LEN]; + if(is_mapped_alfa(pc)) { + get_sp_name_any(spn,KEY_LEN,keymap[0][pc][0],keymap[0][pc][1]); + printf(LINE_PREFIX FUNC_MAPALFA "(%s,%s);\n",(char*)pcn,(char*)spn); + } else if(is_mapped_all(pc)) { + get_sp_name_any(spn,KEY_LEN,keymap[0][pc][0],keymap[0][pc][1]); + printf(LINE_PREFIX FUNC_MAPALL "(%s,%s);\n",(char*)pcn,(char*)spn); + } else if(is_mapped_xall(pc)) { + get_sp_name_any(spn,KEY_LEN,keymap[1][pc][0],keymap[1][pc][1]); + printf(LINE_PREFIX FUNC_MAPXALL "(%s,%s);\n",(char*)pcn,(char*)spn); + } else { + u8 m; + for(m=0;m<8;m++) { + u8 sp[2]; + sp[0]=keymap[m][pc][0]; + sp[1]=keymap[m][pc][1]; + if(sp[0]||sp[1]) { + printf(LINE_PREFIX FUNC_MAP "("); + if(m) print_mods(m); + get_sp_name_any(spn,KEY_LEN,sp[0],sp[1]); + printf("%s,%s);\n",(char*)pcn,(char*)spn); + } + } + } + } else { + if(force) + printf(LINE_PREFIX "/* Key %s is not mapped */\n",(char*)pcn); + } +} + +void dump_localized_defs() { + int pl=strlen(KEY_PREFIX_PC),l=0,k; + /* get key name's maximal length */ + for(k=0;pc_keys[k].name;k++) + if(pc_keys[k].loc==1) { + int len=pl+strlen(pc_keys[k].name); + if(l0) { printf(" "); n--; } /* padding */ + printf("0x%02hhX\n",(unsigned char)pc_keys[k].key); + } +} + +/* f=256 x 1-bit flags (packed) for processed keys */ +void dump_known_keys(char loc,u8 *f) { + int i; + for(i=0;pc_keys[i].name;i++) + if(pc_keys[i].loc==loc) { + int k=pc_keys[i].key; + dump_key(k,1); + f[k/8]|=1<<(k%8); /* mark key as processed */ + } +} + +void dump_unknown_keys(u8 *f) { + int k; + for(k=0;k<256;k++) if(!(f[k/8]&(1<<(k%8)))) dump_key(k,0); +} + +void dump_keymap() { + u8 f[256/8]; /* 256 x 1-bit flags (packed) for processed keys */ + memset(f,0,sizeof(f)); + printf("%s", + "/*\n" + " * keymap_us.c\n" + " *\n" + " * SPDX-FileType: SOURCE\n" + " * SPDX-FileCopyrightText: ?\n" + " * SPDX-FileContributor: ?\n" + " * SPDX-FileNotice: ?\n" + " * SPDX-License-Identifier: GPL-3.0-or-later\n" + " * SPDX-LicenseComments: ?\n" + " */\n" + "\n" + "#define KEYMAP_US \"us\"\n" + "#define COMMENT_US \"English (US) layout\"\n" + "#define VERSION_US \"1.0\"\n" + "\n" + ); + dump_localized_defs(); + printf("%s", + "\n" + "void gen_keymap_us() {\n" + LINE_PREFIX "/* Standard keys: */\n" + ); + dump_known_keys(0,f); + printf("%s","\n" LINE_PREFIX "/* Localized keys: */\n"); + dump_known_keys(1,f); + dump_unknown_keys(f); + printf("}\n"); +} + +/* Returns 0 on success, 1 if no arguments, other value on other error */ +int parse_args(int argc,const char **argv) { + int f,i; + char optsend=0; + if(argc==1) return 1; + f=0; + for(i=1;i + +void message(const char *format,...); +void error(const char *format,...); +void error_missing_arg(const char *name,unsigned index); +void error_bad_arg(const char *name,unsigned index); + +#endif /* !ERRORS_H */ diff --git a/cores/Spectrum/keymaps/genkeybmap.c b/cores/Spectrum/keymaps/genkeybmap.c new file mode 100644 index 00000000..8b927222 --- /dev/null +++ b/cores/Spectrum/keymaps/genkeybmap.c @@ -0,0 +1,336 @@ +/* + * genkeybmap - generates ZX Spectrum core's keymap file for ZXUNO/ZXDOS. + * + * Copyright (C) 2014-2023 Miguel Angel Rodriguez Jodar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-FileType: SOURCE + * SPDX-FileCopyrightText: 2014-2023 Miguel Angel Rodriguez Jodar + * SPDX-FileContributor: 2022 Antonio Villena + * SPDX-FileContributor: 2023 Ivan Tatarinov + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include +#include + +#define PROGRAM "genkeybmap" +#define DESCRIPTION \ +"Generates ZX Spectrum core's keymap file for ZXUNO/ZXDOS." +#define VERSION "1.0" +#define COPYRIGHT \ +"Copyright (C) 2014-2023 Miguel Angel Rodriguez Jodar\n" \ +"Contributors: 2022 Antonio Villena, 2023 Ivan Tatarinov" +#define LICENSE \ +"This program is free software: you can redistribute it and/or modify\n" \ +"it under the terms of the GNU General Public License as published by\n" \ +"the Free Software Foundation, either version 3 of the License, or\n" \ +"(at your option) any later version." +#define HOMEPAGE "https://github.com/ivan-tat/zxuno" + +#define HELP_HINT \ +"Use \"-h\" to get help." + +typedef unsigned char u8; +typedef unsigned short u16; + +/* Options */ +char opt_help=0; +char opt_version=0; +char opt_hex=0; /* do output hex. files */ +const char *opt_hexf[2]={ /* output hex. filenames */ + NULL,NULL + }; +int opt_ki=-1; /* keymap index (none) */ +const char *opt_of=NULL; /* output filename */ + +/* + SPkey - Spectrum key +7<-----0 +AAADDDDD + +AAA = semi-row of the keyboard to be modified | this information is +DDDDD = data (bit-negated) from that semi-row | stored for two keys + +Each PC key to Spectrum key(s) mapping will occupy two consecutive directions: +D+0 : SPkey1 (or 0 if there is none) +D+1 : SPkey2 (or 0 if there is none) + +Parameter to map routines (16-bit integer): + SPkey1 SPkey2 +F<-----8 7<-----0 +AAADDDDD AAADDDDD + +Example 1: in the memory address D corresponding to the code of the 6 key +(PC), which would correspond to the single pressing of 6 (Spectrum), we would +put: + +SPkey1=00000000 (no key) +SPkey2=10010000 (6) + +Parameter to map routine (16-bit integer): + SPkey1 SPkey2 +F<-----8 7<-----0 +00000000 10010000 + +That is: semi-row 4 is activated, and in that one bit 4 is activated + +Example 2: in the memory address D corresponding to the code of the ESC key +(PC), which would correspond to the simultaneous pressing of CAPS SHIFT+SPACE +(Spectrum), we would put: + +SPkey1=00000001 (CAPS SHIFT) +SPkey2=11100001 (SPACE) + +Parameter to map routine (16-bit integer): + SPkey1 SPkey2 +F<-----8 7<-----0 +00000001 11100001 + +That is: semi-rows 0 and 7 are activated, and in each one, bit 0 is activated + +128 codes + E0 = 256 codes (E0=extended scan code flag, 1-bit) +SHIFT, CTRL, ALT = 8 combinations +256 codes x 8 combinations = 2048 addresses +2048 addresses x 16 bits = 32768 bits +In the core will be available as a 4096 x 8-bit memory +*/ + +u8 keymap[8][256][2]; + +#include "keys_pc.h" +#include "keys_sp.h" +#include "errors.c" + +void map(u16 pc,u16 sp) { + keymap[(pc>>8)&7][pc&255][0]=sp>>8; + keymap[(pc>>8)&7][pc&255][1]=sp&255; +} + +void map_alfa(u8 pc,u8 sp) { + /* No modifiers: */ + keymap[0][pc][0]=0; + keymap[0][pc][1]=sp; + /* SHIFT modifier: */ + keymap[1][pc][0]=SP_CAPS; + keymap[1][pc][1]=sp; +} + +void map_all(u8 pc,u16 sp) { + u8 m; + for(m=0;m<8;m++) { + keymap[m][pc&255][0]=sp>>8; + keymap[m][pc&255][1]=sp&255; + } +} + +void map_xall(u8 pc,u16 sp) { + u8 m; + /* All modifiers only: */ + for(m=1;m<8;m++) { + keymap[m][pc&255][0]=sp>>8; + keymap[m][pc&255][1]=sp&255; + } +} + +#include "keymap_av.c" +#include "keymap_es.c" +#include "keymap_us.c" + +const struct keymap_t { + const char *id,*comment,*version; + void (*gen)(); /* keymap generator */ +} keymaps[]={ + {KEYMAP_AV,COMMENT_AV,VERSION_AV,gen_keymap_av}, + {KEYMAP_ES,COMMENT_ES,VERSION_ES,gen_keymap_es}, + {KEYMAP_US,COMMENT_US,VERSION_US,gen_keymap_us}, + {NULL,NULL,NULL} /* stop mark */ +}; + +void show_version() { + printf( + PROGRAM ", version " VERSION " (built on " __DATE__ " " __TIME__ ")\n" + ); +} + +void show_usage() { + int i; + show_version(); + printf( + DESCRIPTION "\n" + COPYRIGHT "\n" + LICENSE "\n" + "Home page: <" HOMEPAGE ">\n" + ); + printf( + "\n" + "Usage:\n" + " " PROGRAM " [options...] [--] ID [OUTPUT]\n" + "\n" + "Options:\n" + " -h, --help Show this help\n" + " -v, --version Show version\n" + " --hex FILE1 FILE2 Write Verilog files for ZXUNO/ZXDOS core\n" + " -- Stop parsing options\n" + "\n" + "Where:\n" + " ID Keymap ID (see `Available keymaps' below)\n" + " OUTPUT ZX Spectrum core's keymap file (4 KiB size)\n" + ); + printf( + "\n" + "Available keymaps (ID - comment, version):\n" + ); + for(i=0;keymaps[i].id;i++) + printf(" %s - %s, version %s\n", + (char*)keymaps[i].id, + (char*)keymaps[i].comment, + (char*)keymaps[i].version + ); +} + +/* Returns 0 on success, other value on error */ +int parse_arg_keymap_id(int *a,const char *arg) { + int i; + for(i=0;keymaps[i].id;i++) + if(!strcmp(keymaps[i].id,arg)) { + *a=i; + return 0; + } + return -1; +} + +/* Returns 0 on success, 1 if no arguments, other value on other error */ +int parse_args(int argc,const char **argv) { + int f,i; + char optsend=0; + if(argc==1) return 1; + f=0; + for(i=1;i=argc) { + error_missing_arg(argv[i],i); + return -1; + } + opt_hex=1; + opt_hexf[0]=argv[++i]; + opt_hexf[1]=argv[++i]; + } else { + error("Unknown option \"%s\" (argument %u)",argv[i],i); + return -1; + } + } else { + switch(f++) { + case 0: + if(parse_arg_keymap_id(&opt_ki,argv[i])) { + error_bad_arg("keymap ID",i); + return -1; + } + break; + case 1: opt_of=argv[i]; break; + default: + error("Extra parameter \"%s\" given (argument %u)",argv[i],i); + return -1; + } + } + } + return 0; +} + +int save_hex(u8 *data,size_t size,const char *name) { + FILE *f=fopen(name,"w"); + int i; + if(!f) { + error("Failed to open output file \"%s\"",name); + return 1; + } + for(i=0;i */ +#define PC_US_SLASH 0x4A /* / ? */ + +void gen_keymap_us() { + /* Standard keys: */ + map_all(PC_ESC,SP_BREAK); + /* Key PC_F1 is not mapped */ + map_all(PC_F2,SP_EDIT); + /* Key PC_F3 is not mapped */ + /* Key PC_F4 is not mapped */ + /* Key PC_F5 is not mapped */ + /* Key PC_F6 is not mapped */ + /* Key PC_F7 is not mapped */ + /* Key PC_F8 is not mapped */ + /* Key PC_F9 is not mapped */ + map(PC_F10,SP_GRAPH); + /* Key PC_F11 is not mapped */ + /* Key PC_F12 is not mapped */ + /* Key PC_SCRLOCK is not mapped */ + map(PC_1,SP_1); + map(MD_SHIFT|PC_1,SP_BANG); + map(PC_2,SP_2); + map(MD_SHIFT|PC_2,SP_AT); + map(PC_3,SP_3); + map(MD_SHIFT|PC_3,SP_HASH); + map(PC_4,SP_4); + map(MD_SHIFT|PC_4,SP_DOLLAR); + map(PC_5,SP_5); + map(MD_SHIFT|PC_5,SP_PERCEN); + map(PC_6,SP_6); + map(MD_SHIFT|PC_6,SP_CARET); + map(PC_7,SP_7); + map(MD_SHIFT|PC_7,SP_AMP); + map(PC_8,SP_8); + map(MD_SHIFT|PC_8,SP_STAR); + map(PC_9,SP_9); + map(MD_SHIFT|PC_9,SP_PAROPEN); + map(PC_0,SP_0); + map(MD_SHIFT|PC_0,SP_PARCLOS); + map(PC_BKSPACE,SP_DELETE); + map_all(PC_TAB,SP_EXTEND); + map_alfa(PC_Q,SP_Q); + map_alfa(PC_W,SP_W); + map_alfa(PC_E,SP_E); + map_alfa(PC_R,SP_R); + map_alfa(PC_T,SP_T); + map_alfa(PC_Y,SP_Y); + map_alfa(PC_U,SP_U); + map_alfa(PC_I,SP_I); + map_alfa(PC_O,SP_O); + map_alfa(PC_P,SP_P); + map_all(PC_CPSLOCK,SP_CPSLOCK); + map_alfa(PC_A,SP_A); + map_alfa(PC_S,SP_S); + map_alfa(PC_D,SP_D); + map_alfa(PC_F,SP_F); + map_alfa(PC_G,SP_G); + map_alfa(PC_H,SP_H); + map_alfa(PC_J,SP_J); + map_alfa(PC_K,SP_K); + map_alfa(PC_L,SP_L); + map_all(PC_ENTER,SP_ENTER); + /* Key PC_LSHIFT is not mapped */ + map_alfa(PC_Z,SP_Z); + map_alfa(PC_X,SP_X); + map_alfa(PC_C,SP_C); + map_alfa(PC_V,SP_V); + map_alfa(PC_B,SP_B); + map_alfa(PC_N,SP_N); + map_alfa(PC_M,SP_M); + /* Key PC_RSHIFT is not mapped */ + map_all(PC_LCTRL,SP_CAPS); + /* Key PC_LWIN is not mapped */ + /* Key PC_LALT is not mapped */ + map_all(PC_SPACE,SP_SPACE); + /* Key PC_RALT is not mapped */ + /* Key PC_RWIN is not mapped */ + map_all(PC_APPS,SP_SYMBOL); + map_all(PC_RCTRL,SP_SYMBOL); + /* Key PC_INSERT is not mapped */ + /* Key PC_HOME is not mapped */ + /* Key PC_PGUP is not mapped */ + /* Key PC_DELETE is not mapped */ + /* Key PC_END is not mapped */ + /* Key PC_PGDOWN is not mapped */ + map_all(PC_UP,SP_UP); + map_all(PC_LEFT,SP_LEFT); + map_all(PC_DOWN,SP_DOWN); + map_all(PC_RIGHT,SP_RIGHT); + /* Key PC_NUMLOCK is not mapped */ + map_all(PC_KP_DIVIS,SP_SLASH); + map_all(PC_KP_MULT,SP_STAR); + map_all(PC_KP_MINUS,SP_MINUS); + /* Key PC_KP_7 is not mapped */ + /* Key PC_KP_8 is not mapped */ + /* Key PC_KP_9 is not mapped */ + map_all(PC_KP_PLUS,SP_PLUS); + /* Key PC_KP_4 is not mapped */ + /* Key PC_KP_5 is not mapped */ + /* Key PC_KP_6 is not mapped */ + /* Key PC_KP_1 is not mapped */ + /* Key PC_KP_2 is not mapped */ + /* Key PC_KP_3 is not mapped */ + /* Key PC_KP_0 is not mapped */ + map_all(PC_KP_DOT,SP_DOT); + map_all(PC_KP_ENTER,SP_ENTER); + + /* Localized keys: */ + /* Key PC_US_GRAVEAC is not mapped */ + map(PC_US_MINUS,SP_MINUS); + map(MD_SHIFT|PC_US_MINUS,SP_UNDERSC); + map(PC_US_EQUAL,SP_EQUAL); + map(MD_SHIFT|PC_US_EQUAL,SP_PLUS); + map(PC_US_BRAOPEN,SP_BRAOPEN); + map(MD_SHIFT|PC_US_BRAOPEN,SP_CUROPEN); + map(PC_US_BRACLOS,SP_BRACLOS); + map(MD_SHIFT|PC_US_BRACLOS,SP_BRACLOS); + map(PC_US_BACKSLA,SP_BACKSLA); + map(MD_SHIFT|PC_US_BACKSLA,SP_PIPE); + map(PC_US_SEMICOL,SP_SEMICOL); + map(MD_SHIFT|PC_US_SEMICOL,SP_COLON); + map(PC_US_APOSTRO,SP_APOSTRO); + map(MD_SHIFT|PC_US_APOSTRO,SP_QUOTE); + map(PC_US_COMMA,SP_COMMA); + map(MD_SHIFT|PC_US_COMMA,SP_LESS); + map(PC_US_DOT,SP_DOT); + map(MD_SHIFT|PC_US_DOT,SP_GREATER); + map(PC_US_SLASH,SP_SLASH); + map(MD_SHIFT|PC_US_SLASH,SP_QUEST); +} diff --git a/cores/Spectrum/keymaps/keys_pc.h b/cores/Spectrum/keymaps/keys_pc.h new file mode 100644 index 00000000..cbd447c4 --- /dev/null +++ b/cores/Spectrum/keymaps/keys_pc.h @@ -0,0 +1,125 @@ +/* + * keys_pc.h - PS/2 keyboard scan codes (set 2) without localized keys. + * + * https://wiki.osdev.org/PS/2_Keyboard + * https://techdocs.altium.com/display/FPGA/PS2+Keyboard+Scan+Codes + * + * SPDX-FileType: SOURCE + * SPDX-FileCopyrightText: 2022, 2023 Miguel Angel Rodriguez Jodar + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef KEYS_PC_H +#define KEYS_PC_H + +/* Extended scan code flag, received from PS/2 controller, but mapped into + key's scan code field thus limiting the usage of scan codes above 0x7F */ +#define EXT (1<<7) + +/* A key can be pressed with up to three key modifiers + which generates 8 combinations for each key */ +#define MD_SHIFT (1<<8) +#define MD_CTRL (1<<9) +#define MD_ALT (1<<10) + +/* PS/2 keyboard scan codes (set 2) */ + +#define PC_A 0x1C +#define PC_B 0x32 +#define PC_C 0x21 +#define PC_D 0x23 +#define PC_E 0x24 +#define PC_F 0x2B +#define PC_G 0x34 +#define PC_H 0x33 +#define PC_I 0x43 +#define PC_J 0x3B +#define PC_K 0x42 +#define PC_L 0x4B +#define PC_M 0x3A +#define PC_N 0x31 +#define PC_O 0x44 +#define PC_P 0x4D +#define PC_Q 0x15 +#define PC_R 0x2D +#define PC_S 0x1B +#define PC_T 0x2C +#define PC_U 0x3C +#define PC_V 0x2A +#define PC_W 0x1D +#define PC_X 0x22 +#define PC_Y 0x35 +#define PC_Z 0x1A + +#define PC_0 0x45 /* 0 ) */ +#define PC_1 0x16 /* 1 ! */ +#define PC_2 0x1E /* 2 @ */ +#define PC_3 0x26 /* 3 # */ +#define PC_4 0x25 /* 4 $ */ +#define PC_5 0x2E /* 5 % */ +#define PC_6 0x36 /* 6 ^ */ +#define PC_7 0x3D /* 7 & */ +#define PC_8 0x3E /* 8 * */ +#define PC_9 0x46 /* 9 ( */ + +#define PC_F1 0x05 +#define PC_F2 0x06 +#define PC_F3 0x04 +#define PC_F4 0x0C +#define PC_F5 0x03 +#define PC_F6 0x0B +#define PC_F7 0x83 | EXT /* Caution: scan code > 0x7F */ +#define PC_F8 0x0A +#define PC_F9 0x01 +#define PC_F10 0x09 +#define PC_F11 0x78 +#define PC_F12 0x07 + +#define PC_ESC 0x76 +#define PC_SPACE 0x29 +#define PC_LCTRL 0x14 +#define PC_RCTRL 0x14 | EXT +#define PC_LSHIFT 0x12 +#define PC_RSHIFT 0x59 +#define PC_LALT 0x11 +#define PC_RALT 0x11 | EXT +#define PC_LWIN 0x1F | EXT +#define PC_RWIN 0x27 | EXT +#define PC_APPS 0x2F | EXT /* a.k.a. MENUS */ + +#define PC_TAB 0x0D +#define PC_CPSLOCK 0x58 +#define PC_SCRLOCK 0x7E + +#define PC_INSERT 0x70 | EXT +#define PC_DELETE 0x71 | EXT +#define PC_HOME 0x6C | EXT +#define PC_END 0x69 | EXT +#define PC_PGUP 0x7D | EXT +#define PC_PGDOWN 0x7A | EXT +#define PC_BKSPACE 0x66 +#define PC_ENTER 0x5A +#define PC_UP 0x75 | EXT +#define PC_DOWN 0x72 | EXT +#define PC_LEFT 0x6B | EXT +#define PC_RIGHT 0x74 | EXT + +#define PC_NUMLOCK 0x77 +#define PC_KP_DIVIS 0x4A | EXT +#define PC_KP_MULT 0x7C +#define PC_KP_MINUS 0x7B +#define PC_KP_PLUS 0x79 +#define PC_KP_ENTER 0x5A | EXT +#define PC_KP_DOT 0x71 /* . Delete */ +#define PC_KP_0 0x70 /* 0 Insert */ +#define PC_KP_1 0x69 /* 1 End */ +#define PC_KP_2 0x72 /* 2 DOWN ARROW */ +#define PC_KP_3 0x7A /* 3 Page Down */ +#define PC_KP_4 0x6B /* 4 LEFT ARROW */ +#define PC_KP_5 0x73 /* 5 */ +#define PC_KP_6 0x74 /* 6 RIGHT ARROW */ +#define PC_KP_7 0x6C /* 7 Home */ +#define PC_KP_8 0x75 /* 8 UP ARROW */ +#define PC_KP_9 0x7D /* 9 Page Up */ + +#endif /* !KEYS_PC_H */ diff --git a/cores/Spectrum/keymaps/keys_sp.h b/cores/Spectrum/keymaps/keys_sp.h new file mode 100644 index 00000000..5f779050 --- /dev/null +++ b/cores/Spectrum/keymaps/keys_sp.h @@ -0,0 +1,118 @@ +/* + * keys_sp.h - ZX Spectrum keys definitions. + * + * SPDX-FileType: SOURCE + * SPDX-FileCopyrightText: 2022, 2023 Miguel Angel Rodriguez Jodar + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef KEYS_SP_H +#define KEYS_SP_H + +/* + * You shouldn't have to touch these defs unless your Spectrum has a different + * keyboard layout (because, for example, you are using a different ROM) + */ + +#define SP_1 0x61 +#define SP_2 0x62 +#define SP_3 0x64 +#define SP_4 0x68 +#define SP_5 0x70 + +#define SP_6 0x90 +#define SP_7 0x88 +#define SP_8 0x84 +#define SP_9 0x82 +#define SP_0 0x81 + +#define SP_Q 0x41 +#define SP_W 0x42 +#define SP_E 0x44 +#define SP_R 0x48 +#define SP_T 0x50 + +#define SP_Y 0xB0 +#define SP_U 0xA8 +#define SP_I 0xA4 +#define SP_O 0xA2 +#define SP_P 0xA1 + +#define SP_A 0x21 +#define SP_S 0x22 +#define SP_D 0x24 +#define SP_F 0x28 +#define SP_G 0x30 + +#define SP_H 0xD0 +#define SP_J 0xC8 +#define SP_K 0xC4 +#define SP_L 0xC2 +#define SP_ENTER 0xC1 + +#define SP_CAPS 0x01 /* CAPS SHIFT */ +#define SP_Z 0x02 +#define SP_X 0x04 +#define SP_C 0x08 +#define SP_V 0x10 + +#define SP_B 0xF0 +#define SP_N 0xE8 +#define SP_M 0xE4 +#define SP_SYMBOL 0xE2 /* SYMBOL SHIFT */ +#define SP_SPACE 0xE1 + +#define SP_EDIT (SP_CAPS<<8) | SP_1 /* EDIT */ +#define SP_CPSLOCK (SP_CAPS<<8) | SP_2 /* CAPS LOCK */ +#define SP_TRUE (SP_CAPS<<8) | SP_3 /* TRUE VIDEO */ +#define SP_INVERSE (SP_CAPS<<8) | SP_4 /* INVERSE VIDEO */ +#define SP_LEFT (SP_CAPS<<8) | SP_5 /* LEFT ARROW */ +#define SP_DOWN (SP_CAPS<<8) | SP_6 /* DOWN ARROW */ +#define SP_UP (SP_CAPS<<8) | SP_7 /* UP ARROW */ +#define SP_RIGHT (SP_CAPS<<8) | SP_8 /* RIGHT ARROW */ +#define SP_GRAPH (SP_CAPS<<8) | SP_9 /* GRAPHICS MODE */ +#define SP_DELETE (SP_CAPS<<8) | SP_0 /* DELETE */ + +#define SP_EXTEND (SP_CAPS<<8) | SP_SYMBOL /* EXTEND MODE */ +#define SP_BREAK (SP_CAPS<<8) | SP_SPACE /* BREAK */ + +#define SP_BANG (SP_SYMBOL<<8) | SP_1 /* ! */ +#define SP_AT (SP_SYMBOL<<8) | SP_2 /* @ */ +#define SP_HASH (SP_SYMBOL<<8) | SP_3 /* # */ +#define SP_DOLLAR (SP_SYMBOL<<8) | SP_4 /* $ */ +#define SP_PERCEN (SP_SYMBOL<<8) | SP_5 /* % */ +#define SP_AMP (SP_SYMBOL<<8) | SP_6 /* & */ +#define SP_APOSTRO (SP_SYMBOL<<8) | SP_7 /* ' */ +#define SP_PAROPEN (SP_SYMBOL<<8) | SP_8 /* ( */ +#define SP_PARCLOS (SP_SYMBOL<<8) | SP_9 /* ) */ +#define SP_UNDERSC (SP_SYMBOL<<8) | SP_0 /* _ */ + +#define SP_LESSEQ (SP_SYMBOL<<8) | SP_Q /* <= */ +#define SP_NOTEQ (SP_SYMBOL<<8) | SP_W /* != */ +#define SP_GREATEQ (SP_SYMBOL<<8) | SP_E /* >= */ +#define SP_LESS (SP_SYMBOL<<8) | SP_R /* < */ +#define SP_GREATER (SP_SYMBOL<<8) | SP_T /* > */ +#define SP_BRAOPEN (SP_SYMBOL<<8) | SP_Y /* [ */ +#define SP_BRACLOS (SP_SYMBOL<<8) | SP_U /* ] */ +#define SP_SEMICOL (SP_SYMBOL<<8) | SP_O /* ; */ +#define SP_QUOTE (SP_SYMBOL<<8) | SP_P /* " */ + +#define SP_TILDE (SP_SYMBOL<<8) | SP_A /* ~ */ +#define SP_PIPE (SP_SYMBOL<<8) | SP_S /* | */ +#define SP_BACKSLA (SP_SYMBOL<<8) | SP_D /* \ */ +#define SP_CUROPEN (SP_SYMBOL<<8) | SP_F /* { */ +#define SP_CURCLOS (SP_SYMBOL<<8) | SP_G /* } */ +#define SP_CARET (SP_SYMBOL<<8) | SP_H /* ^ */ +#define SP_MINUS (SP_SYMBOL<<8) | SP_J /* - */ +#define SP_PLUS (SP_SYMBOL<<8) | SP_K /* + */ +#define SP_EQUAL (SP_SYMBOL<<8) | SP_L /* = */ + +#define SP_COLON (SP_SYMBOL<<8) | SP_Z /* : */ +#define SP_POUND (SP_SYMBOL<<8) | SP_X /* £ */ +#define SP_QUEST (SP_SYMBOL<<8) | SP_C /* ? */ +#define SP_SLASH (SP_SYMBOL<<8) | SP_V /* / */ +#define SP_STAR (SP_SYMBOL<<8) | SP_B /* * */ +#define SP_COMMA (SP_SYMBOL<<8) | SP_N /* , */ +#define SP_DOT (SP_SYMBOL<<8) | SP_M /* . */ + +#endif /* !KEYS_SP_H */