Beispiel #1
0
void CUCode_AX::HandleMail(u32 mail)
{
	// Indicates if the next message is a command list address.
	static bool next_is_cmdlist = false;
	static u16 cmdlist_size = 0;

	bool set_next_is_cmdlist = false;

	// Wait for DSP processing to be done before answering any mail. This is
	// safe to do because it matches what the DSP does on real hardware: there
	// is no interrupt when a mail from CPU is received.
	m_processing.lock();

	if (next_is_cmdlist)
	{
		CopyCmdList(mail, cmdlist_size);
		StartWorking();
		NotifyAXThread();
	}
	else if (m_UploadSetupInProgress)
	{
		PrepareBootUCode(mail);
	}
	else if (mail == MAIL_RESUME)
	{
		// Acknowledge the resume request
		m_rMailHandler.PushMail(DSP_RESUME);
		DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
	}
	else if (mail == MAIL_NEW_UCODE)
	{
		soundStream->GetMixer()->SetHLEReady(false);
		m_UploadSetupInProgress = true;
	}
	else if (mail == MAIL_RESET)
	{
		m_DSPHLE->SetUCode(UCODE_ROM);
	}
	else if (mail == MAIL_CONTINUE)
	{
		// We don't have to do anything here - the CPU does not wait for a ACK
		// and sends a cmdlist mail just after.
	}
	else if ((mail & MAIL_CMDLIST_MASK) == MAIL_CMDLIST)
	{
		// A command list address is going to be sent next.
		set_next_is_cmdlist = true;
		cmdlist_size = (u16)(mail & ~MAIL_CMDLIST_MASK);
	}
	else
	{
		ERROR_LOG(DSPHLE, "Unknown mail sent to AX::HandleMail: %08x", mail);
	}

	m_processing.unlock();
	next_is_cmdlist = set_next_is_cmdlist;
}
Beispiel #2
0
void AXUCode::HandleMail(u32 mail)
{
	// Indicates if the next message is a command list address.
	static bool next_is_cmdlist = false;
	static u16 cmdlist_size = 0;

	bool set_next_is_cmdlist = false;

	if (next_is_cmdlist)
	{
		CopyCmdList(mail, cmdlist_size);
		HandleCommandList();
		m_cmdlist_size = 0;
		SignalWorkEnd();
	}
	else if (m_upload_setup_in_progress)
	{
		PrepareBootUCode(mail);
	}
	else if (mail == MAIL_RESUME)
	{
		// Acknowledge the resume request
		m_mail_handler.PushMail(DSP_RESUME);
		DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
	}
	else if (mail == MAIL_NEW_UCODE)
	{
		m_upload_setup_in_progress = true;
	}
	else if (mail == MAIL_RESET)
	{
		m_dsphle->SetUCode(UCODE_ROM);
	}
	else if (mail == MAIL_CONTINUE)
	{
		// We don't have to do anything here - the CPU does not wait for a ACK
		// and sends a cmdlist mail just after.
	}
	else if ((mail & MAIL_CMDLIST_MASK) == MAIL_CMDLIST)
	{
		// A command list address is going to be sent next.
		set_next_is_cmdlist = true;
		cmdlist_size = (u16)(mail & ~MAIL_CMDLIST_MASK);
	}
	else
	{
		ERROR_LOG(DSPHLE, "Unknown mail sent to AX::HandleMail: %08x", mail);
	}

	next_is_cmdlist = set_next_is_cmdlist;
}
Beispiel #3
0
void CUCode_AX::HandleCommandList()
{
	// Temp variables for addresses computation
	u16 addr_hi, addr_lo;
	u16 addr2_hi, addr2_lo;
	u16 size;

	u32 pb_addr = 0;

#if 0
	WARN_LOG(DSPHLE, "Command list:");
	for (u32 i = 0; m_cmdlist[i] != CMD_END; ++i)
		WARN_LOG(DSPHLE, "%04x", m_cmdlist[i]);
	WARN_LOG(DSPHLE, "-------------");
#endif

	u32 curr_idx = 0;
	bool end = false;
	while (!end)
	{
		u16 cmd = m_cmdlist[curr_idx++];

		switch (cmd)
		{
			// Some of these commands are unknown, or unused in this AX HLE.
			// We still need to skip their arguments using "curr_idx += N".

			case CMD_SETUP:
				addr_hi = m_cmdlist[curr_idx++];
				addr_lo = m_cmdlist[curr_idx++];
				SetupProcessing(HILO_TO_32(addr));
				break;

			case CMD_DL_AND_VOL_MIX:
			{
				addr_hi = m_cmdlist[curr_idx++];
				addr_lo = m_cmdlist[curr_idx++];
				u16 vol_main = m_cmdlist[curr_idx++];
				u16 vol_auxa = m_cmdlist[curr_idx++];
				u16 vol_auxb = m_cmdlist[curr_idx++];
				DownloadAndMixWithVolume(HILO_TO_32(addr), vol_main, vol_auxa, vol_auxb);
				break;
			}

			case CMD_PB_ADDR:
				addr_hi = m_cmdlist[curr_idx++];
				addr_lo = m_cmdlist[curr_idx++];
				pb_addr = HILO_TO_32(addr);
				break;

			case CMD_PROCESS:
				ProcessPBList(pb_addr);
				break;

			case CMD_MIX_AUXA:
			case CMD_MIX_AUXB:
				// These two commands are handled almost the same internally.
				addr_hi = m_cmdlist[curr_idx++];
				addr_lo = m_cmdlist[curr_idx++];
				addr2_hi = m_cmdlist[curr_idx++];
				addr2_lo = m_cmdlist[curr_idx++];
				MixAUXSamples(cmd - CMD_MIX_AUXA, HILO_TO_32(addr), HILO_TO_32(addr2));
				break;

			case CMD_UPLOAD_LRS:
				addr_hi = m_cmdlist[curr_idx++];
				addr_lo = m_cmdlist[curr_idx++];
				UploadLRS(HILO_TO_32(addr));
				break;

			case CMD_SET_LR:
				addr_hi = m_cmdlist[curr_idx++];
				addr_lo = m_cmdlist[curr_idx++];
				SetMainLR(HILO_TO_32(addr));
				break;

			case CMD_UNK_08: curr_idx += 10; break;	// TODO: check

			case CMD_MIX_AUXB_NOWRITE:
				addr_hi = m_cmdlist[curr_idx++];
				addr_lo = m_cmdlist[curr_idx++];
				MixAUXSamples(false, 0, HILO_TO_32(addr));
				break;

			case CMD_COMPRESSOR_TABLE_ADDR: curr_idx += 2; break;
			case CMD_UNK_0B: break; // TODO: check other versions
			case CMD_UNK_0C: break; // TODO: check other versions

			case CMD_MORE:
				addr_hi = m_cmdlist[curr_idx++];
				addr_lo = m_cmdlist[curr_idx++];
				size = m_cmdlist[curr_idx++];

				CopyCmdList(HILO_TO_32(addr), size);
				curr_idx = 0;
				break;

			case CMD_OUTPUT:
				addr_hi = m_cmdlist[curr_idx++];
				addr_lo = m_cmdlist[curr_idx++];
				addr2_hi = m_cmdlist[curr_idx++];
				addr2_lo = m_cmdlist[curr_idx++];
				OutputSamples(HILO_TO_32(addr2), HILO_TO_32(addr));
				break;

			case CMD_END:
				end = true;
				break;

			case CMD_MIX_AUXB_LR:
				addr_hi = m_cmdlist[curr_idx++];
				addr_lo = m_cmdlist[curr_idx++];
				addr2_hi = m_cmdlist[curr_idx++];
				addr2_lo = m_cmdlist[curr_idx++];
				MixAUXBLR(HILO_TO_32(addr), HILO_TO_32(addr2));
				break;

			case CMD_UNK_11: curr_idx += 2; break;

			case CMD_UNK_12:
			{
				u16 samp_val = m_cmdlist[curr_idx++];
				u16 idx = m_cmdlist[curr_idx++];
				addr_hi = m_cmdlist[curr_idx++];
				addr_lo = m_cmdlist[curr_idx++];

				// TODO
				(void)samp_val;
				(void)idx;

				break;
			}

			// Send the contents of MAIN LRS, AUXA LRS and AUXB S to RAM, and
			// mix data to MAIN LR and AUXB LR.
			case CMD_SEND_AUX_AND_MIX:
			{
				// Address for Main + AUXA LRS upload
				u16 main_auxa_up_hi = m_cmdlist[curr_idx++];
				u16 main_auxa_up_lo = m_cmdlist[curr_idx++];

				// Address for AUXB S upload
				u16 auxb_s_up_hi = m_cmdlist[curr_idx++];
				u16 auxb_s_up_lo = m_cmdlist[curr_idx++];

				// Address to read data for Main L
				u16 main_l_dl_hi = m_cmdlist[curr_idx++];
				u16 main_l_dl_lo = m_cmdlist[curr_idx++];

				// Address to read data for Main R
				u16 main_r_dl_hi = m_cmdlist[curr_idx++];
				u16 main_r_dl_lo = m_cmdlist[curr_idx++];

				// Address to read data for AUXB L
				u16 auxb_l_dl_hi = m_cmdlist[curr_idx++];
				u16 auxb_l_dl_lo = m_cmdlist[curr_idx++];

				// Address to read data for AUXB R
				u16 auxb_r_dl_hi = m_cmdlist[curr_idx++];
				u16 auxb_r_dl_lo = m_cmdlist[curr_idx++];

				SendAUXAndMix(HILO_TO_32(main_auxa_up), HILO_TO_32(auxb_s_up),
				              HILO_TO_32(main_l_dl), HILO_TO_32(main_r_dl),
				              HILO_TO_32(auxb_l_dl), HILO_TO_32(auxb_r_dl));
				break;
			}

			default:
				ERROR_LOG(DSPHLE, "Unknown command in AX cmdlist: %04x", cmd);
				end = true;
				break;
		}
	}
}