	TITLE   RUS_DRV

	.MODEL  tiny

	DOSSEG

	; устанавливаем стек 256 байт
	.STACK  100h

	; сегмент кода
	.CODE

	; производим инициализацию сегментных регистров
	.STARTUP

		jmp     start

		; файл cga_font.inc содержит описание шрифта 8х8 пикселов

		include cga_font.inc

		; файл ega_font.inc содержит описание шрифта 8х14 пикселов

		include ega_font.inc

		; файл vga_font.inc содержит описание шрифта 8х16 пикселов

		include vga_font.inc


		; информация о программе, отображается на экране при
		; ее запуске

		hello_msg      DB      254, "  Драйвер русских букв.", 13, 10
							DB      254, "  Copyright (C) Фролов Г.В., 1992"
							DB      13, 10, "$"

		; в следующие две переменные будет записан старый вектор прерывания 10h
		off_int_10h   DW    ?
		seg_int_10h   DW    ?

		not_clr       DB  ?

		; начало программы
	start:

		; получаем и сохраняем старый вектор прерывания 10h

		mov     ax,3510h
		int     21h
		mov     off_int_10h,bx
		mov     seg_int_10h,es

		; устанавливаем новый обработчик прерывания 10h

		mov     dx,OFFSET int_10h
		mov     ax,2510h
		int     21h

		; устанавливаем режим 3 видеоадаптера
		; при этом сразу загружаются новые шрифты

		mov     ax,3
		int     10h

		; выводим сообщение о программе

		mov     ah, 9h
		mov     dx, OFFSET hello_msg
		int     21h

		; завершаем программу, при этом оставляем ее резидентной в памяти

		mov     ax,3100h
		mov     dx,OFFSET resident
		shr     dx,1
		shr     dx,1
		shr     dx,1
		shr     dx,1
		inc     dx
		int     21h

