Регистр горизонтального панорамирования (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
}
}
Содержание раздела