// File: /workspace/github_cpp_makefile_star2_O2/OpenFodder[P]SOS_Unpacker/capsimg/CAPSImg/CapsFDCEmulator.cpp
// Function: FdcShiftBit(CapsFdc*)
void FdcShiftBit(PCAPSFDC pc)
{
	// get selected drive
	PCAPSDRIVE pd=pc->driveprc;

	// do nothing in bit skip area
	if (pc->datalock<=pd->ovlmax && pc->datalock>=pd->ovlmin)
		return;

	// read real or random data
	int bval=(pc->datamode == cfdcdmNoise) ? FdcReadBitNoise(pc) : FdcReadBit(pc);

	// shift read bit into am decoder
	UDWORD amdecode=pc->amdecode<<1;
	if (bval)
		amdecode|=1;
	pc->amdecode=amdecode;

	// get am info, clear AM found, A1 and C2 mark signals
	UDWORD aminfo=pc->aminfo & ~(CAPSFDC_AI_AMFOUND|CAPSFDC_AI_MARKA1|CAPSFDC_AI_MARKC2);

	// bitcell distance of last mark detected
	if (pc->ammarkdist)
		pc->ammarkdist--;

	// am detector if enabled
	if (aminfo & CAPSFDC_AI_AMDETENABLE) {
		// not a mark in shifter/decoder
		int amt=0;

		// check if shifter/decoder has a mark
		// the real hardware probably has two shifters (clocked and fed by data separator) connected to a decoder
		// each bit of the shifter/decoder is for shifter0#0, shifter1#0...shifter0#7, shifter1#7, 
		// only 2 comparisons is needed per cell instead of 8 (A1/0A, C2/14 and 0A/A1, 14/C2)
		switch (amdecode & 0xffff) {
			// A1 mark only enabled if not overlapped with another A1
			case 0x4489:
				if (!pc->ammarkdist || pc->ammarktype!=1)
					amt=1;
				break;

			// C2 mark always enabled
			case 0x5224:
				amt=2;
				break;
		}

		// process mark if found
		if (amt) {
			// we just read the last data bit of a mark, delay by a clock bit to read from decoder#1
			pc->amdatadelay=1;

			// if overlapped with a different mark
			if (pc->ammarkdist && pc->ammarktype!=amt) {
				// dsr value is invalid
				pc->amdataskip++;

				// delay by an additional data bit (data, clock)
				pc->amdatadelay+=2;
			}

			// if dsr is empty dsr shouldn't be flushed, dsr value is invalid
			if (!pc->dsrcnt)
				pc->amdataskip++;

			// force dsr to flush its current value, since data values start from next data bit
			pc->dsrcnt=7;

			// 16 bitcells must be read before next mark, otherwise marks are overlapped (8 clock+data bits)
			pc->ammarkdist=16;

			// save last mark type; only used when marks overlap
			pc->ammarktype=amt;

			// set mark signal, the shifter/decoder must be connected to the crc logic, not dsr
			if (amt == 1) {
				aminfo|=CAPSFDC_AI_MARKA1|CAPSFDC_AI_MA1ACTIVE;

				// if CRC is enabled, first A1 mark activates the CRC logic
				if (aminfo & CAPSFDC_AI_CRCENABLE) {
					// if CRC logic is not activate yet reset CRC value and counter, 16 cells already available as mark
					if (!(aminfo & CAPSFDC_AI_CRCACTIVE)) {
						aminfo|=CAPSFDC_AI_CRCACTIVE;
						pc->crc=~0;
						pc->crccnt=16;
					}
				}
			} else
				aminfo|=CAPSFDC_AI_MARKC2;
		}
	}

	// process CRC if activated
	if (aminfo & CAPSFDC_AI_CRCACTIVE) {
		// process new value at every 16 cells (8 clock/data)
		if (!(pc->crccnt & 0xf)) {
			// reset CRC process if less than 3 consecutive A1 marks detected
			if (pc->crccnt>48 || (aminfo & CAPSFDC_AI_MARKA1)) {
				// 3 consecutive A1 marks found: set AM found signal, disable AM detector
				if (pc->crccnt == 48) {
					aminfo|=CAPSFDC_AI_AMFOUND|CAPSFDC_AI_AMACTIVE;
					aminfo&=~CAPSFDC_AI_AMDETENABLE;
				}

				// select data bits for CRC source byte value; needed without separate clock and data shifters
				int value=0;
				for (int mask=0x4000; mask; mask>>=2) {
					value<<=1;
					if (amdecode & mask)
						value|=1;
				}

				// update CRC
				UWORD crc=(UWORD)pc->crc;
				pc->crc=crctab_ccitt[value^(crc>>8)] ^ (crc << 8);
			} else
				aminfo&=~(CAPSFDC_AI_CRCACTIVE|CAPSFDC_AI_AMACTIVE);
		}

		pc->crccnt++;
	}

	// wait for data clock cycle plus bitcell delay
	if (!pc->amdatadelay) {
		// set next delay
		// just read a clock bit here, next cell is data, that gets processed at the clock bit after that
		pc->amdatadelay=1;

		// clear dsr signals
		aminfo&=~(CAPSFDC_AI_DSRREADY|CAPSFDC_AI_DSRAM|CAPSFDC_AI_DSRMA1);

		// shift data bit into dsr, this is a clock bit, data bit is at decoder#1
		pc->dsr=((pc->dsr<<1) | (amdecode>>1 & 1)) & 0xff;

		// process data if 8 bits are dsr now, otherwise just increase dsr counter
		if (++pc->dsrcnt == 8) {
			// reset dsr counter
			pc->dsrcnt=0;

			// if AM found set dsr signal
			if (aminfo & CAPSFDC_AI_AMACTIVE) {
				aminfo&=~CAPSFDC_AI_AMACTIVE;
				aminfo|=CAPSFDC_AI_DSRAM;
			}

			// if A1 mark found set dsr signal
			if (aminfo & CAPSFDC_AI_MA1ACTIVE) {
				aminfo&=~CAPSFDC_AI_MA1ACTIVE;
				aminfo|=CAPSFDC_AI_DSRMA1;
			}

			// set dsr ready signal, unless data is invalid
			if (!pc->amdataskip)
				aminfo|=CAPSFDC_AI_DSRREADY;
			else
				pc->amdataskip--;
		}
	} else
		pc->amdatadelay--;

	// save new am info
	pc->aminfo=aminfo;
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
movq 0x100(%rdi), %rax
movl 0x80(%rdi), %ecx
cmpl 0x58(%rax), %ecx
jg 0x6cb8
cmpl 0x54(%rax), %ecx
jge 0x6eb2
cmpl $0x1, 0x84(%rbx)
jne 0x6ccb
movq %rbx, %rdi
callq 0x6ede
jmp 0x6cd3
movq %rbx, %rdi
callq 0x6eb4
movl 0x5c(%rbx), %ecx
movl 0x60(%rbx), %esi
xorl %edx, %edx
testl %eax, %eax
setne %dl
leal (%rdx,%rcx,2), %edx
movl %edx, 0x5c(%rbx)
movl 0x70(%rbx), %eax
testl %eax, %eax
je 0x6cf8
decl %eax
movl %eax, 0x70(%rbx)
sete %r9b
jmp 0x6cfb
movb $0x1, %r9b
movl %esi, %eax
andl $0xffffff1f, %eax       # imm = 0xFFFFFF1F
testb $0x1, %sil
je 0x6db4
cmpw $0x5224, %dx            # imm = 0x5224
je 0x6d37
movzwl %dx, %edi
cmpl $0x4489, %edi           # imm = 0x4489
jne 0x6db4
testb %r9b, %r9b
je 0x6d4b
movl $0x1, 0x68(%rbx)
movb $0x1, %dil
pushq $0x1
popq %r8
jmp 0x6d6f
movl $0x1, 0x68(%rbx)
pushq $0x2
popq %r8
xorl %edi, %edi
testb %r9b, %r9b
je 0x6d5f
jmp 0x6d6f
cmpl $0x1, 0x74(%rbx)
je 0x6db4
movl $0x1, 0x68(%rbx)
movb $0x1, %dil
pushq $0x1
popq %r8
cmpl %r8d, 0x74(%rbx)
je 0x6d6f
incl 0x6c(%rbx)
movl $0x3, 0x68(%rbx)
cmpl $0x0, 0x7c(%rbx)
jne 0x6d78
incl 0x6c(%rbx)
movl $0x7, 0x7c(%rbx)
movl $0x10, 0x70(%rbx)
movl %r8d, 0x74(%rbx)
testb %dil, %dil
je 0x6daa
andl $0x6, %esi
cmpl $0x2, %esi
jne 0x6db1
orl $0x54, %eax
movabsq $0x10ffffffff, %rsi     # imm = 0x10FFFFFFFF
movq %rsi, 0x54(%rbx)
jmp 0x6db4
orl $0x80, %eax
jmp 0x6db4
orl $0x50, %eax
movl %eax, %edi
testb $0x4, %dil
je 0x6e36
movl 0x58(%rbx), %esi
testb $0xf, %sil
jne 0x6e31
cmpl $0x31, %esi
setb %r8b
testb $0x40, %dil
sete %dil
testb %r8b, %dil
je 0x6dde
andl $-0x4d, %eax
jmp 0x6e31
movl %eax, %edi
andl $-0x2a, %edi
orl $0x28, %edi
movl $0x4000, %r9d           # imm = 0x4000
xorl %r8d, %r8d
testl %r9d, %r9d
je 0x6e08
xorl %r10d, %r10d
testl %edx, %r9d
setne %r10b
leal (%r10,%r8,2), %r8d
shrl $0x2, %r9d
jmp 0x6def
cmpl $0x30, %esi
cmovel %edi, %eax
movzwl 0x54(%rbx), %edx
movl %edx, %edi
shrl $0x8, %edi
xorl %r8d, %edi
movslq %edi, %rdi
leaq 0x112cc(%rip), %r8      # 0x180f0
movzwl (%r8,%rdi,2), %edi
shll $0x8, %edx
xorl %edi, %edx
movl %edx, 0x54(%rbx)
incl %esi
movl %esi, 0x58(%rbx)
movl 0x68(%rbx), %edx
testl %edx, %edx
je 0x6e44
decl %edx
movl %edx, 0x68(%rbx)
jmp 0x6eaf
movl $0x1, 0x68(%rbx)
movl %eax, %edx
andl $0xfffff8ff, %edx       # imm = 0xFFFFF8FF
andl $0x1, %ecx
movl 0x78(%rbx), %esi
movl 0x7c(%rbx), %edi
andl $0x7f, %esi
leal (%rcx,%rsi,2), %ecx
movl %ecx, 0x78(%rbx)
incl %edi
movl %edi, 0x7c(%rbx)
cmpl $0x8, %edi
jne 0x6ea6
andl $0x0, 0x7c(%rbx)
movl %eax, %ecx
andl $0xfffff8f7, %ecx       # imm = 0xFFFFF8F7
orl $0x200, %ecx            # imm = 0x200
testb $0x8, %al
cmovel %edx, %ecx
movl %ecx, %eax
andl $0xfffffaef, %eax       # imm = 0xFFFFFAEF
orl $0x400, %eax            # imm = 0x400
testb $0x10, %cl
cmovel %ecx, %eax
movl 0x6c(%rbx), %ecx
testl %ecx, %ecx
je 0x6eaa
decl %ecx
movl %ecx, 0x6c(%rbx)
jmp 0x6eaf
movl %edx, %eax
jmp 0x6eaf
orl $0x100, %eax            # imm = 0x100
movl %eax, 0x60(%rbx)
popq %rbx
retq