www.delorie.com/djgpp/doc/ug/dpmi/farptr-intro.html   search  
Guia: Introducción a los punteros Far

¿Comentarios, sugerencias, preguntas o cualquier cosa? Por favor contacte al autor, Bruno Barberi Gnecco, via email: brunobg@geocities.com.

Introducción

Una de las preguntas más frecuentes en comp.os.msdos.djgpp es ¿Cómo trabajar con punteros far en DJGPP?, por lo que trataré de dar una corta explicación.

Algunos compiladores tienen la palabra clave far. Cuando uno declara un puntero far, como:

char far *ptr;

Significa: crear un puntero a una dirección de memoria. Los punteros far le dejan accesar la memoria RAM usando el tipo de direcciones de memoria que usa DOS(SEGMENTO:DESPLAZAMIENTO). Pero como DJGPP usa DPMI y modo protegido, usted no puede accesar la memoria como con los otros compiladores.

Sin embargo, hay una forma de hacerlo; de hecho hay muchas de ellas. Usted puede leer en la FAQ sección 18, especialmente en la pregunta 4. Nosotros discutiremos solo una de ellas: usando _far*.

Operaciones básicas de la memoria.

DJGPP tiene una librería, sys/farptr.h para manejar las operaciónes directas con la memoria. Las funciones de la librería pueden dividirse básicamente en dos: peek(obtener) y poke (enviar). Las funciones "peek" son usadas para obtener información de la memoria, mientras que las funciones "poke" son usadas para mover información hacia la memoria.

Todos los adapatadores de video a color tienen su memoria de video en la dirección B800:0000. Los adaptadores monocromo la tienen en B000:0000. Como los adaptadores monocromo son dificiles de encontrar en estos días, usaré B800 como el inicio de su memoria de video. Usted, sin embargo, puede escribir una función para saber que adaptadores tiene el sitema: La interrupción 16, función15 regresa el modo de video actual; si el modo es 7, es un adaptador monocromo. Nosotros estaremos usando el modo de video por defecto, 3, que es 80x25 y 16 colores.

Usted debe saber que la memoria de video requiere dos bytes por cada caracter: uno es el caracter a ser desplegado y el segundo es el atributo. Por lo que toma 160 bytes por cada línea y 4000 bytes para desplegar toda la pantalla.

Tambien es importante saber cómo las direcciones serán usadas en las funciones _far*: usted debe usar la formula:

address = segment*16+offset

Comencemos con un ejemplo: Queremos escribir 'Godzilla', comenzando en 0, 0 (la esquina superior-izquierda de la pantalla). Escribimos:

#include <go32.h>
#include <sys/farptr.h>
#include <string.h>
#define NORMAL 7

int
main()
{
    int i, limit;
    char *st = "Godzilla";
    limit = strlen(st);
    for ( i = 0; i < limit; i++ )
    {
        _farpokeb(_dos_ds, 0xB800*16+2*i, *st++ );
        _farpokeb(_dos_ds, 0xB800*16+2*i+1, NORMAL );
    }
    return 0;
}

Miremos el código. Primero, debemos incluir sys/farptr.h, que contiene las funciones_far*, y go32.h, que contiene _dos_ds (que es más corto que _go32_info_block.selector_for_linear_memory. Hablaremos de esto después). En main(), creamos dos enteros y una cadena, actualizamos el valor de limit a la longitud de la cadena. Luego abrimos un ciclo for que contará, de uno en uno, desde cero hasta limit. Ahora, la parte interesante.

_farpokeb es la función que copia un byte a una posición específica en la memoria. Su sintaxis es: (unsigned short selector, unsigned long offset, unsigned char val). El selector que usaremos es _dos_ds, que nos permite usar memoria DOS y usar la formula anterior para calcular el desplazamiento, que es el segundo parámetro. Por último, pero no menos importante, el tercer parámetro es lo que queremos mostrar. En el ejemplo, imprimimos cada uno de los caracteres. y en el segundo _farpokeb? Recuerde, usted debe enviar el atributo del caracter: es la siguiente posición en memoria.

El colorido mundo de la memoria de video.

