Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Богатырев А. Весь текст 1009.15 Kb

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

Предыдущая страница Следующая страница
1 ... 60 61 62 63 64 65 66  67 68 69 70 71 72 73 ... 87
вете функцию refresh() ("обновить"), все изменения происшедшие в окнах будут  отобра-
жены  на  экране  дисплея  (такое  одновременное  обновление всех изменившихся частей
экрана позволяет провести ряд оптимизаций).  Если вы забудете сделать refresh - экран
останется  неизменным. Обычно эту функцию вызывают перед тем, как запросить у пользо-
вателя какой-либо ввод с клавиатуры, чтобы пользователь увидел текущую "свежую"  кар-
тинку.   Хранение содержимого окон в памяти программы позволяет ей считывать содержи-
мое окон, тогда как большинство обычных терминалов не  способны  выдать  в  компьютер
содержимое какой-либо области экрана.

     Общение с терминалом через линию связи (или вообще через последовательный прото-
кол) является довольно медленным.  На персональных компьютерах существует другой спо-
соб работы с экраном: через прямой доступ в так называемую "видеопамять" -  специаль-
ную  область  памяти  компьютера, содержимое которой аппаратно отображается на экране
консоли.  Работа с экраном превращается для программиста в  работу  с  этим  массивом
байт (запись/чтение).  Программы, пользующиеся этим способом, просты и работают очень
быстро (ибо доступ к памяти черезвычайно быстр, и сделанные в ней изменения "проявля-
ются"  на  экране почти мгновенно). Недостаток таких программ - привязанность к конк-
ретному типу машины. Эти программы немобильны и не могут работать ни на обычных  тер-
миналах  (подключаемых к линии связи), ни на машинах с другой структурой видеопамяти.
Выбор между "традиционной" работой с экраном и прямым доступом  (фактически  -  между
мобильностью  и  скоростью)  -  вопрос  принципиальный, тем не менее принятие решения
зависит только от вас.  Видеопамять IBM PC в текстовом режиме 80x25 16  цветов  имеет
следующую структуру:

       struct symbol{       /* IBM PC family           */
            char chr;       /* код символа             */
            char attr;      /* атрибуты символа (цвет) */
       } mem[ 25 ] [ 80 ];  /* 25 строк по 80 символов */

               Структура байта атрибутов:
     -------------------------------------------
     | 7   | 6 | 5 | 4 | 3         | 2 | 1 | 0 | # бита
     ------------------|------------------------
     |blink| R | G | B | intensity | r | g | b | цвет
     ------------------|------------------------
     background (фон)  | foreground (цвет букв)

    R - red (красный) G - green (зеленый) B - blue (синий)
    blink     - мерцание букв (не фона!)
    intensity - повышенная яркость

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

Координатная система на экране: верхний левый угол экрана имеет координаты (0,0), ось
X горизонтальна, ось Y вертикальна и направлена сверху вниз.
     Цвет символа получается смешиванием  3х  цветов:  красного,  зеленого  и  синего
(электронно-лучевая  трубка  дисплея  имеет 3 электронные пушки, отвечающие этим цве-
там).  Кроме того, допустимы более яркие цвета. 4 бита задают комбинацию 3х  основных
цветов и повышенной яркости. Образуется 2**4=16 цветов:

                 I R G B   номер цвета
    BLACK        0 0 0 0    0    черный
    BLUE         0 0 0 1    1    синий
    GREEN        0 0 1 0    2    зеленый
    CYAN         0 0 1 1    3    циановый (серо-голубой)
    RED          0 1 0 0    4    красный
    MAGENTA      0 1 0 1    5    малиновый
    BROWN        0 1 1 0    6    коричневый
    LIGHTGRAY    0 1 1 1    7    светло-серый (темно-белый)

    DARKGRAY     1 0 0 0    8    темно-серый
    LIGHTBLUE    1 0 0 1    9    светло-синий
    LIGHTGREEN   1 0 1 0   10    светло-зеленый
    LIGHTCYAN    1 0 1 1   11    светло-циановый
    LIGHTRED     1 1 0 0   12    ярко-красный
    LIGHTMAGENTA 1 1 0 1   13    ярко-малиновый
    YELLOW       1 1 1 0   14    желтый
    WHITE        1 1 1 1   15    (ярко)-белый

     Физический адрес видеопамяти IBM PC в цветном алфавитно-цифровом режиме  (80x25,
16  цветов)  равен 0xB800:0x0000. В MS DOS указатель на эту память можно получить при
помощи макроса make far pointer: MK_FP (это должен быть far или huge указатель!).   В
XENIX[*] указатель получается при помощи системного вызова ioctl, причем  система  пре-
доставит  вам  виртуальный адрес, ибо привелегия работы с физическими адресами в UNIX
принадлежит только системе.  Работу с экраном в XENIX вы  можете  увидеть  в  примере
"осыпающиеся буквы".

8.1.

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

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

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

    #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);

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

    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" );
         }
    }

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

    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;
               }
            }
    }

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

    /* осыпать буквы в одном столбце */
    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 );
Предыдущая страница Следующая страница
1 ... 60 61 62 63 64 65 66  67 68 69 70 71 72 73 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама