Volver menú revistas Volver página anterior

El Amiga Me Encanta ha conseguido el permiso por escrito de IDG Comunications España para ofrecer los artículos de la revista Amiga World España.

N° 37 - Noviembre 1992

     COLABORACION     

 

COLABORACIONES DE LOS LECTORES


Las colaboraciones de los lectores son un elemento importante en la relación con la revista. En esta ocasión, además de didácticos, son programas prácticos y de utilidad. Además, el lector se beneficia de una pequeña compesación a su esfuerzo de programación. Pequeñas rutinas, trucos, todo tiene cabida en esta sección reservada al usuario programador.

COLOR v1.00

Por Alvaro Mateos Herrero

Color es un programa que llamado como un comando desde el CLI nos permitirá cambiar el color de la pantalla donde se encuentre nuestra ventana CLI. El formato de este comando es:

Color <núm color> <rojo> <verde> <azul>

'núm color' es el número del color que queremos cambiar. El número puede estar entre 0 y 63 aunque en una pantalla CLI normal se utilizan los colores de 0 a 3. Por otra parte, con este comando también podremos cambiar los colores del sprite del ratón, que corresponde a los números 17 18 y 19.

'rojo' cantidad de rojo del color (entre 0 y 15)

'verde' cantidad de verde del color (entre 0 y 15)

'azul' cantidad de azul del color (0 a 15)

Todos estos parámetros son obligatorios. De todas formas si nos olvidamos del formato, podemos escribir simplemente el nombre del comando y nos aparecerá la ayuda.

Ejemplos:
Color 0 15 0 0 ; pone ROJO el color 0
Color 1 0 15 0 ; pone VERDE el color 1
Color 2 0 0 15 ; pone AZUL el color 2
Color 3 10 10 10 ; pone GRIS el color 3
Color 17 12 1 15 ; pone VIOLETA el primer color del ratón
Color 18 15 10 12 ; pone ROSA el segundo color del ratón
Color 19 15 9 0 ; pone NARANJA el tercer color del ratón

Este programa es de dominio público, y puede distribuirse libremente siempre que no sea con fines comerciales. Se incluye el fuente del programa por si alguien quiere modificarlo.


JOYSTICK

Por Alvaro Mateos Herrera

Leer el joystick del AMIGA no es tan simple como leer el valor de un puerto y coger el valor de un registro. Por una parte tenemos que decodificar la información que se nos da en los registros JOY0DAT y JOY1DAT, y por otra leer los botones de disparo en el registro 'cra' del CIAA.

JOY0DAT es uno de los registros conectados al puerto 1 del joystick (donde va conectado el ratón) mientras que JOY1DAT es el relacionado con el puerto 2.

Para interpretar la información de estos registros tenemos que tener en cuenta lo siguiente:

bit 1 corresponde a la derecha
bit 2 corresponde a la izquierda
bit 1 XOR bit 0 corresponde a abajo
bit 9 XOR bit 8 corresponde a arriba

De tal forma que si el bit (o la combinación de bits) vale 1 significará que el usuario esta dirigiendo el joystick a esa o esas direcciones.

Por otra parte, para leer los botones del joystick tendremos que examinar los bits 6 y 7 del regitro 'cra' ($bfe001) donde el bit 6 corresponde al puerto 1 y el bit 7 al puerto 2.

En este caso si el bit vale 1 significará que NO esta pulsado.

En el fichero Joystick se incluye una función en ensamblador que nos ahorra todo el trabajo. La función llamada Joystick nos devolverá en d0 una larga palabra que se interpretará de la forma siguiente:

bit 0 -> JOY 1 Derecha
bit 1 -> JOY 1 Izquierda
bit 2 -> JOY 1 Abajo
bit 3 -> JOY 1 Arriba
bit 4 -> JOY 1 Disparo
bit 16 -> JOY 2 Derecha
bit 17 -> JOY 2 Izquierda
bit 18 -> JOY 2 Abajo
bit 19 -> JOY 2 Arriba
bit 20 -> JOY 2 Disparo

Si el bit esta a 1 es que el usuario esta pidiendo que se realice esa o esas acciones.

