first commit

This commit is contained in:
2022-08-14 15:36:56 +02:00
commit 3f53e503af
3 changed files with 832 additions and 0 deletions

482
asteroids.cpp Normal file
View File

@@ -0,0 +1,482 @@
// En "crt" ficaré el "pegamento" amb SDL i les coses de Pascal
// que vullga mantindre, com els noms dels tipos.
#include "crt.h"
// Amb "keybord.pas" faré el mateix, el convertiré a SDL, mantenint
// la mateixa interficie
#include "keyboard.h"
// =================================================================
// CONST
// =================================================================
// He decidit ficar defines per a les constants, que es el més
// paregut. La constant "velocitat" se pegaba amb algunes variables
// així que la he renombrat "velocitat_inicial"
#define marge_dalt 20
#define marge_baix 460
#define marge_esq 20
#define marge_dret 620
#define max_ipunts 30
#define max_ornis 15
#define velocitat_inicial 2
#define velocitat_max 6
#define max_bales 3
// =================================================================
// TYPE
// =================================================================
// Els tipos son structs normals. El ivector el tracte a part.
struct ipunt {
real r, angle;
};
struct punt {
integer x, y;
};
// ivector es un simple array estatic de ipunts
// typedef ipunt[max_ipunts] ivector;
struct triangle {
ipunt p1,p2,p3;
punt centre;
real angle;
real velocitat;
};
struct poligon {
ipunt ipuntx[max_ipunts];
punt centre;
real angle;
real velocitat;
byte n;
real drotacio, rotacio;
boolean esta;
};
// NOTA1:
// pvirt es un array estatic pa definir un punter que despres
// pillem memoria dinamica... que mareig. Si total, es la pantalla
// virtual que pillem la memoria i no la soltem en tot el joc.
// Així que millor un simple array estatic i menys feina
//pvirt=array [1..38400] of byte;
// =================================================================
// VAR
// =================================================================
// Ací han d'anar les variables globals. He llevat moltes perque nomes s'usen
// dins del main, les quals son locals a main
triangle nau;
poligon pol;
real ang;
//char ch;
//word Dx, Dy;
byte i, aux;
integer dist;
punt puntaux;
poligon orni[max_ornis];
byte virt[38400];
poligon bales[max_bales];
// NOTA2:
// Durant el joc se usa "mem" per a accedir a la memòria directament
// per a escriure a la memòria de video (mem[$A000:i]) o a/desde la
// memòria de la pantalla virtual (mem[sef(virt^):i]), lo qual es
// marejador i ara ja no val per a res. Podria fingir-ho, pero seria
// un desperdici de memòria. Així que vaig a intercanviar tot els
// accesos a memoria de video per un access al array "video[]" i tots
// els accesos a la pantalla virtual per acces al array "virt[]".
// video[] està definit en "crt.h"
void volca() {
for (int i=0;i<38400;++i) video[i] = virt[i];
}
void crear_poligon_regular(poligon &pol, byte n, real r) {
real act, interval;
ipunt aux;
interval = 2*pi/n;
act = 0;
for (int i=0;i<n;++i) {
aux.r = r;
aux.angle = act;
pol.ipuntx[i] = aux;
act = act + interval;
}
pol.centre.x = 320;
pol.centre.y = 200;
pol.angle = 0;
pol.velocitat = velocitat_inicial;
pol.n = n;
pol.drotacio = 0.078539816;
pol.rotacio = 0;
}
/*procedure MCGA;
begin
asm
mov ax,0012h
int 10h
end;
directvideo:= false;
end;
procedure Text;
begin
asm
mov ax,0003h
int 10h
end;
end;*/
/*procedure WaitRetrace; assembler;
label
l1,l2;
asm
mov dx,3DAh
l1:
in al,dx
and al,08h
jnz l1
l2:
in al,dx
and al,08h
jz l2
end;*/
void posa(word x, word y, byte color) {
if (color==1) {
switch (x % 8) {
case 0: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0x7F) | 0x80; break;
case 1: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xBF) | 0x40; break;
case 2: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xDF) | 0x20; break;
case 3: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xEF) | 0x10; break;
case 4: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xF7) | 0x08; break;
case 5: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xFB) | 0x04; break;
case 6: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xFD) | 0x02; break;
case 7: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xFE) | 0x01; break;
}
} else if (color==0) {
switch (x % 8) {
case 0: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0x7F; break;
case 1: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xBF; break;
case 2: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xDF; break;
case 3: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xEF; break;
case 4: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xF7; break;
case 5: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xFB; break;
case 6: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xFD; break;
case 7: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xFE; break;
}
}
}
byte llig(word x, word y) {
switch (x % 8) {
case 0: return (virt[y*80+(x>>3)] & 0x80) >> 7; break;
case 1: return (virt[y*80+(x>>3)] & 0x40) >> 6; break;
case 2: return (virt[y*80+(x>>3)] & 0x20) >> 5; break;
case 3: return (virt[y*80+(x>>3)] & 0x10) >> 4; break;
case 4: return (virt[y*80+(x>>3)] & 0x08) >> 3; break;
case 5: return (virt[y*80+(x>>3)] & 0x04) >> 2; break;
case 6: return (virt[y*80+(x>>3)] & 0x02) >> 1; break;
case 7: return virt[y*80+(x>>3)] & 0x01; break;
}
}
void posavga(word x, word y, byte color) {
if (color==1) {
switch (x % 8) {
case 0: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0x7F) | 0x80; break;
case 1: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xBF) | 0x40; break;
case 2: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xDF) | 0x20; break;
case 3: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xEF) | 0x10; break;
case 4: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xF7) | 0x08; break;
case 5: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xFB) | 0x04; break;
case 6: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xFD) | 0x02; break;
case 7: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xFE) | 0x01; break;
}
} else if (color==0) {
switch (x % 8) {
case 0: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0x7F; break;
case 1: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xBF; break;
case 2: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xDF; break;
case 3: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xEF; break;
case 4: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xF7; break;
case 5: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xFB; break;
case 6: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xFD; break;
case 7: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xFE; break;
}
}
}
real modul(punt p) {
// sqr(p.x) es p.x al quadrat, que sería p.x^2. Pero es mes rapid p.x*p.x
return sqrt(p.x*p.x + p.y*p.y);
}
void diferencia(punt o, punt d, punt &p) {
p.x = o.x-d.x;
p.y = o.y-d.y;
}
integer distancia(punt o, punt d) {
punt p;
diferencia(o,d,p);
return round(modul(p));
}
real angle(punt p) {
// p.x/p.y peta si p.y es zero, obviament, així que si es zero, canviem la operació
// per un nombre proper a zero (0.001).
return p.y!=0?atan(p.x/p.y):atan(p.x/0.001);
}
void clsvirt() {
for (int i=0;i<38400;++i) virt[i]=0;
}
integer sign(integer x) { //like sgn(x) in basic
// PASCAL:
// if x<0 then sign:=-1 else if x>0 then sign:=1 else sign:=0 end;
// C:
// if (x<0) return -1; else if (x>0) return 1; else return 0;
// DOC:
return x<0?-1:x>0?1:0;
}
boolean linea(word x1, word y1, word x2, word y2, word color) {
bool result = false;
integer count;
integer col = 0;
integer x = x1, y = y1;
integer xs = x2-x1, ys = y2-y1;
integer xm = sign(xs), ym = sign(ys);
integer xs = fabs(xs), ys = fabs(ys);
if (llig(x,y)==1) col++;
posa(x,y,color);
if (xs > ys) { // flat line <45 deg
count = -(xs >> 1);
while (x != x2) {
count += ys;
x += xm;
if (count>0) {
y += ym;
count -= xs;
}
if (llig(x,y)==1) col++;
posa(x,y,color);
}
} else { // steep line >=45 deg
count = -(ys >> 1);
while (y != y2) {
count += xs;
y += ym;
if (count>0) {
x += xm;
count -= ys;
}
if (llig(x,y)==1) col++;
posa(x,y,color);
}
}
if (col>2) result = true;
return result;
}
byte rota_tri(triangle tri, real angul, real velocitat, byte color) {
word x1 = round((tri.p1.r+velocitat)*cos(tri.p1.angle+angul))+tri.centre.x;
word x2 = round((tri.p2.r+velocitat)*cos(tri.p2.angle+angul))+tri.centre.x;
word x3 = round((tri.p3.r+velocitat)*cos(tri.p3.angle+angul))+tri.centre.x;
word y1 = round((tri.p1.r+velocitat)*sin(tri.p1.angle+angul))+tri.centre.y;
word y2 = round((tri.p2.r+velocitat)*sin(tri.p2.angle+angul))+tri.centre.y;
word y3 = round((tri.p3.r+velocitat)*sin(tri.p3.angle+angul))+tri.centre.y;
bool result = 0;
if (linea(x1,y1,x2,y2,color)) result = 1;
if (linea(x1,y1,x3,y3,color)) result = 1;
if (linea(x3,y3,x2,y2,color)) result = 1;
return result;
}
void rota_pol(poligon pol, real angul, byte color) {
punt xy[max_ipunts];
for (int i=0;i<pol.n;++i) {
xy[i].x = round((pol.ipuntx[i].r)*cos(pol.ipuntx[i].angle+angul))+pol.centre.x;
xy[i].y = round((pol.ipuntx[i].r)*sin(pol.ipuntx[i].angle+angul))+pol.centre.y;
}
for (int i=0;i<pol.n-1;++i) {
linea(xy[i].x,xy[i].y,xy[i+1].x,xy[i+1].y,color);
linea(xy[pol.n-1].x,xy[pol.n-1].y,xy[0].x,xy[0].y,color);
}
}
void mou_orni(poligon &orni) {
orni.angle = orni.angle/*+(random(256)/512)*(random(3)-1)*/;
real dy = round(orni.velocitat*sin(orni.angle-pi/2))+orni.centre.y;
real dx = round(orni.velocitat*cos(orni.angle-pi/2))+orni.centre.x;
if ((dy>marge_dalt) && (dy<marge_baix)) {
orni.centre.y = round(dy);
} else {
orni.angle = orni.angle+(random(256)/512)*(random(3)-1);
}
if ((dx>marge_esq) && (dx<marge_dret)) {
orni.centre.x = round(dx);
} else {
orni.angle = orni.angle+(random(256)/512)*(random(3)-1);
}
orni.rotacio = orni.rotacio+orni.drotacio;
}
void mou_bales(poligon &orni) {
orni.angle = orni.angle/*+(random(256)/512)*(random(3)-1)*/;
real dy = round(orni.velocitat*sin(orni.angle-pi/2))+orni.centre.y;
real dx = round(orni.velocitat*cos(orni.angle-pi/2))+orni.centre.x;
if ((dy>marge_dalt) && (dy<marge_baix)) {
orni.centre.y = round(dy);
} else {
/*orni.angle:=orni.angle+(random(256)/512)*(random(3)-1)*/
orni.esta = false;
}
if ((dx>marge_esq) && (dx<marge_dret)) {
orni.centre.x = round(dx);
} else {
/*orni.angle:=orni.angle+(random(256)/512)*(random(3)-1)*/
orni.esta = false;
}
}
//var
word itocado;
poligon chatarra_cosmica;
void tocado() {
if (itocado==1) {
chatarra_cosmica.centre.x = nau.centre.x;
chatarra_cosmica.centre.y = nau.centre.y;
chatarra_cosmica.n = max_ipunts;
for (int i=0;i<max_ipunts;++i) {
chatarra_cosmica.ipuntx[i].r = 1;
chatarra_cosmica.ipuntx[i].angle = random(360)*57.295779513;
}
nau.velocitat = 0;
}
if ((nau.p1.r>1) && (nau.p2.r>1) && (nau.p3.r>1) && (itocado<170)) {
nau.p1.r = nau.p1.r-0.7;
nau.p2.r = nau.p2.r-0.7;
nau.p3.r = nau.p3.r-0.7;
nau.angle = nau.angle-0.3;
rota_tri(nau,nau.angle,0,1);
} else {
for (int i=0;i<max_ipunts;++i) {
chatarra_cosmica.ipuntx[i].r = chatarra_cosmica.ipuntx[i].r+3;
word dx = round((chatarra_cosmica.ipuntx[i].r)*cos(chatarra_cosmica.ipuntx[i].angle))
+ chatarra_cosmica.centre.x;
word dy = round((chatarra_cosmica.ipuntx[i].r)*sin(chatarra_cosmica.ipuntx[i].angle))
+ chatarra_cosmica.centre.y;
if ((dx>=0)&&(dx<640)&&(dy>0)&&(dy<480)) posa(dx,dy,1);
}
}
itocado++;
if (itocado==170) {
nau.p1.r = 12; nau.p1.angle = 3*pi/2;
nau.p2.r = 12; nau.p2.angle = pi/4;
nau.p3.r = 12; nau.p3.angle = (3*pi)/4;
nau.angle = 0;
nau.centre.x = 320; nau.centre.y = 240;
}
if ((itocado>170)&&((itocado%3)==0)) rota_tri(nau,nau.angle,nau.velocitat,1);
if (itocado>250) itocado=0;
}
int main(int argc, char argv[]) {
randomize();
//getmem(virt,38400); virt es un array estatic, no fa falta reservar memòria
itocado = 0;
clsvirt();
nau.p1.r = 12; nau.p1.angle = 3*pi/2;
nau.p2.r = 12; nau.p2.angle = pi/4;
nau.p3.r = 12; nau.p3.angle = (3*pi)/4;
nau.angle = 0;
nau.centre.x = 320; nau.centre.y = 240;
crear_poligon_regular(pol, 10, 200);
for (int i=1;i<max_ornis;++i) crear_poligon_regular(orni[i], 5, 20);
mcga();
rota_pol(pol,0,1);
instalarkb();
do {
clsvirt();
if (teclapuls(KEYarrowright)) nau.angle += 0.157079632;
if (teclapuls(KEYarrowleft)) nau.angle -= 0.157079632;
if (teclapuls(KEYarrowup)) {
if (nau.velocitat<velocitat_max) nau.velocitat += 0.2;
}
if (teclapuls(KEYspace) && (!bales[1].esta)) {
bales[1].esta = true;
bales[1].centre.x = nau.centre.x;
bales[1].centre.y = nau.centre.y;
bales[1].n = 2;
bales[1].velocitat = 7;
bales[1].ipuntx[1].r = 10;
bales[1].ipuntx[1].angle = pi/2+nau.angle;
bales[1].ipuntx[2].r = 20;
bales[1].ipuntx[2].angle = pi/2+nau.angle;
bales[1].angle = nau.angle;
}
word dy = round(nau.velocitat*sin(nau.angle-pi/2))+nau.centre.y;
word dx = round(nau.velocitat*cos(nau.angle-pi/2))+nau.centre.x;
if ((dy>marge_dalt) && (dy<marge_baix)) nau.centre.y = dy;
if ((dx>marge_esq) && (dx<marge_dret)) nau.centre.x = dx;
if (nau.velocitat>0.1) nau.velocitat -= 0.1;
/* dist:=distancia(nau.centre,pol.centre);
diferencia(pol.centre,nau.centre,puntaux);
if dist<(pol.ipuntx[1].r+30) then begin
nau.centre.x:=nau.centre.x
+round(dist*cos(angle(puntaux)+0.031415));
nau.centre.y:=nau.centre.y
+round(dist*sin(angle(puntaux)+0.031415));
end;*/
/* for i:=1 to 5 do begin
rota_pol(orni[i],ang,0);
end;*/
for (int i=1;i<max_ornis;++i) {
mou_orni(orni[i]);
rota_pol(orni[i],orni[i].rotacio,1);
}
if (itocado==0) {
aux = rota_tri(nau,nau.angle,nau.velocitat,1);
} else {
tocado();
}
if (aux==1) { itocado++; aux=0; }
if (bales[1].esta) {
mou_bales(bales[1]);
rota_pol(bales[1],0,1);
}
waitretrace();
volca();
/* if aux=1 then begin {gotoxy(0,0);write('tocado')tocado;delay(200);end;*/
gotoxy(50,24);
write("¸ Visente i Sergi");
gotoxy(50,25);
write("áETA 2.2 2/6/99");
} while (!teclapuls(keyesc));
desinstalarkb();
ang = 0;
do {
waitretrace();
rota_pol(pol,ang,0);
ang += 0.031415;
rota_pol(pol,ang,1);
} while (!keypressed());
text();
return 0;
}

