// File: DoubleString[P]RtConverter/src/Rtklib/rt17.cpp
// Function: bamboo::input_rt17(bamboo::raw_t*, unsigned char)
EXPORT int input_rt17(raw_t *Raw, unsigned char Data)
{
    rt17_t *rt17 = (rt17_t*) Raw->rcv_data;
    unsigned char *MessageBuffer = rt17->MessageBuffer;
    unsigned char *PacketBuffer = rt17->PacketBuffer;
    unsigned int Page, Pages, Reply;
    int Ret = 0;

    /* If no current packet */
    if (rt17->PacketBytes == 0)
    {   
        /* Find something that looks like a packet. */
        if (SyncPacket(rt17, Data))
        {
            /* Found one. */
            rt17->PacketLength = 4 + PacketBuffer[3] + 2; /* 4 (header) + length + 2 (trailer) */
            rt17->PacketBytes = 4; /* We now have four bytes in the packet buffer */
        }
                
        /* Continue reading the rest of the packet from the stream */
        return 0;
    }

    /* Store the next byte of the packet */
    PacketBuffer[rt17->PacketBytes++] = Data;

    /*
    | Keep storing bytes into the current packet
    | until we have what we think are all of them.
    */
    if (rt17->PacketBytes < rt17->PacketLength)
        return 0;

    /*
    | At this point we think have an entire packet.
    | The prospective packet must end with an ETX.
    */
    if (rt17->PacketBuffer[rt17->PacketLength-1] != ETX)
    {
        tracet(2, "RT17: Prospective packet did not end with an ETX character. Some data lost.\n");
        ClearPacketBuffer(rt17);
        return 0;
    }

    /*
    | We do indeed have an entire packet.
    | Check the packet checksum.
    */
    if (!CheckPacketChecksum(PacketBuffer))
    {
        tracet(2, "RT17: Packet checksum failure. Packet discarded.\n");
        ClearPacketBuffer(rt17);
        return 0;
    }

    if (Raw->outtype)
        sprintf(Raw->msgtype, "RT17 0x%02X (%4d)", PacketBuffer[2], rt17->PacketLength);

    /* If this is a SVDATA packet, then process it immediately */
    if (PacketBuffer[2] == RETSVDATA)
    {
        Ret = DecodeRetsvdata(Raw);
        ClearPacketBuffer(rt17);
        return Ret;
    }
        
    /* Accumulate a sequence of RAWDATA packets (pages) */
    if (PacketBuffer[2] == RAWDATA)
    {
        Page  = PacketBuffer[5] >> 4;
        Pages = PacketBuffer[5] & 15;
        Reply = PacketBuffer[6];

        /*
        | If this is the first RAWDATA packet in a sequence of RAWDATA packets,
        | then make sure it's page one and not a packet somewhere in the middle.
        | If not page one, then skip it and continue reading from the stream
        | until we find one that starts at page one. Otherwise make sure it is
        | a part of the same requence of packets as the last one, that it's
        | page number is in sequence.
        */
        if (rt17->MessageBytes == 0)
        {       
            if (Page != 1)
            {
                tracet(2, "RT17: First RAWDATA packet is not page #1. Packet discarded.\n");
                ClearPacketBuffer(rt17);
                return 0;
            }

            rt17->Reply = PacketBuffer[6];
        }
        else if ((Reply != rt17->Reply) || (Page != (rt17->Page + 1)))
        {
            tracet(2, "RT17: RAWDATA packet sequence number mismatch or page out of order. %u RAWDATA packets discarded.\n", Page);
            ClearMessageBuffer(rt17);
            ClearPacketBuffer(rt17);
            return 0;
        }
        
        /* Check for message buffer overflow */
        if ((rt17->MessageBytes + rt17->PacketBytes) > MBUFF_LENGTH)
        {
            tracet(2, "RT17: Buffer would overflow. %u RAWDATA packets discarded.\n", Page);
            ClearMessageBuffer(rt17);
            ClearPacketBuffer(rt17);
            return 0; 
        }

        memcpy(MessageBuffer + rt17->MessageBytes, PacketBuffer, rt17->PacketBytes);
        rt17->MessageBytes += rt17->PacketBytes;
        rt17->MessageLength += rt17->PacketLength;
        ClearPacketBuffer(rt17);

        if (Page == Pages)
        {
            Ret = DecodeRawdata(Raw);
            ClearMessageBuffer(rt17);
            return Ret;
        }

        rt17->Page = Page;

        return 0;
    }

    /* Accumulate a sequence of GENOUT (GSOF) packets (pages) */
    if (PacketBuffer[2] == GENOUT)
    {
        Reply = PacketBuffer[4];
        Page  = PacketBuffer[5];
        Pages = PacketBuffer[6];

        /*
        | If this is the first GENOUT packet in a sequence of GENOUT packets,
        | then make sure it's page zero and not a packet somewhere in the middle.
        | If not page zero, then skip it and continue reading from the stream
        | until we find one that starts at page zero. Otherwise make sure it is
        | a part of the same requence of packets as the last one, that it's
        | page number is in sequence.
        */
        if (rt17->MessageBytes == 0)
        {       
            if (Page != 0)
            {
                tracet(3, "RT17: First GENOUT packet is not page #0. Packet discarded.\n");
                ClearPacketBuffer(rt17);
                return 0;
            }

            rt17->Reply = PacketBuffer[4];
        }
        else if ((Reply != rt17->Reply) || (Page != (rt17->Page + 1)))
        {
            tracet(2, "RT17: GENOUT packet sequence number mismatch or page out of order. %u GENOUT packets discarded.\n", Page);
            ClearMessageBuffer(rt17);
            ClearPacketBuffer(rt17);
            return 0;
        }
        
        /* Check for message buffer overflow. */
        if ((rt17->MessageBytes + rt17->PacketBytes) > MBUFF_LENGTH)
        {
            tracet(2, "RT17: Buffer would overflow. %u GENOUT packets discarded.\n", Page);
            ClearMessageBuffer(rt17);
            ClearPacketBuffer(rt17);
            return 0; 
        }

        memcpy(MessageBuffer + rt17->MessageBytes, PacketBuffer, rt17->PacketBytes);
        rt17->MessageBytes += rt17->PacketBytes;
        rt17->MessageLength += rt17->PacketLength;
        ClearPacketBuffer(rt17);

        if (Page == Pages)
        {
            Ret = DecodeGSOF(Raw);
            ClearMessageBuffer(rt17);
            return Ret;
        }

        rt17->Page = Page;

        return 0;
    }

    /*
    | If we fall through to here, then the packet is not one that we support
    | (and hence we can't really even get here). Dump the packet on the floor
    | and continue reading from the stream.
    */
    tracet(2, "RT17: Packet is not GENOUT, RAWDATA or RETSVDATA. Packet discarded.\n"); 
    ClearPacketBuffer(rt17);
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movb %sil, %al
movq %rdi, -0x10(%rbp)
movb %al, -0x11(%rbp)
movq -0x10(%rbp), %rax
movq 0x82ba0(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movl $0x0, -0x40(%rbp)
movq -0x20(%rbp), %rax
cmpl $0x0, 0x24(%rax)
jne 0x68057
movq -0x20(%rbp), %rdi
movzbl -0x11(%rbp), %esi
callq 0x684e0
cmpl $0x0, %eax
je 0x6804b
movq -0x30(%rbp), %rax
movzbl 0x3(%rax), %ecx
addl $0x4, %ecx
addl $0x2, %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x28(%rax)
movq -0x20(%rbp), %rax
movl $0x4, 0x24(%rax)
movl $0x0, -0x4(%rbp)
jmp 0x684ce
movb -0x11(%rbp), %dl
movq -0x30(%rbp), %rax
movq -0x20(%rbp), %rsi
movl 0x24(%rsi), %ecx
movl %ecx, %edi
addl $0x1, %edi
movl %edi, 0x24(%rsi)
movl %ecx, %ecx
movb %dl, (%rax,%rcx)
movq -0x20(%rbp), %rax
movl 0x24(%rax), %eax
movq -0x20(%rbp), %rcx
cmpl 0x28(%rcx), %eax
jae 0x6808e
movl $0x0, -0x4(%rbp)
jmp 0x684ce
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x20(%rbp), %rcx
movl 0x28(%rcx), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
cmpl $0x3, %eax
je 0x680d3
movl $0x2, %edi
leaq 0x5756f(%rip), %rsi     # 0xbf626
movb $0x0, %al
callq 0x95890
movq -0x20(%rbp), %rdi
callq 0x68590
movl $0x0, -0x4(%rbp)
jmp 0x684ce
movq -0x30(%rbp), %rdi
callq 0x685e0
cmpl $0x0, %eax
jne 0x68109
movl $0x2, %edi
leaq 0x57586(%rip), %rsi     # 0xbf673
movb $0x0, %al
callq 0x95890
movq -0x20(%rbp), %rdi
callq 0x68590
movl $0x0, -0x4(%rbp)
jmp 0x684ce
movq -0x10(%rbp), %rax
cmpl $0x0, 0x81a8c(%rax)
je 0x6813e
movq -0x10(%rbp), %rdi
addq $0x70e70, %rdi          # imm = 0x70E70
movq -0x30(%rbp), %rax
movzbl 0x2(%rax), %edx
movq -0x20(%rbp), %rax
movl 0x28(%rax), %ecx
leaq 0x5756e(%rip), %rsi     # 0xbf6a5
movb $0x0, %al
callq 0x9150
movq -0x30(%rbp), %rax
movzbl 0x2(%rax), %eax
cmpl $0x55, %eax
jne 0x6816b
movq -0x10(%rbp), %rdi
callq 0x68650
movl %eax, -0x40(%rbp)
movq -0x20(%rbp), %rdi
callq 0x68590
movl -0x40(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x684ce
movq -0x30(%rbp), %rax
movzbl 0x2(%rax), %eax
cmpl $0x57, %eax
jne 0x68311
movq -0x30(%rbp), %rax
movzbl 0x5(%rax), %eax
sarl $0x4, %eax
movl %eax, -0x34(%rbp)
movq -0x30(%rbp), %rax
movzbl 0x5(%rax), %eax
andl $0xf, %eax
movl %eax, -0x38(%rbp)
movq -0x30(%rbp), %rax
movzbl 0x6(%rax), %eax
movl %eax, -0x3c(%rbp)
movq -0x20(%rbp), %rax
cmpl $0x0, 0x1c(%rax)
jne 0x681ec
cmpl $0x1, -0x34(%rbp)
je 0x681db
movl $0x2, %edi
leaq 0x574f8(%rip), %rsi     # 0xbf6b7
movb $0x0, %al
callq 0x95890
movq -0x20(%rbp), %rdi
callq 0x68590
movl $0x0, -0x4(%rbp)
jmp 0x684ce
movq -0x30(%rbp), %rax
movzbl 0x6(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x30(%rax)
jmp 0x6823f
movl -0x3c(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl 0x30(%rcx), %eax
jne 0x68209
movl -0x34(%rbp), %eax
movq -0x20(%rbp), %rcx
movl 0x2c(%rcx), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
je 0x6823d
movl -0x34(%rbp), %edx
movl $0x2, %edi
leaq 0x574dd(%rip), %rsi     # 0xbf6f5
movb $0x0, %al
callq 0x95890
movq -0x20(%rbp), %rdi
callq 0x68780
movq -0x20(%rbp), %rdi
callq 0x68590
movl $0x0, -0x4(%rbp)
jmp 0x684ce
jmp 0x6823f
movq -0x20(%rbp), %rax
movl 0x1c(%rax), %eax
movq -0x20(%rbp), %rcx
addl 0x24(%rcx), %eax
cmpl $0x2000, %eax           # imm = 0x2000
jbe 0x68288
movl -0x34(%rbp), %edx
movl $0x2, %edi
leaq 0x574f5(%rip), %rsi     # 0xbf758
movb $0x0, %al
callq 0x95890
movq -0x20(%rbp), %rdi
callq 0x68780
movq -0x20(%rbp), %rdi
callq 0x68590
movl $0x0, -0x4(%rbp)
jmp 0x684ce
movq -0x28(%rbp), %rdi
movq -0x20(%rbp), %rax
movl 0x1c(%rax), %eax
addq %rax, %rdi
movq -0x30(%rbp), %rsi
movq -0x20(%rbp), %rax
movl 0x24(%rax), %eax
movl %eax, %edx
callq 0x9610
movq -0x20(%rbp), %rax
movl 0x24(%rax), %ecx
movq -0x20(%rbp), %rax
addl 0x1c(%rax), %ecx
movl %ecx, 0x1c(%rax)
movq -0x20(%rbp), %rax
movl 0x28(%rax), %ecx
movq -0x20(%rbp), %rax
addl 0x20(%rax), %ecx
movl %ecx, 0x20(%rax)
movq -0x20(%rbp), %rdi
callq 0x68590
movl -0x34(%rbp), %eax
cmpl -0x38(%rbp), %eax
jne 0x682fb
movq -0x10(%rbp), %rdi
callq 0x687e0
movl %eax, -0x40(%rbp)
movq -0x20(%rbp), %rdi
callq 0x68780
movl -0x40(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x684ce
movl -0x34(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x2c(%rax)
movl $0x0, -0x4(%rbp)
jmp 0x684ce
movq -0x30(%rbp), %rax
movzbl 0x2(%rax), %eax
cmpl $0x40, %eax
jne 0x684ab
movq -0x30(%rbp), %rax
movzbl 0x4(%rax), %eax
movl %eax, -0x3c(%rbp)
movq -0x30(%rbp), %rax
movzbl 0x5(%rax), %eax
movl %eax, -0x34(%rbp)
movq -0x30(%rbp), %rax
movzbl 0x6(%rax), %eax
movl %eax, -0x38(%rbp)
movq -0x20(%rbp), %rax
cmpl $0x0, 0x1c(%rax)
jne 0x6838c
cmpl $0x0, -0x34(%rbp)
je 0x6837b
movl $0x3, %edi
leaq 0x57435(%rip), %rsi     # 0xbf794
movb $0x0, %al
callq 0x95890
movq -0x20(%rbp), %rdi
callq 0x68590
movl $0x0, -0x4(%rbp)
jmp 0x684ce
movq -0x30(%rbp), %rax
movzbl 0x4(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x30(%rax)
jmp 0x683df
movl -0x3c(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl 0x30(%rcx), %eax
jne 0x683a9
movl -0x34(%rbp), %eax
movq -0x20(%rbp), %rcx
movl 0x2c(%rcx), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
je 0x683dd
movl -0x34(%rbp), %edx
movl $0x2, %edi
leaq 0x57419(%rip), %rsi     # 0xbf7d1
movb $0x0, %al
callq 0x95890
movq -0x20(%rbp), %rdi
callq 0x68780
movq -0x20(%rbp), %rdi
callq 0x68590
movl $0x0, -0x4(%rbp)
jmp 0x684ce
jmp 0x683df
movq -0x20(%rbp), %rax
movl 0x1c(%rax), %eax
movq -0x20(%rbp), %rcx
addl 0x24(%rcx), %eax
cmpl $0x2000, %eax           # imm = 0x2000
jbe 0x68428
movl -0x34(%rbp), %edx
movl $0x2, %edi
leaq 0x5742f(%rip), %rsi     # 0xbf832
movb $0x0, %al
callq 0x95890
movq -0x20(%rbp), %rdi
callq 0x68780
movq -0x20(%rbp), %rdi
callq 0x68590
movl $0x0, -0x4(%rbp)
jmp 0x684ce
movq -0x28(%rbp), %rdi
movq -0x20(%rbp), %rax
movl 0x1c(%rax), %eax
addq %rax, %rdi
movq -0x30(%rbp), %rsi
movq -0x20(%rbp), %rax
movl 0x24(%rax), %eax
movl %eax, %edx
callq 0x9610
movq -0x20(%rbp), %rax
movl 0x24(%rax), %ecx
movq -0x20(%rbp), %rax
addl 0x1c(%rax), %ecx
movl %ecx, 0x1c(%rax)
movq -0x20(%rbp), %rax
movl 0x28(%rax), %ecx
movq -0x20(%rbp), %rax
addl 0x20(%rax), %ecx
movl %ecx, 0x20(%rax)
movq -0x20(%rbp), %rdi
callq 0x68590
movl -0x34(%rbp), %eax
cmpl -0x38(%rbp), %eax
jne 0x68498
movq -0x10(%rbp), %rdi
callq 0x688e0
movl %eax, -0x40(%rbp)
movq -0x20(%rbp), %rdi
callq 0x68780
movl -0x40(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x684ce
movl -0x34(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x2c(%rax)
movl $0x0, -0x4(%rbp)
jmp 0x684ce
movl $0x2, %edi
leaq 0x573b6(%rip), %rsi     # 0xbf86d
movb $0x0, %al
callq 0x95890
movq -0x20(%rbp), %rdi
callq 0x68590
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nopw (%rax,%rax)