NOTA: Si tenemos conectado el ratón en vez de un joystick, los valores devueltos serán aleatorios a excepción del botón de disparo.


KEYBOARD v1.00

Por Alvaro Mateos Herrera

Keyboard consiste en un conjunto de funciones y subrutinas para leer el teclado del AMIGA. Estas funciones nos permiten comunicarnos con el keyboard.device para leer el estado de las teclas. Su uso es bastante simple, y puede incluirse en cualquier programa que necesite saber que teclas están pulsadas o cuales han dejado de pulsarse. Las funciones son compatibles con el sistema de tal forma que correrán en total armonía con la multitarea del AMIGA. Además la rapidez de la función Read_Keyboard no ralentiza el programa principal así como las tareas que corran simultáneamente.

Las tres funciones principales son Open_Keyboard, Read_Keyboard y Close_Keyboard. Estas funciones hacen uso de las subrutinas Create_Port, Delete_Port, Create_ExtIO, Delete_ExtIO. Todas ellas están incluidas en el fichero KeyDevice, con una amplia descripción de lo que hacen.

Para saber como se utilizan se incluye un ejemplo llamado KeyEjmp que demuestra lo fácil de su uso. De todas formas aquí viene una amplia descripción de los pasos a seguir.

1. LLamamos a la función Open_Keyboard al mismo tiempo que creará las estructuras necesarias para comunicarnos con el device. Todo esto es transparente a nosotros y no nos interesa entrar en detalles.

NOTA: Open_Keyboard deberá devolver cero en d0. Si no es así es que ha habido algún error. Por jemplo. -1 indica error de memoria. Cualquier otro valor distinto de cero será un código de error devuelto por OpenDevice de EXEC.

2. Una vez abierto el keyboard.device y cada vez que queramos leer el estado de las teclas, llamaremos a la función Read_Keyboard que tomara como argumento en a0 el puntero a un buffer de 13 bytes que se interpretará como una matriz de 13 x 8 bits. Cada bit representará a una tecla. Si el bit esta a uno es que la tecla esta siendo pulsada, mientras que siesta a 0 es que no lo esta. Para saber a que byte corresponde una tecla determinada dentro de ese buffer, y en concreto a que bit dentro de ese byte, existen unos códigos relacionados con cada tecla. Más adelante se dará un esquema del teclado con su código correspondiente. Este código, dividido por 8 nos dará el número de byte dentro del buffer, y el resto de la división nos dará el orden del bit. Por ejemplo, si queremos leer la tecla correspondiente a la letra 'D' cuyo código es $22 hexadecimal lo dividimos por 8 que nos dará 4 y de resto 2, luego tendremos que examinar el byte cuatro del buffer y dentro de este byte, el bit 2. Si el bit esta a uno es que la tecla 'D' esta siendo pulsada. Hay que tener en cuenta que no tenemos por que darle siempre el mismo buffer a la función Read_Keyboard, luego podemos utilizar dos buffers diferentes donde vamos leyendo simultáneamente en uno y otro y comparando que tecla o teclas han modificado su estado.

3. Una vez que hayamos terminado tendremos que llamar a la función Close_Keyboard, teniendo en cuenta que no podremos hacer ninguna llamada a Read_Keyboard después de haber llamado a esta, a no ser que volvamos a abrir el keyboard.device mediante Open_Keyboard. No es recomendable estar abriendo y cerrando el Keyboard para hacer una llamada a Read_Keyboard. Lo normal es hacer una llamada a Open_Keyboard al principio del programa y Close_Keyboard al final y dentro del programa hacer todas las llamadas que queramos a Read_Keyboard.

En la Tabla 1 viene el esquema de los códigos de las teclas.

NOTA: los códigos están en hexadecimal.

Esta información deberá ser suministrada junto con el fichero KeyDevice que contiene el fuente de las rutinas y el programa KeyEjmp de ejemplo.

