// File: rellla[P]E3DC-Rscp/RscpProtocol.cpp
// Function: RscpProtocol::createFrameAsBuffer(SRscpFrameBuffer*, SRscpFrame const&, bool)
int32_t RscpProtocol::createFrameAsBuffer(SRscpFrameBuffer *frameBuffer, const SRscpFrame & frame, 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 < frame.data.size(); ++i) {
		sDataSize += sizeof(SRscpValue) - sizeof(frame.data[i].data) + frame.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);

	// copy header information
	memcpy(frameBuffer->data, &frame.header, sFrameSize);

	// insert data from the SRscpValues
	uint8_t *dataPtr = frameBuffer->data + sFrameSize;
	for(size_t i = 0; i < frame.data.size(); ++i) {
		SRscpValue *value = reinterpret_cast<SRscpValue *>(dataPtr);
		value->tag = frame.data[i].tag;
		value->dataType = frame.data[i].dataType;
		value->length = frame.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, frame.data[i].data, frame.data[i].length);
		}
		dataPtr += sizeof(SRscpValue) - sizeof(frame.data[i].data) + frame.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 $0x88, %rsp
movb %cl, %al
movq %rdi, 0x78(%rsp)
movq %rsi, 0x70(%rsp)
movq %rdx, 0x68(%rsp)
andb $0x1, %al
movb %al, 0x67(%rsp)
movq 0x78(%rsp), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, 0x70(%rsp)
jne 0x80d0
movl $0xffffffff, 0x84(%rsp) # imm = 0xFFFFFFFF
jmp 0x8361
movq $0x12, 0x58(%rsp)
movq $0x0, 0x50(%rsp)
movq $0x0, 0x48(%rsp)
movq 0x48(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x68(%rsp), %rdi
addq $0x18, %rdi
callq 0x5e80
movq %rax, %rcx
movq 0x18(%rsp), %rax
cmpq %rcx, %rax
jae 0x8145
movq 0x68(%rsp), %rdi
addq $0x18, %rdi
movq 0x48(%rsp), %rsi
callq 0x95d0
movzwl 0x5(%rax), %eax
addq $0x7, %rax
addq 0x50(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x48(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x48(%rsp)
jmp 0x80eb
movq 0x58(%rsp), %rdi
addq 0x50(%rsp), %rdi
movb 0x67(%rsp), %dl
xorl %eax, %eax
movl $0x4, %ecx
testb $0x1, %dl
cmovnel %ecx, %eax
cltq
addq %rax, %rdi
callq 0x21d0
movq %rax, %rcx
movq 0x70(%rsp), %rax
movq %rcx, (%rax)
movq 0x70(%rsp), %rax
cmpq $0x0, (%rax)
jne 0x8190
movl $0xfffffffe, 0x84(%rsp) # imm = 0xFFFFFFFE
jmp 0x8361
movq 0x58(%rsp), %rax
addq 0x50(%rsp), %rax
movb 0x67(%rsp), %sil
xorl %ecx, %ecx
movl $0x4, %edx
testb $0x1, %sil
cmovnel %edx, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movl %eax, %ecx
movq 0x70(%rsp), %rax
movl %ecx, 0x8(%rax)
movq 0x70(%rsp), %rax
movq (%rax), %rdi
movq 0x68(%rsp), %rsi
movq 0x58(%rsp), %rdx
callq 0x2130
movq 0x70(%rsp), %rax
movq (%rax), %rax
addq 0x58(%rsp), %rax
movq %rax, 0x40(%rsp)
movq $0x0, 0x38(%rsp)
movq 0x38(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x68(%rsp), %rdi
addq $0x18, %rdi
callq 0x5e80
movq %rax, %rcx
movq 0x10(%rsp), %rax
cmpq %rcx, %rax
jae 0x8312
movq 0x40(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x68(%rsp), %rdi
addq $0x18, %rdi
movq 0x38(%rsp), %rsi
callq 0x95d0
movl (%rax), %ecx
movq 0x30(%rsp), %rax
movl %ecx, (%rax)
movq 0x68(%rsp), %rdi
addq $0x18, %rdi
movq 0x38(%rsp), %rsi
callq 0x95d0
movb 0x4(%rax), %cl
movq 0x30(%rsp), %rax
movb %cl, 0x4(%rax)
movq 0x68(%rsp), %rdi
addq $0x18, %rdi
movq 0x38(%rsp), %rsi
callq 0x95d0
movw 0x5(%rax), %cx
movq 0x30(%rsp), %rax
movw %cx, 0x5(%rax)
movq 0x30(%rsp), %rax
movzwl 0x5(%rax), %eax
cmpl $0x0, %eax
jle 0x82da
movq 0x30(%rsp), %rax
addq $0x7, %rax
movq %rax, (%rsp)
movq 0x68(%rsp), %rdi
addq $0x18, %rdi
movq 0x38(%rsp), %rsi
callq 0x95d0
movq 0x7(%rax), %rax
movq %rax, 0x8(%rsp)
movq 0x68(%rsp), %rdi
addq $0x18, %rdi
movq 0x38(%rsp), %rsi
callq 0x95d0
movq (%rsp), %rdi
movq 0x8(%rsp), %rsi
movzwl 0x5(%rax), %eax
movl %eax, %edx
callq 0x2130
movq 0x68(%rsp), %rdi
addq $0x18, %rdi
movq 0x38(%rsp), %rsi
callq 0x95d0
movzwl 0x5(%rax), %eax
addq $0x7, %rax
addq 0x40(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x38(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x38(%rsp)
jmp 0x81ef
testb $0x1, 0x67(%rsp)
je 0x8356
movq 0x20(%rsp), %rdi
movq 0x70(%rsp), %rax
movq (%rax), %rsi
movq 0x70(%rsp), %rax
movl 0x8(%rax), %eax
subq $0x4, %rax
movzwl %ax, %edx
callq 0x7910
movl %eax, 0x2c(%rsp)
movq 0x70(%rsp), %rax
movq (%rax), %rax
movq 0x70(%rsp), %rcx
movl 0x8(%rcx), %ecx
movl 0x2c(%rsp), %edx
movl %edx, -0x4(%rax,%rcx)
movl $0x0, 0x84(%rsp)
movl 0x84(%rsp), %eax
addq $0x88, %rsp
retq