koreth@ssyx.ucsc.edu (Steven Grimm) (02/25/89)
Submitted-by: uunet!mcvax!cwi.nl!eddy (Eddy Boeve)
Posting-number: Volume 2, Issue 14
Archive-name: keyfix
Here is a program to fix the 'gulam.prg' binary for non-american keyboards.
You do not have to edit the program, just run it. The program does the
rest. The binary is also being posted in comp.binaries.atari.st.
/*
* keyfix.c -- Utility for Gulam
*
* Original version: copyright (c) 1986, 1987 pm@cwru.edu
*
* Rewrite : eddyright (e) 1989 eddy@cwi.nl
*
* This is an utility for GULAM to patch the default key bindings
* in the 'gulam.prg' binary. It was originally created by
* 'pm@cwru.edu' to change the USA key bindings for us Europeans
* and contained a 3*128 table with the desired new bindings.
*
* This version is different because you don't have to edit it for
* your own machine. It works out for itself what keys produce what
* characters.
*
* This program takes your default key translation tables via the
* XBIOS function 'Keytbl' and adds the GULAM function, arrow and
* keypad key translations. (Why Gulam doesn't do this is unclear).
* If you already have a USA key binding, everything will stay the
* same. Otherwise the '@~#\|$' keys will hopefully appear under the
* right button.
*
* Compile 'kmpfix.c'. Run the resulting program from the directory
* that contains the 'gulam.prg'.
* The new version of 'gulam.prg' (with the new key mapping) will be
* written out as 'gulamnew.prg' in the current directory.
*
* Below we define ST520/1040 keynames; the values are the ascii codes
* returned by ST BIOS.
*
* The values below are chosen to have certain patterns:
*
* to SHIFT add 0040
* F1-10 0201 to 0212
* keypad 0-9 0260 to 0272 (subtract -0200 to get ascii digits)
* keypad()/ *-+.cr add 0300 to the ascii ()/ *-+.cr
*
* Other choices may be better, I don't know. However, I think it is
* unwise to use numbers in the range 0000 to 0177, because they are
* regular ascii codes.
*
* If you want to change some bindings, do it in the routine
* 'copy_map':
* kn['scan_code'] = 'ascii_code';
*
* Exit values:
* 0 : No errors,
* -1 : Error in finding key map in binary,
* -2 : Error in memory allocation,
* -3 : Error in file reading/writing.
*/
#include <osbind.h>
#include <xbios.h>
#include <bios.h>
#define GULAM_SIZE (100000L) /* Number larger than size gulam
* program (in bytes) */
/*
* These 'KC_' scan code values are not defined in <bios.h>
*/
#define KC_KLP 0x63 /* Keypad ( */
#define KC_KRP 0x64 /* Keypad ) */
#define KC_KSTAR 0x66 /* Keypad * */
#define KC_KPLUS 0x4E /* Keypad + */
#define KC_KENT 0x72 /* Keypad Enter */
#define KC_KMINUS 0x4A /* Keypad - */
#define KC_KDOT 0x71 /* Keypad . */
#define KC_KSLASH 0x65 /* Keypad / */
#define KC_K0 0x70 /* Keypad 0 */
#define KC_K1 0x6D /* Keypad 1 */
#define KC_K2 0x6E /* Keypad 2 */
#define KC_K3 0x6F /* Keypad 3 */
#define KC_K4 0x6A /* Keypad 4 */
#define KC_K5 0x6B /* Keypad 5 */
#define KC_K6 0x6C /* Keypad 6 */
#define KC_K7 0x67 /* Keypad 7 */
#define KC_K8 0x68 /* Keypad 8 */
#define KC_K9 0x69 /* Keypad 9 */
/*
* ST520/1040 keynames
*/
#define F1 0201
#define F2 0202
#define F3 0203
#define F4 0204
#define F5 0205
#define F6 0206
#define F7 0207
#define F8 0210
#define F9 0211
#define F10 0212
#define HELP 0213
#define UNDO 0214
#define INSERT 0215
#define HOME 0216
#define UPARRO 0273
#define DNARRO 0274
#define LTARRO 0275
#define RTARRO 0276
#define KLP 0300
#define KRP 0301
#define KSTAR 0302
#define KPLUS 0303
#define KENTER 0304
#define KMINUS 0305
#define KDOT 0306
#define KSLASH 0307
#define K0 0260
#define K1 0261
#define K2 0262
#define K3 0263
#define K4 0264
#define K5 0265
#define K6 0266
#define K7 0267
#define K8 0270
#define K9 0271
/*
* The above are the unshifted values. Shifted, as well as
* 'capslocked' (for only these keys) values that I use are these +0040.
*/
#define SHIFTED 0040
#define UNSHIFTED_MODE 0 /* Normal (unshifted) mode */
#define SHIFTED_MODE 1 /* With shift key pressed */
#define CAPSLOCK_MODE 2 /* With capslock key pressed */
static
char *mode_string [] =
{
"Unshifted Mode", /* Mode_string[UNSHIFTED_MODE] */
"Shifted Mode", /* Mode_string[SHIFTED_MODE] */
"Capslock Mode" /* Mode_string[CAPSLOCK_MODE] */
};
/*
* Error ( string, ec)
*
* Write string and exit (ec).
*/
Error (str, ec)
char *str;
int ec;
{
printf ("Error: ** %s **\n", str);
exit (ec);
} /* error */
/*
* copy_map (mode, k_orig, k_new)
*
* This routine will copy the contents of 'k_orig' (the original
* keyboard's translation table for mode 'mode', obtained by the
* xbios function 'Keytbl') to the new defined translation table
* 'k_new'. Also the function/arrow/keypad key entries in 'k_new'
* will be changed to the preferred Gulam settings.
*/
void copy_map (mode, k_orig, k_new)
register short mode;
char *k_orig, /* Pointer to original key table for 'mode' */
*k_new; /* New defined key table for Gulam */
{
register char *ko = k_orig,
*kn = k_new;
register int i,
offset = 0; /* If shifted mode, add this */
printf ("Changing keyboard translation table (%s) at %06lx.\n",
mode_string[mode], k_orig);
for (i=0; i<128; i++)
kn[i] = ko[i];
/*
* Change Function/Arrow/Keypad keys
* Here you can add/change entries.
*/
if (mode == SHIFTED_MODE)
offset = SHIFTED;
kn[KC_F1] = F1 + offset;
kn[KC_F2] = F2 + offset;
kn[KC_F3] = F3 + offset;
kn[KC_F4] = F4 + offset;
kn[KC_F5] = F5 + offset;
kn[KC_F6] = F6 + offset;
kn[KC_F7] = F7 + offset;
kn[KC_F8] = F8 + offset;
kn[KC_F9] = F9 + offset;
kn[KC_F10] = F10 + offset;
kn[KC_HELP] = HELP + offset;
kn[KC_UNDO] = UNDO + offset;
kn[KC_INS] = INSERT + offset;
kn[KC_CLR] = HOME + offset;
kn[KC_CUP] = UPARRO + offset;
kn[KC_CDOWN] = DNARRO + offset;
kn[KC_CLEFT] = LTARRO + offset;
kn[KC_CRIGHT] = RTARRO + offset;
kn[KC_KLP] = KLP + offset;
kn[KC_KRP] = KRP + offset;
kn[KC_KSLASH] = KSLASH + offset;
kn[KC_KSTAR] = KSTAR + offset;
kn[KC_KPLUS] = KPLUS + offset;
kn[KC_KENT] = KENTER + offset;
kn[KC_KMINUS] = KMINUS + offset;
kn[KC_KDOT] = KDOT + offset;
kn[KC_K0] = K0 + offset;
kn[KC_K1] = K1 + offset;
kn[KC_K2] = K2 + offset;
kn[KC_K3] = K3 + offset;
kn[KC_K4] = K4 + offset;
kn[KC_K5] = K5 + offset;
kn[KC_K6] = K6 + offset;
kn[KC_K7] = K7 + offset;
kn[KC_K8] = K8 + offset;
kn[KC_K9] = K9 + offset;
} /* copy_map */
/*
* Return offset in the binary file gulam.prg where the keymap[] begins.
* 80336 (decimal) is this number valid for beta-version
* 1.03.04.05 (121887).
*/
char * kmpbgn(buf, n)
register char *buf;
register long n;
{
/* kmp[] is extracted from Gulam's src; do NOT change it. */
static char kmp[16] = {
/* -------scan codes: 0x00-0x0f --------------- */
'\000' /*nul*/, '\033' /*esc*/,
'1' , '2' , '3' , '4' , '5' , '6' ,
'7' , '8' , '9' , '0' , '-' , '=' ,
'\010' /* bs*/, '\011' /* ht*/
};
register long i;
register int j;
register char *p, *q;
for (i = 0L; i < n; i++)
{ p = &buf[i]; q = kmp;
for (j = 0; j < 16; j++)
if (*p++ != *q++) break;
if (j == 16) goto found;
}
Error ("key map begin not found!", -1);
found: printf("Key map begins at byte %ld\r\n", i);
return &buf[i];
}
main()
{
struct keytbl *kp;
register char *buf, *q;
register int i;
register long n, m;
register unsigned long lsz;
lsz = GULAM_SIZE; /* Enough space to hold entire
* gulam.prg! */
buf = (char *) Malloc(lsz);
if (buf == 0L)
Error ("can't Malloc", -2);
/* read all of gulam.prg into buf */
i = Fopen("gulam.prg", 0);
if (i <= 0)
Error ("gulam.prg not found", -3);
n = Fread(i, lsz, buf);
if (n <= 0L)
Error ("error reading file", -3);
else
if (n == GULAM_SIZE)
Error ("gulam.prg probably bigger", -3);
Fclose(i);
/*
* Get the keymap beginning in 'gulam.prg'
*/
q = kmpbgn(buf, n);
/*
* Fix the keymap tables
*/
kp = Keytbl (-1L,-1L,-1L); /* Get keytable structure */
copy_map (UNSHIFTED_MODE, kp->kt_normal, (char *) q );
copy_map (SHIFTED_MODE, kp->kt_shifted, (char *) (q + 128) );
copy_map (CAPSLOCK_MODE, kp->kt_capslock, (char *) (q + 256) );
/* write the new gulam.prg out */
i = Fcreate("gulamnew.prg", 0);
if (i <= 0)
Error ("could not create gulamnew.prg", -3);
m = Fwrite(i, n, buf);
if (m != n)
Error ("error writing file", -3);
Fclose(i);
printf("new version of gulam is gulamnew.prg\n\n");
} /* main */