Хрестоматия по программированию на Си в Unix



   Детальное описание натуральный жемчуг бусы у нас на сайте.             

Экранные библиотеки и работа с видеопамятью. Хрестоматия по программированию на Си в Unix - стр. 4


/*#! /bin/cc fall.c -o fall -lx * "Осыпающиеся буквы". * Использование видеопамяти IBM PC в ОС XENIX. * Данная программа иллюстрирует доступ к экрану * персонального компьютера как к массиву байт; * все изменения в массиве немедленно отображаются на экране. * Функция nap() находится в библиотеке -lx * Показана также работа с портами IBM PC при помощи ioctl(). */ #include <stdio.h>

#include <fcntl.h> /* O_RDWR */ #include <signal.h>

#include <ctype.h>

#include <sys/types.h>

#include <sys/at_ansi.h>

#include <sys/kd.h> /* for System V/4 and Interactive UNIX only */ /*#include <sys/machdep.h> for XENIX and SCO UNIX only */ #include <sys/sysmacros.h>

#ifdef M_I386 # define far /* на 32-битной машине far не требуется */ #endif char far *screen; /* видеопамять как массив байт */ /* far - "длинный" (32-битный) адрес(segment,offset) */ int segm; /* сегмент с видеопамятью */ #define COLS 80 /* число колонок на экране */ #define LINES 25 /* число строк */ #define DELAY 20 /* задержка (миллисекунд) */ int ega; /* дескриптор для доступа к драйверу EGA */ /* структура для обмена с портами */ static struct port_io_struct PORT[ 4 /* не более 4 за раз */] = { /* операция номер порта данные */ /* .dir .port .data */ /* Переустановить flip/flop: * заставить порт 0x3C0 ожидать пары адрес/значение * при последовательной записи байтов в этот порт. */ { IN_ON_PORT, 0x3DA, -1 }, /* IN-чтение */ /* Теперь 3c0 ожидает пары адрес/значение */ { OUT_ON_PORT, 0x3C0, -1 /* адрес */ }, { OUT_ON_PORT, 0x3C0, -1 /* значение*/ }, /* OUT-запись */ /* переинициализировать дисплей, установив бит #5 порта 3c0 */ { OUT_ON_PORT, 0x3C0, 0x20 } }; void closescr(nsig){ /* конец работы */ setbgcolor(0); /* установить черный фон экрана */ exit(0); } /* получение доступа к видеопамяти адаптера VGA/EGA/CGA */ void openscr () { static struct videodev { char *dev; int mapmode; } vd[] = { { "/dev/vga", MAPVGA }, { "/dev/ega", MAPEGA }, { "/dev/cga", MAPCGA }, { NULL, -1 } }, *v; /* устройство для доступа к видеоадаптеру */ for(v=vd; v->dev;v++ ) if((ega = open (v->dev, O_RDWR)) >= 0 ) goto ok; fprintf( stderr, "Can't open video adapter\n" ); exit(1); ok: /* fprintf(stderr, "Adapter:%s\n", v->dev); */ /* получить адрес видеопамяти и доступ к ней */ #ifdef M_I386 screen = (char *) ioctl (ega, v->mapmode, 0); #else segm = ioctl (ega, v->mapmode, 0); screen = sotofar (segm, 0); /* (segment,offset) to far pointer */ #endif signal( SIGINT, closescr ); } /* макросы для доступа к байтам "символ" и "атрибуты" * в координатах (x,y) экрана. */ #define GET(x,y) screen[ ((x) + (y) * COLS ) * 2 ] #define PUT(x,y, c) screen[ ((x) + (y) * COLS ) * 2 ] = (c) #define GETATTR(x,y) screen[ ((x) + (y) * COLS ) * 2 + 1 ] #define PUTATTR(x,y, a) screen[ ((x) + (y) * COLS ) * 2 + 1 ] = (a) /* символ изображается как черный пробел ? */ #define white(c,a) ((isspace(c) c==0) && (attr & 0160)==0) /* установить цвет фона экрана */ void setbgcolor( color ){ PORT[1].data = 0; /* регистр номер 0 палитры содержит цвет фона */ /* всего в палитре 16 регистров (0x00...0xFF) */ PORT[2].data = color ; /* новое значение цвета, составленное как битовая маска * RGBrgb (r- красный, g- зеленый, b- синий, RGB- дополнительные * тусклые цвета) */ /* выполнить обмены с портами */ if( ioctl( ega, EGAIO, PORT ) < 0 ){ fprintf( stderr, "Can't out port\n" ); perror( "out" ); } } void main(ac, av) char **av;{ void fall(); openscr(); if( ac == 1 ){ setbgcolor(020); /* темно-зеленый фон экрана */ fall(); /* осыпание букв */ } else { if(*av[1] == 'g') /* Установить режим адаптера graphics 640x350 16-colors */ ioctl( ega, SW_CG640x350, NULL); /* Если вы хотите получить адрес видеопамяти в графическом режиме, * вы должны СНАЧАЛА включить этот режим, * ЗАТЕМ сделать screen=ioctl(ega, v->mapmode, NULL); * и ЕЩЕ РАЗ сделать включение графического режима. */ /* Установить режим адаптера text 80x25 16-colors */ else ioctl( ega, SW_ENHC80x25, NULL); } closescr(0); } /* осыпать буквы вниз */ void fall(){ register i, j; int rest; int nextcol; int n; int changed = 1; /* не 0, если еще не все буквы опали */ char mask [ COLS ]; while( changed ){ changed = 0; for( i = 0 ; i < COLS ; i++ ) mask[ i ] = 0; for( i = 0 ; i < COLS ; i++ ){ rest = COLS - i; /* осталось осыпать колонок */ nextcol = rand() % rest; j = 0; /* индекс в mask */ n = 0; /* счетчик */ for(;;){ if( mask[j] == 0 ){ if( n == nextcol ) break; n++; } j++; } changed += fallColumn( j ); mask[j] = 1; } } } /* осыпать буквы в одном столбце */ int fallColumn( x ){ register int y; char ch, attr; int firstspace = (-1); int firstnospace = (-1); Again: /* find the falled array */ for( y=LINES-1; y >= 0 ; y-- ){ ch = GET( x, y ); attr = GETATTR( x,y ); if( white(ch, attr)){ firstspace = y; goto FindNoSpace; } } AllNoSpaces: return 0; /* ничего не изменилось */ FindNoSpace: /* найти не пробел */ for( ; y >= 0 ; y-- ){ ch = GET( x, y ); attr = GETATTR( x, y ); if( !white(ch, attr)){ firstnospace = y; goto Fall; } } AllSpaces: /* в данном столбце все упало */ return 0; Fall: /* "уронить" букву */ for( y = firstnospace ; y < firstspace ; y++ ){ /* переместить символ на экране на одну позицию вниз */ ch = GET( x, y ); attr = GETATTR( x, y ); PUT( x, y, 0 ); PUTATTR( x, y, 0 ); PUT( x, y+1 , ch ); PUTATTR( x, y+1, attr ); nap( DELAY ); /* подождать DELAY миллисекунд */ } return 1; /* что-то изменилось */ }

* - Под протоколом в программировании подразумевают ряд соглашений двух сторон (сервера и клиентов; двух машин в сети (кстати, термин для обозначения машины в сети "host" или "site")) о формате (правилах оформления) и смысле данных в передаваемых друг другу сообщениях. Аналогия из жизни - человеческие речь и язык. Речь всех людей состоит из одних и тех же звуков и может быть записана одними и теми же буквами (а данные - байтами). Но если два человека говорят на разных языках - т.е. поразному конструируют фразы и интерпретируют звуки - они не поймут друг друга!

** - XENIX - (произносится "зиникс") версия UNIX для IBM PC, первоначально разработанная фирмой Microsoft и поставляемая фирмой Santa Cruz Operation (SCO).

© Copyright А. Богатырев, 1992-95
Си в UNIX

| |




Содержание  Назад  Вперед