// File: rellla[P]E3DC-Rscp/RscpProtocol.cpp
// Function: RscpProtocol::createFrameAsBuffer(SRscpFrameBuffer*, std::vector<SRscpValue, std::allocator<SRscpValue>> const&, bool)
int32_t RscpProtocol::createFrameAsBuffer(SRscpFrameBuffer *frameBuffer, const std::vector<SRscpValue> & data, bool calcCRC) {
	if(frameBuffer == NULL) {
		return RSCP::ERR_INVALID_INPUT;
	}

	// calculate the required frame size
	size_t sFrameSize =  sizeof(SRscpFrameHeader);

	// calculate the complete data size
	size_t sDataSize = 0;
	for(size_t i = 0; i < data.size(); ++i) {
		sDataSize += sizeof(SRscpValue) - sizeof(data[i].data) + data[i].length;
	}

	// allocate the required memory
	frameBuffer->data = (uint8_t *) malloc(sFrameSize + sDataSize + (calcCRC ? 4 : 0));
	if(frameBuffer->data == NULL) {
		return RSCP::ERR_NO_MEMORY;
	}
	// set the memory size
	frameBuffer->dataLength = sFrameSize + sDataSize + (calcCRC ? 4 : 0);

	// set initial header values
	memset(frameBuffer->data, 0, sizeof(SRscpFrameHeader));
	SRscpFrame* tmpFrame = reinterpret_cast<SRscpFrame*> (frameBuffer->data);
	tmpFrame->header.magic = RSCP::MAGIC;
	tmpFrame->header.ctrl.bits.crc = calcCRC;
	tmpFrame->header.ctrl.bits.version = RSCP::VERSION;
	tmpFrame->header.dataLength = sDataSize;
	setHeaderTimestamp(tmpFrame);

	// insert data from the SRscpValues
	uint8_t *dataPtr = frameBuffer->data + sFrameSize;
	for(size_t i = 0; i < data.size(); ++i) {
		SRscpValue *value = reinterpret_cast<SRscpValue *>(dataPtr);
		value->tag = data[i].tag;
		value->dataType = data[i].dataType;
		value->length = data[i].length;
		if(value->length > 0) {
			// copy into the position of the data pointer and not into the data pointer itself as the data is appended
			memcpy(&value->data, data[i].data, data[i].length);
		}
		dataPtr += sizeof(SRscpValue) - sizeof(data[i].data) + data[i].length;
	}

	// calculate CRC if necessary and add to the frame
	if(calcCRC) {
		uint32_t uCRC32 = calculateCRC32(frameBuffer->data, frameBuffer->dataLength - sizeof(uint32_t));
		memcpy(frameBuffer->data + frameBuffer->dataLength - sizeof(uCRC32), &uCRC32, sizeof(uCRC32));
	}

	return RSCP::OK;
}