TABLA 1
El teclado principal
Tecla           ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10
Código          45  50 51 52 53 54 55 56 57 58 59
Tecla           '  1  2  3  4  5  6  7  8  9  0  -  =  \  DEL
Código          00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 41
Tecla           TAB Q  W  E  R  T  Y  U  I  O  P  £  >  RETURN
Código          42  10 11 12 13 14 15 16 17 18 19 1a 1b 44
Tecla           CTL CAP A  S  D  F  G  H  J  K  L  -  ;  Ç
Código          63  62  20 21 22 23 24 25 26 27 28 29 2a 2b
Tecla           MAY  <  Z  X  C  V  B  N  M  ,  .  '  MAY
Código          60   0  31 32 33 34 35 36 37 38 39 3a 61
Tecla           ALT  AMIGA  ESPACIO  AMIGA  ALT
Código          64   66     40       67     65
El teclado expandido
Tecla           DEL HELP  {  }  /  *
Código          46  5f    5a 5b 5c 5d
Tecla           7  8  9  -
Código          3d 3e 3f 4a
Tecla           ARR  4  5  6  +
Código          4c   2d 2e 2f 5e
Tecla           IZQ ABA DER  1  2  3  ENTER
Código          4f  4d  4e   1d 1e 1f 43
Tecla           0  .
Código          0f 3c

NOTA:
El esquema corresponde a un teclado A500. La configuración de las teclas nos pueden ayudar a saber a cual corresponde exactamente en caso de duda.

No han podido ser introducidos todos los listados por falta de espacio físico.

En nuestros discos Amiga World 37 podrán encontrar los listados completos. También pueden solicitarlos a la redacción, enviando un disco formateado para Amiga.

RATON

Por Alvaro Mateos Herrera

En la mayoría de los programas nos va a hacer falta esperar la respuesta del usuario para hacer algo determinado. El famoso 'pulsa el botón del ratón para continuar' es un ejemplo de ello.

Esperar a que el botón del ratón sea pulsado es la forma más simple y cómoda de comunicar nuestro programa con el exterior. En el fichero 'Ratón' hay una amplia información con las rutinas necesarias para leer los botones izquierdo, derecho e incluso el botón del medio (para los que tengan un 'Super Ratón'), tanto si esta conectado al puerto 1 como si lo esta al puerto 2.

Para cualquier sugerencia me pueden escribir o ponerse en contacto a través de la redacción de Amiga World.

ALVARO MATEOS HERRERA
C/ Bermúdez de Castro, 4
41011 Sevilla

* LISTADOS COLABORACIONES *
/
/*************************************************/
/*     Color v1.0 16/jul/92                      */
/*                                               */
/*     Copyright 1992 hi-score Alvaro Mateos     */
/*                                               */
/*************************************************/
#include 
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <proto/all.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
/* declaracion de funciones */
int number(char *);
int openall(void);
void closeall(void);
void chgcolor(SHORT,UBYTE,UBYTE,UBYTE);
/* declaracion de variables globales */
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
/* Funcion principal donde comprobamos el numero de parametros,
los convertimos en numeros, abrimos las librerias necesarias,
llamamos a la funcion que cambian el color especificado y
cerramos la librerias.
Si hay algun error en la linea de comandos imprimimos el mensaje de ayuda.
*/
void main (int argc,char *argv[])
{
SHORT colorN;
UBYTE colorR,colorG,colorB;
   if (argc==5)
   {
      if ((colorN=(SHORT) number(argv[1]))!=-1)
         if ((colorR=(UBYTE) number(argv[2]))!=-1)
            if ((colorG=(UBYTE) number(arg[3]))!=-1)
               if ((colorB=(UBYTE) number(arg[4]))!=-1)
                  if (colorN<64) && ((colorR*colorG*colorB)<4096) )
                  {
                      if (openall())
                         chgcolor(colorN,colorR,colorG,colorB);
                      closeall();
                      exit (0);
                  }
               printf ("** Expresion no valida **\n");
               }
               printf("Usar: Color    \n");
               printf("Ejemplo: Color 0 15 15 15 pone el fondo de color
blanco\n");
               printf("Color v1.0 Copyright hi-score 1992\n");
           }
