spazi shifts spazi scan spazi nuovo_scan spazi ascii spazi commento
spazi | uno o più spazi o tabulazioni. Possono anche non essere presenti. |
shifts | uno dei seguenti caratteri o una loro combinazione (senza
spazi tra un carattere e l'altro):
A ALT C CTRL L LEFT SHIFT R RIGHT SHIFT N Nessuno shift Lo shift N è ignorato se non e' il solo presente. |
spazi | uno o più spazi o tabulazioni. |
scan | scan code del tasto da ridefinire (2 cifre esadecimali). |
spazi | uno o più spazi o tabulazioni. |
nuovo_scan | nuovo scan code per il tasto (2 cifre esadecimali). Può essere uguale a SCAN. |
spazi | uno o più spazi o tabulazioni. |
ascii | ASCII code per il tasto (2 cifre esadecimali). |
spazi | uno o più spazi o tabulazioni. |
commento | è opzionale e non ha formato particolare. |
CA 01 1C 0D - Il tasto ESC, premuto con CTRL e ALT, equivale a ENTER.Gli shift sono indicati all'inizio della riga: CA significa CTRL ALT. Uno spazio separa gli shift dallo scan code del tasto: 01 è il tasto ESC. Il nuovo scan code (cioè lo scan code che viene inserito nel buffer di tastiera alla pressione di CTRL ALT ESC è 1C (lo scan code del tasto RETURN). Il nuovo codice ASCII da inserire nel buffer è 0D, corrispondente anch'esso al tasto RETURN. Tutto ciò che segue 0D, sino alla fine della riga, rappresenta un commento ed è ignorato dal programma.
/************************************************************************** KBDPLUS.C - KBDPLUS - Barninga_Z! 1991 Ridefinitore di tastiera. Modalita' di funzionamento. Legge un file in formato ASCII e in base al suo contenuto ridefinisce la tastiera. Ogni riga del file deve essere lunga al massimo 80 caratteri ed e' strutturata come segue: shf spc scc spc nsc spc asc spc commento crlf dove: spc.......uno o piu' blanks o tabs. Possono anche essere presenti prima di shifts; in tal caso saranno ignorati. shf.......uno dei seguenti caratteri o una loro combinazione (senza spazi tra un carattere e l'altro): A ALT C CTRL L LEFT SHIFT R RIGHT SHIFT N Nessuno shift (ignorato se non e' il solo presente). scc.......scan code in esadecimale (2 cifre) del tasto da ridefinire. nsc.......nuovo scan code in esadecimale (2 cifre) per il tasto. Puo' essere uguale a scancode. asc.......codice ascii in esadecimale (2 cifre) per il tasto. commento..e' opzionale e non ha formato particolare. crlf......sequenza CR LF che chiude ogni riga di testo. Esempio di riga che ridefinisce CTRL ALT ESC: CA 01 1C 0D - Il tasto ESC, premuto con CTRL e ALT, equivale a ENTER. KBDPLUS accetta, alternativamente al nome di file, due parametri: KBDPLUS ? produce la visualizzazione di uno schermo di aiuto; KBDPLUS * provoca la disinstallazione del programma (purche' esso sia gia' presente in RAM). Compilato sotto BORLAND C++ 2.0: tcc -O -d -rd -k- -Tm2 kbdplus.C **************************************************************************/ #pragma inline #pragma warn -pia #pragma option -k- /* attenzione: non serve la std stack frame */ #include <dos.h> #include <stdio.h> #include <string.h> #define PRG "KBDPLUS" /* nome del programma */ #define YEAR "1991" /* anno */ #define PSPENVOFF 0x2C /* offset, nel PSP, del ptr all'environment */ #define ALT_V ((char)8) #define CTRL_V ((char)4) #define LSHF_V ((char)2) #define RSHF_V ((char)1) #define NONE_V ((char)0) #define ALT_C 'A' #define CTRL_C 'C' #define LSHF_C 'L' #define RSHF_C 'R' #define NONE_C 'N' #define SHFMASK 0x0F /* shift status mask (elimina NumLock, etc.) */ #define INKEYPORT 0x60 /* porta di input della tastiera */ #define CTRKEYPORT 0x61 /* porta di controllo della tastiera */ #define ENABLEKBBIT 0x80 /* bit di abilitazione della tastiera */ #define E_O_I 0x20 /* segnale di fine interrupt */ #define I_CTRPORT 0x20 /* porta di controllo degli interrupt */ #define KBDOFF 0x3FE /* off di seg implicito nei puntatori - 2 */ #define MAXLEN 83 /* n. max di carat. in ogni riga del file dati */ #define BLANK ' ' /* spazio bianco (ascii 32) */ #define ARRDIM 360 /* dimensione della func-array Dummy() (90*4)*/ #define TSR_TEST 0xAD /* HANDSHAKE per TSR */ #define TSR_YES 0xEDAF /* se installato risponde cosi' al test */ #define TSR_INST 0x00 /* serv. 0 int 2Fh. Testa se installato */ #define TSR_FREE 0x01 /* serv. 1 int 2Fh. Disinstalla il TSR */ #define DEFEXT ".DEF" /* il file di default e' KBDPLUS.DEF */ #define HELP_REQUEST '?' /* opzione cmd line per richiedere help */ #define FREE_REQUEST '*' /* opzione cmd line per disinstall. TSR */ #define int09h ((void(interrupt *)())*(((long *)Dummy)+0)) /* off 0 */ #define int2Fh ((void(interrupt *)())*(((long *)Dummy)+1)) /* off 4 */ #define ShiftFlag (*((char far *)*(((int *)Dummy)+4))) /* offset 8 */ #define HeadPtr (*((int far *)*(((int *)Dummy)+5))) /* offset 10 */ #define TailPtr (*((int far *)*(((int *)Dummy)+6))) /* offset 12 */ #define StartPtr (*((int far *)*(((int *)Dummy)+7))) /* offset 14 */ #define EndPtr (*((int far *)*(((int *)Dummy)+8))) /* offset 16 */ #define nk (*(((int *)Dummy)+9)) /* offset 18 */ #define ResPSP (*(((unsigned *)Dummy)+10)) /* offset 20 */ #define keys (((struct KbDef far *)Dummy)+6) /* offset 24 */ #define int09h_asm Dummy /* usata nell'inline assembly */ #define int2Fh_asm Dummy+4 /* usata nell'inline assembly */ #define ResPSP_asm Dummy+20 /* usata nell'inline assembly */ extern unsigned cdecl _heaplen = 8000; /* riduce ingombro al caricamento */ struct KbDef { /* struttura per la gestione della tastiera */ char shf; /* shifts usati per ridefinire il tasto */ char scan; /* scan code originale del tasto */ char nwscn; /* nuovo scan code del tasto */ char nwasc; /* nuovo codice ASCII del tasto */ }; struct ShfFlag { /* struttura di definizione dei possibili shifts */ char kc; /* carattere usato per rappresentare lo shift */ char kv; /* valore dello shift status byte */ } shf[] = { {ALT_C,ALT_V}, {CTRL_C,CTRL_V}, {LSHF_C,LSHF_V}, {RSHF_C,RSHF_V}, {NONE_C,NONE_V} /* NONE deve essere l'ultimo item (ultimo .kv = 0) */ }; void Dummy(void); /* necessaria per JMP in newint09h() e newint16h() */ void far newint09h(void) /* handler int 09h */ { int i; asm { push ax; push bx; push cx; push dx; push es; } for(i = 0; i < nk; i++) { /* scandisce tabella ridefinizioni */ if((ShiftFlag & SHFMASK) == keys[i].shf) { asm in al,INKEYPORT; asm mov cl,al; /* salva al; ax e' usato per i puntatori */ if(_CL == keys[i].scan) { TailPtr += 2; if(TailPtr == HeadPtr || (TailPtr == EndPtr && HeadPtr == StartPtr)) { TailPtr -= 2; break; /* se il buffer e' pieno lascia al BIOS */ } _CH = keys[i].nwscn; _CL = keys[i].nwasc; *((int far *)((TailPtr)+KBDOFF)) = _CX; /* tasto --> buf */ if(TailPtr == EndPtr) /* se è in fondo al buffer */ TailPtr = StartPtr; /* aggiorna i puntatori */ asm { in al,CTRKEYPORT; /* legge lo stato della tastiera */ mov ah,al; /* lo salva */ or al,ENABLEKBBIT; /* setta il bit "enable kbd" */ out CTRKEYPORT,al; /* lo scrive sulla porta di ctrl */ xchg ah,al; /* riprende lo stato originale della tast. */ out CTRKEYPORT,al; /* e lo riscrive */ mov al,E_O_I; /* manda il segnale di fine Interrupt */ out I_CTRPORT,al; /* al controllore dell'8259 */ jmp _EXIT; } } } } asm { pop es; pop dx; pop cx; pop bx; pop ax; mov sp,bp; pop bp; jmp dword ptr int09h_asm; /* concatena handler originale */ } _EXIT: asm { pop es; pop dx; pop cx; pop bx; pop ax; mov sp,bp; pop bp; iret; /* ritorna al processo interrotto */ } } void far newint2Fh(void) /* gestore dell'int 2Fh */ { asm { cmp ah,TSR_TEST; /* la chiamata viene da KBDPLUS ? */ jne _CHAIN; /* no: salta */ cmp al,TSR_INST; /* si: e' richiesto il test di gia' installato ? */ jne _FREETSR; /* no: salta al servizio successivo */ mov ax,TSR_YES; /* si: carica AX con la "passwd" per restituirla */ iret; } _FREETSR: asm { cmp al,TSR_FREE; /* e' richiesta la disinstallazione ? */ jne _CHAIN; /* no: salta */ mov ax,offset Dummy; /* carica AX con l'offset di Dummy */ mov dx,seg Dummy; /* carica DX con il segmento di Dummy */ iret; } _CHAIN: asm jmp dword ptr int2Fh_asm; /* concatena gestore originale */ } void Dummy(void) /* spazio dati globali e strutture KbDef */ { asm { dd 0; /* punta all'int 09h */ dd 0; /* punta all'int 2Fh originale */ dw 0417h; /* punta allo shift status byte */ dw 041Ah; /* punta alla testa del kbd buf */ dw 041Ch; /* punta alla coda del kbd buf */ dw 0480h; /* punta all'inizio del kbd buf */ dw 0482h; /* punta alla fine del kbd buf */ dw 0; /* n. di ridefinizioni (nk) */ dw 0; /* PSP del TSR */ dw 0; /* tappo per sincronizzare gli offset */ db ARRDIM dup (0); /* spazio per strutture di template KbDef */ } } char *hlpmsg = "\n\ Type "PRG" ? for help; "PRG" * to uninstall.\n\ DATA FILE DESCRIPTION (if no name given, "PRG" tries for "PRG""DEFEXT"):\n\ Each line in the file redefines a key and has the following format:\n\ \n\ shifts spaces scan spaces newscan spaces ascii spaces comment crlf\n\ \n\ spaces...one or more blanks (or tabs).\n\ shifts...the combination of shift keys: one or more of the following:\n\ A (the ALT key)\n\ C (the CTRL key)\n\ L (the LEFT SHIFT key)\n\ R (the RIGHT SHIFT key)\n\ N (no shift has to be pressed with the redefined key)\n\ scan.....the hex scan code of the redefined key.\n\ newscan..the new hex scan code for the redefined key. Can be = <scan>.\n\ ascii....the hex ASCII code of the char for the redefined key.\n\ comment..optional entry; useful to scribble some remarks.\n\ crlf.....a CR LF seq. (End-of-line; max 80 chrs).\n\ \n\ CA 01 1C 0D Example that makes CTRL ALT ESC same as the ENTER key.\ "; /* stringa di help */ void release_env(void) /* libera environment del TSR */ { extern unsigned _envseg; asm { mov es,_envseg; /* ...carica in ES l'ind. di segmento dell'env. */ mov ah,0x49; /* chiede al DOS di liberare il MCB dell'environment */ int 0x21; } } int nibble(char c) /* 2 hex digit string ===> int */ { if(c > (char)0x29 && c < (char)0x40) return(c-'0'); return(((c <= 'Z') ? c : c-BLANK)-('A'-10)); } char *setcodes(char *bufptr,char far *code) /* legge i codici dal file */ { for(; *bufptr <= BLANK;) ++bufptr; *code = (char)((nibble(*bufptr) << 4) + nibble(*(++bufptr))); return(++bufptr); } void readdata(FILE *in) /* legge i codici e prepara tabella in memoria */ { char shift[MAXLEN], *bufptr; register int i, lim; lim = ARRDIM / sizeof(struct KbDef); for(; fgets(shift,MAXLEN,in) && nk < lim; nk++) { for(bufptr = shift; *bufptr <= BLANK;) ++bufptr; for(; *bufptr > BLANK;) ++bufptr; *bufptr = (char)NULL; for(i = 0; shf[i].kv; i++) if(strchr(shift,shf[i].kc)) keys[nk].shf |= shf[i].kv; bufptr = setcodes(bufptr,&(keys[nk].scan)); bufptr = setcodes(bufptr,&(keys[nk].nwscn)); setcodes(bufptr,&(keys[nk].nwasc)); } } int readfile(int argc,char **argv) /* apre e chiude il file */ { FILE *in; strcpy(strrchr(argv[0],'.'),DEFEXT); for(; argc;) /* ipotesi: ogni parm in cmdline = nome di file */ if(in = fopen(argv[--argc],"rb")) { printf(PRG": found %s. Reading...\n",argv[argc]); readdata(in); fclose(in); break; } else printf(PRG": %s not found.\n",argv[argc]); return(nk); } int resparas(void) /* calcola paragrafi residenti indispensabili */ { return(FP_SEG(keys)+((FP_OFF(keys)+nk*sizeof(struct KbDef)) >> 4)+1-_psp); } int tsrtest(void) /* controlla se gia' residente */ { asm { mov ah,TSR_TEST; mov al,TSR_INST; int 0x2F; cmp ax,TSR_YES; je _RESIDENT; xor ax,ax; } _RESIDENT: return(_AX); } void uninstall(void) /* disinstalla KBDPLUS residente */ { void far * ResDataPtr; asm { mov ah,TSR_TEST; mov al,TSR_FREE; int 0x2F; mov word ptr ResDataPtr,ax; /* DX:AX e' l'ind. della Dummy resid. */ mov word ptr ResDataPtr+2,dx; /* e va gestito in back-words */ } setvect(0x09,(void(interrupt *)())(*((long far *)ResDataPtr))); setvect(0x2F,(void(interrupt *)())(*(((long far *)ResDataPtr)+1))); _ES = *(((unsigned far *)ResDataPtr)+10); asm { mov ah,0x49; /* chiede al DOS di liberare il MCB del PSP del TSR */ int 0x21; } } void install(void) /* installa TSR KBDPLUS */ { asm cli; int09h = getvect(0x09); int2Fh = getvect(0x2F); setvect(0x09,(void(interrupt *)())newint09h); setvect(0x2F,(void(interrupt *)())newint2Fh); asm sti; ResPSP = _psp; release_env(); printf(PRG": Installed... %d key redefinition(s).\n",nk); keep(0,resparas()); /* TSR ! */ } void main(int argc,char **argv) { printf(PRG": Keyboard ReDef Utility - Barninga_Z! "YEAR"\n"); if(argv[1][0] == HELP_REQUEST) printf(PRG": help screen.\n%s",hlpmsg); else if(tsrtest()) if(argv[1][0] == FREE_REQUEST) { uninstall(); printf(PRG": Uninstalled: original keys restored.\n"); } else printf(PRG": Already installed.\n%s",hlpmsg); else if(readfile(argc,argv)) install(); else printf(PRG": Invalid data file name or lines.\n%s",hlpmsg); }Il programma installa i gestori dell' int09h e dell' int2Fh. L'int 2Fh ha il compito di determinare se KBDPLUS è già presente in memoria e collabora alla disintallazione: esso controlla se in ingresso AH contiene il valore della costante manifesta TSR_TEST, nel qual caso valuta AL. Se questo contiene TSR_INST (il valore è 0 come suggerito da Microsoft) la routine restituisce in AX il valore TSR_YES, riconosciuto da tsrtest().
/****************************************************************************** KBDPLUS2.C - KBDPLUS 2.5 - Barninga_Z! 14-06-93 Ridefinitore di tastiera. Modalita' di funzionamento. Legge un file in formato ASCII e in base al suo contenuto ridefinisce la tastiera. Ogni riga del file deve essere lunga max. 80 caratteri ed e' strutturata come segue: shf spc scc spc nsc spc asc spc commento crlf dove: spc.......uno o piu' blanks o tabs. Possono anche essere presenti prima di shifts; in tal caso saranno ignorati. shf.......uno dei seguenti caratteri o una loro combinazione (senza spazi tra un carattere e l'altro): A ALT G ALT GR C CTRL T CTRL RIGHT L LEFT SHIFT R RIGHT SHIFT N Nessuno shift (ignorato se non e' il solo presente). scc.......scan code in esadecimale (2 cifre) del tasto da ridefinire. nsc.......nuovo scan code in esadecimale (2 cifre) per il tasto. Puo' essere uguale a scancode. asc.......codice ascii in esadecimale (2 cifre) per il tasto. commento..e' opzionale e non ha formato particolare. crlf......sequenza CR LF che chiude ogni riga di testo. Esempio di riga che ridefinisce CTRL ALT ESC: CA 01 1C 0D - Il tasto ESC, premuto con CTRL e ALT, equivale a ENTER. Se gia' presente in RAM, KBDPLUS si riconosce e non si installa una seconda volta. KBDPLUS2 accetta, alternativamente al nome di file, due parametri: ?: KBDPLUS2 ? produce la visualizzazione di uno schermo di aiuto; *: KBDPLUS2 * provoca la disinstallazione del programma (purche' esso sia gia' presente in RAM). Compilato sotto TURBO C++ 3.1: tcc -O -d -rd -k- -Tm2 kbdplus2.c ******************************************************************************/ #pragma inline #pragma warn -pia #pragma option -k- // no std stack frame!! serve per assembly! #include <dos.h> #include <stdio.h> #include <string.h> #define PRG "KBDPLUS2" /* nome del programma */ #define VER "2.5" /* release */ #define YEAR "1993" /* anno */ #define PSPENVOFF 0x2C /* offset, nel PSP, del ptr all'environment */ #define ALT_V ((int)520) // 512 + 8 #define ALTGR_V ((int)8) // gestito con kbd st. byte (0x496) #define CTRL_V ((int)260) // 256 + 4 #define CTRLR_V ((int)4) #define LSHF_V ((int)2) #define RSHF_V ((int)1) #define NONE_V ((int)0) #define ALT_C 'A' #define ALTGR_C 'G' #define CTRL_C 'C' #define CTRLR_C 'T' #define LSHF_C 'L' #define RSHF_C 'R' #define NONE_C 'N' #define SHFMASK 0x30F /* shift status mask per entrambi i bytes */ #define INKEYPORT 0x60 /* porta di input della tastiera */ #define CTRKEYPORT 0x61 /* porta di controllo della tastiera */ #define ENABLEKBBIT 0x80 /* bit di abilitazione della tastiera */ #define E_O_I 0x20 /* segnale di fine interrupt */ #define I_CTRPORT 0x20 /* porta di controllo degli interrupt */ #define KBSTBYTE 0x496 /* puntatore al keyboard status byte */ #define KBDOFF 0x3FE /* offset di seg implicito nei puntatori - 2 */ #define MAXLEN 83 /* n. max di carat. in ogni riga del file dati */ #define BLANK ' ' /* spazio bianco (ascii 32) */ #define ARRDIM 1280 /* dimensione della func-array Dummy() (256*5) */ #define TSR_TEST 0xAD /* HANDSHAKE per TSR */ #define TSR_YES 0xEDAF /* se instal., int 16 risponde cosi' al test */ #define TSR_INST 0x00 /* serv. 0 int 2Fh. Testa se installato */ #define TSR_FREE 0x01 /* serv. 1 int 2Fh. Disinstalla il TSR */ #define DEFEXT ".DEF" /* il file di default e' KBDPLUS.DEF */ #define HELP_REQUEST '?' /* opzione cmd line per richiedere help */ #define FREE_REQUEST '*' /* opzione cmd line per disinstall. TSR */ #define int09h ((void (interrupt *)())*(((long *)Dummy)+0)) /* offset 0 */ #define int2Fh ((void (interrupt *)())*(((long *)Dummy)+1)) /* offset 4 */ #define ShiftFlag (*((int far *)*(((int *)Dummy)+4))) /* offset 8 */ #define HeadPtr (*((int far *)*(((int *)Dummy)+5))) /* offset 10 */ #define TailPtr (*((int far *)*(((int *)Dummy)+6))) /* offset 12 */ #define StartPtr (*((int far *)*(((int *)Dummy)+7))) /* offset 14 */ #define EndPtr (*((int far *)*(((int *)Dummy)+8))) /* offset 16 */ #define nk (*(((int *)Dummy)+9)) /* offset 18 */ #define ResPSP (*(((unsigned *)Dummy)+10)) /* offset 20 */ #define keys ((struct KbDef far *)DummyFkeys) #define int09h_asm Dummy /* usata nell'inline assembly */ #define int2Fh_asm Dummy+4 /* usata nell'inline assembly */ #define ResPSP_asm Dummy+20 /* usata nell'inline assembly */ extern unsigned cdecl _heaplen = 8000; struct KbDef { int shf; char scan; char nwscn; char nwasc; }; struct ShfFlag { char kc; int kv; } shf[] = { {ALT_C,ALT_V}, {ALTGR_C,ALTGR_V}, // aggiunta 14-06-93 {CTRL_C,CTRL_V}, {CTRLR_C,CTRLR_V}, // aggiunta 14-06-93 {LSHF_C,LSHF_V}, {RSHF_C,RSHF_V}, {NONE_C,NONE_V} /* NONE deve essere l'ultimo item (ultimo .kv = 0) */ }; void Dummy(void); /* necessaria per newint09h() e newint16h() */ void DummyFkeys(void); /* necessaria per newint09h() e newint16h() */ void far newint09h(void) { asm { push ax; push bx; push cx; push dx; push es; } for(_SI = 0; _SI < nk; _SI++) { if(((*(char far *)KBSTBYTE & keys[_SI].shf) == keys[_SI].shf) || ((ShiftFlag & SHFMASK) == keys[_SI].shf)) { asm in al,INKEYPORT; asm mov cl,al; /* salva al; ax e' usato per i puntatori */ if(_CL == keys[_SI].scan) { TailPtr += 2; if(TailPtr == HeadPtr || (TailPtr == EndPtr && HeadPtr == StartPtr)) { TailPtr -= 2; break; /* se il buffer e' pieno scarica barile al BIOS */ } _CH = keys[_SI].nwscn; _CL = keys[_SI].nwasc; *((int far *)((TailPtr)+KBDOFF)) = _CX; if(TailPtr == EndPtr) TailPtr = StartPtr; asm { in al,CTRKEYPORT; /* legge lo stato della tastiera */ mov ah,al; /* lo salva */ or al,ENABLEKBBIT; /* setta il bit "enable kbd" */ out CTRKEYPORT,al; /* lo scrive sulla porta di controllo */ xchg ah,al; /* riprende lo stato originale della tast. */ out CTRKEYPORT,al; /* e lo riscrive */ mov al,E_O_I; /* manda il segnale di fine Interrupt */ out I_CTRPORT,al; /* al controllore dell'8259 */ jmp _EXIT; } } } } asm { pop es; pop dx; pop cx; pop bx; pop ax; pop si; jmp dword ptr int09h_asm; } _EXIT: asm { pop es; pop dx; pop cx; pop bx; pop ax; pop si; iret; } } void far newint2Fh(void) { asm { cmp ah,TSR_TEST; /* la chiamata viene da KBDPLUS ? */ jne _CHAIN; /* no: salta */ cmp al,TSR_INST; /* si: e' richiesto il test di gia' installato ? */ jne _FREETSR; /* no: salta al servizio successivo */ mov ax,TSR_YES; /* si: carica AX con la "password" per restituirla */ iret; } _FREETSR: asm { cmp al,TSR_FREE; /* e' richiesta la disinstallazione ? */ jne _CHAIN; /* no: salta */ mov ax,offset Dummy; /* carica AX con l'offset di Dummy */ mov dx,seg Dummy; /* carica DX con il segmento di Dummy */ iret; } _CHAIN: asm jmp dword ptr int2Fh_asm; /* concatena gestore originale */ } void Dummy(void) /* spazio dati globali e strutture KbDef */ { asm { dd 0; /* ptr int 09 */ dd 0; /* punta all'int 2Fh originale */ dw 0417h; /* punta allo shift status byte */ dw 041Ah; /* punta alla testa */ dw 041Ch; /* punta alla coda */ dw 0480h; /* punta all'inizio */ dw 0482h; /* punta alla fine */ dw 0; /* n. di ridefinizioni (nk) */ dw 0; /* PSP del TSR */ } } void DummyFkeys(void) { asm { db ARRDIM dup (0); /* spazio per strutture di template KbDef */ } } char *hlpmsg = "\n\ Type KBDPLUS ? for help; KBDPLUS * to uninstall.\n\ DATA FILE DESCRIPTION (if no name given, "PRG" searches for "PRG""DEFEXT"):\n\ Each line in the file redefines a key and has the following format:\n\ \n\ shifts spaces scan spaces newscan spaces ascii spaces comment\n\ \n\ spaces...one or more blanks (or tabs).\n\ shifts...the combination of shift keys: one or more of the following:\n\ A (the ALT key)\n\ G (the ALT GR key)\n\ C (the LEFT CTRL key)\n\ T (the RIGHT CTRL key)\n\ L (the LEFT SHIFT key)\n\ R (the RIGHT SHIFT key)\n\ N (no shift has to be pressed with the redefined key)\n\ scan.....the hex scan code of the redefined key.\n\ newscan..the new hex scan code for the redefined key. It can be = <scan>.\n\ ascii....the hex ASCII code of the char for the redefined key.\n\ comment..optional entry; useful to scribble some remarks.\n\ \n\ CA 01 1C 0D Example that makes CTRL ALT ESC equivalent to the ENTER key."; void release_env(void) { extern unsigned _envseg; asm { mov es,_envseg; /* ...carica in ES l'ind. di segmento dell'environm. */ mov ah,0x49; /* richiede al DOS di liberare il MCB dell'environment */ int 0x21; } } int nibble(char c) /* hex digit string ===> int */ { if(c > (char)0x29 && c < (char)0x40) return(c-'0'); return(((c <= 'Z') ? c : c-BLANK)-('A'-10)); } char *setcodes(char *bufptr,char far *code) { for(; *bufptr <= BLANK;) ++bufptr; *code = (char)((nibble(*bufptr) << 4) + nibble(*(++bufptr))); return(++bufptr); } void readdata(FILE *in) { char shift[MAXLEN], *bufptr; register int i, lim; lim = ARRDIM / sizeof(struct KbDef); for(; fgets(shift,MAXLEN,in) && nk < lim; nk++) { for(bufptr = shift; *bufptr <= BLANK;) ++bufptr; for(; *bufptr > BLANK;) ++bufptr; *bufptr = (char)NULL; for(i = 0; shf[i].kv; i++) if(strchr(shift,shf[i].kc)) keys[nk].shf |= shf[i].kv; bufptr = setcodes(bufptr,&(keys[nk].scan)); bufptr = setcodes(bufptr,&(keys[nk].nwscn)); (void)setcodes(bufptr,&(keys[nk].nwasc)); } } int readfile(int argc,char **argv) { FILE *in; strcpy(strrchr(argv[0],'.'),DEFEXT); for(; argc;) if(in = fopen(argv[--argc],"rb")) { (void)printf(PRG": found %s. Reading...\n",argv[argc]); readdata(in); (void)fclose(in); break; } else (void)printf(PRG": %s not found.\n",argv[argc]); return(nk); } int resparas(void) { return(FP_SEG(keys)+((FP_OFF(keys)+nk*sizeof(struct KbDef)) >> 4)+1-_psp); } int tsrtest(void) { asm { mov ah,TSR_TEST; mov al,TSR_INST; int 0x2F; cmp ax,TSR_YES; je _RESIDENT; xor ax,ax; } _RESIDENT: return(_AX); } void uninstall(void) { void far * ResDataPtr; asm { mov ah,TSR_TEST; mov al,TSR_FREE; int 0x2F; mov word ptr ResDataPtr,ax; /* DX:AX e' l'ind. della Dummy residente */ mov word ptr ResDataPtr+2,dx; /* e va trattato in back-words */ } setvect(0x09,(void(interrupt *)())(*((long far *)ResDataPtr))); setvect(0x2F,(void(interrupt *)())(*(((long far *)ResDataPtr)+1))); _ES = *(((unsigned far *)ResDataPtr)+10); asm { mov ah,0x49; /* richiede al DOS di liberare il MCB del PSP del TSR */ int 0x21; } } void install(void) { asm cli; int09h = getvect(0x09); int2Fh = getvect(0x2F); setvect(0x09,(void(interrupt *)())newint09h); setvect(0x2F,(void(interrupt *)())newint2Fh); asm sti; ResPSP = _psp; release_env(); (void)printf(PRG": Installed... %d key redefinition(s).\n",nk); keep(0,resparas()); /* TSR ! */ } void main(int argc,char **argv) { (void)printf(PRG" "VER": Keyboard ReDef Utility - Barninga_Z! "YEAR"\n"); if(argv[1][0] == HELP_REQUEST) (void)printf(PRG": help screen.\n%s",hlpmsg); else if(tsrtest()) if(argv[1][0] == FREE_REQUEST) { uninstall(); (void)printf(PRG": Uninstalled: original keys restored.\n"); } else (void)printf(PRG": Already installed.\n%s",hlpmsg); else if(readfile(argc,argv)) install(); else (void)printf(PRG": Invalid data file name or lines.\n%s",hlpmsg); }Sono state introdotte anche alcune modifiche volte ad incrementare l'efficienza complessiva del programma: in particolare, nella newint09h() il ciclo di scansione della tabella dei tasti ridefiniti è gestito esplicitamente mediante il registro SI (nella precedente versione era utilizzata una variabile automatica allocata nello stack). Detta tabella, infine, è stata scorporata dalla funzione jolly Dummy() e lo spazio ad essa necessario è ora riservato mediante una seconda funzione fittizia, la dummyFkeys(); è stata inoltre coerentemente modificata la definizione della costante manifesta keys.
/************************************************************************** KBDCODES.C - Barninga_Z! - 1991 Visualizza scan code e ascii code del tasto premuto. Per uscire basta premere ESC due volte di seguito. Compilato sotto BORLAND C++ 2.0 tcc -O -d -mt -lt kbdcodes.c **************************************************************************/ #include <stdio.h> #define ESC ((char)0x1B) #define NORMAL ((char)0x00) #define EXTENDED ((char)0x10) #define NORMOPT '-' #define EXTOPT '+' #define YRLIMIT ((char)0x05) #define YRADDR ((char far *)0xF000FFFCL) char *msg[] ={"\ KEYBCODE 1.0 : Keyboard Codes : Barninga_Z! : Torino, 14/04/1991\n\n\ Current setting is %s bios service:\n\ KBDCODES + forces extended bios service;\n\ KBDCODES - forces normal bios service.\n\n\ Press keys to see ScanCodes and AsciiCodes;\n\ Press ESC twice to exit.\n\n", "\ ScanCode = %02Xh (%3d); AsciiCode = %02Xh (%3d)\n", "\ normal", "\ extended" }; void main(int argc,char **argv) { unsigned char scan, ascii, service = NORMAL; register count = 2; char far *BiosYear = YRADDR; if(*BiosYear > YRLIMIT) { service = EXTENDED; count = 3; } if(argc > 1) if(*argv[1] == NORMOPT) { service = NORMAL; count = 2; } else if(*argv[1] == EXTOPT) { service = EXTENDED; count = 3; } printf(msg[0],msg[count]); for(count = 0; ; count < 2) { _AH = service; asm int 16h; scan = _AH; ascii = _AL; printf(msg[1],(int)scan,(int)scan,(int)ascii,(int)ascii); if(ascii == ESC) ++count; else count = 0; } }KBDCODES si basa sull'int 16h, di cui invoca il servizio 10h (tastiera estesa) se il bios della macchina è datato 1986 o piu' recente, altrimenti usa il servizio 00h. E' possibile forzare l'uso del servizio 10h invocando il programma con il parametro '+' sulla command line; il parametro '', al contrario, forza l'utilizzo del servizio 00h. Per uscire dal programma è sufficiente premere il tasto ESC due volte consecutive oppure la sequenza CTRLBREAK.