;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;; GRAPH32.INC ;; ;; ;; ;; 32bpp graph engine for Kolibri-A ;; ;; ;; ;; art_zh (kolibri@jerdev.co.uk) Dec. 2010 : ;; ;; - 4x2 granularity & tiled winmap structure ;; ;; - speed-optimized line/box graphics ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision: 1708 $ ;************************************************* ; getpixel ; ; in: ; eax = x coordinate ; ebx = y coordinate ; ; ret: ; ecx = 00 RR GG BB get_pixel: mov ecx, [BytesPerScanLine] imul ecx, ebx lea ecx, [ecx+eax*4] ; ecx = x*4+(y*y multiplier) mov ecx, [ecx+LFB_BASE] and ecx, 0xffffff ret ;----------------------------------------------------------------------------------- ; esi : Buffer origin ; edi : Screen origin ; ebp : Map origin ; ecx : block height (pix) ; ebx : bit[24] = odd line; bh = temp; bl = current task align 4 draw_aligned_box: pushad xor edx, edx .new_line: btr ebx, 26 mov eax, [img_map_x] xor ecx, ecx cmp bl, byte[ebp] ; check the left tile first je .new_tile bts ebx, 26 ; ebx[26] = 1 if edi/esi pushed push edi push esi push [img_bitoffset] jmp .seek_visible .new_tile: inc ecx ; visible - scan the open space cmp ecx, eax jz .end_of_line cmp bl, byte[ebp+ecx] je .new_tile ; overlapped? draw the last visible segment if so bts ebx, 26 ; check if edi/esi already pushed jc @f push edi push esi push [img_bitoffset] @@: call [img_draw_core_fn] ; bpp-specific helper (see below) .seek_visible: inc ecx cmp ecx, eax je .next_line cmp bl, byte[ebp+ecx] jne .seek_visible .got_visible: sub eax, ecx shl ecx, 4 add edi, ecx ; shift the left edge bt ebx, 25 ; 1bpp? jc @f shr ecx, 2 imul ecx, [img_bytes_per_pix] jmp .new_visible @@: shr ecx, 8 ; 2 tiles = 1 byte jnc .new_visible rol [img_bitoffset], 4 jnc .new_visible inc ecx .new_visible: add esi, ecx xor ecx, ecx jmp .new_tile .end_of_line: call [img_draw_core_fn] .next_line: bt ebx, 26 jnc @f pop [img_bitoffset] pop esi pop edi @@: inc edx cmp edx, [esp+24] ; stacked ecx = image height je .finish add edi, [BytesPerScanLine] add esi, [img_buf_line_size] btc ebx, 24 ; odd line? jnc .new_line add ebp, [_WinMapWidth] jmp .new_line .finish: popad ret ;-------------------------------- ; ebx : bit[24] = odd line; bh = reserved; bl = current task ; ecx : column height (pix) ; edx : max tile offset: 0, 4, 8, or 12 bytes (1,2,3 or 4 pix to draw) ; ebp : map origin ; esi : buffer image origin ; edi : LFB-origin (4byte-aligned) align 4 draw_unaligned_edge: pushad mov eax, [img_buf_line_size] mov bh, dl ; store the 1st tile offset btr ebx, 24 ; check if the 1st line odd jnc .new_tile cmp bl, byte[ebp] jne @f call [img_draw_edge_fn] ; bpp-specific helper (see below) @@: dec ecx jz .exit add edi, [BytesPerScanLine] add ebp, [_WinMapWidth] add esi, eax .new_tile: cmp bl, byte[ebp] jne .skip_tile call [img_draw_edge_fn] dec ecx jz .exit add edi, [BytesPerScanLine] add esi, eax call [img_draw_edge_fn] dec ecx jz .exit add edi, [BytesPerScanLine] add ebp, [_WinMapWidth] add esi, eax jmp .new_tile .skip_tile: sub cx, 2 jbe .exit add edi, [BytesPerScanLine] add edi, [BytesPerScanLine] add esi, eax add esi, eax add ebp, [_WinMapWidth] jmp .new_tile .exit: popad ret ;------------- ; unaligned edge helpers ; esi -> left point of the image edge ; edi -> left point of the screen edge ; bh = edx = tile offset (0, 4, 8 or 12 bytes) align 4 draw_edge_0bpp: push eax mov eax, [esi] .putpix: mov [edi+edx], eax sub dl, 4 jae .putpix .exit: movzx edx, bh pop eax ret align 4 draw_edge_32bpp: push eax .putpix: mov eax, [esi+edx] mov [edi+edx], eax sub dl, 4 jae .putpix .exit: movzx edx, bh pop eax ret align 4 draw_edge_24bpp: push eax esi xor dl, dl .putpix: mov eax, [esi] and eax, 0x00FFFFFF mov [edi+edx], eax cmp dl, bh je .exit add dl, 4 add esi, 3 jmp .putpix .exit: pop esi eax ret align 4 draw_edge_8bpp: push eax esi ebp xor dl, dl mov ebp, [img_palette] .putpix: movzx eax, byte[esi] mov eax, [ebp+eax*4] mov [edi+edx], eax cmp dl, bh je .exit add dl, 4 inc esi jmp .putpix .exit: pop ebp esi eax ret align 4 draw_edge_1bpp: pushad movzx edx, bh add edx, edi mov ebp, [img_palette] mov ebx, [ebp+4] ; forecolor mov ebp, [ebp] ; backcolor mov ecx, [img_edgeoffset] ; cl = 1 << left_edge_pix_num mov eax, [esi] .testbit: test eax, ecx jnz @f mov eax, ebp jmp .putpix @@: mov eax, ebx .putpix: mov [edi], eax cmp edi, edx je .exit add edi, 4 rol ecx, 1 jmp .testbit .exit: popad ret draw_edge_16bpp: draw_core_16bpp: ret ;------------- ; aligned core helpers ; esi -> left point address (buffer) ; edi -> left point address (screen) ; ecx = number of tiles to draw align 4 draw_core_0bpp: push eax ecx edi pushfd ; cli cld mov eax, [esi] shl ecx, 2 rep stosd popfd pop edi ecx eax ret align 4 draw_core_32bpp: push ecx esi edi pushfd ; cli cld shl ecx, 2 rep movsd popfd pop edi esi ecx ret align 4 draw_core_24bpp: push eax ecx edx shl ecx, 2 ; ecx = numpixels dec ecx lea edx, [ecx*2+ecx] ; edx = buffer byte offset .putpix: mov eax, [esi+edx] and eax, 0x00FFFFFF mov [edi+ecx*4], eax dec ecx sub edx, 3 jnb .putpix pop edx ecx eax ret align 4 draw_core_8bpp: pushad mov ebp, [img_palette] .putpix: xor edx, edx mov eax, dword[esi] ; block of 4 pixels .putone: movzx ebx, al mov ebx, [ebp+ebx*4] mov [edi+edx*4], ebx shr eax, 8 inc dl cmp dl, 4 jnz .putone add esi, edx ;-) add edi, 16 dec ecx jnz .putpix .exit: popad ret align 4 draw_core_1bpp: pushad mov ebp, [img_palette] mov edx, [ebp+4] ; foreground color mov ebp, [ebp] ; background color mov ebx, [img_bitoffset] shl ecx, 2 ; 1 tyle = 4 pix .newblock: mov eax, [esi] .putpix: test ebx, eax jz .bkcolor mov [edi], edx jmp .nextpix .bkcolor: mov [edi], ebp .nextpix: dec ecx jz .exit rol ebx, 1 jc .nextblock add edi, 4 jmp .putpix .nextblock: add esi, 4 jmp .newblock .exit: popad ret ;----------------------------------------- virtual at esp putimg: .image_sx dd ? ; X-size (pix) .image_sy dd ? ; Y-size .stack_data = 2*4 end virtual align 4 ; ebx -> Buffer origin ; ecx = packed size [x|y] ; edx = packed coordinates [x|y] ; static variables required: ; [img_draw_core_fn], [img_draw_edge_fn] ; [img_bytes_per_pix], [img_buf_line_size] ; [img_palette] (1bpp and 8bpp only) _putimage: ; call [_display.disable_mouse] pushad sub esp, putimg.stack_data mov [img_buf_origin], ebx ; save pointer to image buffer mov esi, ebx ; pointer to image .unpack_coords: mov eax, ecx and ecx, 0xFFFF ; Ysize shr eax, 16 ; Xsize mov [putimg.image_sy], ecx mov [putimg.image_sx], eax mov eax, edx and edx, 0xFFFF ; Ytop shr eax, 16 ; Xleft .calculate_abs_coords: mov edi, [TASK_BASE] mov ebx, [edi-twdw + WDATA.box.left] mov ecx, [edi-twdw + WDATA.box.top] add ebx, eax add ecx, edx mov [img_screen_x], ebx ; abs Xleft ; mov [img_screen_y], ecx ; ecx = abs Ytop ; hold it ! .check_x_size: mov ebx, [edi-twdw + WDATA.box.width] inc ebx ; ebx = window Xsize sub ebx, eax ; eax = rel Xleft jbe .finish ; image is out of the window mov eax, [putimg.image_sx] cmp ebx, eax ; real_sx = MIN(wnd_sx-image_cx, image_sx); jae @f mov eax, ebx @@: dec eax mov [img_pix_x], eax .check_y_size: mov ebx, [edi-twdw + WDATA.box.height] inc ebx ; ebx = real window y-size sub ebx, edx ; edx = rel Ytop jbe .finish ; image isn't visible mov edx, [putimg.image_sy] cmp ebx, edx jae @f mov edx, ebx @@: mov [img_pix_y], edx .calculate_lfb_origin: mov edi, ecx ; ecx = absY imul edi, [BytesPerScanLine] mov eax, [img_screen_x] ; eax = absX lea edi, [edi+eax*4] add edi, LFB_BASE ; edi -> Screen origin mov [img_lfb_origin], edi .calculate_map_origin: xor ebx, ebx mov bl, byte [img_bytes_per_pix] or bl, bl jnz @f mov ecx, [img_buf_line_size] or cl, cl je @f bts ebx, 25 @@: mov bl, byte [CURRENT_TASK] ; get process number mov ebp, ecx ; ecx = absY shr ebp, 1 ; CF= odd line jnc @f bts ebx, 24 ; ebx[24] = odd start line @@: imul ebp, [_WinMapWidth] add ebp, [_WinMapAddress] mov ecx, eax ; eax = absX shr ecx, 2 add eax, [img_pix_x] inc eax shr eax, 2 add eax, ebp ; mov [img_map_right], eax ; right edge tile add ebp, ecx ; left edge Map origin mov ecx, [img_pix_y] sub eax, ebp jz .thin_bar ; special case: all image is 1 tile thick mov [img_map_x], eax ; tiles in row (excluding the right one) ; ----- at this point: ; esi = [img_buf_origin] -> buffered image ; edi = [img_lfb_origin] -> LFB image (corner point, 0RGB format) ; ebp -> corner tile position ; ecx = [img_pix_y] = image height ; bl = task # ; ebx[24] = 1 if Ytop is odd ; ebx[25] = 1 if 1bpp image .start: bt ebx, 25 jnc @f xor eax, eax inc al mov [img_bitoffset], eax ; 1bpp image must be byte-aligned mov [img_edgeoffset], eax @@: mov edx, edi mov dh, 0x0C and dl, dh jz .go_right ; left edge already aligned .left_edge: sub dh, dl movzx edx, dh call draw_unaligned_edge dec [img_map_x] shr edi, 4 inc edi ; align edi to the next 16-byte tile shl edi, 4 mov [img_lfb_origin], edi ; core Screen origin shr edx, 2 inc edx sub [img_pix_x], edx ; shrink image width bt ebx, 25 jnc @f xchg dl, cl mov eax, [img_edgeoffset] ; that's for 1bpp images only shl eax, cl mov [img_edgeoffset], eax mov [img_bitoffset], eax xchg dl, cl @@: mov eax, edx imul eax, [img_bytes_per_pix] ; 0 for 1bbp bitmaps add esi, eax mov [img_buf_origin], esi ; core Buffer origin inc ebp ; core Map origin .go_right: mov eax, [img_map_x] mov edx, eax bt ebx, 25 ; 1bpp image ? jc .shift_mono shl eax, 2 imul eax, [img_bytes_per_pix] jmp .get_right .shift_mono: shr eax, 1 ; 2 tiles = 1 byte Buffer offset jnc .get_right rol byte [img_edgeoffset], 4 ; odd number of tiles: shift 4bits .get_right: add esi, eax ; rightEdge Buffer origin push ebp add ebp, edx ; rightEdge Map origin mov eax, [img_pix_x] shl eax, 2 ; 1 pix = 4 bytes add eax, edi ; rightEdge last pix (LFB addr) shl edx, 4 add edi, edx ; rightEdge Screen origin movzx edx, al mov eax, [img_map_x] and dl, 0x0C cmp dl, 0x0C je .core_block ; rightEdge is already tile-aligned .right_edge: call draw_unaligned_edge .core_block: or eax, eax ; empty central core? jz .finish mov ebp, [esp] mov edi, [img_lfb_origin] mov esi, [img_buf_origin] call draw_aligned_box .finish: add esp, (putimg.stack_data + 4) ; call [_display.enable_mouse] popad ret .thin_bar: ; < a special case > : one-tile-wide image mov edx, [img_pix_x] shl edx, 2 ; edx = rightmost tile offset (0, 4, 8, or 12 bytes) call draw_unaligned_edge add esp, putimg.stack_data popad ret ;align 64 ;img_test_struct_32: ; 8 x 10 ; dd 0x112233, 0x223344, 0x334455, 0x445566, 0x556677, 0x667788, 0x778899, 0x887766 ; dd 0x223344, 0x334455, 0x445566, 0x556677, 0x667788, 0x777799, 0x887766, 0x997755 ; dd 0x334455, 0x445566, 0x556677, 0x667788, 0x777799, 0x887766, 0x997755, 0xAA7744 ; dd 0x445566, 0x556677, 0x667788, 0x777799, 0x887766, 0x997755, 0xAA7744, 0xBB7733 ; dd 0x334455, 0x445566, 0x556677, 0x667788, 0x777799, 0x887766, 0x997755, 0xAA7744 ; dd 0x223344, 0x334455, 0x445566, 0x556677, 0x667788, 0x777799, 0x887766, 0x997755 ; dd 0x112233, 0x223344, 0x334455, 0x445566, 0x556677, 0x667788, 0x777799, 0x887766 ; dd 0x001122, 0x112233, 0x223344, 0x334455, 0x445566, 0x556677, 0x667788, 0x777799 ; dd 0x220000, 0x001122, 0x112233, 0x223344, 0x334455, 0x445566, 0x556677, 0x667788 ; dd 0x441100, 0x220000, 0x001122, 0x112233, 0x223344, 0x334455, 0x445566, 0x556677 ;align 64 ;img_test_struct_24: ; 8 x 16 ; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB ; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211 ; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB ; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211 ; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB ; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211 ; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB ; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211 ; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB ; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211 ; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB ; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211 ; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB ; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211 ; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB ; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211 ;align 64 ;img_test_struct_8: ; 20 x 10 ; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 ; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 ; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 ; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 ; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 ; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 ; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 ; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 ; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 ; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 ;align 64 ;img_test_struct_1: ; 16 x 10 ; db 0x0F, 0xF0 ; db 0x0F, 0xF0 ; db 0x3C, 0xC3 ; db 0x3C, 0xC3 ; db 0xF0, 0x0F ; db 0xF0, 0x0F ; db 0x3C, 0xC3 ; db 0x3C, 0xC3 ; db 0x0F, 0xF0 ; db 0x0F, 0xF0 ;align 64 ;img_test_palette: ; 6 colors ; dd 0x00BB2233, 0xAA4466, 0x995555, 0x00339966, 0x00884455, 0x00775566, 0x00664455, 0x00553344, 0x0 ;************************************************************************************** align 4 __sys_putpixel: push edx mov edx, [TASK_BASE] add eax, [edx-twdw+WDATA.box.left] add ebx, [edx-twdw+WDATA.box.top] pop edx _putpixel: ; eax = x coordinate ; ebx = y coordinate ; ecx = ?? RR GG BB ; 0x01000000 negation ; edi = 0x00000001 force cmp [Screen_Max_X], eax jb .exit0 cmp [Screen_Max_Y], ebx jb .exit0 .check_forced: test edi,1 ; force ? jnz .checked .not_forced: push ebx eax shr eax, 2 shr ebx, 1 imul ebx, [_WinMapWidth] ; win_map (X size)/2 add ebx, eax mov al, byte [CURRENT_TASK] mov ah, byte [_WinMapAddress+ebx] cmp ah, al pop eax ebx jne .exit0 .checked: push ebx imul ebx, [BytesPerScanLine] lea ebx, [ebx+eax*4] bt ecx, 24 jnc .noneg mov ecx, [LFB_BASE+ebx] xor ecx, 0x00FFFFFF .noneg: mov [LFB_BASE+ebx], ecx pop ebx .exit0: ret ;align 4 ;_put_pixel: ; left for compatibility with Vesa20_putpixel32 ;; eax = x ;; ebx = y ; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier ; lea edi, [ebx+eax*4] ; edi = x*4+(y*y multiplier) ;; mov eax, [esp+32-8+4] ; eax = color ; mov [LFB_BASE+edi], ecx ; ret ; DRAWLINE align 4 __sys_draw_line: call [_display.disable_mouse] ; draw a line ; eax = HIWORD = x1 ; LOWORD = x2 ; ebx = HIWORD = y1 ; LOWORD = y2 ; ecx = color ; edi = force ? pusha dl_x1 equ esp+20 dl_y1 equ esp+16 dl_x2 equ esp+12 dl_y2 equ esp+8 dl_dx equ esp+4 dl_dy equ esp+0 xor edx, edx ; clear edx xor esi, esi ; unpack arguments xor ebp, ebp mov si, ax ; esi = x2 mov bp, bx ; ebp = y2 shr eax, 16 ; eax = x1 shr ebx, 16 ; ebx = y1 push eax ; save x1 push ebx ; save y1 push esi ; save x2 push ebp ; save y2 ; checking x-axis... sub esi, eax ; esi = x2-x1 push esi ; save y2-y1 jl .x2lx1 ; is x2 less than x1 ? jg .no_vline ; x1 > x2 ? mov edx, ebp ; else (if x1=x2) call vline push edx ; necessary to rightly restore stack frame at .exit jmp .exit .x2lx1: neg esi ; get esi absolute value .no_vline: ; checking y-axis... sub ebp, ebx ; ebp = y2-y1 push ebp ; save y2-y1 jl .y2ly1 ; is y2 less than y1 ? jg .no_hline ; y1 > y2 ? mov edx, [dl_x2] ; else (if y1=y2) call hline jmp .exit .y2ly1: neg ebp ; get ebp absolute value .no_hline: cmp ebp, esi jle .x_rules ; |y2-y1| < |x2-x1| ? cmp [dl_y2], ebx ; make sure y1 is at the begining jge .no_reverse1 neg dword [dl_dx] mov edx, [dl_x2] mov [dl_x2], eax mov [dl_x1], edx mov edx, [dl_y2] mov [dl_y2], ebx mov [dl_y1], edx .no_reverse1: mov eax, [dl_dx] cdq ; extend eax sing to edx shl eax, 16 ; using 16bit fix-point maths idiv ebp ; eax = ((x2-x1)*65536)/(y2-y1) mov edx, ebp ; edx = counter (number of pixels to draw) mov ebp, 1 *65536 ; <<16 ; ebp = dy = 1.0 mov esi, eax ; esi = dx jmp .y_rules .x_rules: cmp [dl_x2], eax ; make sure x1 is at the begining jge .no_reverse2 neg dword [dl_dy] mov edx, [dl_x2] mov [dl_x2], eax mov [dl_x1], edx mov edx, [dl_y2] mov [dl_y2], ebx mov [dl_y1], edx .no_reverse2: xor edx, edx mov eax, [dl_dy] cdq ; extend eax sing to edx shl eax, 16 ; using 16bit fix-point maths idiv esi ; eax = ((y2-y1)*65536)/(x2-x1) mov edx, esi ; edx = counter (number of pixels to draw) mov esi, 1 *65536 ;<< 16 ; esi = dx = 1.0 mov ebp, eax ; ebp = dy .y_rules: mov eax, [dl_x1] mov ebx, [dl_y1] shl eax, 16 shl ebx, 16 align 4 .draw: push eax ebx shr eax, 16 shr ebx, 16 call _putpixel pop ebx eax add ebx, ebp ; y = y+dy add eax, esi ; x = x+dx dec edx jnz .draw ; force last drawn pixel to be at (x2,y2) mov eax, [dl_x2] mov ebx, [dl_y2] call _putpixel .exit: add esp, 6*4 popa call [draw_pointer] ; mouse ret align 4 hline: ; ------------ draw a horizontal line ------------- ; eax = x1 ; edx = x2 ; ebx = y ; ecx = color ; edi = force ? cmp ebx, [Screen_Max_Y] jge .out pushad bt ecx, 24 ; color inversion check rcl edi,1 ; forced graphics check mov ebp, ebx shr ebp, 1 imul ebp, [_WinMapWidth] ; ebp = screen map base add ebp, [_WinMapAddress] cmp edx, eax ; to make sure x2 > x1 jge @f xchg eax, edx @@: cmp eax, [Screen_Max_X] jge .exit mov esi, eax shr esi, 4 add ebp, esi ; ebp -> win_map element imul ebx, [BytesPerScanLine] ; ebx -> LFB pix_line add ebx, LFB_BASE cmp edx, [Screen_Max_X] ; last check jb @f mov edx, [Screen_Max_X] @@: mov esi, ecx ; store color here mov cl, byte [CURRENT_TASK] ; mov ch, cl mov [CURRENT_TASK+2], cx mov [CURRENT_TASK+1], cl ; replicate byte to dword .newsegment: mov ecx, [ebp] ; check the line segment (16 pixels!) xor ecx, [CURRENT_TASK] ; -- the line --- jmp dword [hline.drawtable + edi*4] ; (C) Serge, 2010 align 4 ; internal loop .invert_color: mov esi, [ebx+eax*4] xor esi, 0x00FFFFFF align 4 .check_overlap: or cl, cl jz .putpixel jmp .nextpixel align 4 .invert_force: mov esi, [ebx+eax*4] xor esi, 0x00FFFFFF align 4 .putpixel: mov [ebx+eax*4], esi align 4 .nextpixel: inc eax cmp eax, edx ja .exit ; line drawn -- exit all loops test al, 3 jz .newtile .newpixel: jmp dword [hline.drawtable + edi*4] ; the internal loop .newtile: inc ebp test ebp, 3 jz .newsegment ; the external loop shr ecx, 8 jmp dword [hline.drawtable + edi*4] .exit: mov eax, 0x0FF and [CURRENT_TASK], eax popad .out: ret align 4 .drawtable: dd .check_overlap ; general case dd .invert_color dd .putpixel ; force to draw it dd .invert_force align 4 vline: ; --------- draw a vertical line ------------ ; eax = x ; ebx = y1 ; edx = y2 ; ecx = color ; edi = force ? cmp eax, [Screen_Max_X] jge .out pushad bt ecx, 24 ; color inversion check rcl edi, 1 ; forced graphics check cmp edx, ebx ; to make sure y2 > y1 jge @f xchg ebx, edx @@: cmp ebx, [Screen_Max_Y] jge .exit mov ebp, ebx shr ebp, 1 imul ebp, [_WinMapWidth] add ebp, [_WinMapAddress] mov esi, eax shr esi, 1 shr esi, 1 add ebp, esi ; ebp = screen map at (x, y1) push ebx imul ebx, [BytesPerScanLine] shl eax, 1 shl eax, 1 add eax, ebx add eax, LFB_BASE pop ebx ; restore ebx = y1 cmp edx, [Screen_Max_Y] ; the last check jb .draw mov edx, [Screen_Max_Y] ; to prevent off-screen drawing .draw: jmp dword [vline.drawtable + edi*4] align 4 .invert_color: mov ecx, [eax] xor ecx, 0x00FFFFFF align 4 .check_overlap: movzx esi, byte [ebp] cmp esi, [CURRENT_TASK] je .putpixel jmp .nextpixel align 4 .invert_force: mov ecx, [eax] xor ecx, 0x00FFFFFF align 4 .putpixel: mov [eax], ecx align 4 .nextpixel: add eax, [BytesPerScanLine] inc ebx test bl, 1 jnz @f add ebp, [_WinMapWidth] @@: cmp ebx, edx ja .exit jmp dword [vline.drawtable + edi*4] .exit: shr edi, 1 popad .out: ret align 4 .drawtable: dd .check_overlap ; general case dd .invert_color dd .putpixel ; force to draw it dd .invert_force ;************************************************* align 4 ; eax xOrigin ; ebx yOrigin ; ecx xSize ; edx ySize ; edi color _drawbar: pushad sub esp, putimg.stack_data mov [img_bytes_per_pix], 0 mov [img_buf_line_size], 0 mov [img_draw_core_fn], draw_core_0bpp mov [img_draw_edge_fn], draw_edge_0bpp mov [putimg.image_sx], ecx mov [putimg.image_sy], edx mov edx, ebx mov [img_palette], edi mov esi, img_palette mov [img_buf_origin], esi jmp _putimage.calculate_abs_coords ; ret draw_background: pushad pushfd cld ; increment edi here! mov ebp, [_WinMapAddress] mov eax, 0x00337766 ; bgndcolor mov bl, 1 mov edx, [Screen_Max_X] shr edx, 1 mov edi, LFB_BASE mov esi, [BytesPerScanLine] .new_row: xor ecx, ecx .fill: cmp byte [ebp+ecx], bl jne .next mov [edi+esi], eax ; fill all 8 pixels of this tile stosd mov [edi+esi], eax stosd mov [edi+esi], eax stosd mov [edi+esi], eax stosd .next: inc ecx cmp ecx, [_WinMapWidth] jb .fill dec edx jz .done add ebp, ecx ; += [_WinMapWidth] add edi, esi ; += [BytesPerScanLine] jmp .new_row .done: popfd popad ret drawbackground_stretch: ; left for future development call drawbackground ret drawbackground_tiled: ; left for future development call drawbackground ret uglobal align 4 bgr_cur_line rd 1920 ; maximum width of screen bgr_next_line rd 1920 endg _init_background: ; mov edi, BgrAuxTable ; xor edx, edx ;.loop2: ; mov eax, edx ; shl eax, 8 ; neg eax ; mov ecx, 0x200 ;.loop1: ; mov byte [edi], ah ; inc edi ; add eax, edx ; loop .loop1 ; add dl, 4 ; jnz .loop2 mov byte [REDRAW_BACKGROUND], 1 ; mov dword[BgrAuxTable], 0x00337766 ret diff16 "GRAPH32 code end ",0,$ diff10 "GRAPH32 code size",get_pixel,$