// File: OpenFodder[P]SOS_Unpacker/capsimg/CAPSImg/CapsFDCEmulator.cpp
// Function: FdcComT2_ReadLoop(CapsFdc*)
void FdcComT2_ReadLoop(PCAPSFDC pc)
{
	// update data access
	FdcUpdateData(pc);

	// get access hook, crc
	FDCREAD ph=FdcGetReadAccess(pc);

	// clock cycles to complete
	UDWORD cst=pc->clockact;

	// process requested cycles
	while (!pc->endrequest && pc->clockact<pc->clockreq) {
		// read byte when ready
		if (!ph(pc))
			continue;

		// check ID
		switch (pc->dataphase) {
			case 0:
				// AM detected, read returns on dsr ready
				pc->amisigmask=CAPSFDC_AI_DSRREADY;
				pc->dataphase++;
				break;

			case 1:
				//if not fc...ff, restart
				if (pc->dsr < 0xfc) {
					FdcResetAm(pc);
					continue;
				}

				pc->dataphase++;
				break;

			case 2:
				//if not the track, restart
				if (pc->dsr != pc->r_track) {
					FdcResetAm(pc);
					continue;
				}

				pc->dataphase++;
				break;

			case 4:
				//if not the sector, restart
				if (pc->dsr != pc->r_sector) {
					FdcResetAm(pc);
					continue;
				}

				pc->dataphase++;
				break;

			case 5:
				// get sector length
				pc->seclen=0x80<<(pc->dsr & pc->seclenmask);
				pc->dataphase++;
				break;

			// skip rest ofID
			case 3:
			case 6:
				pc->dataphase++;
				break;

			case 7:
				// if crc error, set crc flag, restart
				if (pc->crc & 0xffff) {
					FdcResetAm(pc);
					pc->r_st0|=CAPSFDC_SR_CRCERR;
					continue;
				}

				// clear crc flag
				pc->r_st0&=~CAPSFDC_SR_CRCERR;

				// read on dsr ready
				pc->dataphase++;
				break;

			case 8:
				// ignore 28 bytes, the fdc can't read them
				if (pc->datapcnt < 28) {
					if (pc->datapcnt == 27) {
						FdcResetAm(pc, 1);
						pc->amisigmask=CAPSFDC_AI_DSRREADY|CAPSFDC_AI_DSRMA1;
					}

					pc->datapcnt++;
					break;
				}
				pc->dataphase++;

			case 9:
				// wait maximum 43 bytes for A1 mark, then restart
				if (!(pc->aminfo & CAPSFDC_AI_DSRMA1)) {
					if (pc->datapcnt >= 43)
						FdcResetAm(pc);
					else
						pc->datapcnt++;
					continue;
				}
				pc->dataphase++;
				pc->datapcnt=0;

			case 10:
				//if not A1 mark, restart
				if (!(pc->aminfo & CAPSFDC_AI_DSRMA1)) {
					FdcResetAm(pc);
					continue;
				}

				// wait for AM
				if (!(pc->aminfo & CAPSFDC_AI_DSRAM))
					continue;

				// AM detected, read returns on dsr ready
				pc->amisigmask=CAPSFDC_AI_DSRREADY;
				pc->dataphase++;
				break;

			case 11:
				// check data type
				switch (pc->dsr) {
					// f8, f9 deleted data
					case 0xf8:
					case 0xf9:
						pc->r_st1|=CAPSFDC_SR_SU_RT;
						break;

					// fa, fb normal data
					case 0xfa:
					case 0xfb:
						pc->r_st1&=~CAPSFDC_SR_SU_RT;
						break;

					default:
						FdcResetAm(pc);
						continue;
				}

				pc->dataphase++;
				break;

			case 12:
				// dsr to data, drq signal
				pc->r_data=pc->dsr;
				FdcSetLine(pc, pc->lineout|CAPSFDC_LO_DRQSET);

				if (!--pc->seclen)
					pc->dataphase++;
				break;

			case 13:
				pc->dataphase++;
				break;

			case 14:
				// if crc error, set crc flag, stop
				if (pc->crc & 0xffff) {
					pc->r_st0|=CAPSFDC_SR_CRCERR;

					// run cycles used on unselected drives
					FdcComIdleOther(pc, pc->clockact-cst);

					// end
					pc->endrequest|=CAPSFDC_ER_COMEND;
					return;
				}

				// clear crc flag
				pc->r_st0&=~CAPSFDC_SR_CRCERR;

				// if multiple sector, restart on next sector
				if (pc->r_command & DF_4) {
					// next sector, 255 wraps to 1 (due to add with carry)
					if (pc->r_sector == 0xff)
						pc->r_sector=0x01;
					else
						pc->r_sector++;

					FdcResetAm(pc);
					continue;
				}

				// run cycles used on unselected drives
				FdcComIdleOther(pc, pc->clockact-cst);

				// end
				pc->endrequest|=CAPSFDC_ER_COMEND;
				return;

			default:
				NODEFAULT;
		}
	}

	// end requested, set seek error
	if (pc->endrequest & CAPSFDC_ER_COMEND)
		pc->r_st0|=CAPSFDC_SR_RNF;

	// run cycles on unselected drives
	FdcComIdleOther(pc, pc->clockact-cst);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
callq 0xb000
movq -0x8(%rbp), %rdi
callq 0xb130
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, -0x14(%rbp)
movq -0x8(%rbp), %rcx
xorl %eax, %eax
cmpl $0x0, 0x8(%rcx)
movb %al, -0x15(%rbp)
jne 0x93ef
movq -0x8(%rbp), %rax
movl 0xc(%rax), %eax
movq -0x8(%rbp), %rcx
cmpl 0x10(%rcx), %eax
setb %al
movb %al, -0x15(%rbp)
movb -0x15(%rbp), %al
testb $0x1, %al
jne 0x93fb
jmp 0x985d
movq -0x10(%rbp), %rax
movq -0x8(%rbp), %rdi
callq *%rax
cmpl $0x0, %eax
jne 0x940c
jmp 0x93cc
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %eax
movq %rax, -0x20(%rbp)
subq $0xe, %rax
ja 0x9856
movq -0x20(%rbp), %rax
leaq 0x14c6d(%rip), %rcx     # 0x1e09c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x8(%rbp), %rax
movl $0x100, 0x64(%rax)      # imm = 0x100
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
cmpl $0xfc, 0x78(%rax)
jae 0x9478
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0xb1a0
jmp 0x93cc
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
movl 0x78(%rax), %eax
movq -0x8(%rbp), %rcx
cmpl 0x40(%rcx), %eax
je 0x94b0
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0xb1a0
jmp 0x93cc
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
movl 0x78(%rax), %eax
movq -0x8(%rbp), %rcx
cmpl 0x44(%rcx), %eax
je 0x94e8
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0xb1a0
jmp 0x93cc
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
movl 0x78(%rax), %ecx
movq -0x8(%rbp), %rax
andl 0x4c(%rax), %ecx
movl $0x80, %eax
shll %cl, %eax
movl %eax, %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x50(%rax)
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
movl 0x54(%rax), %eax
andl $0xffff, %eax           # imm = 0xFFFF
cmpl $0x0, %eax
je 0x957d
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0xb1a0
movq -0x8(%rbp), %rax
movl 0x30(%rax), %ecx
orq $0x8, %rcx
movl %ecx, 0x30(%rax)
jmp 0x93cc
movq -0x8(%rbp), %rax
movl 0x30(%rax), %ecx
andq $-0x9, %rcx
movl %ecx, 0x30(%rax)
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
cmpl $0x1c, 0x90(%rax)
jae 0x95ee
movq -0x8(%rbp), %rax
cmpl $0x1b, 0x90(%rax)
jne 0x95d6
movq -0x8(%rbp), %rdi
movl $0x1, %esi
callq 0xb1a0
movq -0x8(%rbp), %rax
movl $0x500, 0x64(%rax)      # imm = 0x500
movq -0x8(%rbp), %rax
movl 0x90(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x90(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
movq -0x8(%rbp), %rax
movl 0x60(%rax), %eax
andq $0x400, %rax            # imm = 0x400
cmpq $0x0, %rax
jne 0x9646
movq -0x8(%rbp), %rax
cmpl $0x2b, 0x90(%rax)
jb 0x962e
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0xb1a0
jmp 0x9641
movq -0x8(%rbp), %rax
movl 0x90(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x90(%rax)
jmp 0x93cc
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
movq -0x8(%rbp), %rax
movl $0x0, 0x90(%rax)
movq -0x8(%rbp), %rax
movl 0x60(%rax), %eax
andq $0x400, %rax            # imm = 0x400
cmpq $0x0, %rax
jne 0x968a
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0xb1a0
jmp 0x93cc
movq -0x8(%rbp), %rax
movl 0x60(%rax), %eax
andq $0x200, %rax            # imm = 0x200
cmpq $0x0, %rax
jne 0x96a2
jmp 0x93cc
movq -0x8(%rbp), %rax
movl $0x100, 0x64(%rax)      # imm = 0x100
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
movl 0x78(%rax), %eax
movl %eax, -0x24(%rbp)
addl $0xffffff08, %eax       # imm = 0xFFFFFF08
subl $0x2, %eax
jb 0x96ea
jmp 0x96db
movl -0x24(%rbp), %eax
addl $0xffffff06, %eax       # imm = 0xFFFFFF06
subl $0x2, %eax
jb 0x96fa
jmp 0x970a
movq -0x8(%rbp), %rax
movl 0x34(%rax), %ecx
orq $0x20, %rcx
movl %ecx, 0x34(%rax)
jmp 0x971a
movq -0x8(%rbp), %rax
movl 0x34(%rax), %ecx
andq $-0x21, %rcx
movl %ecx, 0x34(%rax)
jmp 0x971a
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0xb1a0
jmp 0x93cc
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
movl 0x78(%rax), %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x48(%rax)
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movl 0x24(%rax), %eax
orq $0x40, %rax
movl %eax, %esi
callq 0xa860
movq -0x8(%rbp), %rcx
movl 0x50(%rcx), %eax
addl $-0x1, %eax
movl %eax, 0x50(%rcx)
cmpl $0x0, %eax
jne 0x977b
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
movl 0x8c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x9858
movq -0x8(%rbp), %rax
movl 0x54(%rax), %eax
andl $0xffff, %eax           # imm = 0xFFFF
cmpl $0x0, %eax
je 0x97dd
movq -0x8(%rbp), %rax
movl 0x30(%rax), %ecx
orq $0x8, %rcx
movl %ecx, 0x30(%rax)
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movl 0xc(%rax), %esi
subl -0x14(%rbp), %esi
callq 0xb200
movq -0x8(%rbp), %rax
movl 0x8(%rax), %ecx
orq $0x1, %rcx
movl %ecx, 0x8(%rax)
jmp 0x988f
movq -0x8(%rbp), %rax
movl 0x30(%rax), %ecx
andq $-0x9, %rcx
movl %ecx, 0x30(%rax)
movq -0x8(%rbp), %rax
movl 0x3c(%rax), %eax
andq $0x10, %rax
cmpq $0x0, %rax
je 0x9833
movq -0x8(%rbp), %rax
cmpl $0xff, 0x44(%rax)
jne 0x9816
movq -0x8(%rbp), %rax
movl $0x1, 0x44(%rax)
jmp 0x9823
movq -0x8(%rbp), %rax
movl 0x44(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x44(%rax)
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0xb1a0
jmp 0x93cc
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movl 0xc(%rax), %esi
subl -0x14(%rbp), %esi
callq 0xb200
movq -0x8(%rbp), %rax
movl 0x8(%rax), %ecx
orq $0x1, %rcx
movl %ecx, 0x8(%rax)
jmp 0x988f
jmp 0x9858
jmp 0x93cc
movq -0x8(%rbp), %rax
movl 0x8(%rax), %eax
andq $0x1, %rax
cmpq $0x0, %rax
je 0x987c
movq -0x8(%rbp), %rax
movl 0x30(%rax), %ecx
orq $0x10, %rcx
movl %ecx, 0x30(%rax)
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movl 0xc(%rax), %esi
subl -0x14(%rbp), %esi
callq 0xb200
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)