/* Esta funcion convierte una cadena de caracteres en un numero
entero. Devuelve -1 si hay algun error
*/
int number(char *cadena)
{
int n,num;
n=0
num=0;
   while (cadena[n]!='\0')
   {
      if (1(cadena[n]>='0' && cadena[n]<='9'))
         return (-1);
      num=num*10+(cadena[n]-'0');
      n++;
   }
   return (num);
}
/* Aqui abrimos las librerias necesarias. Si ocurre algun error
devolvemos FALSE.
*/
int openall(void)
{
   if ( (IntuitionBase=(struct IntuitionBase *)
      OpenLibrary ("intuition.library",0)) != NULL)
         if ((GfxBase=(struct GfxBase *)
      OpenLibrary ("graphics.library",0)) != NULL)
         return (TRUE);
   return (FALSE);
}
/* Aquí cerramos las librerias abiertas anteriormente
*/
void closeall(void)
{
   if (IntuitionBase) CloseLibrary( (struct Library *) IntuitionBase);
   if (GfxBase) CloseLibrary( (struct Library *) GfxBase);
}
/* Esta es la funcion que cambia el color
Primero cogemos la ventana que esta activada, cogemos su estructura ViewPort
y con esto llamamos a la funcion de la
libreria Graphics SetRGB4, que toma como parametros el ViewPort,
el numero de color y los valores de rojo, verde y azul.
*/
void chgcolor(SHORT colorN, UBYTE colorR, UBYTE colorG, UBYTE colorB)
{
struct Window *window;
struct ViewPort *vp;
   window=IntuitionBase->ActiveWindow;
   vp=ViewPortAddress(window);
   SetRGB4(vp,colorN,colorR,colorG,colorB);
}
;*****************************************
; Lectura de los dos puertos del Joystick
;  Copyright 1992 hi-score Alvaro Mateos
;               25/Sep/1992
;
;*****************************************
| Situar el tabulador a 4 espacios
;**********
; JOYSTICK
;**********
; Esta funcion devuelve en d0 el estado de los dos puetos del Joystick
; de la siguiente forma:
; PUERTO 1                PUERTO 2
; bit 0 -> derecha        bit 16 -> derecha
; bit 1 -> izquierda      bit 17 -> izquierda
; bit 2 -> abajo          bit 18 -> abajo
; bit 3 -> arriba         bit 19 -> arriba
; bit 4 -> disparo        bit 20 -> disparo
;
; Conserva todos los registros menos d0 y d1
Joystick:
    move    CUSTOM+joy1dat,d0    ; cogemos el valor del puerto 2
    bsr         Decode_JoyDat    ; lo decodificamos
    move.b  $bfe001,d1
    not         d1
    and         #$0080,d1        ; cogemos el bit 'disparo'
    lsr         #3,d1
    or          d0,d1            ; ponemos el valor del Joystick 2
    swap    d1                   ; en la palabra alta
    move    CUSTOM+joy0dat,d0    ; cogemos el valor del puerto 1
    bsr         Decode_JoyDat    ; lo decodificamos
    move.b  $bfe001,d1
    not         d1
    and         #$0040,d1        ; cogemos el bit 'disparo'
    lsr         #2,d1
    or          d0,d1            ; unimos los valores en d1
    move.l  d1,d0                ; y pasamos el valor completo a d0
    RTS
; DECODE JOYDAT
; Esta subrutina toma en d0 el valor dado por uno de los puertos del
; joystick y lo decodifica, devolviendo en d0 el estado del joystick de
; la siguiente forma:
;                     bit 0 -> derecha
;                     bit 1 -> izquierda
;                     bit 2 -> abajo
;                     bit 3 -> arriba
Decode_JoyDay:
    movem.l  d1-d2,-(a7)        ; guardamos los registros utilizados
    move     d0,d1              ; copiamos JOYDAT en d1
    lsr          #1,d1
    and          #%0001,d1      ; cogemos el bit 'derecha'
    move     d1,d2              ; en d2 vamos almacenando los valores
    move     d0,d1
    lsr          #8,d1
    and          #%0010,d1      ; cogemos el bit 'izquierda'
    or           d1,d2          ; en d2 ya tenemos el valor de 'izq' y 'der'
    move     d0,d1              ; ahora vienen los valores de 'abajo'
    lsr          #1,d1          ; y 'arriba'- Para ello hay que tener en
    eor          d1,d0          ; cuenta que:
    move     d0,d1              ;            'abajo' = bit 1 XOR bit 0
    lsl          #2,d1          ;            'arriba'= bit 9 XOR bit 8
    and          #%0100,d1
    or           d1,d2          ; ... y lo vamos situando en d2
    lsr          #5,d0
    and          #%1000,d0
    or           d0,d2
    move     d2,d0              ; por ultimo pasamos el valor a d0
    movem.l  (a7)+,d1-d2        ; recuperamos los registros y
    RTS                         ; salimos
