// File: OpenFodder[P]SOS_Unpacker/capsimg/CAPSImg/CapsFDCEmulator.cpp
// Function: FdcUpdateDrive(CapsFdc*, unsigned int)
void FdcUpdateDrive(PCAPSFDC pc, UDWORD cyc)
{
	// process all drives
	for (int drv=0; drv < pc->drivemax; drv++) {
		// get drive
		PCAPSDRIVE pd=pc->drive+drv;

		// set side selected
		pd->side=pd->newside;

		// skip stopped index counter
		int ic=pd->ipcnt;
		if (!ic)
			continue;

		// initialise counter to distance from index after start, add 1 to avoid 0 value (stopped)
		if (ic < 0) {
			pd->ipcnt=pd->idistance+1;
			continue;
		}

		// add cycles to counter
		ic+=cyc;

		// stop index counter when expired
		if (ic > pd->clockip) {
			ic=0;

			// clear index signal if active drive counter stopped
			if (drv == pc->driveact)
				pc->r_st0&=~CAPSFDC_SR_IP_DRQ;
		}

		pd->ipcnt=ic;
	}

	// no changes if drive selection is the same
	if (pc->drivenew == pc->drivesel)
		return;

	// drive selection changed, data lock lost
	pc->datalock=-1;

	// if no drive selected, clear wp, ip, tr0, enable force change
	if (pc->drivenew < 0) {
		pc->drivenew=-1;
		pc->drivesel=-1;
		pc->driveact=-1;
		pc->driveprc=NULL;
		pc->r_st0&=~(CAPSFDC_SR_WP|CAPSFDC_SR_TR0_LD|CAPSFDC_SR_IP_DRQ);
		return;
	}

	// select new drive
	pc->drivesel=pc->drivenew;

	// if invalid drive selected, clear wp, ip, tr0
	if (pc->drivenew >= pc->drivemax) {
		pc->driveact=-1;
		pc->driveprc=NULL;
		pc->r_st0&=~(CAPSFDC_SR_WP|CAPSFDC_SR_TR0_LD|CAPSFDC_SR_IP_DRQ);
		return;
	}

	// new drive is valid
	pc->driveact=pc->drivenew;
	pc->driveprc=pc->drive+pc->driveact;

	// set motor state
	UDWORD attr=pc->driveprc->diskattr;
	if (pc->lineout & CAPSFDC_LO_MO)
		attr|=CAPSDRIVE_DA_MO;
	else
		attr&=~CAPSDRIVE_DA_MO;
	pc->driveprc->diskattr=attr;

	// check selected drive, wp, ip, tr0 default to clear
	UDWORD st0=pc->r_st0 & ~(CAPSFDC_SR_WP|CAPSFDC_SR_TR0_LD|CAPSFDC_SR_IP_DRQ);

	// get tr0
	if (!pc->driveprc->track)
		st0|=CAPSFDC_SR_TR0_LD;

	if (attr & CAPSDRIVE_DA_IN) {
		// disk inserted, get wp
		if (attr & CAPSDRIVE_DA_WP)
			st0 |= CAPSFDC_SR_WP;
	} else {
		// no disk, set wp
		st0|=CAPSFDC_SR_WP;
	}

	// set index signal if counter is active on selected drive
	if (pc->driveprc->ipcnt)
		st0|=CAPSFDC_SR_IP_DRQ;

	// set new status
	pc->r_st0=st0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl $0x0, -0x10(%rbp)
movl -0x10(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0xf0(%rcx), %eax
jge 0xa59b
movq -0x8(%rbp), %rax
movq 0x108(%rax), %rax
movslq -0x10(%rbp), %rcx
imulq $0x78, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl 0x1c(%rax), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x14(%rax)
movq -0x18(%rbp), %rax
movl 0x30(%rax), %eax
movl %eax, -0x1c(%rbp)
cmpl $0x0, -0x1c(%rbp)
jne 0xa52f
jmp 0xa58d
cmpl $0x0, -0x1c(%rbp)
jge 0xa548
movq -0x18(%rbp), %rax
movl 0x24(%rax), %ecx
addl $0x1, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x30(%rax)
jmp 0xa58d
movl -0xc(%rbp), %eax
addl -0x1c(%rbp), %eax
movl %eax, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl 0x2c(%rcx), %eax
jle 0xa583
movl $0x0, -0x1c(%rbp)
movl -0x10(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0xfc(%rcx), %eax
jne 0xa581
movq -0x8(%rbp), %rax
movl 0x30(%rax), %ecx
andq $-0x3, %rcx
movl %ecx, 0x30(%rax)
jmp 0xa583
movl -0x1c(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x30(%rax)
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
jmp 0xa4e2
movq -0x8(%rbp), %rax
movl 0xf4(%rax), %eax
movq -0x8(%rbp), %rcx
cmpl 0xf8(%rcx), %eax
jne 0xa5b6
jmp 0xa77a
movq -0x8(%rbp), %rax
movl $0xffffffff, 0x80(%rax) # imm = 0xFFFFFFFF
movq -0x8(%rbp), %rax
cmpl $0x0, 0xf4(%rax)
jge 0xa61d
movq -0x8(%rbp), %rax
movl $0xffffffff, 0xf4(%rax) # imm = 0xFFFFFFFF
movq -0x8(%rbp), %rax
movl $0xffffffff, 0xf8(%rax) # imm = 0xFFFFFFFF
movq -0x8(%rbp), %rax
movl $0xffffffff, 0xfc(%rax) # imm = 0xFFFFFFFF
movq -0x8(%rbp), %rax
movq $0x0, 0x100(%rax)
movq -0x8(%rbp), %rax
movl 0x30(%rax), %ecx
andq $-0x47, %rcx
movl %ecx, 0x30(%rax)
jmp 0xa77a
movq -0x8(%rbp), %rax
movl 0xf4(%rax), %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0xf8(%rax)
movq -0x8(%rbp), %rax
movl 0xf4(%rax), %eax
movq -0x8(%rbp), %rcx
cmpl 0xf0(%rcx), %eax
jl 0xa677
movq -0x8(%rbp), %rax
movl $0xffffffff, 0xfc(%rax) # imm = 0xFFFFFFFF
movq -0x8(%rbp), %rax
movq $0x0, 0x100(%rax)
movq -0x8(%rbp), %rax
movl 0x30(%rax), %ecx
andq $-0x47, %rcx
movl %ecx, 0x30(%rax)
jmp 0xa77a
movq -0x8(%rbp), %rax
movl 0xf4(%rax), %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0xfc(%rax)
movq -0x8(%rbp), %rax
movq 0x108(%rax), %rcx
movq -0x8(%rbp), %rax
movslq 0xfc(%rax), %rax
imulq $0x78, %rax, %rax
addq %rax, %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x100(%rax)
movq -0x8(%rbp), %rax
movq 0x100(%rax), %rax
movl 0x20(%rax), %eax
movl %eax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movl 0x24(%rax), %eax
andq $0x8, %rax
cmpq $0x0, %rax
je 0xa6e1
movl -0x20(%rbp), %eax
orq $0x4, %rax
movl %eax, -0x20(%rbp)
jmp 0xa6eb
movl -0x20(%rbp), %eax
andq $-0x5, %rax
movl %eax, -0x20(%rbp)
movl -0x20(%rbp), %ecx
movq -0x8(%rbp), %rax
movq 0x100(%rax), %rax
movl %ecx, 0x20(%rax)
movq -0x8(%rbp), %rax
movl 0x30(%rax), %eax
andq $-0x47, %rax
movl %eax, -0x24(%rbp)
movq -0x8(%rbp), %rax
movq 0x100(%rax), %rax
cmpl $0x0, 0xc(%rax)
jne 0xa725
movl -0x24(%rbp), %eax
orq $0x4, %rax
movl %eax, -0x24(%rbp)
movl -0x20(%rbp), %eax
andq $0x1, %rax
cmpq $0x0, %rax
je 0xa74b
movl -0x20(%rbp), %eax
andq $0x2, %rax
cmpq $0x0, %rax
je 0xa749
movl -0x24(%rbp), %eax
orq $0x40, %rax
movl %eax, -0x24(%rbp)
jmp 0xa755
movl -0x24(%rbp), %eax
orq $0x40, %rax
movl %eax, -0x24(%rbp)
movq -0x8(%rbp), %rax
movq 0x100(%rax), %rax
cmpl $0x0, 0x30(%rax)
je 0xa770
movl -0x24(%rbp), %eax
orq $0x2, %rax
movl %eax, -0x24(%rbp)
movl -0x24(%rbp), %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x30(%rax)
popq %rbp
retq
nopl (%rax)