Subversion Repositories Kolibri OS

Rev

Rev 111 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ; @RCHER parser and filter routines
  2. ; Written in pure assembler by Ivushkin Andrey aka Willow
  3.  
  4.   fhs_local   equ 0x04034b50
  5.   fhs_central equ 0x02014b50
  6.   fhs_end     equ 0x06054b50
  7.   fhs_enc     equ 0x08074b50
  8.  
  9. SkipASCIIZ:
  10.     xor  eax,eax
  11.     mov  ecx,255
  12.     mov  edi,esi
  13.     repne scasb
  14.     mov  esi,edi
  15.     ret
  16.  
  17. PrintFilename:
  18.     pusha
  19.     mov  esi,edx
  20.     mov  edi,os_work
  21.     mov  edx,edi
  22.     rep  movsb
  23.     mov  dword[edi],0x00a0d
  24.     call DebugPrint
  25.     popa
  26.     call Add2Fat
  27.     ret
  28.  
  29. Add2Fat:
  30. ; edx - ptr, ecx - len
  31.  
  32.     pusha
  33.     test [Flags],LIST_MODE
  34.     jz   .ex
  35.     mov  ebp,8
  36.     mov  edi,edx
  37.     lea  ebx,[edx+ecx]
  38.     mov  ecx,[lpath_len]
  39.     cmp  ecx,1
  40.     je   .lbl
  41.     mov  esi,[lpath]
  42.     repe cmpsb
  43.     jne  .full
  44.     mov  eax,[lpath_len]
  45.     sub  dword[esp+24],eax;path_len-path
  46.     cmp  edi,ebx
  47.     je   .full
  48.     mov  edx,edi
  49.   .lbl:
  50.     mov  ecx,[esp+24]
  51.     mov  al,'/'
  52.     repne scasb
  53.     mov  eax,[fat_]
  54.     mov  ecx,[esp+24]
  55.     jne  .nofol
  56.     cmp  edi,ebx
  57.     jne  .full
  58.     lea  ecx,[edi-1]
  59.     sub  ecx,edx
  60.     or   byte[eax+11],0x10
  61. ;    sub  edx,ecx
  62.   .nofol:
  63.  
  64.     push [fat_fnum]
  65.     pop  dword[eax+12]
  66.     mov  edi,eax
  67.     mov  esi,edx
  68.   .lp1:
  69.  
  70.     mov  bl,[esi]
  71.     lea  edx,[eax+ebp]
  72.     inc  esi
  73.     cmp  bl,'.'
  74.     jne  .nodot
  75.     lea  edi,[eax+ebp]
  76.     mov  ebp,11
  77.     jmp  .ll
  78.   .nodot:
  79.     cmp  edi,edx
  80.     jae  .ll
  81.     mov  [edi],bl
  82.     inc  edi
  83.   .ll:
  84.     loop .lp1
  85.     mov  ecx,11
  86.     dec  eax
  87.   .lp2:
  88.     cmp  byte[eax+ecx],0
  89.     jne  .no0
  90.     mov  byte[eax+ecx],' '
  91.   .no0:
  92.     loop .lp2
  93.     cmp  eax,child_stack-1
  94.     jae  .full
  95.     add  [fat_],32
  96.   .full:
  97.     inc  [fat_fnum]
  98.   .ex:
  99.     popa
  100.     ret
  101.  
  102. ;path db '/';'fasm/examples/elfexe/'
  103. ;path_len:
  104.  
  105. ; Parse routines:
  106. ;   out: edx= 0 if all ok, 1 - central dir, 2-EOD
  107. ;             50 - encrypted
  108. ;             51 - not deflated
  109. ;             52 - invalid format
  110. ;             53 - dir skipped
  111. ;             1 - encrypted
  112.  
  113. ; ****************************************************
  114. ZipParse:
  115.  
  116.     call ResetFile
  117.   .nxt:
  118.     call ZipCrawl
  119.  
  120.     cmp  edx,3
  121.     je  .ex
  122.     cmp  edx,1
  123.     je   .skipinc
  124. if  IGNORE_DIRS eq 1
  125.     cmp  edx,53
  126.     jne  .skipinc
  127. end if
  128.     inc  [file_count]
  129.   .skipinc:
  130.     cmp  edx,52
  131.     je   .er1
  132.     cmp  edx,50
  133.     jne   .seek
  134.   .er1:
  135.     Msg  edx
  136.     ret
  137.   .seek:
  138.     add  eax,ecx
  139.     mov  ebx,1
  140.     call FileSeek
  141.     jmp  .nxt
  142.   .ex:
  143.     Msg  2
  144.     mov  eax,[file_count]
  145.  if ~ SYS eq win
  146.     dpd  eax
  147.  else
  148.     pusha
  149.     call  int2str
  150.     mov   edx,os_work
  151.         call  DebugPrint
  152.         popa
  153.  end if
  154.     Newline
  155. ;    Dump fat,160,os_work
  156.     ret
  157.  
  158. ZipFindN:
  159. ; ecx - file #
  160.     Msg 33
  161.     or   [Flags],FIND_MODE
  162.     cmp  ecx,[file_count]
  163.     jae  .err
  164.     push ecx
  165.     call ResetFile
  166.   .nxt:
  167.  
  168.     call ZipCrawl
  169.     cmp  edx,51
  170.     je   .ok2
  171.   .noenc:
  172.     test edx,edx
  173.     jnz  .err
  174.   .ok2:
  175.     add  eax,ecx
  176.     cmp  dword[esp],0
  177.     jz   .ok
  178.     dec  dword[esp]
  179.     mov  ebx,1
  180.     call FileSeek
  181.     jmp  .nxt
  182.   .err:
  183.     mov  edx,4
  184.     jmp  .ex
  185.   .ok:
  186.     pop  ecx
  187.     sub  eax,[esi+18]
  188.     add  esi,eax
  189.     mov  edx,5
  190.   .ex:
  191.     and   [Flags],-1-FIND_MODE
  192.     push edx
  193.     Msg  edx
  194.     pop  edx
  195.     ret
  196.  
  197. ZipCrawl:
  198.     mov  edx,52
  199.     cmp  dword[esi],fhs_central
  200.     jne  .noc
  201.     mov  eax,46
  202.     movzx ecx,word[esi+28]
  203.     add  eax,ecx
  204.     movzx ecx,word[esi+30]
  205.     add  eax,ecx
  206.     movzx ecx,word[esi+32]
  207.     mov  edx,1
  208.     ret
  209.   .noc:
  210.     cmp  dword[esi],fhs_end
  211.     jne  .noe
  212.   .edx3:
  213.     Msg 3
  214.     mov  edx,3
  215.     ret
  216.   .noe:
  217.     cmp  dword[esi],fhs_local
  218.     je   .loc
  219.     cmp  dword[esi],fhs_enc
  220.     jne  .err
  221.     mov  eax,16
  222.     xor  ecx,ecx
  223.     mov  edx,1
  224.     ret
  225.   .loc:
  226.     push word[esi+6]
  227.     pop  [gpbf]
  228.     push dword[esi+14]
  229.     pop  [CRC_check]
  230.     push dword[esi+22]
  231.     pop  [unp_size]
  232.     movzx ecx,word[esi+26]
  233.     mov  eax,30
  234.     lea  edx,[esi+eax]
  235.     add  eax,ecx
  236. if  IGNORE_DIRS eq 1
  237.     cmp  byte[edx+ecx-1],'/'
  238.     je   .skipdp
  239. end if
  240.     test [Flags],FIND_MODE
  241.     jnz  .skipdp
  242.     call PrintFilename
  243.   .skipdp:
  244.     movzx ecx,word[esi+28]
  245.     add  eax,[esi+18]
  246.     test [gpbf],1
  247.     jz   .no_enc
  248.     or   [Flags],DECRYPT_MODE  ; encrypted
  249.     mov  edx,51
  250.     jmp  .err
  251.   .no_enc:
  252.     test word[esi+8],7
  253.     rep_err z,50
  254.   .ok:
  255.     xor  edx,edx
  256.   .err:
  257.     ret
  258.  
  259. ; ***********************************************
  260. GzipParse:
  261.     ID1ID2 equ 0x8b1f
  262.     FTEXT equ 1b
  263.     FHCRC equ 10b
  264.     FEXTRA equ 100b
  265.     FNAME equ 1000b
  266.     FCOMMENT equ 10000b
  267.     mov  eax,7
  268.     mov  ebx,2
  269.     call FileSeek
  270.     push dword[esi]
  271.     pop  [CRC_check]
  272.     push dword[esi+4]
  273.     pop  [unp_size]
  274.     call ResetFile
  275.     xor  edx,edx
  276.     cmp  word[esi],ID1ID2
  277.     rep_err e, 52, 15
  278.     cmp  byte[esi+2],8
  279.     rep_err e, 52, 50
  280.     mov  bl,[esi+3]  ; bl - FLG
  281.     add  esi,10 ; esi->extra
  282.     test bl,FEXTRA
  283.     jz   .noextr
  284.     movzx eax,word[esi]
  285.     lea  esi,[esi+eax+2] ; esi->FNAME
  286.   .noextr:
  287.     test bl,FNAME
  288.     jz   .nofname
  289.     mov  edx,esi
  290.     call DebugPrint
  291.     call SkipASCIIZ
  292.     cmp  dword[esi-5],'.tar'
  293.     jne  .nofname
  294.     or   [Flags],TAR_MODE
  295.   .nofname:     ; esi->FCOMMENT
  296.     test bl,FCOMMENT
  297.     jz   .nocomm
  298.     call SkipASCIIZ
  299.   .nocomm:      ; esi->HCRC
  300.     test bl,FHCRC
  301.     jz   .noCRC16
  302.     add  esi,2
  303.   .noCRC16:
  304.     cmp  [unp_size],OUTBUF
  305.     jb   .sizeok2
  306.     Msg  16
  307.     mov  edx,15
  308.     ret
  309.   .sizeok2:
  310.     xor  edx,edx
  311.   .err:
  312.     ret
  313.  
  314. PngParse:
  315.     ID1 equ 0x474e5089
  316.     ID2 equ 0x0a1a0a0d
  317.     FDICT equ 100000b
  318.     InitIDAT equ 2
  319.     mov  [IDATcount],InitIDAT
  320.     call ResetFile
  321.     cmp  dword[esi],ID1
  322.     rep_err e, 52, 18
  323.     cmp  dword[esi+4],ID2
  324.     rep_err e, 52, 18
  325.     add  esi,8
  326.     cmp  dword[esi+4],'IHDR'
  327.     rep_err e,52, 18
  328.     or   [Flags],PNG_MODE
  329.     memcpy_esi PNG_info,13,8
  330.     mov  eax,[PNG_info.Width]
  331.     bswap eax
  332.     mov  [PNG_info.Width],eax
  333.     mov  eax,[PNG_info.Height]
  334.     bswap eax
  335.     mov  ebx,eax
  336.     mov  [PNG_info.Height],eax
  337.     call scanline_calc
  338. ;    dps  'All='
  339.     cmp  [PNG_info.Color_type],3
  340.     jne  .nopal
  341.     shl  eax,3
  342.     inc  eax
  343.   .nopal:
  344.     inc  eax
  345.     imul eax,ebx
  346.     mov  [unp_size],eax
  347. ;    dpd  eax
  348.     add  esi,25
  349.     cmp  byte[esi-5],0
  350.     rep_err e,52,29
  351.   .nxt_sec:
  352.     lodsd
  353.     bswap eax ; eax - section size
  354.     push eax
  355.     lodsd
  356.     mov  edi,Png_ch
  357.     mov  ecx,(E_ch-Png_ch) / 4
  358.     repne scasd
  359.     pop  eax
  360.     mov  ebx,[esi-4]
  361.     mov  edx,os_work
  362.     mov  [edx],ebx
  363.     mov  dword[edx+4],0x0a0d
  364.   .dp:
  365.     sub  edi,Png_ch
  366.     shr  edi,2  ; edi- chunk #
  367.  if SHOW_PNG_SEC eq 1
  368.     call DebugPrint
  369.  end if
  370.     cmp  edi,1
  371.     jne  .noend
  372.     mov  edx,21
  373.     jmp  .err
  374.   .noend:
  375.     cmp  edi,2
  376.     jne  .noplte
  377.     memcpy_esi PNG_info.Palette,eax
  378.     jmp  .noidat
  379.    .noplte:
  380.     cmp  edi,3
  381.     jne  .noidat
  382.     mov  [IDATsize],eax
  383.     cmp  [IDATcount],InitIDAT
  384.     jne  .ex
  385.     mov  [bits],8
  386.   if RBLOCK eq 4
  387.     lodsd
  388.   else
  389.     lodsb
  390.   end if
  391.     call setcurb
  392.     rbits 0,16
  393.     test ah,FDICT
  394.     jz   .ex
  395.     rbits 0,32
  396.     add  [IDATcount],4
  397.     jmp  .ex
  398.    .noidat:
  399.     add  eax,4
  400.     mov  ebx,1
  401.     call FileSeek
  402.     jmp  .nxt_sec
  403.    .ex:
  404.     xor  edx,edx
  405.    .err:
  406.     ret
  407.  
  408. Png_ch:
  409.     dd 'IEND','PLTE','IDAT','????'
  410. E_ch:
  411.  
  412. ZipDecrypt:
  413.     push edi
  414.     mov  ecx,3
  415.     mov  edi,Dheader
  416.     rep  movsd
  417.     pop  edi
  418.     call QueryPwd
  419.     jecxz .ex
  420.     push esi
  421.     mov  [DKeys],  305419896
  422.     mov  [DKeys+4],591751049
  423.     mov  [DKeys+8],878082192
  424.     xor  eax,eax
  425.     mov  esi,Dpassword
  426.   .enc_init:
  427.     lodsb
  428.     call UKeys
  429.     loop .enc_init
  430.     mov  ecx,12
  431.     mov  esi,Dheader
  432.   .dec_header:
  433.     call decrypt_byte
  434.     xor  al,[esi]
  435.     call UKeys
  436.     mov  [esi],al
  437.     inc  esi
  438.     loop .dec_header
  439.     mov  eax,[CRC_check]
  440.     pop  esi
  441.   .ex:
  442.     ret
  443.  
  444. QueryPwd:
  445. ; out: ecx - passwd len
  446. if  SYS eq win
  447.     Msg 32
  448.     invoke ReadConsole,[cons_in],Dpassword,PASSW_LEN,cparam1,NULL
  449.     test eax,eax
  450.     jnz  .inp_ok
  451.     xor  ecx,ecx
  452.     jmp  .ex
  453.   .inp_ok:
  454.     mov  ecx,[cparam1]
  455.     cmp  ecx,PASSW_LEN
  456.     je   .ex
  457.     sub  ecx,2
  458. else
  459. end if
  460.   .ex:
  461.     ret
  462.  
  463. UKeys:
  464. ; in: al - char
  465.     pusha
  466.     mov  edi,134775813
  467.     mov  ebx,DKeys
  468.     mov  esi,os_work
  469.     mov  byte[esi],al
  470.     mov  ecx,1
  471.     push dword[ebx]
  472.     pop  [CRC32]
  473.     call UCRC
  474.     push [CRC32]
  475.     pop  dword[ebx]
  476.     mov  eax,[ebx]
  477.     and  eax,0xff
  478.     add  eax,[ebx+4]
  479.     mul  edi
  480.     inc  eax
  481.     mov  [ebx+4],eax
  482.     shr  eax,24
  483.     mov  byte[esi],al
  484.     push dword[ebx+8]
  485.     pop  [CRC32]
  486.     call UCRC
  487.     push [CRC32]
  488.     pop  dword[ebx+8]
  489.     popa
  490.     ret
  491.  
  492. decrypt_byte:
  493. ; out: al
  494.     push ebx edx
  495.     movzx ebx,word[DKeys+8]
  496.     or   ebx,2
  497.     mov  eax,ebx
  498.     xor  eax,1
  499.     mul  ebx
  500.     shr  eax,8
  501.     pop  edx ebx
  502.     ret
  503.  
  504. setcurb:
  505. ; in: eax
  506.     test [Flags],DECRYPT_MODE
  507.     jz   .noenc
  508.     push eax
  509.     call decrypt_byte
  510.     xor  al,byte[esp]
  511.     add  esp,4
  512.     call UKeys
  513.   .noenc:
  514.     mov  [cur_byte],eax
  515.     ret
  516.  
  517. TarParse:
  518.     mov  esi,output
  519. ;    call ResetFile
  520.   .nxt:
  521.     call TarCrawl
  522. ;    wait
  523.     cmp  edx,3
  524.     je   ZipParse.ex
  525. if  IGNORE_DIRS eq 1
  526.     cmp  edx,53
  527.     jne  .skipinc
  528. end if
  529.     inc  [file_count]
  530.   .skipinc:
  531.     add  eax,ecx
  532. ;    mov  ebx,1
  533.     add  esi,eax
  534. ;    call FileSeek
  535.     jmp  .nxt
  536.  
  537. TarFindN:
  538. ; in:  ecx - file number
  539. ; ecx - file #
  540.     Msg 33
  541.     cmp  ecx,[file_count]
  542.     jae  .err
  543.     push ecx
  544.     mov  esi,output
  545. ;    call ResetFile
  546.   .nxt:
  547.     call TarCrawl
  548. if  IGNORE_DIRS eq 1
  549.     cmp  edx,53
  550.     je  .seek
  551. end if
  552.     test edx,edx
  553.     jnz  .err
  554.     cmp  dword[esp],0
  555.     jz   .ok
  556.     dec  dword[esp]
  557.   .seek:
  558.     add  eax,ecx
  559. ;    mov  ebx,1
  560.     add  esi,eax
  561. ;    call FileSeek
  562.     jmp  .nxt
  563.   .err:
  564.     mov  edx,4
  565.     jmp  .ex
  566.   .ok:
  567.     pop  ecx
  568.     add  esi,eax
  569.     mov  edx,5
  570.   .ex:
  571.     Msg  edx
  572.     ret
  573.  
  574. TarCrawl:
  575.     cmp  byte[esi],0
  576.     jz   ZipCrawl.edx3
  577.     push esi
  578.     mov  ecx,11
  579.     add  esi,0x7c
  580.     call Octal_str
  581.     mov  esi,[esp]
  582.     mov  [outfile.size],eax
  583.     call SkipASCIIZ
  584. if  IGNORE_DIRS eq 1
  585.     cmp  byte[esi-2],'/'
  586.     je   .skipdp
  587. end if
  588.     mov  edx,[esp]
  589.     lea  ecx,[esi-1]
  590.     sub  ecx,edx
  591.     call PrintFilename
  592.   .skipdp:
  593.     mov  ecx,[outfile.size]
  594.     jecxz .zerolen
  595.     shr  ecx,9
  596.     inc  ecx
  597.     shl  ecx,9
  598.   .zerolen:
  599.     mov  eax,512
  600.     pop  esi
  601.     jmp  ZipCrawl.ok
  602.  
  603. Octal_str:
  604. ; in:  esi - ASCIIZ octal string
  605. ;      ecx - its length
  606. ; out: eax - value
  607.     push esi ebx ecx
  608.     xor  ebx,ebx
  609.     xor  eax,eax
  610.   .jec:
  611.     jecxz .zero
  612.     cmp  byte[esi+ecx-1],' '
  613.     jne  .lp
  614.     dec  ecx
  615.     jmp  .jec
  616.   .lp:
  617.     lodsb
  618.     shl  ebx,3
  619.     cmp  eax,' '
  620.     je   .space
  621.     lea  ebx,[ebx+eax-'0']
  622.   .space:
  623.     loop .lp
  624.     mov  eax,ebx
  625.   .zero:
  626.     pop  ecx ebx esi
  627.     ret
  628.  
  629. TRAILING_BUF equ 2048
  630. SfxParse:
  631.     call ResetFile
  632.     cmp  word[esi],'MZ'
  633.     rep_err e, 34
  634.     mov  eax,TRAILING_BUF
  635.     mov  ecx,eax
  636.     mov  ebx,2
  637.     call FileSeek
  638.     mov  edi,esi
  639.     mov  al,'P'
  640.   .lp:
  641.     repne scasb
  642.     cmp  dword[edi-1],fhs_end
  643.     je   .end_found
  644.     jecxz .err
  645.     jmp   .lp
  646.   .end_found:
  647.     dec   edi
  648.     mov   esi,edi
  649.     mov   eax,[edi+12]
  650.     neg   eax
  651.     mov   ebx,1
  652.     call  FileSeek
  653.     push  dword[esi+42]
  654.     pop   [arc_base]
  655.   .err:
  656.     ret
  657.  
  658. scanline_calc:
  659.     movzx ecx,byte[PNG_info.Color_type]
  660.     mov  eax,1
  661.     cmp  cl,3
  662.     je   .palette
  663.     test cl,2
  664.     jz  .notriple
  665.     add  eax,2
  666.   .notriple:
  667.     test cl,4
  668.     jz   .calc_bpp
  669.     inc  eax
  670.   .calc_bpp:
  671.     mul  [PNG_info.Bit_depth]
  672.   .palette:
  673.     mov  ecx,eax   ; in bits
  674.     shr  eax,3     ; in bytes
  675.     test eax,eax
  676.     jnz  .noz
  677.     inc  eax
  678.   .noz:
  679.     mov  [png_bpp],eax
  680.     mov  eax,[PNG_info.Width]
  681.     mov  ebp,eax
  682.     imul ecx
  683.     shr  eax,3
  684.     test eax,eax
  685.     jnz  .noz2
  686.     inc  eax
  687.   .noz2:
  688.     ret
  689.  
  690. ; Created:  May 31, 2005
  691. FiltCall:
  692. dd PngFilter.nofilt,Filt_sub,Filt_up,Filt_av,Filt_paeth,PngFilter.nofilt
  693. PngFilter:
  694. ; esi - filtered uncompressed image data
  695. ; edi - destination
  696.     call scanline_calc
  697.     mov  [sline_len],eax   ; scanline length
  698.     push edi
  699.     and  [Flags],not 1
  700.     mov  ecx,[PNG_info.Height]
  701.   .scanline:
  702. ;    Msg 9,1
  703.     push ecx
  704.     lodsb
  705.     movzx eax,al
  706.     cmp  eax,5
  707.     jb   .f_ok
  708.     mov  eax,5
  709.   .f_ok:
  710.     inc  dword[filters+eax*4]
  711.     jmp  dword[FiltCall+eax*4]
  712.   .nofilt:
  713.     mov  dl,[PNG_info.Color_type]
  714.     cmp  dl,3
  715.     jne  .nopalette
  716.     lodsb
  717.     mov  [cur_byte],eax
  718.     mov  [bits],8
  719.     mov  ecx,ebp
  720.   .pixel:
  721.     push ecx
  722.     movzx ecx,[PNG_info.Bit_depth]
  723.     call rb_png
  724.     push esi
  725.     lea  esi,[eax+eax*2]
  726.     add  esi,PNG_info.Palette
  727.     call PngStore
  728.     pop  esi
  729.     pop  ecx
  730.     loop .pixel
  731.     cmp  [bits],8
  732.     jne  .lp
  733.     dec  esi
  734.   .lp:
  735.     pop  ecx
  736.     loop .sl
  737.     jmp  .sl2
  738.   .sl:
  739. ;//
  740. MV equ 1
  741. ;    mov  eax,ecx
  742. ;    and  eax,1 shl MOVE_SLINE_LEV-1
  743. ;    jnz  .scanline
  744. ;stop
  745. if MV eq 0
  746.     push ecx
  747.     mov  ecx,edi
  748.     sub  ecx,esi
  749.     sub  [outp],esi
  750.     mov  edi,output
  751.     add  [outp],edi
  752.     rep  movsb
  753.     mov  esi,output
  754.     pop  ecx
  755.     pop  eax
  756.     push [outp]
  757. end if
  758. ;;//
  759.     jmp  .scanline
  760.   .sl2:
  761. ;//
  762. ;    call MoveScanline
  763.     sub  edi,[outp]
  764. ;//
  765. ;    sub  edi,[esp]
  766.     pop  eax
  767.     ret
  768.  
  769.   .nopalette:
  770.     test  dl,2
  771.     jz   .notriple1
  772.   .__:
  773.     mov  ecx,[PNG_info.Width]
  774.   .RGBcp:
  775.     call PngStore
  776.     add  esi,[png_bpp]
  777.     loop .RGBcp
  778.     jmp  .lp
  779.   .notriple1:
  780.     test dl,dl
  781.     jz  .gray
  782.     cmp  dl,4
  783.     jne .__
  784. ;    Msg 31
  785. ;    ud2
  786.   .gray:
  787. ;    stop
  788.     push ecx
  789.     mov  ecx,[PNG_info.Width]
  790.     mov  [bits],8
  791.     lodsb
  792.     mov  [cur_byte],eax
  793.   .gray2:
  794.     push ecx
  795.     movzx ecx,[PNG_info.Bit_depth]
  796.     push ecx
  797.     call rb_png
  798.     pop  ecx
  799.     cmp  ecx,8
  800.     jbe  .lo
  801.     add  esi,2
  802.     shr  eax,8
  803.     jmp  .stsb
  804.   .lo:
  805.     neg  ecx
  806.     add  ecx,8
  807.     shl  eax,cl
  808.   .stsb:
  809.     mov  ecx,3
  810.     rep  stosb
  811.     pop  ecx
  812.     loop .gray2
  813.     dec  esi
  814.     pop  ecx
  815.     jmp  .lp
  816.  
  817. Filt_sub:
  818. ;    dps  '-'
  819.     mov  ecx,[sline_len]
  820.     sub  ecx,[png_bpp]
  821.     push esi edi
  822.     mov  edi,esi
  823.     add  edi,[png_bpp]
  824.   .scan:    ; esi - previous, edi - current
  825.     lodsb
  826.     add  [edi],al
  827.     inc  edi
  828.     loop .scan
  829.  
  830.     pop  edi esi
  831. ;    dps  '-'
  832.     jmp  PngFilter.nofilt
  833.  
  834. Filt_up:
  835.     cmp  ecx,[PNG_info.Height]
  836.     je   PngFilter.nofilt
  837.     push esi edi
  838.     mov  ecx,[sline_len]
  839.     mov  edi,esi
  840.     sub  esi,ecx
  841.     dec  esi
  842.     jmp  Filt_sub.scan
  843.  
  844. Filt_av:
  845.     pusha
  846.     mov  ecx,[sline_len]
  847.     mov  ebp,[PNG_info.Height]
  848.     mov  edx,[png_bpp] ; edx-raw
  849.     neg  edx
  850.     mov  ebx,ecx
  851.     sub  ebx,[png_bpp]
  852.     mov  edi,esi
  853.     sub  esi,ecx
  854.     dec  esi           ; esi-prior
  855.   .lpavg:
  856.     xor  eax,eax
  857.     cmp  [esp+24h],ebp
  858.     je   .1stl
  859.     movzx eax,byte[esi]
  860.   .1stl:
  861.     cmp  ecx,ebx
  862.     ja   .leftbad
  863.     push ecx
  864.     movzx ecx,byte[edi+edx]
  865.     add  eax,ecx
  866.     pop  ecx
  867.   .leftbad:
  868.     shr  eax,1
  869.     add  [edi],al
  870.     inc  esi
  871.     inc  edi
  872.     loop .lpavg
  873.     popa
  874.     jmp  PngFilter.nofilt
  875.  
  876. Filt_paeth:
  877.     pusha
  878.     mov  ecx,[sline_len]
  879.     mov  edx,[png_bpp]
  880.     neg  edx
  881.     lea  ebp,[ecx+edx] ; left edge
  882.     mov  edi,esi
  883.     sub  esi,ecx
  884.     dec  esi
  885.   .lpaeth:
  886.     push ecx
  887.     movzx eax,byte[edi+edx]
  888.     movzx ebx,byte[esi]
  889.     movzx ecx,byte[esi+edx]
  890.     push eax
  891.     mov  eax,[esp+28h]
  892.     cmp  eax,[PNG_info.Height] ; 1st line
  893.     jne  .no1stlineok
  894.     xor  ebx,ebx
  895.     xor  ecx,ecx
  896.   .no1stlineok:
  897.     pop  eax
  898.     cmp  [esp],ebp     ; ecx
  899.     jbe  .leftok      ; x-bpp>=0
  900.     xor  eax,eax
  901.     xor  ecx,ecx
  902.   .leftok:
  903.     pusha   ; eax-28, ebx-16, ecx-24
  904.     lea  edx,[eax+ebx]
  905.     sub  edx,ecx        ; p=edx
  906.     sub  eax,edx        ; pa := abs(p - a)
  907.     jge  .eaxp
  908.     neg  eax
  909.   .eaxp:
  910.     sub  ebx,edx        ; pb := abs(p - b)
  911.     jge  .ebxp
  912.     neg  ebx
  913.   .ebxp:
  914.     sub  ecx,edx        ; pc := abs(p - c)
  915.     jge  .ecxp
  916.     neg  ecx
  917.   .ecxp:
  918.     cmp  eax,ebx
  919.     ja   .noa
  920.     cmp  eax,ecx
  921.     jbe  .ex            ; pa-min
  922.   .noa:
  923.     cmp  ebx,ecx
  924.     ja   .nob
  925.     mov  eax,[esp+16]
  926.     jmp  .ex2
  927.   .nob:
  928.     mov  eax,[esp+24]
  929.   .ex2:
  930.     mov  [esp+28],eax
  931.   .ex:
  932.     popa
  933.     add  [edi],al
  934.     inc  esi
  935.     inc  edi
  936.     pop  ecx
  937.     loop .lpaeth
  938.     popa
  939.     jmp  PngFilter.nofilt
  940.  
  941. rb_png: ; eax-dest; ecx-count
  942.     push ecx
  943.     xor  eax,eax
  944.   .shift:
  945.     rol  byte[cur_byte],1
  946.     rcl  eax,1
  947.   .dec:
  948.     dec  [bits]
  949.     jnz  .loop1
  950.   .push:
  951.     push dword[esi]
  952.     pop  [cur_byte]
  953.     mov  [bits],8
  954.     inc  esi
  955.   .loop1:
  956.     loop .shift
  957.     pop  ecx
  958.     ret
  959.  
  960. PngStore:
  961.     push esi
  962.     cmp  [PNG_info.Bit_depth],8
  963.     jbe  .lo
  964.     add  esi,3
  965.   .lo:
  966.   if ~ SYS eq win
  967.     mov  esi,[esi]
  968.     bswap esi
  969.     shr  esi,8
  970.     mov  [edi],esi
  971.     add  edi,3
  972.   else
  973.     movsw
  974.     movsb
  975.   end if
  976.     pop  esi
  977.     ret
  978.  
  979. FiltStats:
  980.     pusha
  981.     xor  ebx,ebx
  982.     mov  edx,23
  983.     mov  ecx,6
  984.   .lp:
  985.     push ecx edx
  986.     Msg  edx
  987.     mov  eax,[filters+ebx*4]
  988.     DebugPrintDec
  989.     pop  edx ecx
  990.     inc  edx
  991.     inc  ebx
  992.     loop .lp
  993.     Newline
  994.     popa
  995.     ret
  996.  
  997.