; Etiquetas utilizadas
CUSTOM  equ $dff000
joy0dat equ $000a
joy1dat equ $000c
;*********************************************************************
; KeyDevice v1.00
; Copyright 1992 hi-score Alvaro Mateos
; 22/Sep/92
;
; Rutinas necesarias para leer el teclado mediante el keyboard.device
; Estas rutinas pueden ser utilizadas libremente, sin hacerse
; responsable el autor de cualquier daño o perdida de informacion
; que pudiese ocasionar su uso directa o indirectamente.
; KeyDevice debera ser suministrado con el fichero Readme que explica
; su uso y el programa ejemplo KeyEjmp.
; La distribucion de estos ficheros es libre siempre que se respete
; el copyright del autor, no se haga con fines comerciales y se
; respete lo dicho anteriormente en este o en los otros 2 ficheros.
; Cualquier mejora podra hacerse sobre el programa, en cuyo caso
; agradecieria que me enviaran una copia.
; *******************************************************************
;Ajustar el tabulador a 4 espacios
; Aqui estan las funciones necesarias para leer el keyboard.device
; Open_Keyboard: Abre el keyboard.device y crea las estructuras
; necesarias para trabajar con el. Deberemos llamarla una sola vez
; antes de trabajar con el device.
; Close_Device: Cierra el keyboard.device y desaloja la memoira
; utilizada por las estructuras utilizadas.
; Read_Keyboard: Lee el estado de todas las teclas. En a0 le daremos
; la direccion de un buffer de 13 bytes que se interpretara como una
; matriz de 8 x 13 bits. Cada bit representa una tecla. Si la tecla esta
; pulsada su bit correspondiente estara a 1 y si no esta pulsada a 0.
; Para saber a que byte corresponde una tecla determinada tendremos que
; dividir el codigo de la tecla por 8. El resto de la division nos dara el
; bit correspondiente. Asi por ejemplo para ver si esta pulsada la
; tecla 'espacio' que tiene como codigo el $40 (64 en decimal) hariamos
; lo siguiente:
;    move    #$40,d0      ; cargamos el codigo del 'espacio'
;    lea     buffer,a0    ; apuntamos al buffer
;    divu    #8,d0        ; div. por 8 para saber que byte
;    move    0(a0,d0)d1   ; cogemos el byte correspondiente
;    swap    d0           ; cogemos el resto de la division
;    btst    d0,d1        ; comprobamos si el bit esta a cero
;    beq     tecla_NO_pulsada
;    (aqui sabemos que la tecla
;    en cuestion esta pulsada)
;    ...
; Estas funciones llaman a las siguiente rutinas:
; Create_Port: Crea la estructura MsgPort necesaria para comunicarnos
; con otra tarea, en este caso con el keyboard.device'.
; Create_ExtIO: Crea la estructura IORequest, que sera el mensaje con
; el que nos comunicaremos con el device.
; Delete_Port: Borra el MsgPort creado anteriormente.
; Delete_ExtIO: Borra el IORequest creado anteriormente.
; NOTA IMPORTANTE:
; Todas estas rutinas funcionan bajo el control de EXEC.
; Para el perfecto funcionamiento de ellas tendremos que asegurarnos de
; que las interrupciones del sistema no estan deshabilitadas o
; desactivadas. Todas las rutinas y funciones cumplen con las leyes que
; hacen que el sistema permita la multitarea. Asi pues el uso de estas
; rutinas estara en armonia con otras aplicaciones que esten corriendo
; simultaneamente.
; La velocidad que he calculado de la lectura del teclado es bastante alta.
; esto significa que una llamada a Read_Keyboard volvera casi al
; instante.

Volver menú revistas Volver página anterior