72
crt.h Normal file
View File

@@ -0,0 +1,72 @@
#pragma once
#include <cstdint>
#include <math.h>
#include <SDL2/SDL.h>
#define pi 3.141592653589793
// Tipos de Pascal
typedef double real;
typedef int integer;
typedef unsigned char byte;
typedef bool boolean;
typedef uint16_t word;
byte video[38400];
SDL_Window *sdlWindow;
SDL_Renderer *sdlRenderer;
SDL_Texture *sdlTexture;
SDL_Event sdlEvent;
Uint32 *pixels;
int pitch;
void randomize() {
srand(SDL_GetTicks());
}
int random(int x) {
return rand()%x;
}
void mcga() {
SDL_Init(SDL_INIT_EVERYTHING);
sdlWindow = SDL_CreateWindow("Asteroids", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0);
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, 640, 480);
}
void text() {
SDL_Quit();
}
void waitretrace() {
while (!SDL_PollEvent(&sdlEvent)) {
if (sdlEvent.type == SDL_QUIT) { /*Ja vorem*/ }
}
SDL_LockTexture(sdlTexture, NULL, (void**)&pixels, &pitch);
int pos=0;
for (int y=0; y<480;y++) {
for (int x=0; x<80;x++) {
pixels[pos++] = ((video[y*480+x]>>7)&1)?0xffffffff:0x000000ff;
pixels[pos++] = ((video[y*480+x]>>6)&1)?0xffffffff:0x000000ff;
pixels[pos++] = ((video[y*480+x]>>5)&1)?0xffffffff:0x000000ff;
pixels[pos++] = ((video[y*480+x]>>4)&1)?0xffffffff:0x000000ff;
pixels[pos++] = ((video[y*480+x]>>3)&1)?0xffffffff:0x000000ff;
pixels[pos++] = ((video[y*480+x]>>2)&1)?0xffffffff:0x000000ff;
pixels[pos++] = ((video[y*480+x]>>1)&1)?0xffffffff:0x000000ff;
pixels[pos++] = ((video[y*480+x] )&1)?0xffffffff:0x000000ff;
}
}
SDL_UnlockTexture(sdlTexture);
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
SDL_RenderPresent(sdlRenderer);
}
void gotoxy(int x, int y) {
}
void write(const char* text) {
}

