mirror of https://github.com/zxdos/zxuno.git
465 lines
15 KiB
C
465 lines
15 KiB
C
/*
|
|
This file is part of the ZXUNO Spectrum core.
|
|
Creation date is UNKNOWN by Miguel Angel Rodriguez Jodar
|
|
(c)2014-2020 ZXUNO association.
|
|
ZXUNO official repository: http://svn.zxuno.com/svn/zxuno
|
|
Username: guest Password: zxuno
|
|
Github repository for this core: https://github.com/mcleod-ideafix/zxuno_spectrum_core
|
|
|
|
ZXUNO Spectrum core 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.
|
|
|
|
ZXUNO Spectrum core 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 the ZXUNO Spectrum core. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
Any distributed copy of this file must keep this notice intact.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
typedef unsigned char BYTE;
|
|
/*
|
|
8 8
|
|
AAADDDDD AAADDDDD
|
|
|
|
AAA = semifila del teclado a modificar | esta información está
|
|
DDDDD = dato (AND negado con lo que haya) de esa semifila | repetida para dos teclas
|
|
|
|
Ej: en la dirección de memoria correspondiente al código de la tecla ESC,
|
|
que correspondería a la pulsación simultánea de CAPS SHIFT+SPACE, pondríamos:
|
|
00000001 11100001
|
|
Esto es: se activan las semifilas 0 y 7, y en cada una, se activa el bit 0
|
|
|
|
128 codigos + E0 = 256 codigos
|
|
SHIFT, CTRL, ALT = 8 combinaciones
|
|
|
|
256*8=2048 direcciones x 16 bits = 32768 bits
|
|
En el core se dispondrá como una memoria de 4096x8 bits
|
|
|
|
Cada tecla ocupará dos direcciones consecutivas.
|
|
D+0 : tecla1 (o 0 si no la hay)
|
|
D+1 : tecla2 (o 0 si no la hay)
|
|
*/
|
|
|
|
// 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_0 0x81
|
|
#define SP_9 0x82
|
|
#define SP_8 0x84
|
|
#define SP_7 0x88
|
|
#define SP_6 0x90
|
|
|
|
#define SP_Q 0x41
|
|
#define SP_W 0x42
|
|
#define SP_E 0x44
|
|
#define SP_R 0x48
|
|
#define SP_T 0x50
|
|
|
|
#define SP_P 0xA1
|
|
#define SP_O 0xA2
|
|
#define SP_I 0xA4
|
|
#define SP_U 0xA8
|
|
#define SP_Y 0xB0
|
|
|
|
#define SP_A 0x21
|
|
#define SP_S 0x22
|
|
#define SP_D 0x24
|
|
#define SP_F 0x28
|
|
#define SP_G 0x30
|
|
|
|
#define SP_ENTER 0xC1
|
|
#define SP_L 0xC2
|
|
#define SP_K 0xC4
|
|
#define SP_J 0xC8
|
|
#define SP_H 0xD0
|
|
|
|
#define SP_CAPS 0x01
|
|
#define SP_Z 0x02
|
|
#define SP_X 0x04
|
|
#define SP_C 0x08
|
|
#define SP_V 0x10
|
|
|
|
#define SP_SPACE 0xE1
|
|
#define SP_SYMBOL 0xE2
|
|
#define SP_M 0xE4
|
|
#define SP_N 0xE8
|
|
#define SP_B 0xF0
|
|
|
|
#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_LESS (SP_SYMBOL<<8) | SP_R
|
|
#define SP_LESSEQ (SP_SYMBOL<<8) | SP_Q
|
|
#define SP_GREATER (SP_SYMBOL<<8) | SP_T
|
|
#define SP_GREATEQ (SP_SYMBOL<<8) | SP_E
|
|
#define SP_NOTEQ (SP_SYMBOL<<8) | SP_W
|
|
#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
|
|
|
|
#define SP_EXTEND (SP_CAPS<<8) | SP_SYMBOL
|
|
#define SP_EDIT (SP_CAPS<<8) | SP_1
|
|
#define SP_CPSLOCK (SP_CAPS<<8) | SP_2
|
|
#define SP_TRUE (SP_CAPS<<8) | SP_3
|
|
#define SP_INVERSE (SP_CAPS<<8) | SP_4
|
|
#define SP_LEFT (SP_CAPS<<8) | SP_5
|
|
#define SP_DOWN (SP_CAPS<<8) | SP_6
|
|
#define SP_UP (SP_CAPS<<8) | SP_7
|
|
#define SP_RIGHT (SP_CAPS<<8) | SP_8
|
|
#define SP_GRAPH (SP_CAPS<<8) | SP_9
|
|
#define SP_DELETE (SP_CAPS<<8) | SP_0
|
|
#define SP_BREAK (SP_CAPS<<8) | SP_SPACE
|
|
|
|
// END of Spectrum keys definitions
|
|
|
|
|
|
// A key can be pressed with up to three key modifiers
|
|
// which generates 8 combinations for each key
|
|
#define EXT 0x080
|
|
#define MD_SHIFT 0x100
|
|
#define MD_CTRL 0x200
|
|
#define MD_ALT 0x400
|
|
|
|
// Scan code 2 list. First, non localized keys
|
|
#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 // also )
|
|
#define PC_1 0x16 // also !
|
|
#define PC_2 0x1E // also @
|
|
#define PC_3 0x26 // also #
|
|
#define PC_4 0x25 // also $
|
|
#define PC_5 0x2E // also %
|
|
#define PC_6 0x36 // also ^
|
|
#define PC_7 0x3D // also &
|
|
#define PC_8 0x3E // also *
|
|
#define PC_9 0x46 // also (
|
|
|
|
#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 // not used. scan code>7F
|
|
#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
|
|
|
|
#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
|
|
#define PC_KP_0 0x70
|
|
#define PC_KP_1 0x69
|
|
#define PC_KP_2 0x72
|
|
#define PC_KP_3 0x7A
|
|
#define PC_KP_4 0x6B
|
|
#define PC_KP_5 0x73
|
|
#define PC_KP_6 0x74
|
|
#define PC_KP_7 0x6C
|
|
#define PC_KP_8 0x75
|
|
#define PC_KP_9 0x7D
|
|
|
|
// Localized keyboards start to differenciate from here
|
|
|
|
// Localized keyboard US
|
|
#define PC_GRAVEAC 0x0E // also ~
|
|
#define PC_MINUS 0x4E // also _
|
|
#define PC_EQUAL 0x55 // also +
|
|
#define PC_BRAOPEN 0x54 // also {
|
|
#define PC_BRACLOS 0x5B // also }
|
|
#define PC_BACKSLA 0x5D // also |
|
|
#define PC_SEMICOL 0x4C // also :
|
|
#define PC_APOSTRO 0x52 // also "
|
|
#define PC_COMMA 0x41 // also <
|
|
#define PC_DOT 0x49 // also >
|
|
#define PC_SLASH 0x4A // also ?
|
|
|
|
#define MAP(pc,sp) { \
|
|
rom[(pc)*2] = (((sp)>>8)&0xFF); \
|
|
rom[(pc)*2+1] = (((sp))&0xFF); \
|
|
}
|
|
|
|
#define MAPANY(pc,sp) { \
|
|
MAP((pc),(sp)); \
|
|
MAP(MD_SHIFT|(pc),(sp)); \
|
|
MAP(MD_CTRL|(pc),(sp)); \
|
|
MAP(MD_ALT|(pc),(sp)); \
|
|
MAP(MD_SHIFT|MD_CTRL|(pc),(sp)); \
|
|
MAP(MD_SHIFT|MD_ALT|(pc),(sp)); \
|
|
MAP(MD_CTRL|MD_ALT|(pc),(sp)); \
|
|
MAP(MD_SHIFT|MD_CTRL|MD_ALT|(pc),(sp)); \
|
|
}
|
|
|
|
#define CLEANMAP { \
|
|
int i; \
|
|
for (i=0;i<(sizeof(rom)/sizeof(rom[0]));i++) \
|
|
rom[i] = 0; \
|
|
}
|
|
#define SAVEMAP1HEX(name) { \
|
|
FILE *f; \
|
|
int i; \
|
|
f=fopen(name,"w"); \
|
|
for(i=0;i<(sizeof(rom)/sizeof(rom[0]));i+=2) \
|
|
fprintf(f,"%.2X\n",rom[i]); \
|
|
fclose(f); \
|
|
}
|
|
|
|
#define SAVEMAP2HEX(name) { \
|
|
FILE *f; \
|
|
int i; \
|
|
f=fopen(name,"w"); \
|
|
for(i=1;i<(sizeof(rom)/sizeof(rom[0]));i+=2) \
|
|
fprintf(f,"%.2X\n",rom[i]); \
|
|
fclose(f); \
|
|
}
|
|
|
|
#define SAVEMAPBIN(name) { \
|
|
FILE *f; \
|
|
f=fopen(name,"wb"); \
|
|
fwrite (rom, 1, sizeof(rom), f); \
|
|
fclose(f); \
|
|
}
|
|
|
|
|
|
int main()
|
|
{
|
|
BYTE rom[4096];
|
|
|
|
CLEANMAP;
|
|
|
|
MAPANY(PC_LWIN,SP_CAPS); // CAPS SHIFT
|
|
MAPANY(PC_LCTRL,SP_CAPS); // CAPS SHIFT
|
|
MAPANY(PC_RWIN,SP_SYMBOL); // SYMBOL SHIFT
|
|
MAPANY(PC_APPS,SP_SYMBOL); // SYMBOL SHIFT
|
|
MAPANY(PC_RCTRL,SP_SYMBOL); // SYMBOL SHIFT
|
|
|
|
// Basic mapping: each key from PC is mapped to a key in the Spectrum
|
|
MAP(PC_1,SP_1);
|
|
MAP(PC_2,SP_2);
|
|
MAP(PC_3,SP_3);
|
|
MAP(PC_4,SP_4);
|
|
MAP(PC_5,SP_5);
|
|
MAP(PC_6,SP_6);
|
|
MAP(PC_7,SP_7);
|
|
MAP(PC_8,SP_8);
|
|
MAP(PC_9,SP_9);
|
|
MAP(PC_0,SP_0);
|
|
|
|
MAP(PC_Q,SP_Q);
|
|
MAP(PC_W,SP_W);
|
|
MAP(PC_E,SP_E);
|
|
MAP(PC_R,SP_R);
|
|
MAP(PC_T,SP_T);
|
|
MAP(PC_Y,SP_Y);
|
|
MAP(PC_U,SP_U);
|
|
MAP(PC_I,SP_I);
|
|
MAP(PC_O,SP_O);
|
|
MAP(PC_P,SP_P);
|
|
MAP(PC_A,SP_A);
|
|
MAP(PC_S,SP_S);
|
|
MAP(PC_D,SP_D);
|
|
MAP(PC_F,SP_F);
|
|
MAP(PC_G,SP_G);
|
|
MAP(PC_H,SP_H);
|
|
MAP(PC_J,SP_J);
|
|
MAP(PC_K,SP_K);
|
|
MAP(PC_L,SP_L);
|
|
MAP(PC_Z,SP_Z);
|
|
MAP(PC_X,SP_X);
|
|
MAP(PC_C,SP_C);
|
|
MAP(PC_V,SP_V);
|
|
MAP(PC_B,SP_B);
|
|
MAP(PC_N,SP_N);
|
|
MAP(PC_M,SP_M);
|
|
|
|
MAP(MD_SHIFT|PC_Q,SP_CAPS<<8|SP_Q);
|
|
MAP(MD_SHIFT|PC_W,SP_CAPS<<8|SP_W);
|
|
MAP(MD_SHIFT|PC_E,SP_CAPS<<8|SP_E);
|
|
MAP(MD_SHIFT|PC_R,SP_CAPS<<8|SP_R);
|
|
MAP(MD_SHIFT|PC_T,SP_CAPS<<8|SP_T);
|
|
MAP(MD_SHIFT|PC_Y,SP_CAPS<<8|SP_Y);
|
|
MAP(MD_SHIFT|PC_U,SP_CAPS<<8|SP_U);
|
|
MAP(MD_SHIFT|PC_I,SP_CAPS<<8|SP_I);
|
|
MAP(MD_SHIFT|PC_O,SP_CAPS<<8|SP_O);
|
|
MAP(MD_SHIFT|PC_P,SP_CAPS<<8|SP_P);
|
|
MAP(MD_SHIFT|PC_A,SP_CAPS<<8|SP_A);
|
|
MAP(MD_SHIFT|PC_S,SP_CAPS<<8|SP_S);
|
|
MAP(MD_SHIFT|PC_D,SP_CAPS<<8|SP_D);
|
|
MAP(MD_SHIFT|PC_F,SP_CAPS<<8|SP_F);
|
|
MAP(MD_SHIFT|PC_G,SP_CAPS<<8|SP_G);
|
|
MAP(MD_SHIFT|PC_H,SP_CAPS<<8|SP_H);
|
|
MAP(MD_SHIFT|PC_J,SP_CAPS<<8|SP_J);
|
|
MAP(MD_SHIFT|PC_K,SP_CAPS<<8|SP_K);
|
|
MAP(MD_SHIFT|PC_L,SP_CAPS<<8|SP_L);
|
|
MAP(MD_SHIFT|PC_Z,SP_CAPS<<8|SP_Z);
|
|
MAP(MD_SHIFT|PC_X,SP_CAPS<<8|SP_X);
|
|
MAP(MD_SHIFT|PC_C,SP_CAPS<<8|SP_C);
|
|
MAP(MD_SHIFT|PC_V,SP_CAPS<<8|SP_V);
|
|
MAP(MD_SHIFT|PC_B,SP_CAPS<<8|SP_B);
|
|
MAP(MD_SHIFT|PC_N,SP_CAPS<<8|SP_N);
|
|
MAP(MD_SHIFT|PC_M,SP_CAPS<<8|SP_M);
|
|
|
|
MAPANY(PC_SPACE,SP_SPACE);
|
|
MAPANY(PC_ENTER,SP_ENTER);
|
|
|
|
//Complex mapping. This is for the US keyboard although many
|
|
//combos can be used with any other PC keyboard
|
|
MAPANY(PC_ESC,SP_BREAK);
|
|
MAPANY(PC_CPSLOCK,SP_CPSLOCK);
|
|
MAPANY(PC_TAB,SP_EXTEND);
|
|
MAP(PC_BKSPACE,SP_DELETE);
|
|
MAPANY(PC_UP,SP_UP);
|
|
MAPANY(PC_DOWN,SP_DOWN);
|
|
MAPANY(PC_LEFT,SP_LEFT);
|
|
MAPANY(PC_RIGHT,SP_RIGHT);
|
|
MAPANY(PC_F2,SP_EDIT);
|
|
|
|
MAP(PC_F10,SP_GRAPH); // F10 habilita el modo gráfico. Esto es para Antonio, para la BIOS
|
|
|
|
//keypad
|
|
MAPANY(PC_KP_DIVIS,SP_SLASH);
|
|
MAPANY(PC_KP_MULT,SP_STAR);
|
|
MAPANY(PC_KP_MINUS,SP_MINUS);
|
|
MAPANY(PC_KP_PLUS,SP_PLUS);
|
|
MAPANY(PC_KP_ENTER,SP_ENTER);
|
|
|
|
//Some keys and shift+key mappings for the US keyboard
|
|
MAP(MD_SHIFT|PC_1,SP_BANG);
|
|
MAP(MD_SHIFT|PC_2,SP_AT);
|
|
MAP(MD_SHIFT|PC_3,SP_HASH);
|
|
MAP(MD_SHIFT|PC_4,SP_DOLLAR);
|
|
MAP(MD_SHIFT|PC_5,SP_PERCEN);
|
|
MAP(MD_SHIFT|PC_6,SP_CARET);
|
|
MAP(MD_SHIFT|PC_7,SP_AMP);
|
|
MAP(MD_SHIFT|PC_8,SP_STAR);
|
|
MAP(MD_SHIFT|PC_9,SP_PAROPEN);
|
|
MAP(MD_SHIFT|PC_0,SP_PARCLOS);
|
|
MAP(PC_MINUS,SP_MINUS);
|
|
MAP(MD_SHIFT|PC_MINUS,SP_UNDERSC);
|
|
MAP(PC_EQUAL,SP_EQUAL);
|
|
MAP(MD_SHIFT|PC_EQUAL,SP_PLUS);
|
|
MAP(PC_BRAOPEN,SP_BRAOPEN);
|
|
MAP(MD_SHIFT|PC_BRAOPEN,SP_CUROPEN);
|
|
MAP(PC_BRACLOS,SP_BRACLOS);
|
|
MAP(MD_SHIFT|PC_BRACLOS,SP_BRACLOS);
|
|
MAP(PC_BACKSLA,SP_BACKSLA);
|
|
MAP(MD_SHIFT|PC_BACKSLA,SP_PIPE);
|
|
MAP(PC_APOSTRO,SP_APOSTRO);
|
|
MAP(MD_SHIFT|PC_APOSTRO,SP_QUOTE);
|
|
MAP(PC_COMMA,SP_COMMA);
|
|
MAP(MD_SHIFT|PC_COMMA,SP_LESS);
|
|
MAP(PC_DOT,SP_DOT);
|
|
MAP(MD_SHIFT|PC_DOT,SP_GREATER);
|
|
MAP(PC_SLASH,SP_SLASH);
|
|
MAP(MD_SHIFT|PC_SLASH,SP_QUEST);
|
|
MAP(PC_SEMICOL,SP_SEMICOL);
|
|
MAP(MD_SHIFT|PC_SEMICOL,SP_COLON);
|
|
|
|
// End of mapping. Save .HEX file for Verilog
|
|
//SAVEMAP1HEX("keyb1_us_hex.txt");
|
|
//SAVEMAP2HEX("keyb2_us_hex.txt");
|
|
// And map file for loading from ESXDOS
|
|
SAVEMAPBIN("US");
|
|
|
|
return 0;
|
|
}
|