Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
Теперь и с комментариями :) 21.02.02 13:13 Число просмотров: 949
Автор: Chingachguk <Chingachguk> Статус: Member Отредактировано 21.02.02 13:49 Количество правок: 4
|
> Спасиба! Я её откомпилировал - все нормально. > {...} Или просто опиши > как она работает - на асеме я мало что знаю: только работу > с прерываниями, и то плохо.
Так я сделал - добавил комментарии. Я думаю, ты легко поймешь
алгоритм и реализуешь его на другом языке Ж)
Код очень крив.
Желаю удачи !
Procedure Fill_Area(Color_Bound,Color_In:byte; X,Y:word);
Const
Buff_Size=4000; {Это максимальный размер буфера}
Buff_Rezerv=1000; {А это запасец, с котрого начинаем суетиться}
Flag: boolean = False; {Флаг для процедуры @Check}
Var
Fill_Buffer:Array[1..Buff_Size] of Word;
Begin
; Пошел асм-код
Asm
; Загружаем сегмент видеопамяти 0A000h в ES
push 0A000h
pop ES <-0A000h
; Команды строк(lodsb..) будут обрабатываться вперед, но у меня это мусор
cld <-можно вообще выкинуть, я на автомате их написал
; Подготовка к закраске
; Координаты переданной точки - смещение
mov AX,320
mul Y ; регистры DX:AX = 320*Y
mov BX,X ; BX = X
add BX,AX ; BX = 320*Y+X
; Цвета
mov DH,Color_Bound ; DH будет всегда = цвету границы
mov DL,Color_In ; DL - цвету закраски
; Заделать буфер в стеке, хотя тут я облажался - обявив
; буфер в var, я, фактически, задвоил его
sub BP,Buff_Size ; Тут регистр BP=начало буфера
; Проверим стартовую точку
mov SI,BX ; Координата стартовой точки
xor CX,CX ; CL будет равно после вызова @Check числу соседей
xor DI,DI {Если будут найдены точки, то они будут добавлены в буфер}
; и BP+DI укажет на последнюю точку в буфере
call @Check ; Получить соседей стартовой точки
test CX,CX ; Есть хоть один ? (if CX=0)
jz @Done {Если нет рядом точек, годных к закраске, то EXIT}
; Основной цикл
@Main_Loop:
; Закрасить точку, ее координаты(смещение в памяти) в BX
mov ES:[BX],DL
mov Flag,False {Искать + и добавлять точки}
call @Find_Points
test DI,DI ; В буфере есть точки для обработки ? (if DI=0)
jz @Done ; Нет. EXIT
; Новое
; В буфере осталось места меньше, чем Buff_Rezerv ?
; (Для Числа точек = Buff_Rezerv /2 )
cmp DI,Buff_Size-Buff_Rezerv
jbe @SizeOk ; Пора суетиться - размер на исходе ?!
cmp DI,Buff_Size ; Ваще полный аллес - в буфере НЕТ места
ja @Done ; EXIT
; В буфере осталось места меньше, чем для Buff_Rezerv/2 Точек
; Ищем точку, у которой число соседей =0
; Готовим индекс si для просмотра буфера
xor si,si
; Бежим по буферу в поисках точки с минимальным числом соседей
@FindMin:
; Проверить точку, ее координаты(смещение в памяти) в будет передано в BX
mov bx,[bp+si]
push si ; Сохранит регистр
mov Flag,True {Искать + но не добавлять точки в буфер !!!}
call @Find_Points ; Найти число соседей для очередной точки
pop si ; Восстановить si
cmp cl,1 {Соседей >=1 ? - нахрен эту точку}
jae @NextPoint
; Подбрасываем ее на обработку, уменьшая буфер
; Следующая обрабатываемая точка будет взята последней из буфера,
; поэтому меняем найденную точку с последней в буфере,
; на последнюю счас указывает bp+di-2, на найденную - bp+si
xchg [bp+di-2],bx
mov [bp+si],bx
jmp @SizeOk ; И закончить просмотр буфера (BREAK)
; Смотреть все точки для обработки в буфере
@NextPoint:
inc si
inc si
cmp si,di ; Посмотрели все точки ?
jb @FindMin
; Буфер либо не полон, либо мы попытались его выровнять
@SizeOk:
; Укажем в буфере на последнюю точку (DI)
dec di
dec di
; Загрузим смещение точки на экране в BX (для call @Find_Points
; и mov ES:[BX],DL) - см. код выше
mov BX,[BP+DI]
; Продолжить цикл
jmp @Main_Loop
; Подпрограмма Find_Points
; Получает в BX смещение текущей обрабатываемой точки
; К экрану адресуется через ES:[BX+...
; Добавляет точки в буфер(Если Flag=False) база которого в BP,
; координата последней точки в DI
@Find_Points:
; Будем накапливать число точек в CL
xor CX,CX ; CX=0
; Проверить точку (X,Y-1)
lea SI,[BX-320]
call @Check
; Проверить точку (X,Y+1)
lea SI,[BX+320]
call @Check
; Проверить точку (X-1,Y)
lea SI,[BX-1]
call @Check
; Проверить точку (X+1,Y)
lea SI,[BX+1]
call @Check
; Нужно закрашивать точки (X+-1, Y+-1) ?
test CL,CL ; CL=0 ?
jnz @Found ; Да, есть соседи для закраса
; Проверить саму точку (X,Y)
; Я не уверен счас, что этот код нужен
dec SI
dec SI
call @Check
@Found:
ret ; Вернуться из подпрограммы
; Подпрограмма @Check
; Получает в SI координату точки(смещение),
; И добавляет ее в буфер, если она нуждается в закрасе
; (Если Flag=False), а также увеличивает на 1 число найденных точек-соседей,
; Годных для закраса (в CL)
@Check:
; ВОТ ТУТ ТЕБЕ НУЖНО МЕНЯТЬ АЛГОРИТМ
; ТУТ АНАЛИЗ ЦВЕТОВ ТОЧЕК
; Получить цвет текущей точки в AL
mov AL,ES:[SI]
; Он равен цвету границы ?
cmp AL,DH
jz @Next ; Да. Точка не подходит
; Он равен цвету заливки ?
cmp AL,DL
jz @Next ; Да. Нафиг ее
; Если параметр Flag=TRue, то НЕ ДОБАВЛЯЕМ точку в буфер
cmp Flag,True
jz @NoAddPoint
; Добавляем точку в буфер ПОСЛЕДНЕЙ
mov [BP+DI],SI ; Добавить смещение точки в буфер
inc DI
inc DI
@NoAddPoint:
; Увеличить счетчик найденных точек
inc CL
@Next: ret
@Done:
; Пурга по восстановлению BP. Не обращай внимания.
add BP,Buff_Size
End;
End;
|
|
|