home *** CD-ROM | disk | FTP | other *** search
/ Boldly Go Collection / version40.iso / TS / 17A / DCFG203.ZIP / DCFGT.PAS < prev    next >
Pascal/Delphi Source File  |  1992-02-08  |  13KB  |  398 lines

  1.  
  2. {Dirt Cheap Frame Grabber V2.03T (Text version)}
  3. {as of 8 Feb 1992 - by Michael Day}
  4. {public domain}
  5.  
  6. program DCFGT;
  7. uses crt;
  8. const maxframe = 30000;
  9.       maxintrp = 30000;
  10.  
  11. type frametype = array[0..maxframe] of byte;
  12.      frameptr = ^frametype;
  13.      intrptype = array[0..maxintrp] of byte;
  14.      intrpptr = ^intrptype;
  15.      string8 = string[8];
  16.  
  17.      FrameObj = object
  18.        fary : array[0..3] of frameptr;
  19.        iary : intrpptr;
  20.        inport : word;      {frame port data input address (video data)}
  21.        outport : word;     {frame port data output address (control)}
  22.        frameport : word;   {printer port number to use for frame grabber}
  23.        grabsize : word;    {size of data to grab from port}
  24.        framenum : byte;    {frame sequence number}
  25.        IntrpWidth : word;  {width of the intrp array (scan width) }
  26.        IntrpSize : word;   {size of the intrp array (width*lines) }
  27.  
  28.        constructor Init;
  29.        destructor Done;
  30.        procedure SetFramePort(what:string8);
  31.        function  GrabFrame(inprt,size:word; Fptr:frameptr):boolean;
  32.        function  GrabOne:boolean;
  33.        procedure F2IConvert(Fnum:byte; GSize,IWidth,ISize:word;
  34.                             Iptr:IntrpPtr; Fptr:FramePtr);
  35.      end;
  36.  
  37. var  Frame : FrameObj;
  38.      prnarray : array[0..3] of word absolute $40:$08;
  39.  
  40.      crtmode : byte absolute $40:$49;
  41.      oldmode : byte;
  42.      i:word;
  43.      ib:byte;
  44.      cx:char;
  45.  
  46.  
  47. {-----------------------------------------------------------}
  48. {     gray level interpretation chart                       }
  49. {                                                           }
  50. {          frame data                                       }
  51. {gray    F3  F2  F1  F0   F3 = frame 3, F2 = frame 2        }
  52. {level:  76  54  32  10   F1 = frame 1, F0 = frame 0        }
  53. {   12:  11  xx  xx  xx   each group of two bits            }
  54. {   11: <11  11  xx  xx   represent the video level         }
  55. {   10: <11 <11  11  xx   for the frame indicated           }
  56. {    9: <11 <11 <11  11                                     }
  57. {    8:  10 <11 <11 <11   xx = any bit pattern              }
  58. {    7: <10  10 <11 <11   <11 = less than 11; (10, 01, 00)  }
  59. {    6: <10 <10  10 <11   <10 = less than 10; (01 or 00)    }
  60. {    5: <10 <10 <10  10   11, 10, 01, or 00 = the indicated }
  61. {    4:  01 <10 <10 <10                absolute bit pattern }
  62. {    3:  00  01 <10 <10                                     }
  63. {    2:  00  00  01 <10   the gray level for the specified  }
  64. {    1:  00  00  00  01   bit pattern is shown at the left  }
  65. {    0:  00  00  00  00                                     }
  66. {-----------------------------------------------------------}
  67. {this array is used to translate from the interpretation    }
  68. {array data into a gray level for display on the screen     }
  69. const IntrpXlat : array[0..255] of byte = (
  70.     0,1,5,9,2,2,5,9,         6,6,6,9,10,10,10,10,
  71.     3,3,5,9,3,3,5,9,         6,6,6,9,10,10,10,10,
  72.     7,7,7,9,7,7,7,9,         7,7,7,9,10,10,10,10,
  73.     11,11,11,11,11,11,11,11, 11,11,11,11,11,11,11,11,
  74.     4,4,5,9,4,4,5,9,         6,6,6,9,10,10,10,10,
  75.     4,4,5,9,4,4,5,9,         6,6,6,9,10,10,10,10,
  76.     7,7,7,9,7,7,7,9,         7,7,7,9,10,10,10,10,
  77.     11,11,11,11,11,11,11,11, 11,11,11,11,11,11,11,11,
  78.     8,8,8,9,8,8,8,9,         8,8,8,9,10,10,10,10,
  79.     8,8,8,9,8,8,8,9,         8,8,8,9,10,10,10,10,
  80.     8,8,8,9,8,8,8,9,         8,8,8,9,10,10,10,10,
  81.     11,11,11,11,11,11,11,11, 11,11,11,11,11,11,11,11,
  82.     12,12,12,12,12,12,12,12, 12,12,12,12,12,12,12,12,
  83.     12,12,12,12,12,12,12,12, 12,12,12,12,12,12,12,12,
  84.     12,12,12,12,12,12,12,12, 12,12,12,12,12,12,12,12,
  85.     12,12,12,12,12,12,12,12, 12,12,12,12,12,12,12,12);
  86.  
  87. {-----------------------------------------------------------}
  88.  
  89.  
  90.     {grab a chunk of video from inprt size bytes in length into fary}
  91.     function FrameObj.GrabFrame(inprt,size:word; Fptr:frameptr):boolean; assembler;
  92.      asm
  93.       mov bx,17000      {timeout if we go over 50ms without sync}
  94.       mov dx,[inprt]
  95.       les di,[Fptr]     {now collect a frame}
  96.       mov cx,0
  97.  
  98.      @vsloop1:
  99.       mov ah,8 {[vsyncslice]}  {if we are in a vert sync, get out of it first}
  100.      @vsloop2:
  101.       dec bx
  102.       jz @vdone
  103.       in al,dx
  104.       shl al,1
  105.       jc @vsloop1
  106.       dec ah
  107.       jnz @vsloop2
  108.  
  109.      @vsloop3:
  110.       mov ah,8 {[vsyncslice]}  {find the start of a vert sync}
  111.      @vsloop4:
  112.       dec bx
  113.       jz @vdone
  114.       in al,dx
  115.       shl al,1
  116.       jnc @vsloop3
  117.       dec ah
  118.       jnz @vsloop4
  119.  
  120.       cld
  121.       mov cx,[size]      {start collecting data}
  122.       rep
  123.       db 6ch
  124.  
  125.      @vdone:
  126.       xor al,al        {return error code}
  127.       or bh,bl         {one = all ok}
  128.       jz @vexit        {zero = no sync}
  129.       inc al
  130.      @vexit:
  131.     end;
  132.  
  133.  
  134.   Constructor FrameObj.Init;
  135.   var i:byte;
  136.   begin
  137.  
  138.     for i := 0 to 3 do
  139.     begin
  140.       new(fary[i]);
  141.       fillchar(fary[i]^,sizeof(fary[i]^),0);
  142.     end;
  143.     new(iary);
  144.     fillchar(iary^,sizeof(iary^),0);
  145.     move(IntrpXlat,iary^,256);
  146.   end;
  147.  
  148.  
  149.   Destructor FrameObj.Done;
  150.   begin
  151.   end;
  152.  
  153.  
  154.   procedure FrameObj.SetFramePort(what:string8);
  155.   begin
  156.     frameport := 0;
  157.     if length(what) > 0 then
  158.     begin
  159.       case what[1] of
  160.        '2': frameport := 1;
  161.        '3': frameport := 2;
  162.        '4': frameport := 3;
  163.       end;
  164.     end;
  165.     outport := prnarray[frameport]; {- $378}  {get port base addr}
  166.     inport := outport+1;    {- $379}
  167.  
  168.     port[outport+2] := $04; {- $37A}   {init output control lines}
  169.     port[outport] := $ff;    {init data lines}
  170.     grabsize := 20000;           {default grab size}
  171.     framenum := 0;
  172.     IntrpWidth := 40;
  173.     IntrpSize := IntrpWidth*(262-12);
  174.    end;
  175.  
  176.  
  177.  
  178.   function FrameObj.GrabOne:boolean;
  179.   var Fptr : framePtr;
  180.   begin
  181.     inc(framenum);
  182.     framenum := framenum and 3;
  183.     port[frame.outport] := (framenum shl 6) or $3f;
  184.     Fptr := fary[framenum];
  185.     asm CLI; end;
  186.     GrabOne := GrabFrame(inport,grabsize,Fptr);
  187.     asm STI; end;
  188.     port[frame.outport] := $3f;
  189.   end;
  190.  
  191.  
  192.  
  193. {=====================================================================}
  194.    {now we are gonna display the video on the screen}
  195.    procedure IntrpDisplay(fnum,IWidth,ISize:word; Iptr:IntrpPtr);
  196.    var Bottom:word;
  197.    begin
  198.      asm
  199.        cld
  200.        push ds
  201.        lds si,ss:[Iptr]      {get intrp array pointer}
  202.        mov bx,si             {point bx at the start of the array}
  203.        add si,256            {first 256 bytes has intpr array}
  204.        mov ax,ss:[ISize]     {compute intrp bottom address offset}
  205.        add ax,si
  206.        mov ss:[Bottom],ax    {and save it}
  207.        mov ax,0B800h         {point es to the display segment}
  208.        mov es,ax
  209.        mov cx,ss:[IWidth]    {put intrp right edge offset}
  210.        add si,cx
  211.        add si,cx
  212.        add si,cx
  213.        add si,cx
  214.        add si,cx
  215.        add si,cx
  216.        add si,cx
  217.        add si,cx
  218.        add si,cx
  219.        add si,cx
  220.        add si,cx
  221.        add si,cx
  222.        add si,cx
  223.        add si,cx
  224.  
  225.        mov di,fnum           {start at top left corner of screen}
  226.        and di,2              {offset by frame number count (even/odd)}
  227.  
  228.      @dlp1:
  229.        push di
  230.      @dlp2:
  231.        lodsb          {get a intrp byte}
  232.        xlat           {translate it to gray scale number}
  233.        push bx
  234.        mov ah,al
  235.        lea bx,@ahxlat
  236.        segcs
  237.        xlat
  238.        xchg ah,al
  239.        lea bx,@alxlat
  240.        segcs
  241.        xlat
  242.        pop bx
  243.  
  244.        and di,$fffe
  245.        stosw          {display it}
  246.       { stosw }         {display it}
  247.        inc di
  248.        inc di         {skip a display pixel (we get it next time)}
  249.        dec cx         {end of the scan line?}
  250.        jnz @dlp2      {loop until done}
  251.        pop di         {restore original display start offset}
  252.        add di,160     {add display width to it}
  253.  
  254.        mov cx,ss:[IWidth]  {restore Iwidth to cx}
  255.        add si,cx           {skip three video scan lines}
  256.        add si,cx
  257.        add si,cx           {skip three video scan lines}
  258.        add si,cx
  259.        add si,cx           {skip three video scan lines}
  260.        add si,cx
  261.        add si,cx
  262.        add si,cx           {skip three video scan lines}
  263.        add si,cx
  264.        cmp si,ss:[Bottom]  {are we at the bottom?}
  265.        jc @dlp1            {keep going if not}
  266.        jmp @done
  267.  
  268.      @alxlat: db 32,176,177,178,219,176,177,178,219,176,177,178,219
  269.      @ahxlat: db 7,8,8,8,8,7,7,7,7,15,15,15,15
  270.  
  271.      @done:
  272.        pop ds          {ok, we're done}
  273.      end;
  274.    end;
  275.  
  276.  
  277.  
  278.    {==================================================================}
  279.  
  280.  
  281.    {------------------------------------------------------------------}
  282.    {note: this assumes that the frame grab array has been preformated}
  283.    {with starting with a valid scan line at the top of the screen}
  284.    procedure FrameObj.F2Iconvert(Fnum:byte; GSize,IWidth,ISize:word;
  285.                                  Iptr:IntrpPtr; Fptr:FramePtr);
  286.    var Bottom:word;
  287.    begin
  288.      asm
  289.        cld
  290.        mov cl,ss:[Fnum]      {get gray scale frame number}
  291.        and cl,03H
  292.        add cl,cl             {*2 = shifter count}
  293.        mov ch,0FCH           {create intrp data mask}
  294.        rol ch,cl
  295.        mov dx,ss:[GSize]     {get size of grabbed data to convert}
  296.        inc dx
  297.        les di,ss:[Iptr]      {get intrp array pointer}
  298.        add di,256            {first 256 bytes has xlat array}
  299.        mov ax,di
  300.        add ax,ss:[ISize]     {compute intrp bottom address offset}
  301.        mov ss:[Bottom],ax    {and save it}
  302.        mov bx,ss:[IWidth]    {put intrp right edge offset into bx}
  303.  
  304.        push ds               {save current data segment}
  305.        lds si,ss:[Fptr]      {get video frame pointer to DS:SI}
  306.  
  307.      {data conversion loop starts here}
  308.      @loop1:
  309.        dec dx           {did we run out of data?}
  310.        jz @done
  311.        lodsb            {get a frame scan byte}
  312.        shl al,1         {if it is a sync, try again}
  313.        jc @loop1
  314.  
  315.      @loop2:
  316.        dec dx           {did we run out of data?}
  317.        jz @done
  318.        lodsb            {get a frame scan byte}
  319.        shl al,1         {if it is a sync, we are}
  320.        jc @loop4        {done with the scan line}
  321.  
  322.        {convert scan input data to intrp level reference}
  323.        xor ah,ah        {init to zero level}
  324.        shl al,1         {if highest level on}
  325.        adc ah,0         {add one to level count}
  326.        shl al,1         {if next high level on}
  327.        adc ah,0         {add one to level count}
  328.        shl al,1         {if lowest level on}
  329.        adc ah,0         {add one to level count}
  330.        shl ah,cl        {adjust result to position}
  331.        mov al,es:[di]   {get current intrp value}
  332.        and al,ch        {strip old intrp value}
  333.        or al,ah         {insert new intrp value}
  334.        mov es:[di],al   {save the new intrp value}
  335.        inc di
  336.        dec bx           {if not at end of intrp line}
  337.        jnz @loop2       {go process the next byte}
  338.  
  339.      {ran against right edge of intrp window}
  340.      {so throw away rest of the scan data}
  341.      @loop3:            {suck up extra scan data}
  342.        dec dx           {did we run out of data?}
  343.        jz @done
  344.        lodsb            {get a frame scan byte}
  345.        shl al,1         {if it is not a sync, }
  346.        jnc @loop3       {keep looping}
  347.        jmp @loopd
  348.  
  349.      @loop4:            {fill out rest of intrp data}
  350.        and es:[di],ch   {strip old intrp value to 0}
  351.        inc di
  352.        dec bx           {loop until right edge reached}
  353.        jnz @loop4
  354.  
  355.      @loopd:
  356.        mov bx,ss:[IWidth]    {restore width to reg BX}
  357.        cmp di,ss:[Bottom]    {are we at bottom?}
  358.        jc @loop1             {do more if not at bottom}
  359.  
  360.      @done:
  361.        pop ds             {restore DS and we are done}
  362.      end;
  363.    end;
  364.  
  365.  
  366.  
  367. { ************************************************************** }
  368. { program start }
  369.  
  370. begin
  371.    cx := #55;
  372.  
  373.    directvideo := false;
  374.  
  375.    OldMode := CrtMode;
  376.  
  377.  
  378.    Frame.Init;
  379.    if ParamCount > 0 then
  380.      Frame.SetFramePort(ParamStr(1))
  381.    else
  382.      Frame.SetFramePort('1');
  383.  
  384.   repeat
  385.  
  386.    if Frame.GrabOne then
  387.    begin
  388.       Frame.F2Iconvert(Frame.Framenum,Frame.GrabSize,
  389.                        Frame.IntrpWidth,Frame.IntrpSize,
  390.                        Frame.Iary, Frame.Fary[Frame.framenum]);
  391.    end;
  392.  
  393.    IntrpDisplay(Frame.framenum,Frame.IntrpWidth,Frame.IntrpSize,Frame.Iary);
  394.  
  395.    if keypressed then cx := readkey;
  396.   until cx < #32;
  397. end.
  398.