Программирование видеоадаптеров CGA,EGA и VGA

http://segodnyaprazdnik.com/prazdniki-10-sentyabrya-sobyitiya-istoricheskie-dni-imeninyi.html

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



Рисунок 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 } }







Начало  Назад  Вперед