TITLE	SCROLL.ASM
NAME	SCROLL
PAGE	55,132

P286
IDEAL
NOWARN BRK

SEGMENT SCROLL_TEXT WORD PUBLIC 'CODE'
ASSUME	cs:SCROLL_TEXT


; void HorScroll(unsigned start_addr_reg, unsigned panning_reg)
; Функция смещает содержимое экрана влево на определенное
; число пикселов
; Параметры:
;	start_addr_reg	- значение для регистра начального адреса
;	panning_reg 	- значение для регистра горизонтальной свертки

panning_reg		EQU	[bp+6]
start_addr_reg	EQU	[bp+8]

PUBLIC	HORSCROLL
PROC	HORSCROLL FAR

	enter	0, 0

	push ds

	; Вычисляем адрес регистра состояния 1 (3BAh/3DAh)
	xor  ax,ax
	mov  es,ax
	mov  dx,es:[463h]
	add  dx,6

	; Ожидаем начало обратного вертикального хода луча
	in   al,dx
	test al,08h
	jz   wait_on_h

 wait_off_h:

	in   al,dx
	test al,08h
	jnz  wait_off_h

 wait_on_h:

	in   al,dx
	test al,08h
	jz   wait_on_h

	; Вычисляем адрес порта индексного регистра контроллера ЭЛТ
	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,33h
	out  dx,al

	mov  ax,panning_reg
	out  dx,al

	pop  ds

	leave
	ret 4

ENDP	HORSCROLL


; void VerScroll(start_addr_reg, preset_row_reg)
; Функция смещает содержимое экрана вверх на определенное
; число пикселов
; Параметры:
;	start_addr_reg	- значение для регистра начального адреса
;	preset_row_reg	- значение для регистра предустановки линии скаанирования

preset_row_reg	EQU	[bp+6]
start_addr_reg	EQU	[bp+8]

PUBLIC	VERSCROLL
PROC	VERSCROLL FAR


	enter	0, 0

	push ds

	; Вычисляем адрес регистра состояния 1 (3BAh/3DAh)
	xor  ax,ax
	mov  es,ax
	mov  dx,es:[463h]
	add  dx,6

	; Ожидаем начало обратного вертикального хода луча
	in   al,dx
	test al,08h
	jz   wait_on_v

 wait_off_v:

	in   al,dx
	test al,08h
	jnz  wait_off_v

 wait_on_v:

	in   al,dx
	test al,08h
	jz   wait_on_v



	; Вычисляем адрес порта индексного регистра контроллера ЭЛТ
	sub  dx,6

	; Устанавливаем регистр предустановки линии скаанирования
	mov  al,8
	out  dx,al
	mov  ax,preset_row_reg
	inc  dx
	out  dx,al

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

	; Модифицируем младший байт регистра начального адреса
	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


	pop  ds

	leave
	ret 4

ENDP	VERSCROLL



; void SetColumn(unsigned char col)
; Функция устанавливает логическую ширину экрана
; Параметры:
;	col - логическая ширина экрана (в символах)

col	EQU	[bp+6]

PUBLIC	SETCOLUMN
PROC	SETCOLUMN FAR

	enter	0, 0

	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

	leave
	ret 2

ENDP	SETCOLUMN

ENDS	SCROLL_TEXT

END
