{****************************************************************************}
{Modul VENOMBNK.INC - it is a part of the VenomGFX unit and adds some support}
{for routines which use the banking access into videomemory                  }
{      written by Laaca                                                      }
{****************************************************************************}


Procedure SetScrOffset;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{INPUT: EDI = address of VGA or VGB variable
 DESTROYS: EAX}
asm
{Melo by byt volano na pocatku vsech bankovacich kreslicich procedur}
{(aby byly schopny spravne pracovat se strankovanou videopameti)}

mov eax,[edi+2]                {VWOffset}
mov bank_internal.mem_offset,eax
end;


Procedure SetScrOffset2;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{INPUT: EDI = address of VGA or VGB variable
 DESTROYS: EAX,EBX,EDX}
asm
{Pridatna funkce pro procedury typu vybarveni cele obrazovky}
mov eax,[edi+2]        {VWoffset}
mov ebx,[edi+6]        {size}
mov bank_internal.mem_offset,eax
movzx edx,ax
shr eax,16

mov bank_internal.firstblockpos,edx
neg edx
add edx,65536
mov bank_internal.firstblocksize,edx

imul eax,bank_internal.grann
mov bank_internal.firstbank,eax

add ebx,[edi+2]
{sub ebx,2} {kupodivu musi zustat zakomentovane, jinak pracuje chybne}
movzx edx,bx
shr ebx,16
imul ebx,bank_internal.grann

mov bank_internal.bisgm,ebx
mov bank_internal.lastblocksize,edx
end;


Procedure NavysBank;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{Input:    bank_wr or bank_rd (longint) - actual bank

 Output:   none
 Destroys: EAX, EDX, high word of EBX}
asm
shl ebx,16
cmp bank_internal.zapis,0
jz @probiha_cteci_rutina
   mov edx,bank_internal.bank_wr
   add edx,bank_internal.grann     {granularita muze byt<>64}
   mov bank_internal.bank_wr,edx
   Call bank_internal.SetBank_wr
   jmp @Konec


@probiha_cteci_rutina:
   mov edx,bank_internal.bank_rd
   add edx,bank_internal.grann     {granularita muze byt<>64}
   mov bank_internal.bank_rd,edx
   Call bank_internal.SetBank_rd
@konec:
shr ebx,16
end;


Procedure Open_read_mode;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
asm
push eax
mov bank_internal.zapis,0   {znak pro volane procedury, ze probiha nikoliv zapisova,}
                   {ale cteci operace}

mov al,bank_internal.win_rd        {pokud karta pouziva jen jedno prostupove okno spolecne}
cmp al,bank_internal.win_wr        {pro cteni a zapis, tak musime synchronizovat zmeny}
jnz @nic
mov eax,bank_internal.bank_wr
mov bank_internal.bank_rd,eax
@nic:
pop eax
end;


Procedure Close_read_mode;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
asm
push eax
mov bank_internal.zapis,1   {prepinac zapisu a cteni vratime do puvodniho stavu}
mov al,bank_internal.win_rd        {pokud karta pouziva jen jedno prostupove okno spolecne}
cmp al,bank_internal.win_wr        {pro cteni a zapis, tak musime synchronizovat zmeny}
jnz @nic
mov eax,bank_internal.bank_rd
mov bank_internal.bank_wr,eax
@nic:
pop eax
end;



Procedure Process_read_copy;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{
vstup:
 ES:EDI = SVGA okno pro cteni zdrojoveho mista
 DS:ESI = SVGA okno pro zapis ciloveho mista
 ECX = delka v bajtech

zlikviduje: ECX}
asm
@znovu:
cmp ecx,4
jl @zbytek

mov eax,ES:[edi]
mov DS:[esi],eax
add edi,4
add esi,4
sub ecx,4
jnz @znovu
jmp @konec

@zbytek:
mov ax,ES:[edi]
mov DS:[esi],ax
add edi,2
add esi,2
sub ecx,2

@konec:
end;


Procedure Process_read_copy_and_clr;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{ES:EDI = SVGA okno pro cteni zdrajoveho mista
 ES:ESI = SVGA okno pro zapis zdrojoveho mista (funkce mazani)
 DS:EBX = cil
 EAX = barva rozepsana do 32-bitu (vzdy stejny horni a dolni word)
 ECX = delka v bajtech}
asm
push edx
@znovu:
cmp ecx,4
jl @zbytek

mov edx,ES:[edi]
mov DS:[ebx],edx
mov ES:[esi],eax

add edi,4
add esi,4
add ebx,4
sub ecx,4
jnz @znovu
jmp @konec

@zbytek:
mov dx,ES:[edi]
mov DS:[ebx],dx
mov ES:[esi],ax

add edi,2
add esi,2
add ebx,2
sub ecx,2

@konec:
pop edx
end;



Procedure BankShowTestScreen(var dest:virtualwindow;b1,b2:word);assembler;
{dest muze byt VGA nebo VGB}
var clr1,clr2,mg:longint;
asm
mov mouse.busy2,1
mov edi,dest

Call SetScroffset2

push es
mov es,[edi+0]
mov mg,0
mov ax,b1;shl eax,16;mov ax,b1;mov clr1,eax
mov ax,b2;shl eax,16;mov ax,b2;mov clr2,eax

mov edi,bank_internal.firstblockpos
add edi,bank_internal.seg_wr
mov edx,bank_internal.firstbank
mov ecx,bank_internal.firstblocksize
shr ecx,2  {ECX je vraceno v bajtech, tak prevedu na dwordy}

@znovu:
mov esi,edx
call bank_internal.SetBank_wr    {Nastavi bank}
mov edx,esi

mov eax,clr1
test mg,1
jz @hop
mov eax,clr2
@hop:
inc mg
rep stosd

mov edi,bank_internal.seg_wr   {start, odkud zapisovat}
mov ecx,16384
add edx,bank_internal.grann
cmp edx,bank_internal.bisgm
jb @znovu

{Ted jeste posledni blok - ten je kratsi nez bezne bloky}
mov ecx,bank_internal.lastblocksize
pushf
shr ecx,2
popf
je @znovu  {porad se vztahuje k poslednimu CMP}

sub edx,bank_internal.grann
mov bank_internal.bank_wr,edx  {zapamatujeme si prave pouzivany bank}

pop es
mov mouse.busy2,0
end;



Procedure InternalBankFlip_SVGA_and_clrscr(var source,dest:virtualwindow;c:word);assembler;
{Dest muze byt VGA nebo VGB a source je nejake VirtualWindow}
asm
mov mouse.busy2,1
mov edi,dest

Call SetScroffset2

push es
mov es,[edi+0]
mov esi,source
mov esi,ds:[esi+2]   {ziskani offsetu SOURCE}

mov edi,bank_internal.firstblockpos
add edi,bank_internal.seg_wr
mov edx,bank_internal.firstbank
mov ecx,bank_internal.firstblocksize

mov ax,c
shl eax,16
mov ax,c

@novy_bank:
push eax
call bank_internal.SetBank_wr    {Nastavi bank}
pop eax
{------------------------------------------------------------------------}

Call FastCopyAndDelBlock  {DS:ESI = zdroj; ES:EDI = cil; ECX = delka v bajtech}
                          {EAX = barva}
{------------------------------------------------------------------------}
mov edi,bank_internal.seg_wr   {start, odkud zapisovat}
mov ecx,65536
add edx,bank_internal.grann
cmp edx,bank_internal.bisgm
jb @novy_bank

