title: Does anyone know what's wrong with this Delphi CRC16 algorithm?
body: <p>This is an exported function in a CRC.dll used by our company's main application. I need to replicate it's incorrect calculation of checksums in our new application written in C#, in order to maintain backward compatibility.</p>
  
  <p>It's all way above my head, but I know there are quite a few very intelligent people on Stackoverflow so I thought I'd try my luck. What's wrong with it? How can I replicate it in C#?</p>
  
  <pre><code>  CRC_16_TABLE_1 : array[0..255] of Byte =
     (
      $00, $80, $80, $00, $80, $00, $00, $80, $80, $00, $00, $80, $00, $80, $80, $00,
      $80, $00, $00, $80, $00, $80, $80, $00, $00, $80, $80, $00, $80, $00, $00, $80,
      $80, $00, $00, $80, $00, $80, $80, $00, $00, $80, $80, $00, $80, $00, $00, $80,
      $00, $80, $80, $00, $80, $00, $00, $80, $80, $00, $00, $80, $00, $80, $80, $00,
      $81, $01, $01, $81, $01, $81, $81, $01, $01, $81, $81, $01, $81, $01, $01, $81,
      $01, $81, $81, $01, $81, $01, $01, $81, $81, $01, $01, $81, $01, $81, $81, $01,
      $01, $81, $81, $01, $81, $01, $01, $81, $81, $01, $01, $81, $01, $81, $81, $01,
      $81, $01, $01, $81, $01, $81, $81, $01, $01, $81, $81, $01, $81, $01, $01, $81,
      $83, $03, $03, $83, $03, $83, $83, $03, $03, $83, $83, $03, $83, $03, $03, $83,
      $03, $83, $83, $03, $83, $03, $03, $83, $83, $03, $03, $83, $03, $83, $83, $03,
      $03, $83, $83, $03, $83, $03, $03, $83, $83, $03, $03, $83, $03, $83, $83, $03,
      $83, $03, $03, $83, $03, $83, $83, $03, $03, $83, $83, $03, $83, $03, $03, $83,
      $02, $82, $82, $02, $82, $02, $02, $82, $82, $02, $02, $82, $02, $82, $82, $02,
      $82, $02, $02, $82, $02, $82, $82, $02, $02, $82, $82, $02, $82, $02, $02, $82,
      $82, $02, $02, $82, $02, $82, $82, $02, $02, $82, $82, $02, $82, $02, $02, $82,
      $02, $82, $82, $02, $82, $02, $02, $82, $82, $02, $02, $82, $02, $82, $82, $02
     );
  
    CRC_16_TABLE_2 : array[0..255] of Byte =
     (
      $00, $05, $0f, $0a, $1b, $1e, $14, $11, $33, $36, $3c, $39, $28, $2d, $27, $22,
      $63, $66, $6c, $69, $78, $7d, $77, $72, $50, $55, $5f, $5a, $4b, $4e, $44, $41,
      $c3, $c6, $cc, $c9, $d8, $dd, $d7, $d2, $f0, $f5, $ff, $fa, $eb, $ee, $e4, $e1,
      $a0, $a5, $af, $aa, $bb, $be, $b4, $b1, $93, $96, $9c, $99, $88, $8d, $87, $82,
      $83, $86, $8c, $89, $98, $9d, $97, $92, $b0, $b5, $bf, $ba, $ab, $ae, $a4, $a1,
      $e0, $e5, $ef, $ea, $fb, $fe, $f4, $f1, $d3, $d6, $dc, $d9, $c8, $cd, $c7, $c2,
      $40, $45, $4f, $4a, $5b, $5e, $54, $51, $73, $76, $7c, $79, $68, $6d, $67, $62,
      $23, $26, $2c, $29, $38, $3d, $37, $32, $10, $15, $1f, $1a, $0b, $0e, $04, $01,
      $03, $06, $0c, $09, $18, $1d, $17, $12, $30, $35, $3f, $3a, $2b, $2e, $24, $21,
      $60, $65, $6f, $6a, $7b, $7e, $74, $71, $53, $56, $5c, $59, $48, $4d, $47, $42,
      $c0, $c5, $cf, $ca, $db, $de, $d4, $d1, $f3, $f6, $fc, $f9, $e8, $ed, $e7, $e2,
      $a3, $a6, $ac, $a9, $b8, $bd, $b7, $b2, $90, $95, $9f, $9a, $8b, $8e, $84, $81,
      $80, $85, $8f, $8a, $9b, $9e, $94, $91, $b3, $b6, $bc, $b9, $a8, $ad, $a7, $a2,
      $e3, $e6, $ec, $e9, $f8, $fd, $f7, $f2, $d0, $d5, $df, $da, $cb, $ce, $c4, $c1,
      $43, $46, $4c, $49, $58, $5d, $57, $52, $70, $75, $7f, $7a, $6b, $6e, $64, $61,
      $20, $25, $2f, $2a, $3b, $3e, $34, $31, $13, $16, $1c, $19, $08, $0d, $07, $02
     );
  
  function CRC_16( var buf : array of Byte; Length : Word; Flag : Byte )
           : Word; export;
  var
    i          : Word;
    a1, a2, a3 : Byte;
  begin
    a1 := 0;
    a2 := 0;
    if (Flag = CRC_MAKE) then
      begin
      buf[Length-2] := 0;
      buf[Length-1] := 0;
      end;
    for i := 0 to Length-1 do
      begin
      a3 := a1;
      a1 := CRC_16_TABLE_1[a3] xor a2;
      a2 := CRC_16_TABLE_2[a3] xor Buf[i];
      end;
    if (Flag = CRC_MAKE) then
      begin
      buf[Length-2] := a1;
      buf[Length-1] := a2;
      end;
    result := a1 * 256 + a2;
  end;
  </code></pre>