Программирование видеоадаптеров

       

Регистр горизонтального панорамирования (Horizontal Panning Register - HPR) (индекс13)


Регистр позволяет сдвинуть изображение на экране в горизонтальном направлении. При использовании регистра HPR совместно с регистром начального адреса контроллера атрибутов можно сдвигать изображение на любое количество пикселов.

Формат регистра горизонтального панорамирования представлен ниже:

D3-D0    Биты определяют величину горизонтального сдвига:

Биты

Величина сдвига содержимого экрана (в пикселах)

D3 D2 D1 D0



Монохромный текстовый режим

Режим 13h

Остальные режимы

0  0  0  0

8

0

0

0  0  0  1

0

-

1

0  0  1  0

1

1

2

0  0  1  1

2

-

3

0  1  0  0

3

2

4

0  1  0  1

4

-

5

0  1  1  0

5

3

6

0  1  1  1

6

-

7

1  0  0  0

7

-

-

1  0  0  1

-

-

-

1  0  1  0

-

-

-

1  0  1  1

-

-

-

1  1  0  0

-

-

-

1  1  0  1

-

-

-

1  1  1  0

-

-

-

1  1  1  1

-

-

-

D7-D4    Не используются.

По умолчанию для всех режимов работы видеоадаптера регистр горизонтального панорамирования содержит нулевые значения для всех битов.

На рисунке 8.18 иллюстрируется операция горизонтального сдвига содержимого экрана при различных значениях регистра HPR. На левой части рисунка регистр горизонтального панорамирования содержит ноль, а на правой части рисунка значение регистра увеличено до трех. Изображение на экране сдвигается на три пиксела влево.

PICTURE._FIG_30.PCX;6";4.308";PCX

Рисунок 4.18   Горизонтальный сдвиг экрана

Программа SCRSPLIT позволяет перемещать содержимое экрана по горизонтали и вертикали. Исходный текст программы представлен в листинге 4.11.

Листинг 4.11. Файл SCRSPLIT.C

// Смещение содержимого экрана по горизонтали и вертикали

#include "sysgraph.h"

#include <stdio.h>

#include <stdlib.h>

#include <graph.h>

#include "sysp.h"

#include <dos.h>

void HorScroll(unsigned, unsigned);


void VerScroll(unsigned);

void SetColumn(unsigned char);

void main(void) {

  struct videoconfig vc;

  unsigned char   i,j;

  // выбираем текстовый режим работы видеоадаптера,

  // принятый по умолчанию

  _setvideomode(_DEFAULTMODE);

  // устанавливаем логическую ширину экрана в 100 символов

  SetColumn(100);

  // отображаем на экране монитора 24 строки текста

  for(i = 0; i < 24; i++)

                printf("\ntext text text");

  // производим горизонтальное смещение экрана

  // на i пикселов при каждом нажатии на клавиатуру

  for(i = 0; i < 13; i++) {

                getch();

                HorScroll(i,8);

  }

  // производим вертикальное смещение экрана

  // на i пикселов при каждом нажатии на клавиатуру

  for(i = 0; i < 13; i++) {

                getch();

                VerScroll(i);

  }

  getch();

_setvideomode(_DEFAULTMODE);

}

Сдвиг изображения на экране монитора выполняют функции HorScroll и VerScroll. Функция HorScroll сдвигает изображение в горизонтальном направлении, а функция VerScroll в вертикальном. Исходный текст функций представлен в листинге 4.12.

Листинг 4.12. Файл SPLIT.ASM

/**

*.Name  HorScroll

*

*.Title     Горизонтальный сдвиг содержимого экрана.

*

*.Descr  Функция смещает содержимое экрана влево на определенное

*                              число пикселов.

*

*.Proto   void HorScroll(unsigned offset, unsigned wide)

*

*.Params              unsigned  offset - величина смещения в пикселах,

*

*                              unsigned  wide   - ширина символов (8 или 9).

*

*.Return Не используется.

*

*.Sample               scroll.c

**/