{Ted jeste posledni blok - ten je kratsi nez bezne bloky}
mov ecx,bank_internal.lastblocksize
je @novy_bank  {porad se vztahuje k poslednimu CMP}

sub edx,bank_internal.grann
mov bank_internal.bank_wr,edx  {zapamatujeme si prave pouzivany bank}

pop es
mov mouse.busy2,0
end;


Procedure InternalBankFlip_SVGA(var source,dest:virtualwindow);assembler;
asm
mov mouse.busy2,1
mov edi,dest

Call SetScroffset2

push es
mov es,[edi+0]
mov esi,source
mov esi,ds:[esi+2]   {ziskani offsetu SOURCE}

mov edi,bank_internal.firstblockpos
add edi,bank_internal.seg_wr
mov edx,bank_internal.firstbank
mov ecx,bank_internal.firstblocksize


@novy_bank:
call bank_internal.SetBank_wr    {Nastavi bank}
{------------------------------------------------------------------------}

Call FastCopyBlock  {DS:ESI = zdroj; ES:EDI = cil; ECX = delka v bajtech}

{------------------------------------------------------------------------}
mov edi,bank_internal.seg_wr   {start, odkud zapisovat}
mov ecx,65536
add edx,bank_internal.grann
cmp edx,bank_internal.bisgm
jb @novy_bank

{Ted jeste posledni blok - ten je kratsi nez bezne bloky}
mov ecx,bank_internal.lastblocksize
je @novy_bank  {porad se vztahuje k poslednimu CMP}

sub edx,bank_internal.grann
mov bank_internal.bank_wr,edx  {zapamatujeme si prave pouzivany bank}

pop es
mov mouse.busy2,0
end;


PROCEDURE InternalBankClr(var Dest:virtualwindow;Color:Word); Assembler;
asm
mov mouse.busy2,1
mov edi,dest

Call SetScroffset2

push es
mov es,[edi+0]

mov edi,bank_internal.firstblockpos
add edi,bank_internal.seg_wr
mov edx,bank_internal.firstbank
mov ecx,bank_internal.firstblocksize

mov ax,color
shl eax,16
mov ax,color

@novy_bank:
push eax
call bank_internal.SetBank_wr    {Nastavi bank}
pop eax
{------------------------------------------------------------------------}

Call FastDelBlock  {DS:ESI = zdroj; ES:EDI = cil; ECX = delka v bajtech}
                   {EAX = barva}
{------------------------------------------------------------------------}
mov edi,bank_internal.seg_wr   {start, odkud zapisovat}
mov ecx,65536
add edx,bank_internal.grann
cmp edx,bank_internal.bisgm
jb @novy_bank

{Ted jeste posledni blok - ten je kratsi nez bezne bloky}
mov ecx,bank_internal.lastblocksize
je @novy_bank  {porad se vztahuje k poslednimu CMP}

sub edx,bank_internal.grann
mov bank_internal.bank_wr,edx  {zapamatujeme si prave pouzivany bank}

pop es
mov mouse.busy2,0
end;


