Я не думаю, что они могут исчезнуть, пиксели не работают в режиме 320x200. Я уверен, что они там.
То, что вы называете «исчезающим», возможно, вы устанавливаете для них значение, которого вы не хотели, как ноль.
Чтобы стереть курсор мыши, вы должны установить пиксели, где курсор WAS имеет значения пикселей из фонового изображения, которое должно быть «под» курсором.
Вы можете сделать это, как (псевдо-код):
drawCursor: ; draw cursor at x, y
; there should be no cursor at screen before calling this
mov [oldMouseX],x
mov [oldMouseY],y
copy_memory(to backgroundBuffer, from vram at x,y, cursor size x/y)
blit_cursor(at x, y, cursor gfx)
ret
hideCursor: ; before drawing it at new position
blit_memory(at [oldMouseX], [oldMouseY], from backgroundBuffer, cursor size x/y)
ret
О том копировать/Blit ... Распространено создать некоторую "спрайты" манипуляция процедуру, как, например:
blit_transparent_gfx:
; params x, y, gfx data ptr, gfx data sizex, gfx data sizey
; globals word [ScreenSizeX] = 320, byte [transparent color]
; calculate direct address into VRAM into es:di
push 0a000h
pop es ; es pointing to VRAM
mov ax,[ScreenSizeX] ; 320
mul word [param y]
add ax,[param x]
mov di,ax ; es:di = VRAM address to write pixels
; prepare registers for outside line loop
mov ah,[transparent color]
mov si,[param gfx data ptr]
mov dx,[param gfx data sizey]
blit_transparent_line:
; outer line loop
mov cx,[param gfx data sizex]
push di
; inner loop drawing pixels
blit_transparent_pixel:
mov al,[si]
cmp al,ah
jz blit_transparent_pixel_skip
mov [es:di],al
blit_transparent_pixel_skip:
inc si
inc di
dec cx
jnz blit_transparent_pixel
; move VRAM pointer one line down
pop di
add di,[ScreenSizeX]
dec dx
jnz blit_transparent_line
ret
Процедуры для хранения/восстановления фонового изображения могут быть немного проще, так как им не нужно проверять прозрачность, но принцип тот же (копировать память из/в VRAM размера [sizex, sizey] в некоторый внутренний буфер, или из данных gfx).
Не используйте int 10h
для пиксельного рисунка, рисунок непосредственно A000:xxxx
VRAM очень прост в режиме 320x200 (вы должны увидеть организацию VRAM на ZX Spectrum, а еще лучше один, Atari 2600 консоль (подсказка: это не имеет никакого VRAM вообще), теперь они не были тривиальными, но режим 13h на VGA - это чистая радость использовать напрямую). Очень просто и намного намного быстрее, даже этот наивный неоптимизированный «blit_transparent_gfx» (написанный так, чтобы было легко понять, как он работает) будет невероятно быстрым по сравнению с чем-либо с вызовом int 10h
.
PS. Я не отлаживал этот «blit_transparent_gfx» (очевидно, вы в первую очередь исправляете эти строки pseudo [param ...]
с реальным кодом в любом случае, просто чтобы скомпилировать его), так что, возможно, я сделал там какую-то ошибку, не стесняйтесь отлаживать ее тогда (хотя я вроде бы он должен работать так, как есть, как только вы исправите синтаксис).
Почему вы используете RET 6 в конце PrintPixel? Почему вы не используете только RET? Я имею в виду, вы можете заставить указатель выполнения перейти в цвет/координату [BP + 6]. –
@DavidBS: Это выглядит хорошо для меня. 'ret 6' pops отклоняется от стека * после * popping обратного адреса. Это единственный эффективный способ реализации соглашения о вызове caller-cleans-the-stack. –
@PeterCordes, он не будет истинным ТОЛЬКО, если после завершения мы не будем записывать все регистры и BP? Я не могу считать его регулярным, если выполняются все POP (включая оригинальное BP). –