TITLE   RUS_DRV

.MODEL  tiny

DOSSEG

; Сегмент кода
.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-1995"
							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:0485h

		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

