2000 ; Mystique optimized OPTION LANGUAGE: SYSCALL OPTION SEGMENT: USE16 .386 FALSE EQU 0 TRUE EQU 1 _DATA SEGMENT PARA PUBLIC 'DATA' screen dd 0A0000000h screen_seg dw 0A000h neg_slope dw 0 last_window db 0 _DATA ENDS _BSS SEGMENT PARA PUBLIC 'BSS' PUBLIC _vbe_mode PUBLIC _bytes_per_scanline PUBLIC _win_size, _win_func, _num_win, _tail PUBLIC _font _bytes_per_scanline dd ? _win_size dd ? _win_func dd ? _tail dd ? _font dd ? char_offs dd ? _vbe_mode dw ? dest_add dw ? src_add dw ? char_index dw ? char_x dw ? char_y dw ? _num_win db ? _BSS ENDS DGROUP GROUP _DATA, _BSS _TEXT SEGMENT PARA PUBLIC 'CODE' ASSUME CS:_TEXT, DS:DGROUP PUBLIC _vbeVsync, _vbeChangeWindow PUBLIC _vbePutPixel, _vbeGetPixel PUBLIC _vbeClrArea, _vbeClrScr PUBLIC _vbePutImage, _vbeGetImage, _vbePutSprite PUBLIC _vbeWriteChar, _vbeWriteString PUBLIC _vbeWriteCharOpaque, _vbeWriteStringOpaque PUBLIC _vbeWriteVertString, _vbeWriteVertStringOpaque PUBLIC _vbeSetText, _vbeSetGraph ; void vbeSync(void); ALIGN 4 _vbeVsync PROC mov dx, 3dah wt1: in al, dx test al, 00001000b jnz wt1 wt2: in al, dx test al, 00001000b ;wait until bit is 1 jz wt2 ;indicating vertical blank started ret _vbeVsync ENDP ; int vbeChangeWindow(int window); ALIGN 4 _vbeChangeWindow PROC, window:WORD mov dx, 3deh mov ax, window mov last_window, al mov ah, 4 xchg ah, al out dx, ax ret _vbeChangeWindow ENDP ; int vbePutPixel(int x, int y, unsigned long color); ALIGN 4 _vbePutPixel PROC USES es di, x:WORD, y:WORD, color:DWORD movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 ; edx = 2048 * y shl ax, 2 ; eax = x * 4 add eax, edx ; eax = 2048 * y + x shr edx, 2 add eax, edx ; eax = 2560 * y + x push ax ; Store offset shr eax, 16 ; Get window to use cmp al, last_window ; Same window as before? jz same_window ; Yes mov last_window, al xchg ah, al mov al, 4 mov dx, 3deh out dx, ax same_window: mov es, screen_seg ; Frame buffer to ES:DI pop di ; Pop offset from stack mov edx, color mov es:[di], edx ; Write pixel ret _vbePutPixel ENDP ; unsigned long vbeGetPixel(int x, int y); ALIGN 4 _vbeGetPixel PROC USES es di, x:WORD, y:WORD movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 shl ax, 2 add eax, edx shr edx, 2 add eax, edx push ax ; Store offset shr eax, 16 ; Get window to use cmp al, last_window ; Same window as before? jz same_window ; Yes mov last_window, al xchg ah, al mov al, 4 mov dx, 3deh out dx, ax same_window: mov es, screen_seg ; Frame buffer to ES:DI pop di ; Pop offset from stack mov dx, es:[di + 2] ; Return pixel color mov ax, es:[di] ret _vbeGetPixel ENDP ; int vbePutImage(int x, int y, int w, int h, unsigned long far *image); ALIGN 4 _vbePutImage PROC USES es si di, x:WORD, y:WORD, w:WORD, h:WORD, image:DWORD mov eax, _bytes_per_scanline ; Calculate destination movzx edx, w ; offset value to add shl edx, 2 ; for each line sub eax, edx mov dest_add, ax movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 shl ax, 2 add eax, edx shr edx, 2 add eax, edx push ax ; Store offset shr eax, 16 ; Get starting window xchg ah, al ; Prepare bank change word mov al, 4 mov dx, 3deh ; Preload bank change register cmp ah, last_window ; Same window as before? jz same_win ; Yes out dx, ax same_win: mov es, screen_seg ; Frame buffer to ES:DI pop di ; Pop offset from stack lfs si, image ; Load image address mov cx, h y_loop: push cx mov cx, w x_loop: mov ebx, fs:[si] ; Plot pixel mov es:[di], ebx add si, 4 ; Update pointers jnc no_seg_change mov bx, fs add bx, 1000h mov fs, bx no_seg_change: add di, 4 jnc same_win2 inc ah out dx, ax same_win2: dec cx jnz x_loop pop cx dec cx jz rdy add di, dest_add jnc y_loop inc ah out dx, ax jmp y_loop rdy: mov last_window, ah ret _vbePutImage ENDP ; int vbeGetImage(int x, int y, int w, int h, unsigned long far *image); ALIGN 4 _vbeGetImage PROC USES es si di, x:WORD, y:WORD, w:WORD, h:WORD, image:DWORD mov eax, _bytes_per_scanline ; Calculate destination movzx edx, w ; offset value to add shl edx, 2 ; for each line sub eax, edx mov src_add, ax movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 shl ax, 2 add eax, edx shr edx, 2 add eax, edx push ax ; Store offset shr eax, 16 ; Get starting window xchg ah, al ; Prepare bank change word mov al, 4 mov dx, 3deh ; Preload bank change register cmp ah, last_window ; Same window as before? jz same_win ; Yes out dx, ax same_win: mov es, screen_seg ; Load screen address pop si ; Pop offset from stack lfs di, image ; Load image address mov cx, h y_loop: push cx mov cx, w x_loop: mov ebx, es:[si] ; Get pixel.. mov fs:[di], ebx ; and store it add si, 4 jnc same_win2 inc ah out dx, ax same_win2: add di, 4 jnc no_seg_change mov bx, fs add bx, 1000h mov fs, bx no_seg_change: dec cx jnz x_loop pop cx dec cx jz rdy add si, src_add jnc y_loop inc ah out dx, ax jmp y_loop rdy: mov last_window, ah ret _vbeGetImage ENDP ; int vbePutSprite(int x, int y, int w, int h, unsigned long far *sprite); ALIGN 4 _vbePutSprite PROC USES es si di, x:WORD, y:WORD, w:WORD, h:WORD, sprite:DWORD mov eax, _bytes_per_scanline ; Calculate destination movzx edx, w ; offset value to add shl edx, 2 ; for each line sub eax, edx mov dest_add, ax movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 shl ax, 2 add eax, edx shr edx, 2 add eax, edx push ax ; Store offset shr eax, 16 ; Get starting window xchg ah, al ; Prepare bank change word mov al, 4 mov dx, 3deh ; Preload bank change register cmp ah, last_window ; Same window as before? jz same_win ; Yes out dx, ax same_win: mov es, screen_seg ; Frame buffer to ES:DI pop di ; Pop offset from stack lfs si, sprite ; Load sprite address mov cx, h y_loop: push cx mov cx, w x_loop: cmp dword ptr fs:[si], 0 ; Don't write zero pixels jz no_plot mov ebx, fs:[si] ; Plot pixel mov es:[di], ebx no_plot: add si, 4 ; Update pointers jnc no_seg_change mov bx, fs add bx, 1000h mov fs, bx no_seg_change: add di, 4 jnc same_win2 inc ah out dx, ax same_win2: dec cx jnz x_loop pop cx dec cx jz rdy add di, dest_add jnc y_loop inc ah out dx, ax jmp y_loop rdy: mov last_window, ah ret _vbePutSprite ENDP ;***** ;***** line ;***** ; The following line routine is a modified version of code in Richard ; Wilton's book "Programmer's Guide to PC and PS/2 Video Systems". PIXELADDR MACRO LOCAL same_win shl eax, 11 shl bx, 2 add ebx, eax shr eax, 2 add ebx, eax mov di, bx shr ebx, 16 ; Get starting window mov ah, bl ; Pre-load bank change mov al, 4 ; stuff mov dx, 3deh cmp ah, last_window ; Same window as before? jz same_win ; Yes out dx, ax same_win: ENDM _vbeDrawLine PROC USES cx es si di, x1:WORD, y1:WORD, x2:WORD, y2:WORD, color:DWORD LOCAL VARincr1:WORD, VARincr2:WORD, VARroutine:WORD mov es, screen_seg mov neg_slope, 0 ; check for vertical lines mov si, word ptr[_bytes_per_scanline] ; initial y-increment mov cx, x2 sub cx, x1 ; cx=x2-x1 jz vertLine ; force x1 < x2 jns L01 ; jump if x1=0 neg cx ; force dy>=0 movzx eax, bx ; ax=y2 L31: inc cx ; cx=# of pixels to draw movzx ebx, x1 ; bx=x PIXELADDR ; es:bx mov ebx, color L32: mov es:[di], ebx add di, si ; next line jnc same_win1 inc ah out dx, ax same_win1: dec cx jnz L32 jmp Lexit ; routine for horizontal lines (slope=0) horizLine: movzx eax, y1 movzx ebx, x1 PIXELADDR ; es:bx inc cx mov ebx, color hor_lp: mov es:[di], ebx add di, 4 jnc same_win2 inc ah out dx, ax same_win2: dec cx jnz hor_lp jmp Lexit ; routine for dy<=dx (slope<=1) ; es:di -> video buffer ; bx=y-increment ; cx =# of pixels to draw ; si=decision variable loSlopeLine: mov edx,color L11: mov es:[di], edx ; put pixel, increment x add di, 4 jnc same_win3 push dx inc ah mov dx, 3deh out dx, ax pop dx same_win3: or si,si ; test sign of d jns L12 ; jump id d>=0 add si,VARincr1 ; d=d+incr1 dec cx jnz L11 jmp Lexit L12: add si,VARincr2 ; d=d+incr2 cmp neg_slope, TRUE jnz no_neg1 sub di, bx jnc same_win4 dec ah jmp over_no_neg1 no_neg1: add di,bx ; increment y jnc same_win4 inc ah over_no_neg1: push dx mov dx, 3deh out dx, ax pop dx same_win4: dec cx jnz L11 jmp Lexit ; routine for dy>dx (slope >1) ; es:di -> video buffer ; bx=y-increment ; cx=# of pixels to draw ; si=decision variable hiSlopeLine: mov edx,color L21: mov es:[di], edx ; put pixel, increment x add di, 4 jnc same_win5 push dx mov dx, 3deh inc ah out dx, ax pop dx same_win5: cmp neg_slope, TRUE jnz no_neg2 sub di, bx jnc same_win6 dec ah jmp over_no_neg2 no_neg2: add di,bx ; increment y jnc same_win6 inc ah over_no_neg2: push dx mov dx, 3deh out dx, ax pop dx same_win6: L22: or si,si ; test sign of d jns L23 ; jump if d>=0 add si,VARincr1 ; d=d+incr1 sub di, 4 ; dec x (inc by stosb) jnc same_win7 push dx dec ah mov dx, 3deh out dx, ax pop dx same_win7: dec cx jnz L21 jmp Lexit L23: add si,VARincr2 ; d=d+incr2 dec cx jnz L21 Lexit: mov last_window, ah ret _vbeDrawLine ENDP ; void vbeDrawBox(int x1, int y1, int x2, int y2, unsigned long color); ALIGN 4 _vbeDrawBox PROC, x1:WORD, y1:WORD, x2:WORD, y2:WORD, color:DWORD push color push y1 push x2 push y1 push x1 call _vbeDrawLine add sp, 12 push color push y2 push x2 push y1 push x2 call _vbeDrawLine add sp, 12 push color push y2 push x1 push y2 push x2 call _vbeDrawLine add sp, 12 push color push y1 push x1 push y2 push x1 call _vbeDrawLine add sp, 12 ret _vbeDrawBox ENDP ; void vbeDrawPoly(int numpoints, int far *polypoints, unsigned long color); ALIGN 4 _vbeDrawPoly PROC USES es di, numpoints:WORD, polypoints:DWORD, color:DWORD les di, polypoints mov cx, numpoints dec cx poly_lp: push color push word ptr es:[di + 6] push word ptr es:[di + 4] push word ptr es:[di + 2] push word ptr es:[di + 0] call _vbeDrawLine add sp, 12 add di, 4 ; x2 -> x1, y2 -> y1 dec cx jnz poly_lp ret _vbeDrawPoly ENDP ; int vbeWriteChar(int x, int y, unsigned long color, int c); ALIGN 4 _vbeWriteChar PROC USES es si di, x:WORD, y:WORD, color:DWORD, chr:WORD mov eax, _bytes_per_scanline ; Calculate destination sub eax, 32 mov dest_add, ax movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 shl ax, 2 add eax, edx shr edx, 2 add eax, edx push ax ; Store offset shr eax, 16 ; Get starting window xchg ah, al ; Prepare bank change word mov al, 4 mov dx, 3deh ; Preload bank change register cmp ah, last_window ; Same window as before? jz same_win ; Yes out dx, ax same_win: mov es, screen_seg ; Load screen address pop di lfs si, _font ; Load font address add si, chr ; Character index shl si, 4 ; * 16 mov ebx, color mov cl, 16 row_lp: mov ch, byte ptr fs:[si] test ch, 10000000b jz empty1 mov es:[di], ebx empty1: add di, 4 jnc col2 inc ah out dx, ax col2: test ch, 01000000b jz empty2 mov es:[di], ebx empty2: add di, 4 jnc col3 inc ah out dx, ax col3: test ch, 00100000b jz empty3 mov es:[di], ebx empty3: add di, 4 jnc col4 inc ah out dx, ax col4: test ch, 00010000b jz empty4 mov es:[di], ebx empty4: add di, 4 jnc col5 inc ah out dx, ax col5: test ch, 00001000b jz empty5 mov es:[di], ebx empty5: add di, 4 jnc col6 inc ah out dx, ax col6: test ch, 00000100b jz empty6 mov es:[di], ebx empty6: add di, 4 jnc col7 inc ah out dx, ax col7: test ch, 00000010b jz empty7 mov es:[di], ebx empty7: add di, 4 jnc col8 inc ah out dx, ax col8: test ch, 00000001b jz empty8 mov es:[di], ebx empty8: add di, 4 jnc col_rdy inc ah out dx, ax col_rdy: dec cl jz rdy inc si add di, dest_add jnc row_lp inc ah out dx, ax jmp row_lp rdy: mov last_window, ah ret _vbeWriteChar ENDP ; int vbeWriteCharOpaque(int x, int y, unsigned long fgcol, unsigned long bgcol, int c); ; used by vbePutch, uses background color ALIGN 4 _vbeWriteCharOpaque PROC USES es si di, x:WORD, y:WORD, fgcol:DWORD, bgcol:DWORD, chr:WORD mov eax, _bytes_per_scanline ; Calculate destination sub eax, 32 mov dest_add, ax movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 shl ax, 2 add eax, edx shr edx, 2 add eax, edx push ax ; Store offset shr eax, 16 ; Get starting window xchg ah, al ; Prepare bank change word mov al, 4 mov dx, 3deh ; Preload bank change register cmp ah, last_window ; Same window as before? jz same_win ; Yes out dx, ax same_win: mov es, screen_seg ; Load screen address pop di lfs si, _font ; Load font address add si, chr ; Character index shl si, 4 ; * 16 mov cl, 16 row_lp: mov ch, byte ptr fs:[si] test ch, 10000000b jz empty1 mov ebx, fgcol jmp cont1 empty1: mov ebx, bgcol cont1: mov es:[di], ebx add di, 4 jnc col2 inc ah out dx, ax col2: test ch, 01000000b jz empty2 mov ebx, fgcol jmp cont2 empty2: mov ebx, bgcol cont2: mov es:[di], ebx add di, 4 jnc col3 inc ah out dx, ax col3: test ch, 00100000b jz empty3 mov ebx, fgcol jmp cont3 empty3: mov ebx, bgcol cont3: mov es:[di], ebx add di, 4 jnc col4 inc ah out dx, ax col4: test ch, 00010000b jz empty4 mov ebx, fgcol jmp cont4 empty4: mov ebx, bgcol cont4: mov es:[di], ebx add di, 4 jnc col5 inc ah out dx, ax col5: test ch, 00001000b jz empty5 mov ebx, fgcol jmp cont5 empty5: mov ebx, bgcol cont5: mov es:[di], ebx add di, 4 jnc col6 inc ah out dx, ax col6: test ch, 00000100b jz empty6 mov ebx, fgcol jmp cont6 empty6: mov ebx, bgcol cont6: mov es:[di], ebx add di, 4 2000 jnc col7 inc ah out dx, ax col7: test ch, 00000010b jz empty7 mov ebx, fgcol jmp cont7 empty7: mov ebx, bgcol cont7: mov es:[di], ebx add di, 4 jnc col8 inc ah out dx, ax col8: test ch, 00000001b jz empty8 mov ebx, fgcol jmp cont8 empty8: mov ebx, bgcol cont8: mov es:[di], ebx add di, 4 jnc col_rdy inc ah out dx, ax col_rdy: dec cl jz rdy inc si add di, dest_add jnc row_lp inc ah out dx, ax jmp row_lp rdy: mov last_window, ah ret _vbeWriteCharOpaque ENDP ; int vbeWriteString(int x, int y, unsigned long color, unsigned char far *string); ALIGN 4 _vbeWriteString PROC USES es si di, x:WORD, y:WORD, color:DWORD, string:DWORD mov eax, _bytes_per_scanline ; Calculate destination sub eax, 32 mov dest_add, ax movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 shl ax, 2 add eax, edx shr edx, 2 add eax, edx mov char_offs, eax ; Store offset les di, string lfs si, _font ; Font address -> FS:SI string_lp: cmp byte ptr es:[di], 0 ; End of string? jz string_complete movzx si, byte ptr es:[di] ; Char index shl si, 4 ; * 16 push es push di mov eax, char_offs shr eax, 16 ; Get starting window xchg ah, al ; Prepare bank change word mov al, 4 mov dx, 3deh ; Preload bank change register cmp ah, last_window ; Same window as before? jz same_win ; Yes out dx, ax same_win: mov es, screen_seg ; Load screen address mov di, word ptr[char_offs] mov ebx, color mov cl, 16 row_lp: mov ch, byte ptr fs:[si] test ch, 10000000b jz empty1 mov es:[di], ebx empty1: add di, 4 jnc col2 inc ah out dx, ax col2: test ch, 01000000b jz empty2 mov es:[di], ebx empty2: add di, 4 jnc col3 inc ah out dx, ax col3: test ch, 00100000b jz empty3 mov es:[di], ebx empty3: add di, 4 jnc col4 inc ah out dx, ax col4: test ch, 00010000b jz empty4 mov es:[di], ebx empty4: add di, 4 jnc col5 inc ah out dx, ax col5: test ch, 00001000b jz empty5 mov es:[di], ebx empty5: add di, 4 jnc col6 inc ah out dx, ax col6: test ch, 00000100b jz empty6 mov es:[di], ebx empty6: add di, 4 jnc col7 inc ah out dx, ax col7: test ch, 00000010b jz empty7 mov es:[di], ebx empty7: add di, 4 jnc col8 inc ah out dx, ax col8: test ch, 00000001b jz empty8 mov es:[di], ebx empty8: add di, 4 jnc col_rdy inc ah out dx, ax col_rdy: dec cl jz rdy inc si add di, dest_add jnc row_lp inc ah out dx, ax jmp row_lp rdy: mov last_window, ah pop di pop es add char_offs, 8 * 4 inc di jmp string_lp string_complete: ret _vbeWriteString ENDP ; int vbeWriteStringOpaque(int x, int y, unsigned long fgcol, unsigned long bgcol, unsigned char far *string); ; used by vbePrintf, uses background color ALIGN 4 _vbeWriteStringOpaque PROC USES es si di, x:WORD, y:WORD, fgcol:DWORD, bgcol:DWORD, string:DWORD mov eax, _bytes_per_scanline ; Calculate destination sub eax, 32 mov dest_add, ax movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 shl ax, 2 add eax, edx shr edx, 2 add eax, edx mov char_offs, eax ; Store offset les di, string lfs si, _font ; Font address -> FS:SI string_lp: cmp byte ptr es:[di], 0 ; End of string? jz string_complete movzx si, byte ptr es:[di] ; Char index shl si, 4 ; * 16 push es push di mov eax, char_offs shr eax, 16 ; Get starting window xchg ah, al ; Prepare bank change word mov al, 4 mov dx, 3deh ; Preload bank change register cmp ah, last_window ; Same window as before? jz same_win ; Yes out dx, ax same_win: mov es, screen_seg ; Load screen address mov di, word ptr[char_offs] mov cl, 16 row_lp: mov ch, byte ptr fs:[si] test ch, 10000000b jz empty1 mov ebx, fgcol jmp cont1 empty1: mov ebx, bgcol cont1: mov es:[di], ebx add di, 4 jnc col2 inc ah out dx, ax col2: test ch, 01000000b jz empty2 mov ebx, fgcol jmp cont2 empty2: mov ebx, bgcol cont2: mov es:[di], ebx add di, 4 jnc col3 inc ah out dx, ax col3: test ch, 00100000b jz empty3 mov ebx, fgcol jmp cont3 empty3: mov ebx, bgcol cont3: mov es:[di], ebx add di, 4 jnc col4 inc ah out dx, ax col4: test ch, 00010000b jz empty4 mov ebx, fgcol jmp cont4 empty4: mov ebx, bgcol cont4: mov es:[di], ebx add di, 4 jnc col5 inc ah out dx, ax col5: test ch, 00001000b jz empty5 mov ebx, fgcol jmp cont5 empty5: mov ebx, bgcol cont5: mov es:[di], ebx add di, 4 jnc col6 inc ah out dx, ax col6: test ch, 00000100b jz empty6 mov ebx, fgcol jmp cont6 empty6: mov ebx, bgcol cont6: mov es:[di], ebx add di, 4 jnc col7 inc ah out dx, ax col7: test ch, 00000010b jz empty7 mov ebx, fgcol jmp cont7 empty7: mov ebx, bgcol cont7: mov es:[di], ebx add di, 4 jnc col8 inc ah out dx, ax col8: test ch, 00000001b jz empty8 mov ebx, fgcol jmp cont8 empty8: mov ebx, bgcol cont8: mov es:[di], ebx add di, 4 jnc col_rdy inc ah out dx, ax col_rdy: dec cl jz rdy inc si add di, dest_add jnc row_lp inc ah out dx, ax jmp row_lp rdy: mov last_window, ah pop di pop es add char_offs, 8 * 4 inc di jmp string_lp string_complete: ret _vbeWriteStringOpaque ENDP ; Draws a vertical string from bottom to top ; int vbeWriteVertString(int x, int y, unsigned long color, ; unsigned char far *string); ALIGN 4 _vbeWriteVertString PROC USES es si di, x:WORD, y:WORD, color:DWORD, string:DWORD mov ax, word ptr[_bytes_per_scanline] ; Calculate add value shl ax, 3 ; _bytes_per_scanline * 8 add ax, 4 ; + 4 mov dest_add, ax movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 shl ax, 2 add eax, edx shr edx, 2 add eax, edx mov char_offs, eax ; Store offset les di, string ; String address -> ES:DI lfs si, _font ; Font address -> FS:SI string_lp: cmp byte ptr es:[di], 0 ; End of string? jz string_complete movzx si, byte ptr es:[di] ; Char index shl si, 4 ; * 16 push es push di mov eax, char_offs shr eax, 16 ; Get starting window xchg ah, al ; Prepare bank change word mov al, 4 mov dx, 3deh ; Preload bank change register cmp ah, last_window ; Same window as before? jz same_win ; Yes out dx, ax same_win: mov es, screen_seg ; Load screen address mov di, word ptr[char_offs] mov ebx, color mov cl, 16 row_lp: mov ch, byte ptr fs:[si] test ch, 10000000b jz empty1 mov es:[di], ebx empty1: sub di, 2560 jnc col2 dec ah out dx, ax col2: test ch, 01000000b jz empty2 mov es:[di], ebx empty2: sub di, 2560 jnc col3 dec ah out dx, ax col3: test ch, 00100000b jz empty3 mov es:[di], ebx empty3: sub di, 2560 jnc col4 dec ah out dx, ax col4: test ch, 00010000b jz empty4 mov es:[di], ebx empty4: sub di, 2560 jnc col5 dec ah out dx, ax col5: test ch, 00001000b jz empty5 mov es:[di], ebx empty5: sub di, 2560 jnc col6 dec ah out dx, ax col6: test ch, 00000100b jz empty6 mov es:[di], ebx empty6: sub di, 2560 jnc col7 dec ah out dx, ax col7: test ch, 00000010b jz empty7 mov es:[di], ebx empty7: sub di, 2560 jnc col8 dec ah out dx, ax col8: test ch, 00000001b jz empty8 mov es:[di], ebx empty8: sub di, 2560 jnc col_rdy dec ah out dx, ax col_rdy: dec cl jz rdy inc si add di, dest_add jnc row_lp inc ah out dx, ax jmp row_lp rdy: mov last_window, ah pop di pop es sub char_offs, 2560 * 8 inc di jmp string_lp string_complete: ret _vbeWriteVertString ENDP ; Draws a vertical string from bottom to top ; uses background color ; int vbeWriteVertStringOpaque(int x, int y, unsigned long fgcol, ; unsigned long bgcol, unsigned char far *string); ALIGN 4 _vbeWriteVertStringOpaque PROC USES es si di, x:WORD, y:WORD, fgcol:DWORD, bgcol:DWORD, string:DWORD mov ax, wo 11ba rd ptr[_bytes_per_scanline] ; Calculate add value shl ax, 3 ; _bytes_per_scanline * 8 add ax, 4 ; + 4 mov dest_add, ax movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 shl ax, 2 add eax, edx shr edx, 2 add eax, edx mov char_offs, eax ; Store offset les di, string ; String address -> ES:DI lfs si, _font ; Font address -> FS:SI string_lp: cmp byte ptr es:[di], 0 ; End of string? jz string_complete movzx si, byte ptr es:[di] ; Char index shl si, 4 ; * 16 push es push di mov eax, char_offs shr eax, 16 ; Get starting window xchg ah, al ; Prepare bank change word mov al, 4 mov dx, 3deh ; Preload bank change register cmp ah, last_window ; Same window as before? jz same_win ; Yes out dx, ax same_win: mov es, screen_seg ; Load screen address mov di, word ptr[char_offs] mov cl, 16 row_lp: mov ch, byte ptr fs:[si] test ch, 10000000b jz empty1 mov ebx, fgcol jmp cont1 empty1: mov ebx, bgcol cont1: mov es:[di], ebx sub di, 2560 jnc col2 dec ah out dx, ax col2: test ch, 01000000b jz empty2 mov ebx, fgcol jmp cont2 empty2: mov ebx, bgcol cont2: mov es:[di], ebx sub di, 2560 jnc col3 dec ah out dx, ax col3: test ch, 00100000b jz empty3 mov ebx, fgcol jmp cont3 empty3: mov ebx, bgcol cont3: mov es:[di], ebx sub di, 2560 jnc col4 dec ah out dx, ax col4: test ch, 00010000b jz empty4 mov ebx, fgcol jmp cont4 empty4: mov ebx, bgcol cont4: mov es:[di], ebx sub di, 2560 jnc col5 dec ah out dx, ax col5: test ch, 00001000b jz empty5 mov ebx, fgcol jmp cont5 empty5: mov ebx, bgcol cont5: mov es:[di], ebx sub di, 2560 jnc col6 dec ah out dx, ax col6: test ch, 00000100b jz empty6 mov ebx, fgcol jmp cont6 empty6: mov ebx, bgcol cont6: mov es:[di], ebx sub di, 2560 jnc col7 dec ah out dx, ax col7: test ch, 00000010b jz empty7 mov ebx, fgcol jmp cont7 empty7: mov ebx, bgcol cont7: mov es:[di], ebx sub di, 2560 jnc col8 dec ah out dx, ax col8: test ch, 00000001b jz empty8 mov ebx, fgcol jmp cont8 empty8: mov ebx, bgcol cont8: mov es:[di], ebx sub di, 2560 jnc col_rdy dec ah out dx, ax col_rdy: dec cl jz rdy inc si add di, dest_add jnc row_lp inc ah out dx, ax jmp row_lp rdy: mov last_window, ah pop di pop es sub char_offs, 2560 * 8 inc di jmp string_lp string_complete: ret _vbeWriteVertStringOpaque ENDP ; int vbeClrArea(int x, int y, int w, int h, unsigned long color); ALIGN 4 _vbeClrArea PROC USES es si di, x:WORD, y:WORD, w:WORD, h:WORD, color:DWORD mov esi, color mov eax, _bytes_per_scanline ; Calculate destination movzx edx, w ; offset value to add shl edx, 2 ; for each line sub eax, edx mov dest_add, ax movzx eax, x ; Calculate offset movzx edx, y shl edx, 11 shl ax, 2 add eax, edx shr edx, 2 add eax, edx push ax ; Store offset shr eax, 16 ; Get starting window xchg ah, al mov al, 4 ; Prepare bank change word mov dx, 3deh ; Preload bank change register cmp ah, last_window ; Same window as before? jz same_win ; Yes out dx, ax same_win: mov es, screen_seg ; Frame buffer to ES:DI pop di ; Pop offset from stack mov cx, h y_loop: push cx mov cx, w x_loop: mov ebx, esi ; Plot pixel mov es:[di], ebx add di, 4 jnc same_win2 inc ah out dx, ax same_win2: dec cx jnz x_loop pop cx dec cx jz rdy add di, dest_add jnc y_loop inc ah out dx, ax jmp y_loop rdy: mov last_window, ah ret _vbeClrArea ENDP ; int vbeClrScr(unsigned long color); ALIGN 4 _vbeClrScr PROC USES es di, color:DWORD mov eax, color les di, screen mov bx, 0004h mov dx, 3deh mov ecx, _win_size shr ecx, 2 win_lp: push eax mov ax, bx out dx, ax pop eax push cx xor di, di rep stosd pop cx inc bh cmp bh, _num_win jb win_lp push eax mov ax, bx out dx, ax pop eax mov ecx, _tail shr ecx, 2 xor di, di rep stosd mov last_window, bh ret _vbeClrScr ENDP ; void vbeSetText(void); ALIGN 4 _vbeSetText PROC mov ax, 0003h int 10h ret _vbeSetText ENDP ; void vbeSetGraph(void); ALIGN 4 _vbeSetGraph PROC mov ax, 4f02h mov bx, _vbe_mode int 10h mov last_window, 0 ret _vbeSetGraph ENDP _TEXT ENDS END . 0