// File: rellla[P]E3DC-Rscp/RscpProtocol.cpp
// Function: RscpProtocol::parseFrame(unsigned char const*, unsigned int const&, SRscpFrame*)
int32_t RscpProtocol::parseFrame(const uint8_t* data, const uint32_t & length, SRscpFrame* frame) {
	// sanity check
	if((data == NULL) || (frame == NULL)) {
		return RSCP::ERR_INVALID_INPUT;
	}
	// check first that at least the header size is in the frame
	if(sizeof(SRscpFrameHeader) > length) {
		return RSCP::ERR_INVALID_FRAME_LENGTH;
	}
	// assign pointer to the data struct
	SRscpFrame* inFrame = reinterpret_cast<SRscpFrame*>((uint8_t*)data);
	// check if the magic matches
	if(inFrame->header.magic != RSCP::MAGIC) {
		return RSCP::ERR_INVALID_MAGIC;
	}
	// check the frame version number
	if(inFrame->header.ctrl.bits.version != RSCP::VERSION) {
		return RSCP::ERR_PROT_VERSION_MISMATCH;
	}
	// check the frame length
	uint32_t frameLength = sizeof(SRscpFrameHeader) + inFrame->header.dataLength + ((inFrame->header.ctrl.bits.crc != 0) ? sizeof(uint32_t) : 0);
	if(frameLength > length) {
		return RSCP::ERR_INVALID_FRAME_LENGTH;
	}
	// check that CRC matches before starting to parse
	if(inFrame->header.ctrl.bits.crc != 0) {
		uint32_t calcCRC32 = calculateCRC32(data, frameLength - sizeof(uint32_t));
		uint32_t frameCRC32;
		memcpy(&frameCRC32, data + frameLength - sizeof(uint32_t), sizeof(uint32_t));
		// compare CRC
		if(frameCRC32 != calcCRC32) {
			return RSCP::ERR_INVALID_CRC;
		}
		// CRC matches set the CRC inside the output frame
		frame->CRC = frameCRC32;
	}
	else {
		// no CRC inside the frame -> set 0 for output frame
		frame->CRC = 0;
	}
	// copy header information
	memcpy(&frame->header, &inFrame->header, sizeof(SRscpFrameHeader));
	// parse the SRscpValues
	int32_t iResult = parseData((uint8_t*)(&inFrame->header + 1), inFrame->header.dataLength, frame->data);
	if(iResult < 0) {
		return iResult;
	}
	// parsing done return OK
	frameLength = (sizeof(SRscpFrameHeader) + iResult + ((inFrame->header.ctrl.bits.crc != 0) ? sizeof(uint32_t) : 0));
	return frameLength;
}

// Assembly:
subq $0x58, %rsp
movq %rdi, 0x48(%rsp)
movq %rsi, 0x40(%rsp)
movq %rdx, 0x38(%rsp)
movq %rcx, 0x30(%rsp)
movq 0x48(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, 0x40(%rsp)
je 0x86c2
cmpq $0x0, 0x30(%rsp)
jne 0x86cf
movl $0xffffffff, 0x54(%rsp) # imm = 0xFFFFFFFF
jmp 0x88a1
movq 0x38(%rsp), %rax
movl (%rax), %eax
movl %eax, %ecx
movl $0x12, %eax
cmpq %rcx, %rax
jbe 0x86ef
movl $0xfffffffb, 0x54(%rsp) # imm = 0xFFFFFFFB
jmp 0x88a1
movq 0x40(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x28(%rsp), %rax
movzwl (%rax), %eax
cmpl $0xdce3, %eax           # imm = 0xDCE3
je 0x8715
movl $0xfffffffd, 0x54(%rsp) # imm = 0xFFFFFFFD
jmp 0x88a1
movq 0x28(%rsp), %rax
movw 0x2(%rax), %ax
shrw $0x8, %ax
andw $0xf, %ax
movzbl %al, %eax
cmpl $0x1, %eax
je 0x873b
movl $0xfffffffc, 0x54(%rsp) # imm = 0xFFFFFFFC
jmp 0x88a1
movq 0x28(%rsp), %rax
movzwl 0x10(%rax), %eax
addq $0x12, %rax
movq 0x28(%rsp), %rcx
movw 0x2(%rcx), %cx
shrw $0xc, %cx
andw $0x1, %cx
movzbl %cl, %esi
xorl %ecx, %ecx
movl $0x4, %edx
cmpl $0x0, %esi
cmovneq %rdx, %rcx
addq %rcx, %rax
movl %eax, 0x24(%rsp)
movl 0x24(%rsp), %eax
movq 0x38(%rsp), %rcx
cmpl (%rcx), %eax
jbe 0x878b
movl $0xfffffffb, 0x54(%rsp) # imm = 0xFFFFFFFB
jmp 0x88a1
movq 0x28(%rsp), %rax
movw 0x2(%rax), %ax
shrw $0xc, %ax
andw $0x1, %ax
movzbl %al, %eax
cmpl $0x0, %eax
je 0x87f8
movq 0x8(%rsp), %rdi
movq 0x40(%rsp), %rsi
movl 0x24(%rsp), %eax
subq $0x4, %rax
movzwl %ax, %edx
callq 0x7910
movl %eax, 0x20(%rsp)
movq 0x40(%rsp), %rax
movl 0x24(%rsp), %ecx
movl -0x4(%rax,%rcx), %eax
movl %eax, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
cmpl 0x20(%rsp), %eax
je 0x87ea
movl $0xfffffffa, 0x54(%rsp) # imm = 0xFFFFFFFA
jmp 0x88a1
movl 0x1c(%rsp), %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x30(%rax)
jmp 0x8804
movq 0x30(%rsp), %rax
movl $0x0, 0x30(%rax)
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rax
movq 0x28(%rsp), %rcx
movq (%rcx), %rdx
movq %rdx, (%rax)
movq 0x8(%rcx), %rdx
movq %rdx, 0x8(%rax)
movw 0x10(%rcx), %cx
movw %cx, 0x10(%rax)
movq 0x28(%rsp), %rsi
addq $0x12, %rsi
movq 0x28(%rsp), %rax
movzwl 0x10(%rax), %eax
movl %eax, 0x14(%rsp)
movq 0x30(%rsp), %rcx
addq $0x18, %rcx
leaq 0x14(%rsp), %rdx
callq 0x88b0
movl %eax, 0x18(%rsp)
cmpl $0x0, 0x18(%rsp)
jge 0x8867
movl 0x18(%rsp), %eax
movl %eax, 0x54(%rsp)
jmp 0x88a1
movslq 0x18(%rsp), %rax
addq $0x12, %rax
movq 0x28(%rsp), %rcx
movw 0x2(%rcx), %cx
shrw $0xc, %cx
andw $0x1, %cx
movzbl %cl, %esi
xorl %ecx, %ecx
movl $0x4, %edx
cmpl $0x0, %esi
cmovneq %rdx, %rcx
addq %rcx, %rax
movl %eax, 0x24(%rsp)
movl 0x24(%rsp), %eax
movl %eax, 0x54(%rsp)
movl 0x54(%rsp), %eax
addq $0x58, %rsp
retq
nopw (%rax,%rax)