void HorScroll(unsigned offset, unsigned wide) {

  unsigned start_addr_reg, panning_reg;

  div_t res;

  res = div(offset,wide);

  start_addr_reg = res.quot;

  panning_reg = (wide == 9) ?

                                                ((res.rem == 0) ? 8 : res.rem - 1 ) : res.rem;

  _asm {

                push       ds

; вычисляем адрес регистра состояния 1 (3BAh/3DAh)



                xor          ax,ax

                mov        es,ax

                mov        dx,es:[463h]

                add         dx,6

; ожидаем начало обратного вертикального хода луча

                in             al,dx

                nop

                nop

                test         al,08h

                jz             wait_on

  wait_off:

                in             al,dx

                nop

                nop

                test         al,08h

                jnz           wait_off

  wait_on:

                in             al,dx

                nop

                nop

                test         al,08h

                jz             wait_on

; вычисляем адрес порта индексного регистра контроллера ЭЛТ

                sub         dx,6

; выбираем для доступа младший байт регистра начального адреса

                mov        al,0Dh

                out          dx,al

; вычисляем адрес порта регистра данных контроллера ЭЛТ

                inc          dx

; устанавливаем новый начальный адрес

                mov        ax,start_addr_reg

                out          dx,al

; снова получаем адрес порта регистра состояния 1

                add         dx,5

; сбрасываем внутренний триггер контроллера атрибутов, управляющий

; адресацией его регистров

                in             al,dx

                nop

                nop

; выбираем регистр горизонтального панорамирования

                mov        dx,3C0h

                mov        al,13h

                out          dx,al

                mov        ax,panning_reg

                out          dx,al

                pop         ds

  }

}

/**

*.Name  VerScroll

*

*.Title     Вертикальный сдвиг содержимого экрана.

*

*.Descr  Функция смещает содержимое экрана вверх на определенное

*                              число пикселов.

*

*.Proto   void VerScroll(unsigned offset)

*

*.Params              unsigned  offset - величина смещения в пикслах.

*

*.Return Не используется.



*

*.Sample               scroll.c

**/

void VerScroll(unsigned offset) {

  unsigned start_addr_reg, preset_row_reg;

  div_t res;

  BIOS_VAR _far  *bios_var_ptr;

  bios_var_ptr = (BIOS_VAR _far *) FP_MAKE(0x0000, 0x0410);

  res = div(offset,bios_var_ptr -> wCharHigh);

  start_addr_reg = res.quot * (bios_var_ptr -> wColumns);

  preset_row_reg = res.rem;

  _asm {

                push       ds

; вычисляем адрес регистра состояния 1 (3BAh/3DAh)

                xor          ax,ax

                mov        es,ax

                mov        dx,es:[463h]

                add         dx,6

; ожидаем начало обратного вертикального хода луча

                in             al,dx

                nop

                nop

                test         al,08h

                jz             wait_on

  wait_off:

                in             al,dx

                nop

                nop

                test         al,08h

                jnz           wait_off

  wait_on:

                in             al,dx

                nop

                nop

                test         al,08h

                jz             wait_on

; вычисляем адрес порта индексного регистра контроллера ЭЛТ

                sub         dx,6

; модифицируем младший байт регистра начального адреса

                mov        al,0Dh

                out          dx,al

                inc          dx

                mov        ax,start_addr_reg

                out          dx,al

                dec         dx

; модифицируем старший байт регистра начального адреса

                mov        al,0Ch

                out          dx,al

                inc          dx

                mov        al,ah

                out          dx,al

; вычисляем адрес порта регистра состояния 1

                add         dx,5

; ожидаем вертикальный обратный ход луча

wait_next:

                in             al,dx

                nop

                nop

                test         al,08h

                jz             wait_next



; определяем адрес порта индексного регистра контроллера ЭЛТ

                sub         dx,6

; устанавливаем регистр предустановки линии сканирования

                mov        al,8

                out          dx,al

                mov        ax,preset_row_reg

                inc          dx

                out          dx,al

                pop         ds

  }

}

/**

*.Name  SetColumn

*

*.Title     Установка логической ширины экрана.

*

*.Descr  Функция устанавливает логическую ширину экрана.

*

*.Proto   void SetColumn(unsigned char col)

*

*.Params              unsigned char  col - логическая ширина экрана (в символах).

*

*.Return Не используется.

*

*.Sample               scroll.c

**/

void SetColumn(unsigned char col) {

  _asm {

                xor          ax,ax

                mov        es,ax

; получаем адрес порта индексного регистра

; контроллера ЭЛТ (3B4h/3D4h)

                mov        dx,es:[463h]

; выбираем для обмена регистр логической ширины экрана

                mov        al,13h

                out          dx,al

; вычисляем адрес порта регистра данных контроллера ЭЛТ (3B5h/3D5h)

                inc          dx

; модифицируем переменную BIOS, содержащую число символов в строке

                mov        al,col

                mov        es:[44Ah],al

; регистр логической ширины экрана в текстовых режимах содержит

; смещение между соседними строками текста в словах

                shr          al,1

                out          dx,al

  }

}


Содержание раздела