Вывод информационных строк
Манипуляции с исходным фоном
Информационная строка, как правило, располагается не на пустом экране. Поэтому надо сохранять изображение в той части рабочей области экрана, которую займет текст, и восстанавливать его при удалении текста с экрана. Сохраняемые коды точек изображения копируются из видеопамяти в оперативную память, так чтобы потом их можно было вернуть на прежнее место.
Подпрограммы копирования строки видеопамяти в оперативную память приведены в примерах 3.19 и 3.20, нам остается применить их для пересылки нескольких строк. Восстановление сохраненного фона ничем не отличается от построения рисунка, полностью помещающегося в оперативной памяти. Соответствующая подпрограмма описана в примере 3.21.
Для использования указанных или аналогичных подпрограмм пересылки надо знать исходные адреса видео и оперативной памяти и количество пересылаемых байтов. Начнем с последнего.
Размер и размещение фона
Высота информационной строки нам известна, точнее мы знаем, что ее значение хранится в переменной hsymb. Ширина строки равна произведению ширины символов на их количество, но последнее является переменной величиной. Ее значение зависит как от размера текста сообщения, так и от ответа оператора, если таковой подразумевается. Поэтому лучше выбрать ширину информационной строки равную ширине рабочей области экрана (значению переменной Horsize). При использовании стандартных таблиц в такой строке можно разместить 80, 100, 128 или 160 символов, в зависимости от установленного видеорежима. Чем выше разрешение, тем мельче изображение символов на экране и тем труднее читать текст, поэтому при работе с высоким разрешением вам могут понадобиться таблицы с более крупными символами.
Если информационная строка занимает всю ширину экрана, то количество сохраняемых байтов и размер буфера для их размещения вычисляются как произведение значений переменных Horsize и hsymb. Если hsymb = 16, то, в зависимости от видеорежима PPG, информационная строка содержит следующее количество байтов: 101h – 7680, 103h – 9600, 105h – 12288, 107h – 16384. При работе в режимах Hi-Color указанные числа увеличатся в два раза, а в режимах True Color – в четыре раза. Очевидно, что буфер таких размеров нецелесообразно располагать в разделе данных задачи, для него надо выделить отдельное место в оперативной памяти ПК.
Способы резервирования пространства оперативной памяти описаны в Приложении Б данной книги. При программировании задачи надо следить за тем, чтобы это пространство не использовалось по другому назначению. Для этого надо имя переменной, содержащей адрес выделенного сегмента, использовать только в подпрограммах сохранения и восстановления исходного фона информационной строки, но есть и другой способ защиты.
Нужный нам буфер можно расположить в начале сегмента общего назначения, выделенного в разделе для временного хранения распакованной строки рисунка. Код сегмента хранится в переменной GenSeg, а начало свободного в нем пространства в переменной GenOffs. Если Genoffs присвоить значение horsize и hsymb, то соответствующая часть сегмента будет недоступна другим подпрограммам, при условии, что они используют адрес, хранящийся в Genoffs, и не уменьшают его.
Таким образом, адрес начала информационной строки в видеопамяти хранится в переменных inf lino и inf linw, а буфер для ее размещения расположен в начале сегмента, указанного в переменных Genoffs и GenSeg.
Подпрограмма Savinfo
Текст подпрограммы, выполняющей сохранение исходного фона, приведен в примере 5.21. Перед ее вызовом надо сохранить содержимое переменной cur_win и поместить в нее номер окна из переменной infiinw, предварительная установка этого окна не требуется.
Пример 5.21. Сохранение фона на месте информационной строки.
Savinfo: PushReg <Cur_win,ax,ex,si,di,fs,es>; сохранение в стеке call setwin установка исходного окна mov fs, Vbuff fs = сегмент видеобуфера mov si, Inflino si = адрес начала информ. строки mov es, GenSeg es = сегмент общего назначения xor di, di di = 0 – смещение в GenSeg mov ax, horsize ax = ширина экрана mul byte ptr hsymb умножаем ее на высоту символа mov ex, ax копируем результат в сх shr сх, 02 уменьшаем его в 4 раза Savlp: movs dword ptr [di] fs:[si]; копирование двойного слова or si, si адрес в пределах видеосегмента? jnc @F › да, переход на команду loop call nxtwin установка следующего окна @@: loop savlp " управление циклом копирования PopReg <es,fs,di,si,cx,ax,Cur_win>; восстановление из стека call setwin; восстановление исходного окна ret; возврат из подпрограммы
В примере 5.21 копирование содержимого видеопамяти в оперативную выполняет строковая операция movs, у которой приемник находится в регистрах es:di, а источник в fs:si. Содержимое этих регистров формируется перед циклом пересылки. Затем вычисляется размер информационной области в байтах, и результат преобразуется в количество двойных слов. Строки рабочей области экрана копируются полностью, поэтому нужен только один цикл, в котором пересылается сразу по 4 байта. Цикл пересылки повторяет аналогичный цикл из примера 3.20 с той разницей, что копируются не байты, а двойные слова.
После пересылки восстанавливается содержимое сохраненных в стеке регистров и значение переменной cur_win, восстанавливается исходное окно видеопамяти и происходит возврат на вызывающий модуль.