Procedure StartPosition_into_EDI;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{INPUT:   EBX = start position (upper left corner)
          ECX = line length in bytes (usually set by clipping procedure)
          EDX = number of processed lines (usually set by clipping procedure)
          DS musn't be changed!

 OUTPUT:  EDI = final adress of starting position
          Bank_lines = number of processsed lines (copied EDX value)

Does't change other registers}
asm
mov edi,vga.bytebreite {takto lze pouzit i pokud budeme pouzivat VGB}
mov bank_internal.xxx,edi
mov bank_internal.lines,edx     {pocet radku zkopirujeme do bank_lines}
mov bank_internal.bank_ecx,ecx
mov edi,ebx
end;


Procedure StartPosition_into_ESI;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{INPUT:  EAX - start position in sprite (usually set by clipping proc)
         ESI - sprite of VirtualWindow format

 OUTPUT: ESI - final starting position in sprite
         EAX,Bank_ZZZ - ByteBreite of sprite}
asm
add eax,[esi+2]
mov esi,[esi+26]
xchg esi,eax
mov bank_internal.zzz,eax
end;



Procedure PrepareLine;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{INPUT:   EDI = actual position on screen
          Bank_internal.bank_ECX = length of line

 OUTPUT:   ECX = number of bytes to be copied in line before bank switch
           Bank_Zbytek2 = number of lines to be copied in line after bank
                          switch

           Bank_EDI = copy of all 32 bits of EDI
           EDI = modified to format of final usable address

 DESTROYS: EDX}
asm
{napred zjistim bank na konci radky}
mov bank_internal.bank_edi,edi    {ulozim nezmenene EDI}
add edi,bank_internal.mem_offset {pro strankovani - posun od zac. videopameti}
mov ecx,edi
add ecx,bank_internal.bank_ecx
sub ecx,2
push eax
push ebx
{V EDI poc. zacatku radky, v ECX poc. konce radky}

movzx eax,cx;add eax,2;mov bank_internal.zbytek2,eax  {bajtu do dalsiho banku}

shr ecx,16
imul ecx,bank_internal.grann    {bank na konci radky}

mov edx,edi
shr edx,16
imul edx,bank_internal.grann    {bank na zacatku radky}
and edi,0000ffffh

cmp bank_internal.zapis,0
jz @cteci_operace     {pro rutiny ktere na obrazovku zapisuji}
   add edi,bank_internal.seg_wr
   cmp edx,bank_internal.bank_wr            {je to jiny bank nez prave pouzivany?}
   jz @nemenbank1
      mov bank_internal.bank_wr,edx         {jestli ano, tak musime prepnout}
      Call bank_internal.Setbank_wr
   @nemenbank1:
   jmp @zapis_i_cteni

@cteci_operace:       {pro rutiny, ktere z obrazovky ctou}
   add edi,bank_internal.seg_rd
   cmp edx,bank_internal.bank_rd            {je to jiny bank nez prave pouzivany?}
   jz @nemenbank2
      mov bank_internal.bank_rd,edx         {jestli ano, tak musime prepnout}
      Call bank_internal.Setbank_rd
   @nemenbank2:

@zapis_i_cteni:  {ted uz zase spolecne pro zapis i cteni}

cmp ecx,edx      {je bank na zacatku i konci radky shodny?}
mov ecx,bank_internal.bank_ecx {nemeni priznaky}
jz @NebudePrepnutiBanku

sub ecx,bank_internal.zbytek2
shl bank_internal.zbytek2,17 {posun jen o 16 vede pri hodn. 65536 k chybe}

@NebudePrepnutiBanku:
shr bank_internal.zbytek2,17 {posun jen o 16 vede pri hodn. 65536 k chybe}

pop ebx
pop eax
end;


Procedure PrepareLine2;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{INPUT:    nothing in registers

 OUTPUT:   ZF: 0 = we are not finished, we have to switch bank and continue
               1 = we are finished, let's do next line

           ECX = number of bytes to copy
           EDI = set to new position after second part of line

 DESTROYS: high word of EBX}
asm
cmp bank_internal.zbytek2,0      {je treba prepnout bank?}
jz @Radka_hotova
    push eax
    Call NavysBank
    pop eax
    mov ecx,bank_internal.zbytek2
    cmp bank_internal.zapis,0
    jz @cteci_rutina
       mov edi,bank_internal.seg_wr
       jmp @spoj

    @cteci_rutina:
       mov edi,bank_internal.seg_rd

    @spoj:
    cmp ecx,0                {zajistime, aby bylo vynulovane ZF}
@Radka_hotova:
end;


Procedure FinishLine;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{INPUT:   nothing in registers
 OUTPUT:  EDI = points on first pixel in next line
          ZF: 0 = we are not finished, let's go on next line
              1 = we are on last line, so we are done}
asm
mov edi,bank_internal.bank_edi
add edi,bank_internal.xxx
dec bank_internal.lines
end;


Procedure Process_HC_copy;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{INPUT:   DS:ESI   position in sprite bitmap
          ES:EDI   position in screen (EDI has cleared higher word)
          ECX      how many bytes to copy

 OUTPUT:  DS:ESI and ES:EDI moved into new position
          ECX = 0

 DESTROYS:AX
}
asm
@cykl:
mov ax,ds:[esi]
cmp ax,bank_internal.hc
jz @preskoc
mov es:[edi],ax
@preskoc:
add edi,2
add esi,2
sub ecx,2
jnz @cykl
end;


Procedure Process_FN_copy;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{INPUT:   DS:ESI   position in sprite bitmap
          ES:EDI   position in screen (EDI has cleared higher word)
          AX       color which to paint
          ECX      how many bytes to copy

 OUTPUT:  DS:ESI and ES:EDI moved into new position
          ECX = 0
}
asm
@cykl:
cmp word ptr [esi],0
jz @preskoc
mov es:[edi],ax
@preskoc:
add edi,2
add esi,2
sub ecx,2
jnz @cykl
end;


Procedure RLE_Copy;assembler;{$IFDEF NEWFPC}nostackframe;{$ENDIF}
{INPUT:   DS:ESI   position in sprite bitmap
          DS:EBX   position in RLE map
          ES:EDI   position in screen (EDI has cleared higher word)

          ECX      starting value of ECX
                   (if ECX=0 read new ECX value)
          EDX      how many pixels can be copied if ENDLINE is not reached

 OUTPUT:  DS:ESI and DS:EBX and ES:EDI moved into new position
          EAX      number of not drawn pixels due a bank switch
          ZF       ZF=1 ENDLINE was reached
                   ZF=0 stopped because all EDX pixels was processed

 DESTROYS: ECX,EDX
}

asm
cmp ecx,0                {mam prednactenou hodnotu ECX?}
jnz @RLE_clip_now_ok    {jestli ano, tak nenacitej novou a hned analyzuj}

@Pokracuj_v_RLE_radce:
movsx ecx,byte ds:[ebx]
    inc ebx

@RLE_CLIP_NOW_OK:
    cmp ecx,0
    jz @TOTAL_END        {ECX=0? Skoc na konec radku}
    jg @RLE_CLIP_MOVE           {ECX>0? Skoc na presun}

    @RLE_CLIP_SKIP:             {ECX<0, tzn. preskocime -ECX pixelu}
    neg ecx
    sub edx,ecx
    sbb eax,eax
    and eax,edx
    add ecx,eax

    add esi,ecx
    add edi,ecx
    add esi,ecx
    add edi,ecx


    neg eax
    cmp edx,0
    jle @Temporary_END
    jmp @Pokracuj_v_RLE_radce

    @RLE_CLIP_MOVE:
    sub edx,ecx
    sbb eax,eax
    and eax,edx
    add ecx,eax

    shr ecx,1;rep movsd;adc ecx,ecx;rep movsw  {fast 32bit write}

    cmp edx,0
    jle @Temporary_END
    jmp @Pokracuj_v_RLE_radce

@Temporary_END:
neg eax     {v EAX bude pocet nezpracovanych pixelu z duvodu zalomeni banku}
cmp ebx,0   {EBX nemuze byt 0, takze zarucene dosahnu vynulovani ZF}
@Total_END: {pokud smeroval skok primo sem, tak plati ze ZF=1}
end;



Procedure BankBar(var dest:virtualwindow;x1,y1,x2,y2:longint;c:word);assembler;
asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax
mov eax,x1
mov ebx,y1
mov ecx,x2
mov edx,y2

Call BarClipping
jc @Konec

push es
mov ax,[edi+0]
mov es,ax

mov ax,c
shl eax,16
mov ax,c

Call StartPosition_into_EDI

@SCANLINES_LOOP:

Call PrepareLine

sar ecx,2;rep stosd;adc ecx,ecx;rep stosw  {Zacnu radek}

Call PrepareLine2                          {mozna prepnu bank}
jz @preskoc

sar ecx,2;rep stosd;adc ecx,ecx;rep stosw  {a dodelam ho}

@preskoc:

Call FinishLine
JNZ @SCANLINES_LOOP

pop es
@Konec:
mov mouse.busy2,0
end;


Procedure BankBarXOR(var dest:virtualwindow;x1,y1,x2,y2:longint;c:word);assembler;
{Zakladni problem je v tom, ze s videopameti nelze udelat jednoduche XOR,
 protoze mohou byt oddelena cteci a zapisovaci okna. Napred proto nactu vsechny
 pixely najednou do pole ScanLine, provedu s nimi XOR a pak je naraz
 prekopiruju do videopameti.}
asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax
mov eax,x1
mov ebx,y1
mov ecx,x2
mov edx,y2
Call BarClipping
jc @Konec

push es
mov ax,[edi+0]
mov es,ax

mov ax,c
shl eax,16
mov ax,c

Call StartPosition_into_EDI

@SCANLINES_LOOP:
Call Open_read_mode
push edi
lea esi,ScanLine


Call PrepareLine

sar ecx,2
jecxz @M1
pushf
@L1:
mov ebx,es:[edi]
xor ebx,eax
mov ds:[esi],ebx
add edi,4
add esi,4
loop @L1
popf
jnc @S1
@M1:
mov bx,es:[edi]
xor bx,ax
mov ds:[esi],bx
add edi,2
add esi,2
@S1:

Call PrepareLine2                          {mozna prepnu bank}
jz @preskoc

@L2:
mov ebx,es:[edi]
xor ebx,eax
mov ds:[esi],ebx
add edi,4
add esi,4
loop @L2
popf
jnc @S2
@M2:
mov bx,es:[edi]
xor bx,ax
mov ds:[esi],bx
add edi,2
add esi,2
@S2:
@preskoc:

Call Close_read_mode
pop edi
lea esi,ScanLine
Call PrepareLine

sar ecx,2;rep movsd;adc ecx,ecx;rep movsw  {Zacnu radek}

Call PrepareLine2                          {mozna prepnu bank}
jz @preskoc2
sar ecx,2;rep movsd;adc ecx,ecx;rep movsw  {a dodelam ho}
@preskoc2:

Call FinishLine
JNZ @SCANLINES_LOOP

pop es
@Konec:
mov mouse.busy2,0
end;


Function BankGetClippedPixel(var source:virtualwindow;x,y:longint):word;assembler;
{Source muze byt VGA nebo VGB}
asm
mov mouse.busy2,1
mov edi,source
mov eax,[edi+2];mov bank_internal.mem_offset,eax

  Mov eax,ds:[edi+10]
  Cmp x,eax
  Jae @Ende
  Mov eax,ds:[edi+30]
  Cmp y,eax
  Jae @Ende

Call Open_read_mode

Push es
  mov es,[edi+0]
  mov eax,[edi+26]
  mul y
  add eax,x
  add eax,x
  add eax,bank_internal.mem_offset

  movzx edi,ax
  shr eax,16
  imul eax,bank_internal.grann
  cmp eax,bank_internal.bank_rd

  je @nemenbank
  mov edx,eax
  mov bank_internal.bank_rd,edx
  Call bank_internal.Setbank_rd            {zmeni bank}

@nemenbank:

  add edi,bank_internal.seg_rd
  mov ax,es:[edi]
pop es
Call Close_read_mode
@Ende:
mov mouse.busy2,0

end;



Procedure InternalBankSVGA_to_VW(var source,dest:virtualwindow);assembler;
asm
mov mouse.busy2,1
mov edi,source
call SetScrOffset2
call Open_read_mode

push es
mov es,[edi+0]
mov esi,dest
mov esi,[esi+2]

mov edi,bank_internal.firstblockpos
add edi,bank_internal.seg_rd
mov edx,bank_internal.firstbank
mov ecx,bank_internal.firstblocksize

@novy_bank:
call bank_internal.SetBank_rd    {Nastavi bank}
{------------------------------------------------------------------------}

Call Process_read_copy  {ES:EDI = zdroj; DS:ESI = cil; ECX = delka v bajtech}

{------------------------------------------------------------------------}
mov edi,bank_internal.seg_rd   {start, odkud cist}
mov ecx,65536
add edx,bank_internal.grann
cmp edx,bank_internal.bisgm
jb @novy_bank

{Ted jeste posledni blok - ten je kratsi nez bezne bloky}
mov ecx,bank_internal.lastblocksize
je @novy_bank  {porad se vztahuje k poslednimu CMP}

sub edx,bank_internal.grann
mov bank_internal.bank_rd,edx  {zapamatujeme si prave pouzivany bank}
call Close_read_mode
pop es
mov mouse.busy2,0
end;



Procedure InternalBankSVGA_to_VW_and_ClrScr(var source,dest:virtualwindow;c:word);assembler;
asm
mov mouse.busy2,1
mov edi,source
call SetScrOffset2

push es
mov es,[edi+0]
mov ebx,dest
mov ebx,[ebx+2]

mov edi,bank_internal.firstblockpos
mov esi,edi
add edi,bank_internal.seg_rd
add esi,bank_internal.seg_wr
mov edx,bank_internal.firstbank
mov ecx,bank_internal.firstblocksize

mov ax,c
shl eax,16
mov ax,c

@novy_bank:
push eax
push ebx
call Set_Bank_rdwr    {Nastavi cteci i zapisovy bank}
pop ebx
pop eax
{------------------------------------------------------------------------}

mov ax,c
Call Process_read_copy_and_clr
{ES:EDI = SVGA/cteni
 ES:ESI = SVGA/zapis
 DS:EBX = cil
 EAX = barva rozepsana do 32-bitu (vzdy stejny horni a dolni word)
 ECX = delka v bajtech}
{------------------------------------------------------------------------}
mov edi,bank_internal.seg_rd   {start, odkud cist}
mov esi,bank_internal.seg_wr   {start, odkud zapisovat}
mov ecx,65536
add edx,bank_internal.grann
cmp edx,bank_internal.bisgm
jb @novy_bank

{Ted jeste posledni blok - ten je kratsi nez bezne bloky}
mov ecx,bank_internal.lastblocksize
je @novy_bank  {porad se vztahuje k poslednimu CMP}

sub edx,bank_internal.grann
mov bank_internal.bank_rd,edx  {zapamatujeme si prave pouzivany bank - cteci}
mov bank_internal.bank_wr,edx  {zapamatujeme si prave pouzivany bank - zapis}

pop es
mov mouse.busy2,0
end;




Procedure BankPutClippedPixel(var dest:virtualwindow;x,y:longint;c:word);assembler;
{Dest muze byt VGA nebo VGB}
asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax

  Mov eax,ds:[edi+10]        {breite}
  Cmp x,eax
  Jae @Ende
  Mov eax,ds:[edi+30]        {hoehe}
  Cmp y,eax
  Jae @Ende

Push es
  mov es,[edi+0]
  mov eax,[edi+26]           {bytebreite}
  mul y
  add eax,x
  add eax,x
  add eax,bank_internal.mem_offset

  movzx edi,ax
  shr eax,16
  imul eax,bank_internal.grann
  cmp eax,bank_internal.bank_wr

  je @nemenbank
  mov edx,eax
  mov bank_internal.bank_wr,edx
  Call bank_internal.Setbank_wr            {zmeni bank}

@nemenbank:

  add edi,bank_internal.seg_wr

  mov ax,c
  mov es:[edi],ax
pop es
@Ende:
mov mouse.busy2,0
end;


Procedure BankLineVert(var dest:virtualwindow;x,y1,y2:LongInt;color:word);assembler;
{Dest muze byt VGA nebo VGB}
asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax

  mov eax,y1
  mov ecx,y2
  mov ebx,x
Call VertLineClipping
jc @Ende

push es
mov es,[edi+0]

mov ebx,ds:[edi+26]
mov bank_internal.xxx,ebx
   mul bank_internal.xxx         {Y1 := Y1*dest.ByteBreite}
   add eax,x
   add eax,x
   add eax,bank_internal.mem_offset
   mov esi,eax

@HL:
   movzx edi,si
   mov edx,esi
   shr edx,16
   imul edx,bank_internal.grann
   cmp edx,bank_internal.bank_wr            {je to jiny bank nez prave pouzivany?}

   jz @nemenbank1
      mov bank_internal.bank_wr,edx         {jestli ano, tak musime prepnout}
      Call bank_internal.Setbank_wr         {znici AX a BX}

   @nemenbank1:
   add edi,bank_internal.seg_wr
   mov ax,color
   mov es:[edi],ax

   add esi,bank_internal.xxx

   LOOP @HL
  pop es
@ende:
mov mouse.busy2,0
end;


Procedure BankLineVertXOR(var dest:virtualwindow;x,y1,y2:LongInt;color:word);assembler;
{Zakladni problem je v tom, ze s videopameti nelze udelat jednoduche XOR,
 protoze mohou byt oddelena cteci a zapisovaci okna. Napred proto nactu vsechny
 pixely najednou do pole ScanLine, provedu s nimi XOR a pak je naraz
 prekopiruju do videopameti.}

asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax
  mov eax,y1
  mov ecx,y2
  mov ebx,x
Call VertLineClipping
jc @Ende

push es
mov es,[edi+0]
mov ebx,ds:[edi+26]
mov bank_internal.xxx,ebx
   mul bank_internal.xxx         {Y1 := Y1*dest.ByteBreite}
   add eax,x
   add eax,x
   add eax,bank_internal.mem_offset
   mov esi,eax

push esi
push ecx

Call Open_Read_Mode
mov bank_internal.lines,ecx


lea ecx,Scanline

@HL1:
   movzx edi,si
   mov edx,esi
   shr edx,16
   imul edx,bank_internal.grann
   cmp edx,bank_internal.bank_rd            {je to jiny bank nez prave pouzivany?}

   jz @nemenbank1
      mov bank_internal.bank_rd,edx         {jestli ano, tak musime prepnout}
      Call bank_internal.Setbank_rd         {znici AX a BX}

   @nemenbank1:

   add edi,bank_internal.seg_rd
   mov ax,es:[edi]
   xor ax,color
   mov ds:[ecx],ax
   add esi,bank_internal.xxx
   add ecx,2
   dec bank_internal.lines
   jnz @HL1

pop ecx
mov bank_internal.lines,ecx
pop esi



Call Close_Read_Mode
lea ecx,Scanline

@HL2:
   movzx edi,si
   mov edx,esi
   shr edx,16
   imul edx,bank_internal.grann
   cmp edx,bank_internal.bank_wr            {je to jiny bank nez prave pouzivany?}

   jz @nemenbank2
      mov bank_internal.bank_wr,edx         {jestli ano, tak musime prepnout}
      Call bank_internal.Setbank_wr         {znici AX a BX}

   @nemenbank2:

   add edi,bank_internal.seg_wr
   mov ax,ds:[ecx]
   mov es:[edi],ax

   add esi,bank_internal.xxx
   add ecx,2
   dec bank_internal.lines
   jnz @HL2

  pop es
@ende:
mov mouse.busy2,0
end;



PROCEDURE BankLineVertTexture(var dest:virtualwindow;x,y1,y2:LongInt;dummy:Word);assembler;
var tc:word;
asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax
  mov eax,y1
  mov ecx,y2
  mov ebx,x
Call VertLineClipping
jc @Ende

Call TextureToScanline_vert

{v EAX je porad Y1}

mov edi,dest

push es
mov es,[edi+0]

mov ebx,[edi+26]
mov bank_internal.xxx,ebx
mul ebx                       {Y1 := Y1*dest.ByteBreite}
add eax,x
add eax,x
add eax,bank_internal.mem_offset
mov esi,eax

mov bank_internal.lines,ecx

mov ecx,Texture
mov dx,ds:[ecx+18]         {TransCol}
mov tc,dx
test byte ds:[ecx+20],4    {2.bit pole Flags}

lea ecx,ScanLine      {vlezu na zacatek pripraveneho pomocneho bufferu}
                      {(LEA nemeni priznaky)}
jnz @transparence

@HL1:
   movzx edi,si
   mov edx,esi
   shr edx,16
   imul edx,bank_internal.grann
   cmp edx,bank_internal.bank_wr            {je to jiny bank nez prave pouzivany?}

   jz @nemenbank1
      mov bank_internal.bank_wr,edx         {jestli ano, tak musime prepnout}
      Call bank_internal.Setbank_wr         {znici AX a BX}

   @nemenbank1:
   add edi,bank_internal.seg_wr
   {****}
   mov ax,ds:[ecx]
   mov es:[edi],ax
   {****}
   add esi,bank_internal.xxx
   add ecx,2
   dec dword bank_internal.lines
   jnz @HL1
  pop es
  jmp @ende

@Transparence:
@HL2:
   movzx edi,si
   mov edx,esi
   shr edx,16
   imul edx,bank_internal.grann
   cmp edx,bank_internal.bank_wr            {je to jiny bank nez prave pouzivany?}

   jz @nemenbank2
      mov bank_internal.bank_wr,edx         {jestli ano, tak musime prepnout}
      Call bank_internal.Setbank_wr         {znici AX a BX}

   @nemenbank2:
   add edi,bank_internal.seg_wr
   {****}
   mov ax,ds:[ecx]
   cmp ax,tc
   jz @skip2
   mov es:[edi],ax
   @skip2:
   {****}
   add ecx,2
   add esi,bank_internal.xxx
   dec dword bank_internal.lines
   jnz @HL2
  pop es

@ende:
mov mouse.busy2,0
end;


PROCEDURE BankLineVertMasked(var dest:virtualwindow;x,y1,y2:LongInt;color:Word);assembler;
var tc:word;
asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax
  mov eax,y1
  mov ecx,y2
  mov ebx,x
Call VertLineClipping
jc @Ende

Call TextureToScanline_vert

{v EAX je porad Y1}

mov edi,dest

push es
mov es,[edi+0]

mov ebx,[edi+26]
mov bank_internal.xxx,ebx
mul ebx                       {Y1 := Y1*dest.ByteBreite}
add eax,x
add eax,x
add eax,bank_internal.mem_offset
mov esi,eax

mov bank_internal.lines,ecx

mov ecx,Texture
mov dx,ds:[ecx+18]         {TransCol}
mov tc,dx
test byte ds:[ecx+20],4    {2.bit pole Flags}

lea ecx,ScanLine      {vlezu na zacatek pripraveneho pomocneho bufferu}
                      {(LEA nemeni priznaky)}
jnz @transparence


@HL1:
 movzx edi,si
   mov edx,esi
   shr edx,16
   imul edx,bank_internal.grann
   cmp edx,bank_internal.bank_wr            {je to jiny bank nez prave pouzivany?}

   jz @nemenbank1
      mov bank_internal.bank_wr,edx         {jestli ano, tak musime prepnout}
      Call bank_internal.Setbank_wr         {znici AX a BX}

   @nemenbank1:
   add edi,bank_internal.seg_wr
   {****}
   mov ax,ds:[ecx]
   cmp ax,tc
   jnz @zadana_barva1
   mov ax,color
   @zadana_barva1:
   mov es:[edi],ax
   {****}
   add ecx,2
   add esi,bank_internal.xxx
   dec dword bank_internal.lines
   jnz @HL1
  pop es
  jmp @ende


@Transparence:
@HL2:
   movzx edi,si
   mov edx,esi
   shr edx,16
   imul edx,bank_internal.grann
   cmp edx,bank_internal.bank_wr            {je to jiny bank nez prave pouzivany?}

   jz @nemenbank2
      mov bank_internal.bank_wr,edx         {jestli ano, tak musime prepnout}
      Call bank_internal.Setbank_wr         {znici AX a BX}

   @nemenbank2:
   add edi,bank_internal.seg_wr
   {****}
   mov ax,ds:[ecx]
   cmp ax,tc
   jz @skip
   mov ax,color
   mov es:[edi],ax
   @skip:
   {****}
   add ecx,2
   add esi,bank_internal.xxx
   dec dword bank_internal.lines
   jnz @HL2
  pop es
@ende:
mov mouse.busy2,1
end;


PROCEDURE BankLineHorz(var dest:virtualwindow;x1,x2,y:LongInt;Color:Word);assembler;
asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax
  mov eax,x1
  mov ecx,x2
  mov ebx,y
Call HorizLineClipping
jc @Ende

push es
Mov es ,ds:[edi   ]

   Mov edi,ds:[edi+26]
   IMul edi,y
   shl eax,1
   add edi,eax

   shl ecx,1           {ECX na bajty, aby tomu rozumela proc. PrepareLine}
   mov bank_internal.bank_ecx,ecx    {ECX do bank_internal.ECX, aby tomu rozumela proc. PrepareLine}

   {mam startovni pozici}
   Call PrepareLine

   mov ax,Color
   shl eax,16
   mov ax,color
   push eax
   sar ecx,2;rep stosd;adc ecx,ecx;rep stosw  {fast 32bit write}

   Call PrepareLine2
   pop eax {nemeni priznaky}
   jz @preskoc {odvolava se na vysledek "call PrepareLine2"}

   sar ecx,2;rep stosd;adc ecx,ecx;rep stosw  {fast 32bit write}

   @preskoc:
 Pop es
 @ENDE:
mov mouse.busy2,0
end;


PROCEDURE BankLineHorzXOR(var dest:virtualwindow;x1,x2,y:LongInt;Color:Word);assembler;
{Zakladni problem je v tom, ze s videopameti nelze udelat jednoduche XOR,
 protoze mohou byt oddelena cteci a zapisovaci okna. Napred proto nactu vsechny
 pixely najednou do pole ScanLine, provedu s nimi XOR a pak je naraz
 prekopiruju do videopameti.}
asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax
  mov eax,x1
  mov ecx,x2
  mov ebx,y
Call HorizLineClipping
jc @Ende

push es

   Mov es ,ds:[edi   ]
   Mov edi,ds:[edi+26]
   IMul edi,y
   shl eax,1
   add edi,eax

   shl ecx,1           {ECX na bajty, aby tomu rozumela proc. PrepareLine}
   mov bank_internal.bank_ecx,ecx    {ECX do bank_internal.ECX, aby tomu rozumela proc. PrepareLine}

   {mam startovni pozici}
   push edi
   push ecx
   lea esi,ScanLine
   Call Open_Read_Mode
   Call PrepareLine
   mov ax,color
   shl eax,16
   mov ax,color

   sar ecx,2
   jecxz @M1
   pushf
   @L1:
   mov ebx,es:[edi]
   xor ebx,eax
   mov ds:[esi],ebx
   add edi,4
   add esi,4
   loop @L1
   popf
   jnc @S1
   @M1:
   mov bx,es:[edi]
   xor bx,ax
   mov ds:[esi],bx
   add esi,2
   add edi,2
   @S1:


   Call PrepareLine2
   jz @preskoc {odvolava se na vysledek "call PrepareLine2"}

   sar ecx,2
   jecxz @M2
   pushf
   @L2:
   mov ebx,es:[edi]
   xor ebx,eax
   mov ds:[esi],ebx
   add edi,4
   add esi,4
   loop @L2
   popf
   jnc @S2
   @M2:
   mov bx,es:[edi]
   xor bx,ax
   mov ds:[esi],bx
   @S2:
   @preskoc:

Call Close_Read_Mode
pop ecx
pop edi
mov bank_internal.bank_ecx,ecx
lea esi,ScanLine
Call PrepareLine
sar ecx,2;rep movsd;adc ecx,ecx;rep movsw  {fast 32bit write}
Call PrepareLine2
   jz @preskoc2 {odvolava se na vysledek "call PrepareLine2"}
sar ecx,2;rep movsd;adc ecx,ecx;rep movsw  {fast 32bit write}
@preskoc2:

 Pop es
 @ENDE:
mov mouse.busy2,0
end;



PROCEDURE BankLineHorzTexture(var dest:virtualwindow;x1,x2,y:LongInt;Dummy:Word);assembler;
var mx:word;
{Expects some PVirtualwindow in "Texture" variable}

Asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax
  mov eax,x1
  mov ecx,x2
  mov ebx,y
Call HorizLineClipping
jc @Ende
Call TextureToScanline_horz

mov esi,Texture
test byte ds:[esi+20],4    {2.bit pole Flags}
jnz @transparence

lea esi,ScanLine      {vlezu na zacatek pripraveneho pomocneho bufferu}

push es
   lea edi,vga
   Mov es ,ds:[edi   ]
   Mov edi,ds:[edi+26]
   IMul edi,y
   add edi,eax
   add edi,eax
   shl ecx,1           {ECX na bajty, aby tomu rozumela proc. PrepareLine}
   mov bank_internal.bank_ecx,ecx    {ECX do bank_internal.ECX, aby tomu rozumela proc. PrepareLine}

Call PrepareLine
sar ecx,2;rep movsd;adc ecx,ecx;rep movsw

Call PrepareLine2
jz @preskoc
   sar ecx,2;rep movsd;adc ecx,ecx;rep movsw  {fast 32bit write}
@preskoc:
Pop es
jmp @ende


@transparence:
mov dx,ds:[esi+18]  {TransCol}
mov mx,dx
lea esi,ScanLine      {vlezu na zacatek pripraveneho pomocneho bufferu}
push es
   lea edi,vga
   Mov es ,ds:[edi   ]
   Mov edi,ds:[edi+26]
   IMul edi,y
   add edi,eax
   add edi,eax
   shl ecx,1           {ECX na bajty, aby tomu rozumela proc. PrepareLine}
   mov bank_internal.bank_ecx,ecx    {ECX do bank_internal.ECX, aby tomu rozumela proc. PrepareLine}

Call PrepareLine
@sm1:
mov ax,ds:[esi]
cmp ax,mx
jz @hop1
mov es:[edi],ax
@hop1:
add esi,2
add edi,2
sub ecx,2
jnz @sm1

Call PrepareLine2
jz @hotovo
@sm2:
mov ax,ds:[esi]
cmp ax,mx
jz @hop2
mov es:[edi],ax
@hop2:
add esi,2
add edi,2
sub ecx,2
jnz @sm2
@hotovo:
Pop es

@Ende:
mov mouse.busy2,0
end;



PROCEDURE BankLineHorzMasked(var dest:virtualwindow;x1,x2,y:LongInt;Color:Word);assembler;
var mx,tc,cc:word;
{Expects some PVirtualwindow in "Texture" variable}

Asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax
  mov eax,x1
  mov ecx,x2
  mov ebx,y
Call HorizLineClipping
jc @Ende
Call TextureToScanline_horz

push es
   lea edi,vga
   Mov es ,ds:[edi   ]
   Mov edi,ds:[edi+26]
   IMul edi,y
   add edi,eax
   add edi,eax
   shl ecx,1           {ECX na bajty, aby tomu rozumela proc. PrepareLine}
   mov bank_internal.bank_ecx,ecx    {ECX do bank_internal.ECX, aby tomu rozumela proc. PrepareLine}

mov esi,Texture
mov dx,ds:[esi+18]  {TransCol}
mov tc,dx
mov bx,color
test byte ds:[esi+20],4    {2.bit pole Flags}
jnz @transparence


lea esi,ScanLine      {vlezu na zacatek pripraveneho pomocneho bufferu}
Call PrepareLine
@smycka1:
mov ax,ds:[esi]
cmp ax,tc
jnz @zadana_barva1
mov ax,bx
@zadana_barva1:
mov es:[edi],ax
add esi,2
add edi,2
sub ecx,2
jnz @smycka1
        Call PrepareLine2
        jz @Hotovo
        @smycka2:
        mov ax,ds:[esi]
        cmp ax,tc
        jnz @zadana_barva2
        mov ax,bx
        @zadana_barva2:
        mov es:[edi],ax
        add esi,2
        add edi,2
        sub ecx,2
        jnz @smycka2
        jmp @hotovo

@transparence:
lea esi,ScanLine      {vlezu na zacatek pripraveneho pomocneho bufferu}
Call PrepareLine
@smycka3:
mov ax,ds:[esi]
cmp ax,tc
jz @zadana_barva3
mov es:[edi],bx
@zadana_barva3:
add esi,2
add edi,2
sub ecx,2
jnz @smycka3
        Call PrepareLine2
        jz @Hotovo
        @smycka4:
        mov ax,ds:[esi]
        cmp ax,tc
        jz @zadana_barva4
        mov es:[edi],bx
        @zadana_barva4:
        add esi,2
        add edi,2
        sub ecx,2
        jnz @smycka4

@hotovo:
Pop es
@Ende:
mov mouse.busy2,0
end;



PROCEDURE BankPutClippedHCSprite(var Dest,Sprite:VirtualWindow;x,y:LongInt;HideColor:Word);assembler;
var sprtstrt,skiplin,startecx:longint;
asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax
mov esi,sprite
mov eax,x
mov ebx,y
call SpriteClipping
jc @Konec

push es
pushf      {uklidim priznak ZF ze SpriteClipping}
mov es,[edi+0]
test byte [esi+20],2    {je pripravena RLE mapa?}
jnz @RLE_mapa

popf
Call StartPosition_into_EDI
Call StartPosition_into_ESI

mov ax,Hidecolor
mov bank_internal.hc,ax

@SCANLINES_LOOP:

Call PrepareLine
push esi
Call Process_HC_copy
Call PrepareLine2
jz @preskoc
   Call Process_HC_copy
@preskoc:

pop esi
add esi,bank_internal.zzz
Call FinishLine

JNZ @SCANLINES_LOOP
jmp @Obnov_ES

{============================ Prubeh s RLE mapou ============================}
@RLE_mapa:
push dword [esi+34] {ulozime si odkaz na RLE mapu}
mov sprtstrt,eax    {uschovam si hodnotu posunu od zacatku spritu do EAX}
Call StartPosition_into_EDI
Call StartPosition_into_ESI
pop ebx             {obnovim odkaz na RLE mapu}
mov skiplin,0
popf
jz @RLE_SCANLINES_LOOP
{----------------------------------------------------------------------------}
@RLE_clipping:          {Pokud byl detekovan clipping, tak prepocty}
cmp sprtstrt,0          {sice byl clipping, ale bez posunu startovaci pozice?}
jz @RLE_SCANLINES_LOOP  {v tom pripade je to jako kdyby clipping nebyl}

mov eax,sprtstrt
xor edx,edx          {Delenec je v EDX:EAX, proto musim nulovat EDX}
div bank_internal.zzz         {podil v EAX, zbytek v EDX}
shl eax,2            {EAX:=EAX*4}
add ebx,eax          {EBX nazmeruju na prvni zpracovavanou radku}
mov skiplin,edx      {v SKIPLIN mame pocet vynechanych bajtu v zac.radku}
shr skiplin,1        {prevedeme na pocet pixelu}
mov edx,ecx          {sirka viditelneho useku (v bajtech) do EDX}
shr edx,1            {prepocitam do poctu pixelu}

{----------------------------------------------------------------------------}
@RLE_SCANLINES_LOOP:
push esi
push ebx               {ulozim seznam na radky}
mov ebx,ds:[ebx]       {odkaz na n-ty radek RLE mapy}
mov startecx,0

cmp skiplin,0
jz @No_skiplin

mov eax,skiplin
{----------------------------------------------------------------------------}
@RLE_CLIP_FIRSTSKIP:
    movsx ecx,byte ds:[ebx]
    inc ebx
    cmp ecx,0
    jz @RLE_TOTALEND_LINE  {ECX=0? Skoc na konec radku}
    jg @RLE_CLIP_SK_POZ

@RLE_CLIP_SK_NEG:  {Kdyz je ECX<0}
    add eax,ecx
    cmp eax,0
    jz @No_skiplin
    jl @RLE_PODTECENI1
    jmp @RLE_CLIP_FIRSTSKIP

@RLE_PODTECENI1:
    mov startecx,eax
    jmp @No_skiplin

@RLE_CLIP_SK_POZ:  {Kdyz je ECX>0}
    sub eax,ecx
    cmp eax,0
    jz @No_skiplin
    jl @RLE_PODTECENI2
    jmp @RLE_CLIP_FIRSTSKIP

@RLE_PODTECENI2:
    neg eax
    mov startecx,eax
    jmp @No_skiplin

{----------------------------------------------------------------------------}
@No_skiplin: {neni potreba odpocitavat prostor za levym okrajem}
    push ebx               {uschovam, protoze bude zniceno v PrepareLine}
    Call PrepareLine     {nastavim banky}
    mov edx,ecx          {do EDX dam pocet bajtu ke zprac. pred zmenou banku}
    shr edx,1            {zmenim to na pocet pixelu}
    pop ebx                {obnova ebx}

{-----------------------------------------------------}
    mov ecx,startecx      {prvotni nastaveni ECX (0=nacti novy bajt)}
    Call RLE_copy
    jz @RLE_TOTALEND_LINE {Pokud bylo dosazeno znacky ENDLINE tak dal nepokr.}

    push ebx
    Call PrepareLine2
    pop ebx
    jz @RLE_TOTALEND_LINE
    mov edx,ecx          {do EDX dam pocet bajtu ke zprac. po zmene banku}
    shr edx,1            {zmenim to na pocet pixelu}
    mov ecx,eax          {do ECX vlozim minule nezpracovane pixely kvuli}
    Call RLE_copy            {zalomeni banku}

   @RLE_TOTALEND_LINE:

    pop ebx
    add ebx,4
    pop esi
    add esi,bank_internal.zzz

  Call FinishLine
  JNZ @RLE_SCANLINES_LOOP
{----------------------------------------------------------------------------}
{----------------------------------------------------------------------------}
@Obnov_ES:
pop es
@Konec:
mov mouse.busy2,0
End;


PROCEDURE BankPutClippedSprite(var Dest,Sprite:VirtualWindow;x,y:LongInt);assembler;
asm
mov mouse.busy2,1
mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax
mov esi,sprite
mov eax,x
mov ebx,y
call SpriteClipping
jc @Konec

push es
mov es,[edi+0]

Call StartPosition_into_EDI
Call StartPosition_into_ESI

@SCANLINES_LOOP:

Call PrepareLine
push esi
sar ecx,2;rep movsd;adc ecx,ecx;rep movsw  {fast 32bit write}


Call PrepareLine2
jz @preskoc
sar ecx,2;rep movsd;adc ecx,ecx;rep movsw  {fast 32bit write}
@preskoc:

pop esi
add esi,bank_internal.zzz
Call FinishLine

JNZ @SCANLINES_LOOP

pop es
@Konec:
mov mouse.busy2,0
End;


PROCEDURE BankGetClippedSprite(var Source,sprite:virtualwindow;x,y:LongInt);assembler;
asm
mov mouse.busy2,1
mov edi,source
mov eax,[edi+2];mov bank_internal.mem_offset,eax
mov esi,sprite
mov eax,x
mov ebx,y
call SpriteClipping
jc @Konec

push es
mov es,[edi+0]

Call StartPosition_into_EDI
Call StartPosition_into_ESI

Call Open_read_mode

@SCANLINES_LOOP:

Call PrepareLine
push esi
Call Process_read_copy
Call PrepareLine2
jz @preskoc
   Call Process_read_copy
@preskoc:

pop esi
add esi,bank_internal.zzz
Call FinishLine

JNZ @SCANLINES_LOOP


Call Close_read_mode
pop es
@Konec:
mov mouse.busy2,0
End;



{*********************************************************************}

Function BankPutChar_FN(var dest:virtualwindow;p:pointer;x,y,xd,yd:longint;charbytes:byte;c:word):byte;assembler;
{ For unit FNfont2 }
var tst:longint;
asm

cmp p,0
jz @Konec

mov tst,0


mov mouse.busy2,1
lea esi,fontvw        {nacetl jsem si renderovaci policko pro znaky}

mov edi,dest
mov eax,[edi+2];mov bank_internal.mem_offset,eax

mov eax,xd
mov ebx,yd
mov ecx,eax
shl ecx,1

mov [esi+10],eax  {breite}
mov [esi+30],ebx  {hoehe}
mov [esi+26],ecx  {bytebreite}


mov eax,x
mov ebx,y
call FontClipping
jc @Konec

cmp p,0      {bitmapa je NIL?}
je @Konec    {v tom pripade mame poreseny clipping, ale vykreslovat nebudeme}

{
cmp x,475
jnz @dalee
cmp y,396
jnz @dalee
mov tst,1
@dalee:
}

{--cmp neco;jz @rozpakovano}

push edi          {schovam EDI, protoze ji prepisu}
push esi
push ecx
push edx
mov edi,[esi+2]   {bitmapu rozepisu do 16-bitove pixmapy}
mov esi,p         {vezmu bitmapu}
movzx ecx,charbytes

call BitmapaNaPixmapu

pop edx
pop ecx
pop esi
pop edi


@rozpakovano:

push es
mov es,[edi+0]

Call StartPosition_into_EDI
Call StartPosition_into_ESI

mov ax,c

@SCANLINES_LOOP:

cmp tst,1
jnz @OK2
cmp bank_internal.lines,3
jnz @OK2
nop
@OK2:


Call PrepareLine
push esi
Call Process_FN_copy
Call PrepareLine2
jz @preskoc
   Call Process_FN_copy
@preskoc:

pop esi
add esi,bank_internal.zzz
Call FinishLine

JNZ @SCANLINES_LOOP

pop es
@Konec:
mov al,Font_horiz_clip
mov mouse.busy2,0
end;


Procedure BankClr(var Dest:virtualwindow;Color:Word);
begin
if dest.bytebreite=dest.breite*2
   then InternalBankClr(Dest,Color)
   else BankBar(dest,0,0,dest.breite-1,dest.hoehe-1,color);
end;


Procedure BankFlip_SVGA(var source,dest:virtualwindow);
begin
if dest.bytebreite=dest.breite*2
   then InternalBankFlip_SVGA(source,dest)
   else BankPutClippedSprite(dest,source,0,0);
end;


Procedure BankFlip_SVGA_and_clrscr(var source,dest:virtualwindow;c:word);
begin
if dest.bytebreite=dest.breite*2
   then InternalBankFlip_SVGA_and_clrscr(source,dest,c)
   else begin
   BankPutClippedSprite(dest,source,0,0);
   Clr(source,c);
   end;
end;


Procedure BankSVGA_to_VW(var source,dest:virtualwindow);
begin
if source.bytebreite=source.breite*2
   then InternalBankSVGA_to_VW(source,dest)
   else BankGetClippedSprite(source,dest,0,0);
end;


Procedure BankSVGA_to_VW_and_ClrScr(var source,dest:virtualwindow;c:word);
begin
if source.bytebreite=source.breite*2
   then InternalBankSVGA_to_VW_and_ClrScr(source,dest,c)
   else begin
   BankGetClippedSprite(source,dest,0,0);
   BankBar(source,0,0,dest.breite-1,dest.hoehe-1,c);
   end;
end;



PROCEDURE PutPixelBA(var Dest:VirtualWindow;x,y:LongInt;Color:Word);
begin
if dest.segment=dosmemselector
   then BankPutClippedPixel(dest,x,y,color)
   else LFBPutPixel(dest,x,y,color);
end;

Function  GetPixelBA(var source:virtualwindow;x,y:LongInt):word;
begin
if source.segment=dosmemselector
   then Exit(BankGetClippedPixel(source,x,y))
   else Exit(LFBGetPixel(source,x,y));
end;

PROCEDURE PutClippedPixelBA(var Dest :VirtualWindow;x,y:LongInt;Color:Word);
begin
if dest.segment=dosmemselector
   then BankPutClippedPixel(dest,x,y,color)
   else PutClippedLFBPixel(dest,x,y,color);
end;

FUNCTION GetClippedPixelBA(var source:virtualwindow;x,y:LongInt):Word;
begin
if source.segment=dosmemselector
   then Exit(BankGetClippedPixel(source,x,y))
   else Exit(GetClippedLFBPixel(source,x,y));
end;

PROCEDURE LineHorzBA(var dest:virtualwindow;x1,x2,y:LongInt;Color:Word);
begin
if dest.segment=dosmemselector
   then BankLineHorz(dest,x1,x2,y,color)
   else LFBLineHorz(dest,x1,x2,y,color);
end;


PROCEDURE LineHorzXORba(var dest:virtualwindow;x1,x2,y:LongInt;Color:Word);
begin
if dest.segment=dosmemselector
   then BankLineHorzXOR(dest,x1,x2,y,color)
   else LFBLineHorzXOR(dest,x1,x2,y,color);
end;


Procedure LineHorzTextureBA(var dest:virtualwindow;x1,x2,y:LongInt;Dummy:Word);
begin
if dest.segment=dosmemselector
   then BankLineHorzTexture(dest,x1,x2,y,dummy)
   else LFBLineHorzTexture(dest,x1,x2,y,dummy);
end;


Procedure LineHorzMaskedBA(var dest:virtualwindow;x1,x2,y:LongInt;Color:Word);
begin
if dest.segment=dosmemselector
   then BankLineHorzMasked(dest,x1,x2,y,color)
   else LFBLineHorzMasked(dest,x1,x2,y,color);
end;


PROCEDURE LineVertBA(var dest:virtualwindow;x,y1,y2:LongInt;color:word);
begin
if dest.segment=dosmemselector
   then BankLineVert(dest,x,y1,y2,color)
   else LFBLineVert(dest,x,y1,y2,color);
end;


PROCEDURE LineVertXORba(var dest:virtualwindow;x,y1,y2:LongInt;color:word);
begin
if dest.segment=dosmemselector
   then BankLineVertXOR(dest,x,y1,y2,color)
   else LFBLineVertXOR(dest,x,y1,y2,color);
end;


PROCEDURE LineVertTextureBA(var dest:virtualwindow;x,y1,y2:LongInt;dummy:word);
begin
if dest.segment=dosmemselector
   then BankLineVertTexture(dest,x,y1,y2,dummy)
   else LFBLineVertTexture(dest,x,y1,y2,dummy);
end;


PROCEDURE LineVertMaskedBA(var dest:virtualwindow;x,y1,y2:LongInt;color:word);
begin
if dest.segment=dosmemselector
   then BankLineVertMasked(dest,x,y1,y2,color)
   else LFBLineVertMasked(dest,x,y1,y2,color);
end;


Function PutChar_FNBA(var dest:virtualwindow;p:pointer;x,y,xd,yd:longint;charbytes:byte;c:word):byte;
begin
if dest.segment=dosmemselector
   then PutChar_FNBA:=BankPutChar_FN(dest,p,x,y,xd,yd,charbytes,c)
   else PutChar_FNBA:=LFBPutChar_FN(dest,p,x,y,xd,yd,charbytes,c);
end;

Procedure BarBA(var dest:virtualwindow;x1,y1,x2,y2:LongInt;color:word);
begin
if dest.segment=dosmemselector
   then BankBar(dest,x1,y1,x2,y2,color)
   else LFBBar(dest,x1,y1,x2,y2,color);
end;

Procedure BarXORba(var dest:virtualwindow;x1,y1,x2,y2:LongInt;color:word);
begin
if dest.segment=dosmemselector
   then BankBarXOR(dest,x1,y1,x2,y2,color)
   else LFBBarXOR(dest,x1,y1,x2,y2,color);
end;

