2000 ; 16.7 million color version, Mystique optimized OPTION LANGUAGE: SYSCALL EXTRN _screen:FWORD EXTRN _vbe_mode:WORD EXTRN _bytes_per_scanline:DWORD EXTRN _win_size:DWORD EXTRN _win_func:DWORD EXTRN _num_win:BYTE EXTRN _tail:DWORD EXTRN _font:DWORD FALSE EQU 0 TRUE EQU 1 _TEXT SEGMENT DWORD PUBLIC 'CODE' _TEXT ENDS _DATA SEGMENT DWORD PUBLIC 'DATA' _DATA ENDS _BSS SEGMENT DWORD PUBLIC 'BSS' _BSS ENDS DGROUP GROUP _DATA, _BSS .386 _DATA SEGMENT DWORD PUBLIC 'DATA' lkup dd 00000000, 00002560, 00005120, 00007680, 00010240, 00012800 dd 00015360, 00017920, 00020480, 00023040, 00025600, 00028160 dd 00030720, 00033280, 00035840, 00038400, 00040960, 00043520 dd 00046080, 00048640, 00051200, 00053760, 00056320, 00058880 dd 00061440, 00064000, 00066560, 00069120, 00071680, 00074240 dd 00076800, 00079360, 00081920, 00084480, 00087040, 00089600 dd 00092160, 00094720, 00097280, 00099840, 00102400, 00104960 dd 00107520, 00110080, 00112640, 00115200, 00117760, 00120320 dd 00122880, 00125440, 00128000, 00130560, 00133120, 00135680 dd 00138240, 00140800, 00143360, 00145920, 00148480, 00151040 dd 00153600, 00156160, 00158720, 00161280, 00163840, 00166400 dd 00168960, 00171520, 00174080, 00176640, 00179200, 00181760 dd 00184320, 00186880, 00189440, 00192000, 00194560, 00197120 dd 00199680, 00202240, 00204800, 00207360, 00209920, 00212480 dd 00215040, 00217600, 00220160, 00222720, 00225280, 00227840 dd 00230400, 00232960, 00235520, 00238080, 00240640, 00243200 dd 00245760, 00248320, 00250880, 00253440, 00256000, 00258560 dd 00261120, 00263680, 00266240, 00268800, 00271360, 00273920 dd 00276480, 00279040, 00281600, 00284160, 00286720, 00289280 dd 00291840, 00294400, 00296960, 00299520, 00302080, 00304640 dd 00307200, 00309760, 00312320, 00314880, 00317440, 00320000 dd 00322560, 00325120, 00327680, 00330240, 00332800, 00335360 dd 00337920, 00340480, 00343040, 00345600, 00348160, 00350720 dd 00353280, 00355840, 00358400, 00360960, 00363520, 00366080 dd 00368640, 00371200, 00373760, 00376320, 00378880, 00381440 dd 00384000, 00386560, 00389120, 00391680, 00394240, 00396800 dd 00399360, 00401920, 00404480, 00407040, 00409600, 00412160 dd 00414720, 00417280, 00419840, 00422400, 00424960, 00427520 dd 00430080, 00432640, 00435200, 00437760, 00440320, 00442880 dd 00445440, 00448000, 00450560, 00453120, 00455680, 00458240 dd 00460800, 00463360, 00465920, 00468480, 00471040, 00473600 dd 00476160, 00478720, 00481280, 00483840, 00486400, 00488960 dd 00491520, 00494080, 00496640, 00499200, 00501760, 00504320 dd 00506880, 00509440, 00512000, 00514560, 00517120, 00519680 dd 00522240, 00524800, 00527360, 00529920, 00532480, 00535040 dd 00537600, 00540160, 00542720, 00545280, 00547840, 00550400 dd 00552960, 00555520, 00558080, 00560640, 00563200, 00565760 dd 00568320, 00570880, 00573440, 00576000, 00578560, 00581120 dd 00583680, 00586240, 00588800, 00591360, 00593920, 00596480 dd 00599040, 00601600, 00604160, 00606720, 00609280, 00611840 dd 00614400, 00616960, 00619520, 00622080, 00624640, 00627200 dd 00629760, 00632320, 00634880, 00637440, 00640000, 00642560 dd 00645120, 00647680, 00650240, 00652800, 00655360, 00657920 dd 00660480, 00663040, 00665600, 00668160, 00670720, 00673280 dd 00675840, 00678400, 00680960, 00683520, 00686080, 00688640 dd 00691200, 00693760, 00696320, 00698880, 00701440, 00704000 dd 00706560, 00709120, 00711680, 00714240, 00716800, 00719360 dd 00721920, 00724480, 00727040, 00729600, 00732160, 00734720 dd 00737280, 00739840, 00742400, 00744960, 00747520, 00750080 dd 00752640, 00755200, 00757760, 00760320, 00762880, 00765440 dd 00768000, 00770560, 00773120, 00775680, 00778240, 00780800 dd 00783360, 00785920, 00788480, 00791040, 00793600, 00796160 dd 00798720, 00801280, 00803840, 00806400, 00808960, 00811520 dd 00814080, 00816640, 00819200, 00821760, 00824320, 00826880 dd 00829440, 00832000, 00834560, 00837120, 00839680, 00842240 dd 00844800, 00847360, 00849920, 00852480, 00855040, 00857600 dd 00860160, 00862720, 00865280, 00867840, 00870400, 00872960 dd 00875520, 00878080, 00880640, 00883200, 00885760, 00888320 dd 00890880, 00893440, 00896000, 00898560, 00901120, 00903680 dd 00906240, 00908800, 00911360, 00913920, 00916480, 00919040 dd 00921600, 00924160, 00926720, 00929280, 00931840, 00934400 dd 00936960, 00939520, 00942080, 00944640, 00947200, 00949760 dd 00952320, 00954880, 00957440, 00960000, 00962560, 00965120 dd 00967680, 00970240, 00972800, 00975360, 00977920, 00980480 dd 00983040, 00985600, 00988160, 00990720, 00993280, 00995840 dd 00998400, 01000960, 01003520, 01006080, 01008640, 01011200 dd 01013760, 01016320, 01018880, 01021440, 01024000, 01026560 dd 01029120, 01031680, 01034240, 01036800, 01039360, 01041920 dd 01044480, 01047040, 01049600, 01052160, 01054720, 01057280 dd 01059840, 01062400, 01064960, 01067520, 01070080, 01072640 dd 01075200, 01077760, 01080320, 01082880, 01085440, 01088000 dd 01090560, 01093120, 01095680, 01098240, 01100800, 01103360 dd 01105920, 01108480, 01111040, 01113600, 01116160, 01118720 dd 01121280, 01123840, 01126400, 01128960, 01131520, 01134080 dd 01136640, 01139200, 01141760, 01144320, 01146880, 01149440 dd 01152000, 01154560, 01157120, 01159680, 01162240, 01164800 dd 01167360, 01169920, 01172480, 01175040, 01177600, 01180160 dd 01182720, 01185280, 01187840, 01190400, 01192960, 01195520 dd 01198080, 01200640, 01203200, 01205760, 01208320, 01210880 dd 01213440, 01216000, 01218560, 01221120, 01223680, 01226240 dest_add dd ? src_add dd ? char_offs dd ? nullseg dw 0 last_win dw 0 _DATA ENDS _TEXT SEGMENT DWORD PUBLIC 'CODE' ASSUME CS:_TEXT, DS:DGROUP PUBLIC _vbeVsync, _vbeChangeWindow PUBLIC _vbePutPixel, _vbeGetPixel PUBLIC _vbeClrArea, _vbeClrScr PUBLIC _vbePutImage, _vbeGetImage, _vbePutSprite PUBLIC _vbeDrawLine, _vbeDrawBox, _vbeDrawPoly 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 ; void vbeChangeWindow(int window); ALIGN 4 _vbeChangeWindow PROC, window:WORD mov dx, window cmp dx, last_win jz same_win mov last_win, dx mov ax, 4f05h mov bx, 0 call _win_func same_win: ret _vbeChangeWindow ENDP ; void vbePutPixel(int x, int y, unsigned long color); ALIGN 4 _vbePutPixel PROC USES ES DI, x:WORD, y:WORD, color:DWORD les edi, _screen mov bx, y shl bx, 2 add edi, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add edi, eax mov eax, color mov es:[edi], eax ret _vbePutPixel ENDP ; unsigned long vbeGetPixel(int x, int y); ALIGN 4 _vbeGetPixel PROC USES ES DI, x:WORD, y:WORD les edi, _screen mov bx, y shl bx, 2 add edi, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add edi, eax mov ax, es:[edi] mov dx, es:[edi + 2] ret _vbeGetPixel ENDP ; void 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 les edi, _screen mov bx, y shl bx, 2 add edi, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add edi, eax xor esi, esi mov si, word ptr[image + 2] shl esi, 4 push ds mov ds, nullseg mov eax, 2560 ; Line offset add value xor edx, edx mov dx, w shl dx, 2 sub eax, edx shr dx, 2 mov bx, h y_loop: mov ecx, edx db 0f3h, 67h movsd add edi, eax dec bx jnz y_loop pop ds ret _vbePutImage ENDP ; void 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 xor edi, edi mov di, word ptr[image + 2] shl 2000 edi, 4 mov es, nullseg mov esi, dword ptr[_screen] mov bx, y shl bx, 2 add esi, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add esi, eax push ds mov ds, nullseg mov eax, 2560 ; Calculate destination xor edx, edx mov dx, w ; offset value to add shl dx, 2 ; for each line sub eax, edx shr dx, 2 mov bx, h y_loop: mov ecx, edx db 0f3h, 67h movsd add esi, eax dec bx jnz y_loop pop ds ret _vbeGetImage ENDP ; void 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 les edi, _screen mov bx, y shl bx, 2 add edi, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add edi, eax xor esi, esi mov si, word ptr[sprite + 2] shl esi, 4 push ds mov ds, nullseg mov eax, 2560 ; Calculate destination xor edx, edx mov dx, w ; offset value to add shl dx, 2 ; for each line sub eax, edx shr dx, 2 mov bx, h y_loop: mov cx, dx ; Width x_loop: cmp dword ptr ds:[esi], 0 ; Don't write zero pixels jz no_plot db 67h movsd jmp no_add no_plot: add esi, 4 ; Update pointers add edi, 4 no_add: dec cx jnz x_loop add edi, eax dec bx jnz y_loop pop ds ret _vbePutSprite ENDP ; void vbeDrawLine(int x1, int y1, int x2, int y2, unsigned long color); ; 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 shl bx, 2 mov edx, lkup[bx] add edi, edx shl ax, 2 add edi, eax ENDM ALIGN 4 _vbeDrawLine PROC USES CX ES SI DI, x1:WORD, y1:WORD, x2:WORD, y2:WORD, color:DWORD LOCAL VARincr1:WORD, VARincr2:WORD, VARroutine:WORD les edi, _screen ; check for vertical lines mov esi, _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 mov bx, ax ; ax=y2 L31: inc cx ; cx=# of pixels to draw xor eax, eax mov ax, x1 ; bx=x PIXELADDR ; es:bx mov eax, color L32: mov es:[edi], eax add edi, esi ; next line dec cx jnz L32 jmp Lexit ; routine for horizontal lines (slope=0) horizLine: xor eax, eax mov ax, x1 mov bx, y1 PIXELADDR ; es:bx inc cx mov eax, color and ecx, 0ffffh db 0f3h, 67h ; rep stosd stosd 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 eax,color L11: mov es:[edi], eax ; put pixel, increment x add edi, 4 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 add edi, ebx ; increment y 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 eax,color L21: mov es:[edi], eax ; put pixel, increment x add edi, 4 add edi, ebx ; increment y L22: or si,si ; test sign of d jns L23 ; jump if d>=0 add si,VARincr1 ; d=d+incr1 sub edi, 4 ; dec x (inc by stosb) dec cx jnz L21 jmp Lexit L23: add si,VARincr2 ; d=d+incr2 dec cx jnz L21 Lexit: 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 CX 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 ; void 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 les edi, _screen mov bx, y shl bx, 2 add edi, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add edi, eax mov eax, color ; Color -> EBX lfs si, _font ; Load font address add si, chr ; Character index shl si, 4 ; * 16 mov ebx, 2560 - (8 * 4) ; Line offset add value mov cx, 16 row_lp: test byte ptr fs:[si], 10000000b jz empty1 mov es:[edi], eax empty1: add edi, 4 test byte ptr fs:[si], 01000000b jz empty2 mov es:[edi], eax empty2: add edi, 4 test byte ptr fs:[si], 00100000b jz empty3 mov es:[edi], eax empty3: add edi, 4 test byte ptr fs:[si], 00010000b jz empty4 mov es:[edi], eax empty4: add edi, 4 test byte ptr fs:[si], 00001000b jz empty5 mov es:[edi], eax empty5: add edi, 4 test byte ptr fs:[si], 00000100b jz empty6 mov es:[edi], eax empty6: add edi, 4 test byte ptr fs:[si], 00000010b jz empty7 mov es:[edi], eax empty7: add edi, 4 test byte ptr fs:[si], 00000001b jz empty8 mov es:[edi], eax empty8: add edi, 4 inc si add edi, ebx dec cx jnz row_lp ret _vbeWriteChar ENDP ; void 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 les edi, _screen mov bx, y shl bx, 2 add edi, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add edi, eax lfs si, _font ; Load font address add si, chr ; Character index shl si, 4 ; * 16 mov ebx, 2560 - (8 * 4) mov cx, 16 row_lp: test byte ptr fs:[si], 10000000b jz empty1 mov eax, fgcol jmp cont1 empty1: mov eax, bgcol cont1: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 01000000b jz empty2 mov eax, fgcol jmp cont2 empty2: mov eax, bgcol cont2: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00100000b jz empty3 mov eax, fgcol jmp cont3 empty3: mov eax, bgcol cont3: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00010000b jz empty4 mov eax 2000 , fgcol jmp cont4 empty4: mov eax, bgcol cont4: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00001000b jz empty5 mov eax, fgcol jmp cont5 empty5: mov eax, bgcol cont5: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00000100b jz empty6 mov eax, fgcol jmp cont6 empty6: mov eax, bgcol cont6: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00000010b jz empty7 mov eax, fgcol jmp cont7 empty7: mov eax, bgcol cont7: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00000001b jz empty8 mov eax, fgcol jmp cont8 empty8: mov eax, bgcol cont8: mov es:[edi], eax add edi, 4 inc si add edi, ebx dec cx jnz row_lp ret _vbeWriteCharOpaque ENDP ; void 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 bx, y ; Calculate offset shl bx, 2 mov edx, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add edx, eax les di, string lfs si, _font ; Font address -> FS:SI mov ebx, 2560 - (8 * 4) ; Line offset add value mov eax, color 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 les edi, _screen add edi, edx mov cx, 16 row_lp: test byte ptr fs:[si], 10000000b jz empty1 mov es:[edi], eax empty1: add edi, 4 test byte ptr fs:[si], 01000000b jz empty2 mov es:[edi], eax empty2: add edi, 4 test byte ptr fs:[si], 00100000b jz empty3 mov es:[edi], eax empty3: add edi, 4 test byte ptr fs:[si], 00010000b jz empty4 mov es:[edi], eax empty4: add edi, 4 test byte ptr fs:[si], 00001000b jz empty5 mov es:[edi], eax empty5: add edi, 4 test byte ptr fs:[si], 00000100b jz empty6 mov es:[edi], eax empty6: add edi, 4 test byte ptr fs:[si], 00000010b jz empty7 mov es:[edi], eax empty7: add edi, 4 test byte ptr fs:[si], 00000001b jz empty8 mov es:[edi], eax empty8: add edi, 4 inc si add edi, ebx dec cx jnz row_lp pop di pop es add edx, 8 * 4 inc di jmp string_lp string_complete: ret _vbeWriteString ENDP ; void 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 bx, y ; Calculate offset shl bx, 2 mov edx, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add edx, eax les di, string lfs si, _font ; Font address -> FS:SI mov ebx, 2560 - (8 * 4) ; Line offset add value 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 les edi, _screen add edi, edx mov cx, 16 row_lp: test byte ptr fs:[si], 10000000b jz empty1 mov eax, fgcol jmp cont1 empty1: mov eax, bgcol cont1: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 01000000b jz empty2 mov eax, fgcol jmp cont2 empty2: mov eax, bgcol cont2: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00100000b jz empty3 mov eax, fgcol jmp cont3 empty3: mov eax, bgcol cont3: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00010000b jz empty4 mov eax, fgcol jmp cont4 empty4: mov eax, bgcol cont4: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00001000b jz empty5 mov eax, fgcol jmp cont5 empty5: mov eax, bgcol cont5: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00000100b jz empty6 mov eax, fgcol jmp cont6 empty6: mov eax, bgcol cont6: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00000010b jz empty7 mov eax, fgcol jmp cont7 empty7: mov eax, bgcol cont7: mov es:[edi], eax add edi, 4 test byte ptr fs:[si], 00000001b jz empty8 mov eax, fgcol jmp cont8 empty8: mov eax, bgcol cont8: mov es:[edi], eax add edi, 4 inc si add edi, ebx dec cx jnz row_lp pop di pop es add edx, 8 * 4 inc di jmp string_lp string_complete: ret _vbeWriteStringOpaque ENDP ; Draws a vertical string from bottom to top ; void 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 bx, y ; Calculate offset shl bx, 2 mov edx, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add edx, eax les di, string ; String address -> ES:DI lfs si, _font ; Font address -> FS:SI mov eax, color mov ebx, (2560 * 8) + 4 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 les edi, _screen add edi, edx mov cx, 16 row_lp: test byte ptr fs:[si], 10000000b jz empty1 mov es:[edi], eax empty1: sub edi, 2560 test byte ptr fs:[si], 01000000b jz empty2 mov es:[edi], eax empty2: sub edi, 2560 test byte ptr fs:[si], 00100000b jz empty3 mov es:[edi], eax empty3: sub edi, 2560 test byte ptr fs:[si], 00010000b jz empty4 mov es:[edi], eax empty4: sub edi, 2560 test byte ptr fs:[si], 00001000b jz empty5 mov es:[edi], eax empty5: sub edi, 2560 test byte ptr fs:[si], 00000100b jz empty6 mov es:[edi], eax empty6: sub edi, 2560 test byte ptr fs:[si], 00000010b jz empty7 mov es:[edi], eax empty7: sub edi, 2560 test byte ptr fs:[si], 00000001b jz empty8 mov es:[edi], eax empty8: sub edi, 2560 inc si add edi, ebx dec cx jnz row_lp pop di pop es sub edx, 2560 * 8 inc di jmp string_lp string_complete: ret _vbeWriteVertString ENDP ; Draws a vertical string from bottom to top ; uses background color ; void 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 bx, y ; Calculate offset shl bx, 2 mov edx, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add edx, eax les di, string ; String address -> ES:DI lfs si, _font ; Font address -> FS:SI mov ebx, (2560 * 8) + 4 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 les edi, _screen add edi, edx mov cx, 16 row_lp: test byte ptr fs:[si], 10000000b jz empty1 mov eax, fgcol jmp cont1 empty1: mov eax, bgcol cont1: mov es:[edi], eax sub edi, 2560 test byte ptr fs:[si], 01000000b jz empty2 mov eax, fgcol jmp cont2 empty2: mov eax, bgcol cont2: mov es:[edi], eax sub edi, 2560 test byte ptr fs:[si], 00100000b jz empty3 mov eax, fgcol jmp cont3 empty3: mov eax, bgcol cont3: mov es:[edi], eax sub edi, 2560 test byte ptr fs:[si], 00010000b jz empty4 mov eax, fgcol jmp cont4 empty4: mov eax, bgcol cont4: mov es:[edi], eax sub edi, 2560 test byte ptr fs:[si], 00001000b jz empty5 mov eax, fgcol jmp cont5 empty5: mov eax, bgcol cont5: mov es:[edi], eax sub edi, 2560 test byte ptr fs:[si], 00000100b jz empty6 mov eax, fgcol jmp cont6 empty6: mov eax, bgcol cont6: mov es:[edi], eax sub edi, 2560 test byte ptr fs:[si], 00000010b jz empty7 mov eax, fgcol jmp cont7 empty7: mov eax, bgcol cont7: mov es:[edi], eax sub edi, 2560 test byte ptr fs:[si], 00000001b jz empty8 mov eax, fgcol jmp cont8 empty8: mov eax, bgcol cont8: mov es:[edi], eax sub edi, 2560 inc si add edi, ebx dec cx jnz row_lp pop di pop es sub edx, 2560 * 8 inc di jmp string_lp string_complete: ret _vbeWriteVertStringOpaque ENDP ; void 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 les edi, _screen ; Calculate offset mov bx, 333 y shl bx, 2 add edi, lkup[bx] xor eax, eax mov ax, x shl ax, 2 add edi, eax mov eax, color mov esi, 2560 xor edx, edx mov dx, w shl dx, 2 sub esi, edx shr dx, 2 mov bx, h y_loop: mov ecx, edx db 0f3h, 67h ; rep stosd stosd add edi, esi dec bx jnz y_loop ret _vbeClrArea ENDP ; void vbeClrScr(unsigned long color); ALIGN 4 _vbeClrScr PROC USES ES DI, color:DWORD les edi, _screen mov eax, color mov ecx, 307200 db 0f3h, 67h stosd 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 ret _vbeSetGraph ENDP _TEXT ENDS END . 0