Горизонтальный сдвиг экрана.
Рисунок 8.16 Горизонтальный сдвиг экрана.
Следующая программа позволяет перемещать содержимое экрана по горизонтали и вертикали. Функции HorScroll и VerScroll реализуют, соответственно, горизонтальный и вертикальный сдвиг экрана.
// смещение содержимого экрана по горизонтали и вертикали
#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); }
/** *.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 -> char_height);
start_addr_reg = res.quot * (bios_var_ptr -> columns); 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 } }
Содержание раздела