Рисунки, подготовленные в стандарте PCX
Подпрограмма PackDrw
Перед построением рисунка надо прочитать заголовок файла, проверить его соответствие стандарту PCX и наличие в нем полноцветного упакованного рисунка. Затем из полей заголовка выбираются значения переменных iheight, iwidth и fwidth. Если заголовок прочитан полностью (soh байтов), то файл установлен на начало образа рисунка.
Текст подпрограммы приведен в примере 7.28. Перед ее вызовом устанавливается окно видеопамяти, в котором расположено начало строящегося рисунка. Адрес начала рисунка указывается в регистре di, а регистр es должен содержать код видеосегмента. Кроме того, надо удалить с экрана изображение курсора (call Hidepnt) и восстановить его на экране (call Showpnt) после построения рисунка.
Пример 7.28. Построение упакованного рисунка формата PCX.
or dx, dx обработана вся строка? jnz Unpck2 › нет, продолжение обработки PopReg <cx,di> восстановление содержимого di и сх dec di для записи зеленых или синих цветов loop Unpckl управление внешним циклом PopReg <di, ex, dx, ax> восстановление регистров ret возврат из подпрограммы I PackDrw: pusha сохранение "всех" регистров PushReg <f s, gs, Cur win>; сохранение fs, gs и Cur win mov gs, GenSeg gs = сегмент общего назначения mov f s, SwpSeg fs = сегмент буфера обмена xor si, si адрес начала буфера обмена mov SwpOffs, si адрес начала буфера обмена mov incount, si incount = 0 – буфер обмена пуст mov dx, iwidth dx = количество точек в строке рисунка 1 mov ex, iheight сх = количество строк в рисунке call calloffs bx – константа для коррекции адресов make: push ex; сохраняем счетчик повторов цикла call Unpack распаковка очередной строки PushReg <fs,si> сохраняем содержимое fs и si Ifs si, dword ptr GenOffs; fs:si = адрес распакованной строки raov ex, dx сх = количество точек в строке рисунка call drawline построение очередной строки add di, bx адрес начала следующей строки jnc @F; › адрес в пределах текущего сегмента call Nxtwin установка следующего окна @@: PopReg <s i, f s, cx> восстанавливаем содержимое si, fs и сх loop make управление повторами цикла PopReg <Cur win,gs, fs>; восстановление Cur win, gs и fs popa восстановление "всех" регистров call Setwin восстановление исходного окна ret возврат из подпрограммы
Выполнение примера 7.28 начинается с сохранения в стеке содержимого всех регистров, а также сегментных регистров fs, gs и переменной cur_win. Затем в gs и fs записываются коды сегментов буферов GenSeg и SwpSeg и очищаются регистр si, переменные swpoffs и incount. В регистры dx и сх копируются размеры рисунка, и вызывается подпрограмма caiioffs для вычисления константы переадресации строк.
Основной цикл примера 7.28 имеет метку make. Для построения каждой строки в нем последовательно вызываются подпрограммы unpack и drawline. Перед вызовом drawline сохраняется исходное содержимое пары регистров fs:si, а в них помещается адрес распакованной строки. После возвращения из drawline, как обычно, корректируется адрес видеопамяти, восстанавливается содержимое регистров si, fs, сх и команда loop make управляет повторами цикла.
Перед возвратом на вызывающий модуль восстанавливаются все сохраненные в стеке величины и исходное окно видеопамяти. Завершает подпрограмму команда ret.
В зависимости от видеорежима в примере 7.28 используется один из вариантов подпрограмм drawline, описанных в примере 7.26.
Рисунки, использующие палитру
Подпрограмма PackDrw позволяет строить рисунки, подготовленные с применением палитры цветов. Для распаковки таких рисунков в ней вызывается подпрограмма unpack, описанная в примере 3.26, а вариант подпрограммы drawline выбирается в зависимости от установленного видеорежима.
При работе в режимах PPG для построения распакованной строки вызывается одна из подпрограмм drawline, описанных ранее.
Если же задача работает в одном из режимов direct color, то перед построением рисунка хранящаяся в файле палитра преобразуется в таблицу цветов. В зависимости от видеорежима для этого выбирается одна из подпрограмм 7.17-7.20. Строку рисунка с перекодированием точек по таблице цветов строит подпрограмма примера 7.21.