Example #1
0
void CUCode_AXWii::HandleCommandList()
{
	// Temp variables for addresses computation
	u16 addr_hi, addr_lo;
	u16 addr2_hi, addr2_lo;
	u16 volume;

	u32 pb_addr = 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, "-------------");

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

		if (m_old_axwii)
		{
			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_OLD:
					addr_hi = m_cmdlist[curr_idx++];
					addr_lo = m_cmdlist[curr_idx++];
					SetupProcessing(HILO_TO_32(addr));
					break;

				case CMD_ADD_TO_LR_OLD:
				case CMD_SUB_TO_LR_OLD:
					addr_hi = m_cmdlist[curr_idx++];
					addr_lo = m_cmdlist[curr_idx++];
					AddToLR(HILO_TO_32(addr), cmd == CMD_SUB_TO_LR_OLD);
					break;

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

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

				case CMD_PROCESS_OLD:
					ProcessPBList(pb_addr);
					break;

				case CMD_MIX_AUXA_OLD:
				case CMD_MIX_AUXB_OLD:
				case CMD_MIX_AUXC_OLD:
					volume = m_cmdlist[curr_idx++];
					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_OLD, HILO_TO_32(addr), HILO_TO_32(addr2), volume);
					break;

				case CMD_UPL_AUXA_MIX_LRSC_OLD:
				case CMD_UPL_AUXB_MIX_LRSC_OLD:
				{
					volume = m_cmdlist[curr_idx++];
					u32 addresses[6] = {
						(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
						(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
						(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
						(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
						(u32)(m_cmdlist[curr_idx + 8] << 16) | m_cmdlist[curr_idx + 9],
						(u32)(m_cmdlist[curr_idx + 10] << 16) | m_cmdlist[curr_idx + 11],
					};
					curr_idx += 12;
					UploadAUXMixLRSC(cmd == CMD_UPL_AUXB_MIX_LRSC_OLD, addresses, volume);
					break;
				}

				// TODO(delroth): figure this one out, it's used by almost every
				// game I've tested so far.
				case CMD_UNK_0B_OLD: curr_idx += 4; break;

				case CMD_OUTPUT_OLD:
				case CMD_OUTPUT_DPL2_OLD:
					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), 0x8000,
					             cmd == CMD_OUTPUT_DPL2_OLD);
					break;

				case CMD_WM_OUTPUT_OLD:
				{
					u32 addresses[4] = {
						(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
						(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
						(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
						(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
					};
					curr_idx += 8;
					OutputWMSamples(addresses);
					break;
				}

				case CMD_END_OLD:
					end = true;
					break;
			}
		}
		else
		{
			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_ADD_TO_LR:
				case CMD_SUB_TO_LR:
					addr_hi = m_cmdlist[curr_idx++];
					addr_lo = m_cmdlist[curr_idx++];
					AddToLR(HILO_TO_32(addr), cmd == CMD_SUB_TO_LR);
					break;

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

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

				case CMD_MIX_AUXA:
				case CMD_MIX_AUXB:
				case CMD_MIX_AUXC:
					volume = m_cmdlist[curr_idx++];
					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), volume);
					break;

				case CMD_UPL_AUXA_MIX_LRSC:
				case CMD_UPL_AUXB_MIX_LRSC:
				{
					volume = m_cmdlist[curr_idx++];
					u32 addresses[6] = {
						(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
						(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
						(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
						(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
						(u32)(m_cmdlist[curr_idx + 8] << 16) | m_cmdlist[curr_idx + 9],
						(u32)(m_cmdlist[curr_idx + 10] << 16) | m_cmdlist[curr_idx + 11],
					};
					curr_idx += 12;
					UploadAUXMixLRSC(cmd == CMD_UPL_AUXB_MIX_LRSC, addresses, volume);
					break;
				}

				// TODO(delroth): figure this one out, it's used by almost every
				// game I've tested so far.
				case CMD_UNK_0A: curr_idx += 4; break;

				case CMD_OUTPUT:
				case CMD_OUTPUT_DPL2:
					volume = m_cmdlist[curr_idx++];
					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), volume,
					              cmd == CMD_OUTPUT_DPL2);
					break;

				case CMD_WM_OUTPUT:
				{
					u32 addresses[4] = {
						(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
						(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
						(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
						(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
					};
					curr_idx += 8;
					OutputWMSamples(addresses);
					break;
				}

				case CMD_END:
					end = true;
					break;
			}
		}
	}
}
Example #2
0
void CUCode_AXWii::ProcessPBList(u32 pb_addr)
{
	AXPBWii pb;

	while (pb_addr)
	{
		AXBuffers buffers = {{
			m_samples_left,
			m_samples_right,
			m_samples_surround,
			m_samples_auxA_left,
			m_samples_auxA_right,
			m_samples_auxA_surround,
			m_samples_auxB_left,
			m_samples_auxB_right,
			m_samples_auxB_surround,
			m_samples_auxC_left,
			m_samples_auxC_right,
			m_samples_auxC_surround,
			m_samples_wm0,
			m_samples_aux0,
			m_samples_wm1,
			m_samples_aux1,
			m_samples_wm2,
			m_samples_aux2,
			m_samples_wm3,
			m_samples_aux3
		}};

		if (!ReadPB(pb_addr, pb))
			break;

		u16 num_updates[3];
		u16 updates[1024];
		u32 updates_addr;
		if (ExtractUpdatesFields(pb, num_updates, updates, &updates_addr))
		{
			for (int curr_ms = 0; curr_ms < 3; ++curr_ms)
			{
				ApplyUpdatesForMs(curr_ms, (u16*)&pb, num_updates, updates);
				ProcessVoice(pb, buffers, 32,
				             ConvertMixerControl(HILO_TO_32(pb.mixer_control)),
				             m_coeffs_available ? m_coeffs : NULL);

				// Forward the buffers
				for (u32 i = 0; i < sizeof (buffers.ptrs) / sizeof (buffers.ptrs[0]); ++i)
					buffers.ptrs[i] += 32;
			}
			ReinjectUpdatesFields(pb, num_updates, updates_addr);
		}
		else
		{
			ProcessVoice(pb, buffers, 96,
			             ConvertMixerControl(HILO_TO_32(pb.mixer_control)),
			             m_coeffs_available ? m_coeffs : NULL);
		}

		WritePB(pb_addr, pb);
		pb_addr = HILO_TO_32(pb.next_pb);
	}
}
Example #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;
		}
	}
}