;---------------------------------------------------------------
;   новый обработчик прерывания INT 10h
;---------------------------------------------------------------

	int_10h:

		; проверяем, вызвана ли функция установки режима адаптера
		or      ah,ah
		jz      set_mode  ; да
		jmp     char_gen  ; нет

	set_mode:

		; когда вызвана функция установки режима адаптера, то
		; записываем в переменную not_clr 0h, если при установке
		; нового режима надо очистить видеопамять и 80h в
		; противном случае

		mov     cs:not_clr,0
		test    al,80h
		jz      test_mode

		mov     cs:not_clr,80h

		; сбрасываем бит D8, его содержимое находится в not_clr
		and     al,7Fh

	test_mode:

		; затем сохраняем значения регистров процессора

		push    ax
		push    bx
		push    dx
		push    bp
		push    es
		push    ds

		push    cs
		pop     ds

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

		; текстовые режимы 0 - 3
		cmp     al,3
		jbe     text_0_3

		; текстовый режим 7
		cmp     al,7
		je      text_7

		; графические режимы 4 - 0Eh
		cmp     al,0Eh
		jbe     graph_Eh

		; графический режим 13h
		cmp     al,13h
		je      graph_13h

		; графические режимы 0Eh - 10h
		cmp     al,10h
		jbe     graph_10h

		; графические режимы 11h и 12h
		cmp     al,12h
		jbe     graph_12h

		; если режим нестандартный, передаем управление BIOS
		; для его установки и не загружаем свой шрифт

		jmp     old_int_10h

		; текстовые режимы 0, 1, 2, 3, 7

	text_0_3:
	text_7:

		; восстанавливаем регистр ax
		or      al,cs:not_clr

		; вызываем старый обработчик прерывания 10h
		; для установки нового режима

		pushf
		call    DWORD PTR cs:off_int_10h

		; получаем в bx высоту символов текста в пикселах
		; для установленного выше режима

		; высота символов записывается BIOS при выборе нового режима
		; в переменную по адресу 0000:0485

		xor     dx,dx
		mov     es,dx
		mov     bx,es:[485h]

		; в соответствии с полученной нами высотой символа
		; выбираем шрифт 8х8, 8х14 или 8х16 пикселов

		cmp     bx,8         ; высота символов 8 пикселов
		jne     line_14

		; загружаем в регистр bp смещение таблицы шрифтов 8х8,
		; таблица шрифтов 8х8 пикселов определена в файле
		; cga_font.inc

		mov     bp,OFFSET fon8_ascii0
		jmp     set_text_font

	line_14:

		cmp     bx,14        ; высота символов 14 пикселов
		jne     line_16

		; загружаем в регистр bp смещение таблицы шрифтов 8х14,
		; таблица шрифтов 8х14 пикселов определена в файле
		; ega_font.inc

		mov     bp,OFFSET fon14_ascii0
		jmp     set_text_font

	line_16:

		cmp     bx,16

		; если полученная высота символов не равна 8, 14 и 16
		; завершаем обработку
		jne     exit_int_10h

		; высота символов 16 пикселов

		mov     bp,OFFSET fon16_ascii0

	set_text_font:

		; загружаем наш шрифт в память

		mov     ax,1100h

		push    cs
		pop     es

		xchg    bl,bh

		mov     cx,256


	old_int_10h:

		; вызываем старый обработчик прерывания 10h

		pushf
		call    DWORD PTR cs:off_int_10h

	exit_int_10h:

		; восстанавливаем содержимое регистров процессора

		pop     ds
		pop     es
		pop     bp
		pop     dx
		pop     bx
		pop     ax

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

		iret

		; вызывющая программа устанавливает графические режимы
		; 4, 5, 6, 0Dh, 0Eh

	graph_Eh:
	graph_13h:

		; вызываем старый обработчик прерывания 10h
		; для установки нового режима

		pushf
		call    DWORD PTR cs:off_int_10h

		; подготавливаем регистры для выбора шрифта 8х8

		mov     dx,OFFSET fon8_ascii0
		mov     bp,OFFSET fon8_ascii128
		jmp     set_gr_font

		; вызывющая программа устанавливает графические режимы
		; 0Fh, 10h

	graph_10h:

		; вызываем старый обработчик прерывания 10h
		; для установки нового режима

		pushf
		call    DWORD PTR cs:off_int_10h

		; подготавливаем регистры для выбора шрифта 8х8

		mov     dx,OFFSET fon14_ascii0
		mov     bp,OFFSET fon14_ascii128
		jmp     set_gr_font

		; вызывющая программа устанавливает графические режимы
		; 11Dh, 12h

	graph_12h:

		; вызываем старый обработчик прерывания 10h
		; для установки нового режима

		pushf
		call    DWORD PTR cs:off_int_10h

		; подготавливаем регистры для выбора шрифта 8х8

		mov     dx,OFFSET fon16_ascii0
		mov     bp,OFFSET fon16_ascii128

	set_gr_font:

		; устанавливаем наши графические шрифты,
		; изменяя векторы прерываний 1Fh и 43h

		mov     ax,2543h
		int     21h

		mov     dx,bp

		mov     ax,251Fh
		int     21h

		; завершаем обработку прерывания
		jmp     exit_int_10h


		; если вызывающая программа вызвала не функцию
		; установки режима, проверяем вызвана ли
		; функция выбора нового шрифта

	char_gen:

		cmp     ah,11h
		je      gen_func

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

	go_int_10h:

		pushf
		call    DWORD PTR cs:off_int_10h
		iret


	gen_func:

		; если вызывается функция установки нового шрифта, то
		; смотрим какая вызывается подфункция

		; вызывается подфункция загрузки шрифта 8х8 из BIOS
		cmp     al,1
		je      text_rom_8_14

		; вызывается подфункция загрузки шрифта 8х8 из BIOS
		; с переустановкой контроллера ЭЛТ
		cmp     al,11h
		je      text_rom_8_14

		; вызывается подфункция загрузки шрифта 8х14 из BIOS
		cmp     al,2
		je      text_rom_8_8

		; вызывается подфункция загрузки шрифта 8х14 из BIOS
		; с переустановкой контроллера ЭЛТ
		cmp     al,12h
		je      text_rom_8_8

		; вызывается подфункция загрузки шрифта 8х16 из BIOS
		cmp     al,4
		je      text_rom_8_16

		; вызывается подфункция загрузки шрифта 8х16 из BIOS
		; с переустановкой контроллера ЭЛТ
		cmp     al,14h
		je      text_rom_8_16

		; если вызывается другая подфункция, то передаем управление
		; старому обработчику прерываний

		jmp     go_int_10h

	text_rom_8_8:

		; выбираем шрифт 8х8 пикселов

		mov     bp,OFFSET fon8_ascii0
		mov     bh,8
		jmp     set_our_text_font

	text_rom_8_14:

		; выбираем шрифт 8х14 пикселов

		mov     bp,OFFSET fon14_ascii0
		mov     bh,14
		jmp     set_our_text_font

	text_rom_8_16:

		; выбираем шрифт 8х16 пикселов

		mov     bp,OFFSET fon16_ascii0
		mov     bh,16

	set_our_text_font:

		; устанавливаем свой шрифт

		and     al,0f0h
		push    cs
		pop     es

		mov     cx,256
		xor     dx,dx

		; вызываем старый обработчик прерывания 10h

		pushf
		call    DWORD PTR cs:off_int_10h
		iret

	resident:

		END

