;         ______   ___    ___
;        /\  _  \ /\_ \  /\_ \
;        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
;         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
;          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
;           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
;            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
;                                           /\____/
;                                           \_/__/
;
;      Asm functions for Windows bitmap locking.
;
;      By Isaac Cruz.
;
;      Ported to MASM by Matthew Smith
;
;      Improved dirty rectangles mechanism by Eric Botcazou.
;
;      See readme.txt for copyright information.
;


;#include "src/i386/asmdefs.inc"

INCLUDE  "masmdef.inc"    ; temporary file for testing
						  ; the final version should be autogenerated as obj/msvc/masmdef.inc
						  ; by a new version of asmdef.sh 
						    	    

.386	  ;	select standard 32 bit instruction set

.CODE     ; equivalent to .text in gas 


; gfx_directx_write_bank:
; edx = bitmap
; eax = line
;

gfx_directx_write_bank:

      ;check whether is locked already
      
	  test dword [BMP_ID+edx], BMP_ID_LOCKED
      jnz Locked

      ;lock the surface
      pushad
      push edx
      call dword ptr [ptr_gfx_directx_autolock] 
      pop edx
      popad

   Locked:
      ;
      mov  eax,[BMP_LINE+edx+eax*4]
      
      ret



;  gfx_directx_unwrite_bank:
;   edx = bmp


gfx_directx_unwrite_bank:

      ; only unlock bitmaps that were autolocked
      test [BMP_ID+edx], BMP_ID_AUTOLOCK
      jz NoUnlock

      ; unlock surface
      pushad
      push edx
      call dword ptr [ptr_gfx_directx_unlock] 
      pop edx
      popad

      ; clear the autolock flag 
      and [BMP_ID+edx], NOT BMP_ID_AUTOLOCK 

   NoUnlock:
      ret
      



; gfx_directx_write_bank_win:
;  edx = bitmap
;  eax = line
;

gfx_directx_write_bank_win:
      
      pushad
      mov ebx, dword ptr [_wd_dirty_lines]
      add ebx, dword ptr [BMP_YOFFSET+edx]
      mov byte ptr [ebx + eax], 1   ; wd_dirty_lines[line] = 1; (line has changed) 
      
      ; check whether is locked already
      test ds:dword ptr[BMP_ID+edx], BMP_ID_LOCKED
      jnz Locked_win

      ;lock the surface
      push edx
      call dword ptr [ptr_gfx_directx_autolock] 
      pop  edx

   Locked_win:
      popad
      ; get pointer to the video memory
      mov eax,ds:dword ptr [BMP_LINE + edx + eax*4]
      
      ret


; gfx_directx_unwrite_bank_win:
;  edx = bmp
;


gfx_directx_unwrite_bank_win:
      pushad

      ;only unlock bitmaps that were autolocked
      test ds:dword ptr [BMP_ID+edx], BMP_ID_AUTOLOCK
      jz NoUnlock_win

      ; unlock surface 
      push edx
      call dword ptr [ptr_gfx_directx_unlock] 
      pop  edx
      
      /* clear the autolock flag */
      and ds:dword ptr [BMP+edx], NOT BMP_ID_AUTOLOCK

   NoUnlock_win:

      ; pseudo_screen may still be locked
      mov eax, ds:dword ptr [pseudo_screen]
      test ds:dword ptr [BMP_ID+eax], BMP_ID_LOCKED
      jnz no_update_bank_win

      ; ok, we can safely update 
      call near ptr update_dirty_lines

   no_update_bank_win: 
      popad

      ret


;  gfx_directx_unlock_win:
;  arg1 = bmp
;

gfx_directx_unlock_win:
      push ebp
      mov  ebp, esp
      push ebx
      push esi
      push edi

      ; gfx_directx_unlock(bmp)
      mov edx, ds:dword ptr[8+ebp]
      push edx 
      call dword ptr [ptr_gfx_directx_unlock]
      pop  edx

      ; pseudo_screen may still be locked
      mov eax, ds:dword ptr [pseudo_screen]
      test ds:dword ptr [BMP_ID+eax], BMP_ID_LOCKED
      jnz no_update_win

      /* ok, we can safely update */
      call near ptr update_dirty_lines

   no_update_win:
      pop edi
      pop esi
      pop ebx
      pop ebp

      ret



;#define RECT_LEFT   (%esp)
;#define RECT_TOP    4(%esp)
;#define RECT_RIGHT  8(%esp)
;#define RECT_BOTTOM 12(%esp)

update_dirty_lines:
      subl esp, 16               ; allocate a RECT structure

	  mov ds:dword ptr[esp], 0   ;RECT_LEFT = 0 
      mov ecx, ds:dword ptr[eax]    ; ecx = pseudo_screen->w
      mov ds:dword ptr[8+esp],ecx   ; RECT_RIGHT = ecx
      mov ebx,ds:dword ptr[_wd_dirty_lines]   ; ebx = wd_dirty_lines
      mov esi,ds:dword ptr[4+eax]   ; esi = pseudo_screen->h  
      mov edi,0
      
   _align_

   next_line:
 
	 mov al,ds:byte ptr[ebx+edi]  ; al = wd_dirty_lines[edi]
	 test al,al					  ; is dirty?
	 jz test_end
 
	 mov ds:dword ptr[4+esp],edi  ;  RECT_TOP = edi
loop_dirty_lines:
	 mov ds:byte ptr[ebx+edi],0   ; wd_dirty_lines[edi] = 0
	 inc edi					  ; edi++	
 
	 mov al,ds:byte ptr[ebx+edi]  ; al = wd_dirty_lines[edi]
	 test al,al                   ; is still dirty?

	 jnz loop_dirty_lines         ; yes !
 
	 mov ds:dword ptr[12+esp],edi	;RECT_BOTTOM = edi
	 lea eax,ds:dword ptr[esp]      ;eax = RECT_LEFT  
	 push eax
	 call dword ptr[_update_window]
	 pop eax
test_end:
	 inc edi
	 cmp esi,edi			; last line? 
	 jge next_line          ; no !
	 add esp,16             ; free rect 

     ret



; gfx_gdi_write_bank:
; edx = bitmap
; eax = line
;

gfx_gdi_write_bank:
      



      pushad
	  mov ebx,ds:dword ptr[_gdi_dirty_lines]
      add ebx,ds:dword ptr[BMP_YOFFSET+edx]   
      mov ds:byte ptr[ebx+eax],1     ; gdi_dirty_lines[line] = 1; (line has changed)
 
	  ; check whether it is locked already
	  test ds:dword ptr[BMP_ID+edx], BMP_ID_LOCKED
	  jnz Locked_gdi

      ; lock the surface
	  push edx
	  call dword ptr[_ptr_gfx_gdi_autolock]
	  pop edx

Locked_gdi:
	  popad
	  
	  ;get pointer to the video memory
	  mov eax,ds:dword ptr[BMP_LINE + edx + eax*4]
	  ret	



;   gfx_gdi_unwrite_bank:
;   edx = bmp
;
gfx_gdi_unwrite_bank:
      pushad

      ; only unlock bitmaps that were autolocked
      testl ds:dword ptr[BMP_ID + edx], BMP_ID_AUTOLOCK
      jz NoUnlock_gdi

      ; unlock surface 
      push edx
      call dword ptr[ptr_gfx_gdi_unlock] 
      pop edx
      
      ; clear the autolock flag
      andl $~BMP_ID_AUTOLOCK, BMP_ID(%edx)
	  and ds:dword ptr [BMP_ID + edx], NOT BMP_ID_AUTOLOCK
   
   NoUnlock_gdi:
      popad

      ret
