;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; 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