// Assembly:
subq $0x98, %rsp
movb %cl, %al
movq %rdi, 0x88(%rsp)
movq %rsi, 0x80(%rsp)
movq %rdx, 0x78(%rsp)
andb $0x1, %al
movb %al, 0x77(%rsp)
movq 0x88(%rsp), %rax
movq %rax, 0x28(%rsp)
cmpq $0x0, 0x80(%rsp)
jne 0x7d7c
movl $0xffffffff, 0x94(%rsp) # imm = 0xFFFFFFFF
jmp 0x807e
movq $0x12, 0x68(%rsp)
movq $0x0, 0x60(%rsp)
movq $0x0, 0x58(%rsp)
movq 0x58(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x78(%rsp), %rdi
callq 0x5e80
movq %rax, %rcx
movq 0x20(%rsp), %rax
cmpq %rcx, %rax
jae 0x7de9
movq 0x78(%rsp), %rdi
movq 0x58(%rsp), %rsi
callq 0x95d0
movzwl 0x5(%rax), %eax
addq $0x7, %rax
addq 0x60(%rsp), %rax
movq %rax, 0x60(%rsp)
movq 0x58(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x58(%rsp)
jmp 0x7d97
movq 0x68(%rsp), %rdi
addq 0x60(%rsp), %rdi
movb 0x77(%rsp), %dl
xorl %eax, %eax
movl $0x4, %ecx
testb $0x1, %dl
cmovnel %ecx, %eax
cltq
addq %rax, %rdi
callq 0x21d0
movq %rax, %rcx
movq 0x80(%rsp), %rax
movq %rcx, (%rax)
movq 0x80(%rsp), %rax
cmpq $0x0, (%rax)
jne 0x7e3a
movl $0xfffffffe, 0x94(%rsp) # imm = 0xFFFFFFFE
jmp 0x807e
movq 0x68(%rsp), %rax
addq 0x60(%rsp), %rax
movb 0x77(%rsp), %sil
xorl %ecx, %ecx
movl $0x4, %edx
testb $0x1, %sil
cmovnel %edx, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movl %eax, %ecx
movq 0x80(%rsp), %rax
movl %ecx, 0x8(%rax)
movq 0x80(%rsp), %rax
movq (%rax), %rdi
xorl %esi, %esi
movl $0x12, %edx
callq 0x20e0
movq 0x28(%rsp), %rdi
movq 0x80(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rax
movw $0xdce3, (%rax)         # imm = 0xDCE3
movb 0x77(%rsp), %cl
andb $0x1, %cl
movq 0x50(%rsp), %rax
movzbl %cl, %ecx
movw %cx, %dx
movw 0x2(%rax), %cx
andw $0x1, %dx
shlw $0xc, %dx
andw $0xefff, %cx            # imm = 0xEFFF
orw %dx, %cx
movw %cx, 0x2(%rax)
movq 0x50(%rsp), %rax
movw 0x2(%rax), %cx
andw $0xf0ff, %cx            # imm = 0xF0FF
orw $0x100, %cx             # imm = 0x100
movw %cx, 0x2(%rax)
movq 0x60(%rsp), %rax
movw %ax, %cx
movq 0x50(%rsp), %rax
movw %cx, 0x10(%rax)
movq 0x50(%rsp), %rsi
callq 0x78a0
movq 0x80(%rsp), %rax
movq (%rax), %rax
addq 0x68(%rsp), %rax
movq %rax, 0x48(%rsp)
movq $0x0, 0x40(%rsp)
movq 0x40(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x78(%rsp), %rdi
callq 0x5e80
movq %rax, %rcx
movq 0x18(%rsp), %rax
cmpq %rcx, %rax
jae 0x8023
movq 0x48(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0x78(%rsp), %rdi
movq 0x40(%rsp), %rsi
callq 0x95d0
movl (%rax), %ecx
movq 0x38(%rsp), %rax
movl %ecx, (%rax)
movq 0x78(%rsp), %rdi
movq 0x40(%rsp), %rsi
callq 0x95d0
movb 0x4(%rax), %cl
movq 0x38(%rsp), %rax
movb %cl, 0x4(%rax)
movq 0x78(%rsp), %rdi
movq 0x40(%rsp), %rsi
callq 0x95d0
movw 0x5(%rax), %cx
movq 0x38(%rsp), %rax
movw %cx, 0x5(%rax)
movq 0x38(%rsp), %rax
movzwl 0x5(%rax), %eax
cmpl $0x0, %eax
jle 0x7fef
movq 0x38(%rsp), %rax
addq $0x7, %rax
movq %rax, 0x8(%rsp)
movq 0x78(%rsp), %rdi
movq 0x40(%rsp), %rsi
callq 0x95d0
movq 0x7(%rax), %rax
movq %rax, 0x10(%rsp)
movq 0x78(%rsp), %rdi
movq 0x40(%rsp), %rsi
callq 0x95d0
movq 0x8(%rsp), %rdi
movq 0x10(%rsp), %rsi
movzwl 0x5(%rax), %eax
movl %eax, %edx
callq 0x2130
movq 0x78(%rsp), %rdi
movq 0x40(%rsp), %rsi
callq 0x95d0
movzwl 0x5(%rax), %eax
addq $0x7, %rax
addq 0x48(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x40(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x40(%rsp)
jmp 0x7f1a
testb $0x1, 0x77(%rsp)
je 0x8073
movq 0x28(%rsp), %rdi
movq 0x80(%rsp), %rax
movq (%rax), %rsi
movq 0x80(%rsp), %rax
movl 0x8(%rax), %eax
subq $0x4, %rax
movzwl %ax, %edx
callq 0x7910
movl %eax, 0x34(%rsp)
movq 0x80(%rsp), %rax
movq (%rax), %rax
movq 0x80(%rsp), %rcx
movl 0x8(%rcx), %ecx
movl 0x34(%rsp), %edx
movl %edx, -0x4(%rax,%rcx)
movl $0x0, 0x94(%rsp)
movl 0x94(%rsp), %eax
addq $0x98, %rsp
retq
nopl (%rax)