278
keyboard.h Executable file
View File

@@ -0,0 +1,278 @@
/*
-----------------------------------------------------
File: Keyboard.Pas
By: Ronny Wester, ronny@rat.se
Passat a C by: JailDoctor
Unit to check up/down status of individual key flags.
Written from code I got off rec.games.programmer.
Sorry, I lost the name of the poster.
As most of this code is scancode-dependent some keys
may not be where they "should" on your keyboard.
-----------------------------------------------------
*/
/* unit Keyboard;
interface
uses Dos;
*/
#include <SDL2/SDL.h>
//const
#define keySysReq SDL_SCANCODE_SYSREQ
#define keyCapsLock SDL_SCANCODE_CAPSLOCK
#define keyNumLock 0x45
#define keyScrollLock 0x46
#define keyLeftCtrl 0x1D
#define keyLeftAlt 0x38
#define keyLeftShift 0x2A
#define keyRightCtrl 0x9D
#define keyAltGr 0xB8
#define keyRightShift 0x36
#define keyEsc 0x01
#define keyBackspace 0x0E
#define keyEnter 0x1C
#define keySpace 0x39
#define keyTab 0x0F
#define keyF1 0x3B
#define keyF2 0x3C
#define keyF3 0x3D
#define keyF4 0x3E
#define keyF5 0x3F
#define keyF6 0x40
#define keyF7 0x41
#define keyF8 0x42
#define keyF9 0x43
#define keyF10 0x44
#define keyF11 0x57
#define keyF12 0x58
#define keyA 0x1E
#define keyB 0x30
#define keyC 0x2E
#define keyD 0x20
#define keyE 0x12
#define keyF 0x21
#define keyG 0x22
#define keyH 0x23
#define keyI 0x17
#define keyJ 0x24
#define keyK 0x25
#define keyL 0x26
#define keyM 0x32
#define keyN 0x31
#define keyO 0x18
#define keyP 0x19
#define keyQ 0x10
#define keyR 0x13
#define keyS 0x1F
#define keyT 0x14
#define keyU 0x16
#define keyV 0x2F
#define keyW 0x11
#define keyX 0x2D
#define keyY 0x15
#define keyZ 0x2C
#define key1 0x02
#define key2 0x03
#define key3 0x04
#define key4 0x05
#define key5 0x06
#define key6 0x07
#define key7 0x08
#define key8 0x09
#define key9 0x0A
#define key0 0x0B
#define keyMinus 0x0C
#define keyEqual 0x0D
#define keyLBracket 0x1A
#define keyRBracket 0x1B
#define keySemicolon 0x27
#define keyTick 0x28
#define keyApostrophe 0x29
#define keyBackslash 0x2B
#define keyComma 0x33
#define keyPeriod 0x34
#define keySlash 0x35
#define keyInsert 0xD2
#define keyDelete 0xD3
#define keyHome 0xC7
#define keyEnd 0xCF
#define keyPageUp 0xC9
#define keyArrowLeft 0xCB
#define keyArrowRight 0xCD
#define keyArrowUp 0xC8
#define keyArrowDown 0xD0
#define keyKeypad0 0x52
#define keyKeypad1 0x4F
#define keyKeypad2 0x50
#define keyKeypad3 0x51
#define keyKeypad4 0x4B
#define keyKeypad5 0x4C
#define keyKeypad6 0x4D
#define keyKeypad7 0x47
#define keyKeypad8 0x48
#define keyKeypad9 0x49
#define keyKeypadComma 0x53
#define keyKeypadStar 0x37
#define keyKeypadMinus 0x4A
#define keyKeypadPlus 0x4E
#define keyKeypadEnter 0x9C
#define keyCtrlPrtScr 0xB7
#define keyShiftPrtScr 0xB7
#define keyKeypadSlash 0xB5
const char *keyNames[256] {
/* $00 */ NULL, "Esc", "1", "2", "3", "4", "5", "6",
/* $08 */ "7", "8", "9", "0", "+", "Apostrophe", "Backspace", "Tab",
/* $10 */ "Q", "W", "E", "R", "T", "Y", "U", "I",
/* $18 */ "O", "P", "<EFBFBD>", "?", "Enter", "Left Ctrl", "A", "S",
/* $20 */ "D", "F", "G", "H", "J", "K", "L", "<EFBFBD>",
/* $28 */ "<EFBFBD>", "'", "Left shift", "<", "Z", "X", "C", "V",
/* $30 */ "B", "N", "M", ",", ".", "-", "Right shift", "* (pad)",
/* $38 */ "Alt", "Space", "Caps Lock", "F1", "F2", "F3", "F4", "F5",
/* $40 */ "F6", "F7", "F8", "F9", "F10", "Num Lock", "Scroll Lock", "7 (pad)",
/* $48 */ "8 (pad)", "9 (pad)", "- (pad)", "4 (pad)", "5 (pad)", "6 (pad)", "+ (pad)", "1 (pad)",
/* $50 */ "2 (pad)", "3 (pad)", "0 (pad)", ", (pad)", "SysRq", NULL, NULL, "F11", "F12",
/* $59 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* $60 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* $70 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* $80 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* $90 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Enter (pad)", "Right Ctrl", NULL, NULL,
/* $A0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* $B0 */ NULL, NULL, NULL, NULL, NULL, "/ (pad)", NULL, "PrtScr", "Alt Gr", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* $C0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Home",
/* $C8 */ "Up arrow", "Page Up", NULL, "Left arrow", NULL, "Right arrow", NULL, "End",
/* $D0 */ "Down arrow", NULL, "Insert", "Delete", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* $E0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* $F0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
procedure InstalarKb;
procedure DesinstalarKb;
function TeclaPuls( b : byte ) : Boolean;
function QTeclaPuls : Boolean;
function AgarrarTecla : Byte;
procedure BorrarKb;
procedure EscriuKb;
implementation
var
uOldInt9 : Pointer; { saves location of old OldInt9 vector }
uKeys : array [0..255] of Boolean; { array that holds key values }
e0Flag : Byte;
uExitProc : Pointer;
{$F+}
procedure NewInt9; interrupt; assembler;
asm
cli
in al, $60 { get scan code from keyboard port }
cmp al, $E0 { al = $E0 key ? }
jne @@SetScanCode
mov [e0Flag], 128
mov al, 20h { Send 'generic' EOI to PIC }
out 20h, al
jmp @@exit
@@SetScanCode:
mov bl, al { Save scancode in BL }
and bl, 01111111b
add bl, [e0Flag]
xor bh, bh
and al, 10000000b { keep break bit, if set }
xor al, 10000000b { flip bit, 1 means pressed, 0 no }
rol al, 1 { move breakbit to bit 0 }
mov [offset uKeys + bx], al
mov [e0Flag], 0
mov al, 20h { send EOI to PIC }
out 20h, al
@@exit:
sti
end;
{$F-}
procedure InstalarKb;
begin
GetIntVec( $09, uOldInt9); { save old location of INT 09 handler }
SetIntVec( $09, Addr( NewInt9)); { point to new routine }
FillChar( uKeys, SizeOf( uKeys), 0); { clear the keys array }
end;
procedure DesinstalarKb;
begin
SetIntVec( $09, uOldInt9); { point back to original routine }
uOldInt9 := nil;
end;
function TeclaPuls( b : byte ) : Boolean;
begin
TeclaPuls := uKeys[b];
end;
function QTeclaPuls : Boolean;
var b : Integer;
begin
QTeclaPuls := True;
for b := 0 to 255 do
if uKeys[b] and (keyNames[b] <> nil) then
Exit;
QTeclaPuls := False;
end;
function AgarrarTecla : Byte;
var b : Integer;
begin
AgarrarTecla := 0;
for b := 1 to 255 do
if uKeys[b] and (keyNames[b] <> nil) then
begin
AgarrarTecla := b;
Exit;
end;
end;
procedure BorrarKb;
begin
FillChar( uKeys, SizeOf( uKeys), 0); { clear the keys array }
end;
{$F+}
procedure CleanUp;
begin
ExitProc := uExitProc;
if uOldInt9 <> nil then
DesinstalarKb;
end;
procedure EscriuKb;
var b:byte;
begin
for b := 0 to 255 do
if uKeys[b] and (keyNames[b] <> nil) then
write(keyNames[b],' | ');
writeln;
end;
{$F-}
begin
uExitProc := ExitProc;
ExitProc := @CleanUp;
uOldInt9 := nil;
end.