kolibrios-fun/kernel/trunk/video/vga.inc

788 lines
17 KiB
PHP
Raw Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; VGA.INC ;;
;; ;;
;; 640x480 mode 0x12 VGA functions for MenuetOS ;;
;; ;;
;; Paul Butcher, paul.butcher@asa.co.uk ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
paletteVGA:
;16 colour palette
mov dx,0x3c8
mov al,0
out dx,al
mov ecx,16
mov dx,0x3c9
xor eax,eax
palvganew:
mov al,0
test ah,4
jz palvgalbl1
add al,31
test ah,8
jz palvgalbl1
add al,32
palvgalbl1:
out dx,al ; red 0,31 or 63
mov al,0
test ah,2
jz palvgalbl2
add al,31
test ah,8
jz palvgalbl2
add al,32
palvgalbl2:
out dx,al ; blue 0,31 or 63
mov al,0
test ah,1
jz palvgalbl3
add al,31
test ah,8
jz palvgalbl3
add al,32
palvgalbl3:
out dx,al ; green 0,31 or 63
add ah,1
loop palvganew
ret
vga_putimage:
; pushad
call [disable_mouse]
push ebp ;
push esi ;
push edi ;
push eax ;
push ebx ; +8 [ptrImage]
push ecx ; +4 [BH]
push edx ; +0 [xy]
movzx eax,word [esp+2] ; eax:=x
movzx ebx,word [esp+0] ; ebx:=y
mov ecx,[0x3010] ;
add eax,[ecx-twdw] ; eax+=Xwin
add ebx,[ecx-twdw+4] ; ebx+=Ywin
mov ecx,ebx ; ecx = y+Ywin
mov edx,eax ; edx = x+Xwin
imul ebx, 640*4 ; (y+Ywin)*BytesPerScanLine
shl eax,2 ; (x+Xwin)*BytesPerPixel
add eax,ebx ;
mov edi,eax ; store copy
add eax,[0xfe80] ; +AddrLFB
;entry point in LFB >> EAX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrLFB
shr edi,5 ; change from 4 to 1/8 BytesPerPixel
add edi,0xa0000 ; + VGABasePtr
;VGA start address >> EDI:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrVGA
mov ebx, [0xfe00] ; ScreenXSize
inc ebx ; +1
imul ebx,ecx ; *(y+Ywin)
mov ebp, ebx ;
add ebp, edx ; +(x+Xwin)
add ebp, WinMapAddress ; ebp:=(y+Ywin)*(ScreenXSize+1)+(x+Xwin)+AddrBuffer
mov esi,[esp+8] ; esi:=AddrImg
movzx ecx,word [esp+6] ; ecx:=B
movzx ebx,word [esp+4] ; ebx:=H
; check limits while draw ?
push ecx ; B
push eax ; LFB address
mov eax,[0x3010]
mov ecx,[eax+draw_data-0x3000+0]
cmp ecx,0
jnz dbcblimitlset_vga
mov ecx,[eax+draw_data-0x3000+4]
cmp ecx,0
jnz dbcblimitlset_vga
mov ecx,[eax+draw_data-0x3000+8]
cmp ecx,[0xfe00] ; ecx <> Screen X size
jnz dbcblimitlset_vga
mov ecx,[eax+draw_data-0x3000+12]
cmp ecx,[0xfe04] ; ecx <> Screen Y size
jnz dbcblimitlset_vga
pop eax ; LFB address
pop ecx ; B
push dword 0
jmp pimvga
dbcblimitlset_vga:
pop eax ; LFB address
pop ecx ; B
push dword 1
pimvga:
push edi
push esi
push eax ; LFB address
push ecx ; B
push ebx ; H
push edx ; x+Xwin
mov ebx,[0x3010]
mov bl,[ebx+0xe]
mov bh,[esp+6*4]
cld
npvga:
cmp bl,[ds:ebp]
jnz impvgano
; cmp bh,0
; jz impvgayes
; call voodoodbcplimit
; jnz impvgano
; impvgayes:
push eax ; LFB address
push ebx ; app no.
push ecx ; B
push edx ; x+Xwin
mov edx,[esi] ; color
mov [eax],dx
shr edx,16
mov [eax+2],dl
mov eax,[esi] ; color
mov ecx,[esp] ; x+Xwin
and ecx,0x07 ; modulo 8
call setvgapixel ; eax=color, ecx=x%8, edi=VGA address
pop edx
pop ecx
pop ebx
pop eax
impvgano:
add esi,3 ; esi+=3 ptrImage+=3
add eax,4 ; eax+=4 LFBaddr +=4
inc ebp
inc edx ; x+Xwin+n
test edx,0x07 ; test modulo 8
jnz impvgacont
inc edi
impvgacont:
dec ecx ; B--
jnz npvga
pop edx
pop ebx
pop ecx
pop eax
pop esi
pop edi
add edi,640/8 ; add one VGA line
add eax,640*4 ; add one LFB line
sub ebp, ecx ; -B
add ebp, [0xfe00] ;
inc ebp ; ptrBuffer:=ptrBuffer-B+Screen_Xsize+1
push ecx
lea ecx,[ecx+ecx*2] ;
add esi,ecx ; ptrImage:=ptrImage+B*3
pop ecx
dec ebx ; H--
jnz near pimvga
add esp,4 ; jump saved limit byte
pop edx
pop ecx
pop ebx
pop eax
pop edi
pop esi
pop ebp
; call [draw_pointer]
; call [disable_mouse]
; popad
ret
VGA_putpixel:
; eax = x
; ebx = y
mov ecx,eax
mov eax, [esp+32-8+4] ; color
imul ebx, 640*4 ; y*BytesPerLine (Vesa2.0 32)
lea edx, [ebx+ecx*4] ; + x*BytesPerPixel (Vesa2.0 32)
mov edi,edx
add edi, [0xfe80] ; + LFB address
mov [edi], eax ; write to LFB for Vesa2.0
shr edx,5 ; change BytesPerPixel to 1/8
mov edi,edx
add edi, 0x0a0000 ; address of pixel in VGA area
and ecx,0x07 ; bit no. (modulo 8)
setvgapixel:
cli
; edi = address, eax = 24bit colour, ecx = bit no. (modulo 8)
push eax
mov ebx,eax ; color
;mov al,0x08
;mov dx,0x03ce
;out dx,al ; select GDC bit mask register
inc cl
mov ax, 0x100
shr ax,cl
mov dx,0x03cf
out dx,al ; set bit mask for pixel
mov dl,0
mov eax,ebx
and eax,0x000000ff ; blue
cmp eax,85
jle p13green
or dl,0x01
cmp eax,170
jle p13green
or dl,0x08
p13green:
and ebx,0x0000ff00 ; green
cmp ebx,85*256
jle p13red
or dl,0x02
cmp ebx,170*256
jle p13red
or dl,0x08
p13red:
pop ebx
and ebx,0x00ff0000 ; red
cmp ebx,85*256*256
jle p13cont
or dl,0x04
cmp ebx,170*256*256
jle p13cont
or dl,0x08
p13cont:
mov al,[edi] ; dummy read
mov [edi],dl
sti
ret
vga_drawbar:
; pushad
call [disable_mouse]
sub edx,ebx ; edx:=Yend-Ystart=H
sub ecx,eax ; ecx:=Xend-Xstat=B
push ebp ; +24
push esi ; +20
push edi ; +16
push eax ; +12
push ebx ; +8
push ecx ; +4
push edx ; +0
mov ecx,[0x3010] ;
add eax,[ecx-twdw] ; eax:=Xwin+x
add ebx,[ecx-twdw+4] ; ebx:=Ywin+y
mov ecx, eax ; ecx:=(x+Xwin)
mov edx, ebx ; edx:=(y+Ywin)
imul ebx, 640/8 ;
mov edi, ebx ; edi:=BytesPerScanLine*(y+Ywin)
shr eax, 3 ;
add edi, eax ; + (x+Xwin)*BytesPerPixel
add edi,0xa0000 ; + VGAbaseaddress
mov eax, [0xfe00] ; ScreenXSize
inc eax ; +1
imul eax,edx ; *(y+Ywin)
mov ebp, eax ;
add ebp, ecx ; +(x+Win)
add ebp, WinMapAddress ; +AddrBuffer
mov eax, [0xfe08] ; BytesPerScanLine - LFB
mul edx ; *(y+Ywin)
mov esi,eax
add esi,ecx
add esi,ecx
add esi,ecx
add esi,ecx ; + 4*(x+Xwin)
add esi,[0xfe80] ; +AddrLFB
; edi:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel + AddrVGA
; esi:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel + AddrLFB
; ebp:=(y+Ywin)*(ScreenXSize+1)+(x+Xwin)+AddrBuffer
; x size
mov eax,[esp+4] ; B [esp+4]
mov ebx,[esp+0] ; H
mov edx,[esp+16] ; color
test edx,0x80000000
jz nodbglvga
; no color glide for VGA - set to half glide
shr ebx,1 ; H/2
sub edx,ebx
mov [esp+16],edx
mov ebx,[esp+0] ; reset to H
nodbglvga:
; check limits ?
push eax
push ecx
mov eax,[0x3010]
mov ecx,[eax+draw_data-0x3000+0]
cmp ecx,0
jnz dbcblimitlset_vga2
mov ecx,[eax+draw_data-0x3000+4]
cmp ecx,0
jnz dbcblimitlset_vga2
mov ecx,[eax+draw_data-0x3000+8]
cmp ecx,[0xfe00]
jnz dbcblimitlset_vga2
mov ecx,[eax+draw_data-0x3000+12]
cmp ecx,[0xfe04]
jnz dbcblimitlset_vga2
pop ecx
pop eax
push dword 0
jmp dbnewpivga
dbcblimitlset_vga2:
pop ecx ; x+Xwin
pop eax ; B
push dword 1
dbnewpivga:
push eax; B
push ebx ; H
push edi
push esi
push ecx ; x+Xwin
mov ebx,[0x3010]
movzx ebx,byte[ebx+0xe]
cld
dbnpvga:
mov dl,[ds:ebp]
cmp dl,bl
jnz dbimpvgano
; mov edx,[esp+5*4] ; check limit?
; cmp edx,0
; jz dbimpvgayes
; call voodoodbcplimit
; jnz dbimpvgano
; dbimpvgayes:
push eax ; B
push ebx
push ecx ; x+Xwin
mov eax,[esp+12+20+16+4] ; color
mov ebx,eax
mov [esi],bx ; write LFB pixel
shr ebx,16
mov [esi+2],bl
and ecx,0x07 ; modulo 8
call setvgapixel ; eax=color, ecx=x%8, edi=VGA address
pop ecx
pop ebx
pop eax
dbimpvgano:
add esi,4 ; ptrLFB+=4
inc ebp ; address buffer
inc ecx ; x posn++
test ecx,0x07 ; test modulo 8
jnz dbvgacont
inc edi ; VGA screen ptr++
dbvgacont:
dec eax ; B-- NB ecx in Vesa20 fn?
jnz dbnpvga
dbnpvgad:
pop ecx
pop esi
pop edi
pop ebx
pop eax
add esi,[0xfe08] ; ptrLFB+=BytesPerScanLine
add edi,640/8 ; ptrScreen+=BytesPerScanLine
add ebp,[0xfe00] ;
sub ebp, eax ; was ecx in vesa20 fn?
inc ebp ; ptrBuffer:=ptrBuffer-B+BytesPerLine+1
dec ebx ; H--
jz nodbnewpivga ; H<>0
jmp dbnewpivga
nodbnewpivga:
add esp,7*4 ; NB includes limit check flag
;pop ebx
;pop eax
;pop edi
;pop esi
pop ebp
;pop edx
;pop ecx
; popad
ret
vga_drawbackground_tiled:
call [disable_mouse]
push ebp
push eax
push ebx
push ecx
push edx
mov edx,dword [0x400000-8] ; B
add edx,dword [WinMapAddress-8] ; +B
add edx,dword [WinMapAddress-8] ; +B
push edx
mov eax,[draw_data+32+0] ; x start:=(x+Xwin)
mov ebx,[draw_data+32+4] ; y start:=(y+Ywin)
mov ecx,eax
mov edx,ebx
imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine
shl ecx,2 ; (x+Xwin)*BytesPerPixel
add ecx,edx ;
mov ebp,ecx ; store copy
add ecx,[0xfe80] ; +AddrLFB
;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr
shr ebp,5 ; change from 4 to 1/8 BytesPerPixel
add ebp,0xa0000 ; + VGABasePtr
;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrV
call calculate_edi
dp3vga: ; MAIN LOOP
cmp [edi+WinMapAddress],byte 1 ; ptrBuffer^<>byte(1)
je ybgpvga
jmp nbgpvga
ybgpvga:
push eax ; x
push ebx ; y
push ecx ; LFB address
mov ecx,dword [WinMapAddress-8] ; B
xor edx,edx ; edx:=0
div ecx ; Xstart/B
; eax=Int(qn) edx:=Rem
lea esi,[edx+edx*2] ; esi:=edx*3
mov ecx,dword [WinMapAddress-4] ; ecx:=H
mov eax,[esp+4] ; eax:=Ystart
xor edx,edx ;
div ecx ; Ystart/H
mov eax,edx ; eax:=Rem
xor edx,edx ;
mov ebx,[esp+12] ; ebx:=B*3
mul ebx ;
add esi,eax ;
mov eax,[esi+0x300000] ; color
and eax,0xffffff
mov ecx, [esp] ; LFB address
mov ebx,eax ; copy color
mov [ecx],bx
shr ebx,16
mov [ecx+2],bl
xchg edi, ebp
mov ecx,[esp+8] ; x position
and ecx,0x07 ; x modulo 8
call setvgapixel ; eax=color, ecx=x%8, edi=VGA address
xchg ebp, edi
pop ecx
pop ebx
pop eax
nbgpvga:
inc eax ; x++
cmp eax,[draw_data+32+8] ; X > xend?
jg nodp3vga
test eax,0x07 ; x test modulo 8
jnz hook1vga
inc ebp ; VGA address++
hook1vga:
add ecx,4 ; LFB address += 4
inc edi ; ptrBuffer++
add esi,3 ; ptrImage+=3
jmp dp3vga
nodp3vga:
mov eax,[draw_data+32+0] ; x+Xwin
inc ebx ; y position
mov ecx,eax
mov edx,ebx
imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine
shl ecx,2 ; (x+Xwin)*BytesPerPixel
add ecx,edx ;
mov ebp,ecx ; store copy
add ecx,[0xfe80] ; +AddrLFB
;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr
shr ebp,5 ; change from 4 to 1/8 BytesPerPixel
add ebp,0xa0000 ; + VGABasePtr
;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrV
call calculate_edi
cmp ebx,[draw_data+32+12] ; Y > yend
jg dp4vga
jmp dp3vga
dp4vga:
add esp,4
pop edx
pop ecx
pop ebx
pop eax
pop ebp
ret
; ----------
vga_drawbackground_stretch:
call [disable_mouse]
push ebp
push eax
push ebx
push ecx
push edx
mov edx,dword [WinMapAddress-8] ; B
add edx,dword [WinMapAddress-8] ; +B
add edx,dword [WinMapAddress-8] ; +B
push edx
mov eax,[draw_data+32+0] ; x start:=(x+Xwin)
mov ebx,[draw_data+32+4] ; y start:=(y+Ywin)
mov ecx,eax
mov edx,ebx
imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine
shl ecx,2 ; (x+Xwin)*BytesPerPixel
add ecx,edx ;
mov ebp,ecx ; store copy
add ecx,[0xfe80] ; +AddrLFB
;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr
shr ebp,5 ; change from 4 to 1/8 BytesPerPixel
add ebp,0xa0000 ; + VGABasePtr
;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrV
call calculate_edi
sdp3vga: ; MAIN LOOP
cmp [edi+WinMapAddress],byte 1 ; ptrBuffer^<>byte(1)
je sybgpvga
jmp snbgpvga
sybgpvga:
push eax ; x
push ebx ; y
push ecx ; LFB address
mov eax,dword [WinMapAddress-8] ; B
xor edx,edx
mov ebx,[esp+8] ; Xstart
mul ebx ; B*Xstart
xor edx,edx
mov ebx,[0xfe00] ; x screen width
div ebx ; B*Xstart/xwidth
lea esi,[eax+eax*2] ; *3
mov eax,dword [WinMapAddress-4] ; H
xor edx,edx
mov ebx,[esp+4] ; Ystart
mul ebx ; H*Ystart
xor edx,edx
mov ebx,[0xfe04] ; y screen height
div ebx ; H*Ystart/yheight
xor edx,edx
mov ebx,[esp+12] ; B*3
mul ebx ;
add esi,eax
mov eax,[esi+0x300000] ; color
and eax,0xffffff
mov ecx, [esp] ; LFB address
mov ebx,eax ; copy color
mov [ecx],bx
shr ebx,16
mov [ecx+2],bl
xchg edi, ebp
mov ecx,[esp+8] ; x position
and ecx,0x07 ; x modulo 8
call setvgapixel ; eax=color, ecx=x%8, edi=VGA address
xchg ebp, edi ; ebp+=3
pop ecx
pop ebx
pop eax
snbgpvga:
inc eax ; x++
cmp eax,[draw_data+32+8] ; X > xend?
jg snodp3vga
test eax,0x07 ; x test modulo 8
jnz shook1vga
inc ebp ; VGA address++
shook1vga:
add ecx,4 ; LFB address += 4
inc edi ; ptrBuffer++
add esi,3 ; ptrImage+=3
jmp sdp3vga
snodp3vga:
mov eax,[draw_data+32+0] ; x+Xwin
inc ebx ; y position
mov ecx,eax
mov edx,ebx
imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine
shl ecx,2 ; (x+Xwin)*BytesPerPixel
add ecx,edx ;
mov ebp,ecx ; store copy
add ecx,[0xfe80] ; +AddrLFB
;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr
shr ebp,5 ; change from 4 to 1/8 BytesPerPixel
add ebp,0xa0000 ; + VGABasePtr
;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+A
call calculate_edi
cmp ebx,[draw_data+32+12] ; Y > yend
jg sdp4vga
jmp sdp3vga
sdp4vga:
add esp,4
pop edx
pop ecx
pop ebx
pop eax
pop ebp
ret