Merge pull request #10892 from Pokechu22/dsp-hle-aesnd-more-versions
DSPHLE: Support EDuke32 Wii libaesnd uCode
This commit is contained in:
commit
c7752f80e4
|
@ -26,19 +26,6 @@ constexpr u32 MAIL_GET_PB_ADDRESS = MAIL_PREFIX | 0x0080;
|
|||
constexpr u32 MAIL_SEND_SAMPLES = MAIL_PREFIX | 0x0100;
|
||||
constexpr u32 MAIL_TERMINATE = MAIL_PREFIX | 0xdead;
|
||||
|
||||
// June 5, 2010 version (padded to 0x03e0 bytes) - initial release
|
||||
// First included with libogc 1.8.4 on October 3, 2010: https://devkitpro.org/viewtopic.php?t=2249
|
||||
// https://github.com/devkitPro/libogc/blob/b5fdbdb069c45584aa4dfd950a136a8db9b1144c/libaesnd/dspcode/dspmixer.s
|
||||
constexpr u32 HASH_2010 = 0x008366af;
|
||||
// April 11, 2012 version (padded to 0x03e0 bytes) - swapped input channels
|
||||
// First included with libogc 1.8.11 on April 22, 2012: https://devkitpro.org/viewtopic.php?t=3094
|
||||
// https://github.com/devkitPro/libogc/commit/8f188e12b6a3d8b5a0d49a109fe6a3e4e1702aab
|
||||
constexpr u32 HASH_2012 = 0x078066ab;
|
||||
// June 14, 2020 version (0x03e6 bytes) - added unsigned formats
|
||||
// First included with libogc 2.1.0 on June 15, 2020: https://devkitpro.org/viewtopic.php?t=9079
|
||||
// https://github.com/devkitPro/libogc/commit/eac8fe2c29aa790d552dd6166a1fb195dfdcb825
|
||||
constexpr u32 HASH_2020 = 0x84c680a9;
|
||||
|
||||
constexpr u32 VOICE_MONO8 = 0x00000000;
|
||||
constexpr u32 VOICE_STEREO8 = 0x00000001;
|
||||
constexpr u32 VOICE_MONO16 = 0x00000002;
|
||||
|
@ -81,6 +68,16 @@ constexpr u32 ACCELERATOR_GAIN_8_BIT = 0x0100;
|
|||
// Multiply samples by 0x800/2048 = 1 (for ACCELERATOR_FORMAT_16_BIT)
|
||||
constexpr u32 ACCELERATOR_GAIN_16_BIT = 0x0800;
|
||||
|
||||
bool AESndUCode::SwapLeftRight() const
|
||||
{
|
||||
return m_crc == HASH_2012 || m_crc == HASH_EDUKE32 || m_crc == HASH_2020;
|
||||
}
|
||||
|
||||
bool AESndUCode::UseNewFlagMasks() const
|
||||
{
|
||||
return m_crc == HASH_EDUKE32 || m_crc == HASH_2020;
|
||||
}
|
||||
|
||||
AESndUCode::AESndUCode(DSPHLE* dsphle, u32 crc) : UCodeInterface(dsphle, crc)
|
||||
{
|
||||
}
|
||||
|
@ -136,25 +133,25 @@ void AESndUCode::HandleMail(u32 mail)
|
|||
switch (mail)
|
||||
{
|
||||
case MAIL_PROCESS_FIRST_VOICE:
|
||||
DEBUG_LOG_FMT(DSPHLE, "ASndUCode - MAIL_PROCESS_FIRST_VOICE");
|
||||
DEBUG_LOG_FMT(DSPHLE, "AESndUCode - MAIL_PROCESS_FIRST_VOICE");
|
||||
DMAInParameterBlock(); // dma_pb_block
|
||||
m_output_buffer.fill(0);
|
||||
DoMixing(); // fall through to dsp_mixer
|
||||
// Mail is handled by DoMixing()
|
||||
break;
|
||||
case MAIL_PROCESS_NEXT_VOICE:
|
||||
DEBUG_LOG_FMT(DSPHLE, "ASndUCode - MAIL_PROCESS_NEXT_VOICE");
|
||||
DEBUG_LOG_FMT(DSPHLE, "AESndUCode - MAIL_PROCESS_NEXT_VOICE");
|
||||
DMAInParameterBlock(); // dma_pb_block
|
||||
DoMixing(); // jump to dsp_mixer
|
||||
// Mail is handled by DoMixing()
|
||||
break;
|
||||
case MAIL_GET_PB_ADDRESS:
|
||||
DEBUG_LOG_FMT(DSPHLE, "ASndUCode - MAIL_GET_PB_ADDRESS");
|
||||
DEBUG_LOG_FMT(DSPHLE, "AESndUCode - MAIL_GET_PB_ADDRESS");
|
||||
m_next_mail_is_parameter_block_addr = true;
|
||||
// No mail is sent in response
|
||||
break;
|
||||
case MAIL_SEND_SAMPLES:
|
||||
DEBUG_LOG_FMT(DSPHLE, "ASndUCode - MAIL_SEND_SAMPLES");
|
||||
DEBUG_LOG_FMT(DSPHLE, "AESndUCode - MAIL_SEND_SAMPLES");
|
||||
// send_samples
|
||||
for (u32 i = 0; i < NUM_OUTPUT_SAMPLES * 2; i++)
|
||||
{
|
||||
|
@ -163,8 +160,31 @@ void AESndUCode::HandleMail(u32 mail)
|
|||
m_mail_handler.PushMail(DSP_SYNC, true);
|
||||
break;
|
||||
case MAIL_TERMINATE:
|
||||
INFO_LOG_FMT(DSPHLE, "ASndUCode - MAIL_TERMINATE: {:08x}", mail);
|
||||
// This doesn't actually change the state of the system.
|
||||
INFO_LOG_FMT(DSPHLE, "AESndUCode - MAIL_TERMINATE: {:08x}", mail);
|
||||
if (true) // currently no mainline libogc uCode has this issue fixed
|
||||
{
|
||||
// The relevant code looks like this:
|
||||
//
|
||||
// lrs $acc1.m,@CMBL
|
||||
// ...
|
||||
// cmpi $acc1.m,#0xdead
|
||||
// jeq task_terminate
|
||||
//
|
||||
// The cmpi instruction always sign-extends, so it will compare $acc1 with 0xff'dead'0000.
|
||||
// However, recv_cmd runs in set16 mode, so the load to $acc1 will produce 0x00'dead'0000.
|
||||
// This means that the comparison never succeeds, and no mail is sent in response to
|
||||
// MAIL_TERMINATE. This means that __dsp_donecallback is never called (since that's
|
||||
// normally called in response to DSP_DONE), so __aesnddspinit is never cleared, so
|
||||
// AESND_Reset never returns, resulting in a hang. We always send the mail to avoid this
|
||||
// hang. (It's possible to exit without calling AESND_Reset, so most homebrew probably
|
||||
// isn't affected by this bug in the first place.)
|
||||
//
|
||||
// A fix exists, but has not yet been added to mainline libogc:
|
||||
// https://github.com/extremscorner/libogc2/commit/38edc9db93232faa612f680c91be1eb4d95dd1c6
|
||||
WARN_LOG_FMT(DSPHLE, "AESndUCode - MAIL_TERMINATE is broken in this version of the "
|
||||
"uCode; this will hang on real hardware or with DSP LLE");
|
||||
}
|
||||
// This doesn't actually change the state of the DSP code.
|
||||
m_mail_handler.PushMail(DSP_DONE, true);
|
||||
break;
|
||||
default:
|
||||
|
@ -248,8 +268,8 @@ void AESndUCode::SetUpAccelerator(u16 format, [[maybe_unused]] u16 gain)
|
|||
|
||||
void AESndUCode::DoMixing()
|
||||
{
|
||||
const u32 pause_flag = (m_crc == HASH_2020) ? VOICE_PAUSE_NEW : VOICE_PAUSE_OLD;
|
||||
const u32 format_mask = (m_crc == HASH_2020) ? VOICE_FORMAT_MASK_NEW : VOICE_FORMAT_MASK_OLD;
|
||||
const u32 pause_flag = UseNewFlagMasks() ? VOICE_PAUSE_NEW : VOICE_PAUSE_OLD;
|
||||
const u32 format_mask = UseNewFlagMasks() ? VOICE_FORMAT_MASK_NEW : VOICE_FORMAT_MASK_OLD;
|
||||
// dsp_mixer
|
||||
const bool paused = (m_parameter_block.flags & pause_flag) != 0;
|
||||
const bool running = (m_parameter_block.flags & VOICE_RUNNING) != 0;
|
||||
|
@ -259,6 +279,22 @@ void AESndUCode::DoMixing()
|
|||
// no_change_buffer
|
||||
const u32 voice_format = m_parameter_block.flags & format_mask;
|
||||
const bool is_16_bit = (voice_format & VOICE_16_BIT_FLAG) != 0;
|
||||
if (m_crc == HASH_EDUKE32)
|
||||
{
|
||||
if (voice_format != VOICE_STEREO8 && voice_format != VOICE_STEREO16 &&
|
||||
voice_format != VOICE_STEREO8_UNSIGNED)
|
||||
{
|
||||
// The EDuke32 Wii version does not support 16-but unsigned stereo, and also has broken
|
||||
// handling of all mono formats.
|
||||
if (!m_has_shown_unsupported_sample_format_warning)
|
||||
{
|
||||
m_has_shown_unsupported_sample_format_warning = true;
|
||||
PanicAlertFmt("EDuke32 Wii aesndlib uCode does not correctly handle this sample format: "
|
||||
"{} (flags: {:08x})",
|
||||
voice_format, m_parameter_block.flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
// select_format table
|
||||
const u16 accelerator_format = is_16_bit ? ACCELERATOR_FORMAT_16_BIT : ACCELERATOR_FORMAT_8_BIT;
|
||||
const u16 accelerator_gain = is_16_bit ? ACCELERATOR_GAIN_16_BIT : ACCELERATOR_GAIN_8_BIT;
|
||||
|
@ -363,7 +399,7 @@ void AESndUCode::DoMixing()
|
|||
new_l ^= 0x8000;
|
||||
break;
|
||||
}
|
||||
if (m_crc == HASH_2012 || m_crc == HASH_2020)
|
||||
if (SwapLeftRight())
|
||||
{
|
||||
// The 2012 version swapped the left and right input channels so that left comes first,
|
||||
// and then right. Before, right came before left. The 2012 version didn't update comments
|
||||
|
|
|
@ -23,12 +23,32 @@ public:
|
|||
void Update() override;
|
||||
void DoState(PointerWrap& p) override;
|
||||
|
||||
// June 5, 2010 version (padded to 0x03e0 bytes) - initial release
|
||||
// First included with libogc 1.8.4 on October 3, 2010: https://devkitpro.org/viewtopic.php?t=2249
|
||||
// https://github.com/devkitPro/libogc/blob/b5fdbdb069c45584aa4dfd950a136a8db9b1144c/libaesnd/dspcode/dspmixer.s
|
||||
static constexpr u32 HASH_2010 = 0x008366af;
|
||||
// April 11, 2012 version (padded to 0x03e0 bytes) - swapped input channels
|
||||
// First included with libogc 1.8.11 on April 22, 2012: https://devkitpro.org/viewtopic.php?t=3094
|
||||
// https://github.com/devkitPro/libogc/commit/8f188e12b6a3d8b5a0d49a109fe6a3e4e1702aab
|
||||
static constexpr u32 HASH_2012 = 0x078066ab;
|
||||
// Modified version used by EDuke32 Wii (padded to 0x03e0 bytes) - added unsigned 8-bit formats;
|
||||
// broke the mono formats. The patch is based on the 2010 version, but it also includes the 2012
|
||||
// input channel swap change. https://dukeworld.duke4.net/eduke32/wii/library_source_code/
|
||||
static constexpr u32 HASH_EDUKE32 = 0x5ad4d933;
|
||||
// June 14, 2020 version (0x03e6 bytes) - added unsigned formats
|
||||
// First included with libogc 2.1.0 on June 15, 2020: https://devkitpro.org/viewtopic.php?t=9079
|
||||
// https://github.com/devkitPro/libogc/commit/eac8fe2c29aa790d552dd6166a1fb195dfdcb825
|
||||
static constexpr u32 HASH_2020 = 0x84c680a9;
|
||||
|
||||
private:
|
||||
void DMAInParameterBlock();
|
||||
void DMAOutParameterBlock();
|
||||
void SetUpAccelerator(u16 format, u16 gain);
|
||||
void DoMixing();
|
||||
|
||||
bool SwapLeftRight() const;
|
||||
bool UseNewFlagMasks() const;
|
||||
|
||||
// Copied from libaesnd/aesndlib.c's aesndpb_t (specifically the first 64 bytes)
|
||||
#pragma pack(1)
|
||||
struct ParameterBlock
|
||||
|
@ -70,5 +90,7 @@ private:
|
|||
static constexpr u32 NUM_OUTPUT_SAMPLES = 96;
|
||||
|
||||
std::array<s16, NUM_OUTPUT_SAMPLES * 2> m_output_buffer{};
|
||||
|
||||
bool m_has_shown_unsupported_sample_format_warning = false;
|
||||
};
|
||||
} // namespace DSP::HLE
|
||||
|
|
|
@ -52,27 +52,6 @@ constexpr u32 NEW_FLAGS_SAMPLE_FORMAT_MASK = 7;
|
|||
constexpr u32 FLAGS_SAMPLE_FORMAT_BYTES_MASK = 0xffff0000;
|
||||
constexpr u32 FLAGS_SAMPLE_FORMAT_BYTES_SHIFT = 16;
|
||||
|
||||
// November 14, 2008 version (padded to 0x05a0 bytes) - initial release
|
||||
// https://github.com/devkitPro/libogc/compare/c76d8b851fafc11b0a5debc0b40842929d5a5825~...353a44f038e75e5982eb550173ec8127ab35e3e3
|
||||
constexpr u32 HASH_2008 = 0x8d69a19b;
|
||||
// February 5, 2009 version (padded to 0x05c0 bytes) - added MAIL_TERMINATE
|
||||
// https://github.com/devkitPro/libogc/compare/1925217ffb4c97cbee5cf21fa3c0231029b340e2~...3b1f018dbe372859a43bff8560e2525f6efa4433
|
||||
constexpr u32 HASH_2009 = 0xcc2fd441;
|
||||
// June 11, 2011 version (padded to 0x0620 bytes) - added new sample formats, which shifted flags
|
||||
// Note that the source include in the repo does not match the compiled binary exactly; the compiled
|
||||
// version differs by using asl instead of lsl, $acc1 instead of $acc0, and $ac0.l instead of $ac0.m
|
||||
// in various locations, as well as having the "jmp out_samp" line uncommented in stereo_16bits_le.
|
||||
// None of these result in a behavior difference, from the source, though.
|
||||
// Note that gcdsptool was also updated, which results in some differences in the source that don't
|
||||
// actually correspond to different instructions (e.g. s40 was renamed to s16)
|
||||
// https://github.com/devkitPro/libogc/commit/b1b8ecab3af3745c8df0b401abd512bdf5fcc011
|
||||
constexpr u32 HASH_2011 = 0xa81582e2;
|
||||
// June 12, 2020 version (0x0606 bytes) - libogc switched to compiling the ucode at build time
|
||||
// instead of including a pre-compiled version in the repo, so this now corresponds to the code
|
||||
// provided in the repo. There appear to be no behavior differences from the 2011 version.
|
||||
// https://github.com/devkitPro/libogc/compare/bfb705fe1607a3031d18b65d603975b68a1cffd4~...d20f9bdcfb43260c6c759f4fb98d724931443f93
|
||||
constexpr u32 HASH_2020 = 0xdbbeeb61;
|
||||
|
||||
constexpr u32 SAMPLE_RATE = 48000;
|
||||
|
||||
ASndUCode::ASndUCode(DSPHLE* dsphle, u32 crc) : UCodeInterface(dsphle, crc)
|
||||
|
|
|
@ -23,6 +23,27 @@ public:
|
|||
void Update() override;
|
||||
void DoState(PointerWrap& p) override;
|
||||
|
||||
// November 14, 2008 version (padded to 0x05a0 bytes) - initial release
|
||||
// https://github.com/devkitPro/libogc/compare/c76d8b851fafc11b0a5debc0b40842929d5a5825~...353a44f038e75e5982eb550173ec8127ab35e3e3
|
||||
static constexpr u32 HASH_2008 = 0x8d69a19b;
|
||||
// February 5, 2009 version (padded to 0x05c0 bytes) - added MAIL_TERMINATE
|
||||
// https://github.com/devkitPro/libogc/compare/1925217ffb4c97cbee5cf21fa3c0231029b340e2~...3b1f018dbe372859a43bff8560e2525f6efa4433
|
||||
static constexpr u32 HASH_2009 = 0xcc2fd441;
|
||||
// June 11, 2011 version (padded to 0x0620 bytes) - added new sample formats, which shifted flags
|
||||
// Note that the source include in the repo does not match the compiled binary exactly; the
|
||||
// compiled version differs by using asl instead of lsl, $acc1 instead of $acc0, and $ac0.l
|
||||
// instead of $ac0.m in various locations, as well as having the "jmp out_samp" line uncommented
|
||||
// in stereo_16bits_le. None of these result in a behavior difference, from the source, though.
|
||||
// Note that gcdsptool was also updated, which results in some differences in the source that
|
||||
// don't actually correspond to different instructions (e.g. s40 was renamed to s16)
|
||||
// https://github.com/devkitPro/libogc/commit/b1b8ecab3af3745c8df0b401abd512bdf5fcc011
|
||||
static constexpr u32 HASH_2011 = 0xa81582e2;
|
||||
// June 12, 2020 version (0x0606 bytes) - libogc switched to compiling the ucode at build time
|
||||
// instead of including a pre-compiled version in the repo, so this now corresponds to the code
|
||||
// provided in the repo. There appear to be no behavior differences from the 2011 version.
|
||||
// https://github.com/devkitPro/libogc/compare/bfb705fe1607a3031d18b65d603975b68a1cffd4~...d20f9bdcfb43260c6c759f4fb98d724931443f93
|
||||
static constexpr u32 HASH_2020 = 0xdbbeeb61;
|
||||
|
||||
private:
|
||||
void DMAInVoiceData();
|
||||
void DMAOutVoiceData();
|
||||
|
|
|
@ -284,16 +284,17 @@ std::unique_ptr<UCodeInterface> UCodeFactory(u32 crc, DSPHLE* dsphle, bool wii)
|
|||
INFO_LOG_FMT(DSPHLE, "CRC {:08x}: Wii - AXWii chosen", crc);
|
||||
return std::make_unique<AXWiiUCode>(dsphle, crc);
|
||||
|
||||
case 0x8d69a19b:
|
||||
case 0xcc2fd441:
|
||||
case 0xa81582e2:
|
||||
case 0xdbbeeb61:
|
||||
case ASndUCode::HASH_2008:
|
||||
case ASndUCode::HASH_2009:
|
||||
case ASndUCode::HASH_2011:
|
||||
case ASndUCode::HASH_2020:
|
||||
INFO_LOG_FMT(DSPHLE, "CRC {:08x}: ASnd chosen (Homebrew)", crc);
|
||||
return std::make_unique<ASndUCode>(dsphle, crc);
|
||||
|
||||
case 0x008366af:
|
||||
case 0x078066ab:
|
||||
case 0x84c680a9:
|
||||
case AESndUCode::HASH_2010:
|
||||
case AESndUCode::HASH_2012:
|
||||
case AESndUCode::HASH_EDUKE32:
|
||||
case AESndUCode::HASH_2020:
|
||||
INFO_LOG_FMT(DSPHLE, "CRC {:08x}: AESnd chosen (Homebrew)", crc);
|
||||
return std::make_unique<AESndUCode>(dsphle, crc);
|
||||
|
||||
|
|
Loading…
Reference in New Issue