Usted conoce las bases de la manipulación directa de la memoria de video. Ahora continuemos usando los atributos. Aquí hay una tabla de ellos:

- - - -  - - - 1     1   color azul
- - - -  - - 1 -     2   color verde
- - - -  - 1 - -     4   color rojo
- - - -  1 - - -     8   color blanco
- - - 1  - - - -    16   fondo azul
- - 1 -  - - - -    32   fondo verde
- 1 - -  - - - -    64   fondo rojo
1 - - -  - - - -   128   titilante

Combinándolos, puede desplegar 16 colores(intensidad baja crea un color más claro). El valor pasado a _farpokeb es usualmente hexadecimal o decimal. Por ejemplo: queremos una letra verde en fondo púrpura. Asumiendo, es: 0x5A, o 90. Entonces podemos usar:

_farpokeb(_dos_ds, 0xB800*16+2*i, *st++ );
_farpokeb(_dos_ds, 0xB800*16+2*i+1, 0x5A );

Ejercicio: Crear un programa que despliega el número del atributos en decimal, y pone el valor del cada número como atributo del mismo

Más acerca de las direcciones: fila, columna y _farsetsel

No necesita escribir _dos_ds cada vez que usa _farpoke* o _farpeek*. Si usted escribe:

_farsetsel(_dos_ds);

usted puede usar _farns*. Ejemplo:

_farsetsel(_dos_ds);
for ( i = 0; i < limit; i++ )
{
   _farnspokeb( 0xB800*16+2*i, *st++ );
   _farnspokeb( 0xB800*16+2*i+1, NORMAL );
}

Usar _farsetsel(_dos_ds); tambien es más rápido que seleccionarlo cada vez que usa _far*.

Ahora, suponiendo que quiere escribir 'B' en la posición 50, 18 (50ª columna, 19ª fila). ¿Cómo lo haría? Bueno, si una línea tiene 80 caracteres y cada caracter ocupa dos bytes en la memoria de video, entonces cada línea ocupa 80*2=160 bytes. Por lo que podemos usar:

_farnspokeb( 0xB800*16+160*18+2*50, character );

o en general:

offset = 0xB800*16+160*line+2*column;

Obteniendo memory

Ahora que sabemos cómo obtener una posición específica en memoria dando un par (x,y), tenemos un uso para las funciones _farpeek*. Ellas se usan más o menos de la misma forma que sus hermanas:

char ch = _farpeekb( _dos_ds, 0xB800*16+2*x+160*y );

Las diferencias son: como peek obtiene datos de la memoria, el valor que regresa debe ponerse en una variable; y no hay tercer parámetro.

Las funciones peek son usadas para guardar la pantalla(o algun area de ella). Por ejemplo: queremos imprimir "This is a phrase" con atributo inverso(o fondo blanco) an la posición(26,10), esperar que se presione una tecla y luego restaurar lo que estubiera en esa posición.

#include <go32.h>
#include <sys/farptr.h>
#include <string.h>

void
pause(void)
{
    while( !bioskey(1) )
    {
    }
}

int
main()
{
    int i, length;
    char *st = "This is a phrase";
    char buffer[(2 * strlen(st))];
    length = strlen(st);
    _farsetsel(_dos_ds);
    for ( i = 0; i < length; i++ )
    {
        buffer[2*i] = _farnspeekb( 0xB800*16+160*Y+2*(X+i) );
        buffer[2*i+1] = _farnspeekb( 0xB800*16+160*Y+2*(X+i)+1 );
        _farnspokeb( 0xB800*16+160*Y+2*(X+i), *st++ );
        _farnspokeb( 0xB800*16+160*Y+2*(X+i)+1, 0x70 );
    }
    pause();
    for ( i = 0; i < (2*length); i++ )
    {
        _farnspokeb( 0xB800*16+160*Y+2*(X)+i, buffer[i] );
    }
    return 0;
}

Texto por Bruno Barberi Gnecco < brunobg@geocities.com>


traducido por ADnoctum


  webmaster   donations   bookstore     delorie software   privacy  
  Copyright © 1998   by DJ Delorie     Updated Nov 1998  

Please take a moment to fill out this visitor survey

You can help support this site by visiting the advertisers that sponsor it! (only once each, though)