100% match and link JASTrack (#772)

* Almost fully match JASTrack, regalloc in writeRegParam

* 100% match JASTrack

* Move constructor to header to link successfully
This commit is contained in:
Ammar Askar
2025-05-27 21:02:24 -04:00
committed by GitHub
parent 693c92638f
commit 255d01c6db
7 changed files with 508 additions and 53 deletions
+1 -1
View File
@@ -789,7 +789,7 @@ config.libs = [
Object(Matching, "JSystem/JAudio/JASRegisterParam.cpp"),
Object(Matching, "JSystem/JAudio/JASSeqCtrl.cpp"),
Object(Matching, "JSystem/JAudio/JASSeqParser.cpp"),
Object(NonMatching, "JSystem/JAudio/JASTrack.cpp"),
Object(Matching, "JSystem/JAudio/JASTrack.cpp"),
Object(Matching, "JSystem/JAudio/JASTrackInterrupt.cpp"),
Object(Matching, "JSystem/JAudio/JASTrackPort.cpp"),
Object(Matching, "JSystem/JAudio/JASBank.cpp"),
+20 -6
View File
@@ -22,14 +22,28 @@ namespace JASystem {
JUT_ASSERT(131, index < 4);
return field_0x20[index];
}
void setAddress(int, u32) {}
void setAddress(int index, u32 value) {
JUT_ASSERT(124, index >= 0);
JUT_ASSERT(125, index < 4);
field_0x20[index] = value;
}
void getBendSense() const {}
void getPanPowerBank() const {}
void getPanPowerExt() const {}
void getPanPowerOsc() const {}
void getPanPowerParent() const {}
void getPanPowerTrack() const {}
u16 getPanPowerBank() const {
return mPanPower[0];
}
u16 getPanPowerExt() const {
return mPanPower[1];
}
u16 getPanPowerOsc() const {
return mPanPower[2];
}
u16 getPanPowerParent() const {
return mPanPower[3];
}
u16 getPanPowerTrack() const {
return mPanPower[4];
}
void getPriority() const {}
u16 getFlag() const { return field_0x0[3]; }
void setFlag(u16 flag) { field_0x0[3] = flag; }
+19 -2
View File
@@ -119,7 +119,24 @@ namespace JASystem {
class AInnerParam_ {
public:
AInnerParam_();
AInnerParam_()
: mVolume()
, mPitch()
, mFxmix()
, mPan()
, mDolby()
, _50()
, mOsc0Width()
, mOsc0Rate()
, mOsc0Vertex()
, mOsc1Width()
, mOsc1Rate()
, mOsc1Vertex()
, mIIRs()
, _100()
, _110()
{
}
/* 0x000 */ MoveParam_ mVolume;
/* 0x010 */ MoveParam_ mPitch;
@@ -306,7 +323,7 @@ namespace JASystem {
/* 0x37E */ u8 field_0x37e;
/* 0x37F */ u8 mCalcTypes[3];
/* 0x382 */ u8 mParentCalcTypes[3];
/* 0x385 */ u8 mIsPaused;
/* 0x385 */ bool mIsPaused;
/* 0x386 */ u8 field_0x386;
/* 0x387 */ bool field_0x387;
/* 0x388 */ u8 field_0x388;
@@ -4,6 +4,17 @@
#include "dolphin/types.h"
namespace JASystem {
enum RequestId {
REQUEST_UNK_0 = 0,
REQUEST_UNK_1 = 1,
REQUEST_UNK_2 = 2,
REQUEST_UNK_3 = 3,
REQUEST_UNK_4 = 4,
REQUEST_UNK_5 = 5,
REQUEST_UNK_6 = 6,
REQUEST_UNK_7 = 7,
};
class TIntrMgr {
public:
void disable() { field_0x0 = 0; }
+21
View File
@@ -155,6 +155,27 @@ inline void OSf32tou8(f32* f, u8* out) {
*out = __OSf32tou8(*f);
}
inline s8 __OSf32tos8(register f32 inF) {
register u8 out;
u32 tmp;
register u32* tmpPtr = &tmp;
// clang-format off
#ifdef __MWERKS__
asm {
psq_st inF, 0(tmpPtr), 0x1, 4
lbz out, 0(tmpPtr)
extsb out, out
}
#endif
// clang-format on
return out;
}
inline void OSf32tos8(f32* f, s8* out) {
*out = __OSf32tos8(*f);
}
static inline void OSInitFastCast(void) {
// clang-format off
#ifdef __MWERKS__
+435 -43
View File
@@ -143,7 +143,7 @@ s8 JASystem::TTrack::mainProc() {
mParent->mChannelUpdater.field_0x0++;
}
}
mIntrMgr.request(7);
mIntrMgr.request(REQUEST_UNK_7);
mIntrMgr.timerProcess();
tryInterrupt();
if (mIsPaused == 0 || (mPauseStatus & 2) == 0) {
@@ -319,7 +319,7 @@ int JASystem::TTrack::noteOn(u8 param_1, s32 param_2, s32 param_3, s32 param_4,
}
mNoteMgr.setChannel(param_1, channel);
channel->field_0xe8 = param_5;
channel->setPanPower(mRegisterParam.mPanPower[0], mRegisterParam.mPanPower[1], mRegisterParam.mPanPower[2], 0.0f);
channel->setPanPower(mRegisterParam.getPanPowerBank(), mRegisterParam.getPanPowerExt(), mRegisterParam.getPanPowerOsc(), 0.0f);
overwriteOsc(channel);
if (field_0x374) {
channel->directReleaseOsc(0, field_0x374);
@@ -498,30 +498,248 @@ void JASystem::TTrack::updateTimedParam() {
/* 80281AA4-80281E90 .text updateTrackAll__Q28JASystem6TTrackFv */
void JASystem::TTrack::updateTrackAll() {
/* Nonmatching */
if (field_0x37b == 4) {
return;
}
f32 panWeight = mRegisterParam.field_0x20[0] / 32767.0f;
mChannelUpdater.field_0x68 = mTimedParam.mMoveParams[TIMED_IIR_Unk2].mCurrentValue;
f32 pitch;
f32 vol;
f32 pan;
f32 fx_vol;
f32 dolby;
f32 pan_weight = mRegisterParam.getPanPowerParent() / 32767.0f;
mChannelUpdater.field_0x68 = mRegisterParam.field_0x1a | 0x10000;
mChannelUpdater.field_0x6c = 0;
f32 delay = mTimedParam.mMoveParams[TIMED_Osc1_Rate].mCurrentValue * 128.0f;
panCalc(panWeight, delay, 0.0f, 1);
f32 delayF = mTimedParam.mMoveParams[TIMED_Unk17].mCurrentValue * 128.0f;
s8 delay;
s8 unk = 0;
OSf32tos8(&delayF, &delay);
if (delay < 0) {
unk = -delay;
delay = 0;
}
// if (...) {
//}
// else {
//
mChannelUpdater.field_0x61 = mChannelUpdater.field_0x61 | 0x20;
mChannelUpdater.field_0x60 = 16;
mChannelUpdater.field_0x5a[0] = unk;
mChannelUpdater.field_0x5a[1] = delay;
vol = mTimedParam.mMoveParams[TIMED_Volume].mCurrentValue;
if (mVolumeMode == 0) {
vol *= vol;
}
if (field_0x386) {
vol = 0.0f;
}
f32 cent = Player::pitchToCent(mTimedParam.mMoveParams[TIMED_Pitch].mCurrentValue,
mRegisterParam.field_0xe);
pitch = cent * mVibrate.getValue();
pan = mTimedParam.mMoveParams[TIMED_Pan].mCurrentValue;
fx_vol = mTimedParam.mMoveParams[TIMED_Fxmix].mCurrentValue;
dolby = mTimedParam.mMoveParams[TIMED_Dolby].mCurrentValue;
if (mOuterParam) {
if (mOuterParam->checkOuterSwitch(OUTERPARAM_Volume)) {
vol *= mOuterParam->getVolume();
}
if (mOuterParam->checkOuterSwitch(OUTERPARAM_Pitch)) {
pitch *= mOuterParam->getPitch();
}
if (mOuterParam->checkOuterSwitch(OUTERPARAM_Fxmix)) {
fx_vol = panCalc(fx_vol, mOuterParam->getFxVol(), pan_weight, mCalcTypes[1]);
}
if (mOuterParam->checkOuterSwitch(OUTERPARAM_Dolby)) {
dolby = panCalc(dolby, mOuterParam->getDolby(), pan_weight, mCalcTypes[2]);
}
if (mOuterParam->checkOuterSwitch(OUTERPARAM_Pan)) {
pan = panCalc(pan, mOuterParam->getPan(), pan_weight, mCalcTypes[0]);
}
}
if (mParent == NULL || (field_0x37b & 1)) {
mChannelUpdater.field_0x18 = vol;
mChannelUpdater.field_0x1c = pitch;
mChannelUpdater.field_0x20 = pan;
mChannelUpdater.field_0x24 = fx_vol;
mChannelUpdater.field_0x28 = dolby;
} else {
pan_weight = mRegisterParam.getPanPowerTrack() / 32767.0f;
mChannelUpdater.field_0x18 = mParent->mChannelUpdater.field_0x18 * vol;
mChannelUpdater.field_0x1c = mParent->mChannelUpdater.field_0x1c * pitch;
mChannelUpdater.field_0x20 = panCalc(
pan, mParent->mChannelUpdater.field_0x20, pan_weight, mParentCalcTypes[0]
);
mChannelUpdater.field_0x24 = panCalc(
fx_vol, mParent->mChannelUpdater.field_0x24, pan_weight, mParentCalcTypes[1]
);
mChannelUpdater.field_0x28 = panCalc(
dolby, mParent->mChannelUpdater.field_0x28, pan_weight, mParentCalcTypes[2]
);
if (mOuterParam && mOuterParam->checkOuterSwitch(OUTERPARAM_FIR8Filter)) {
for (u8 i = 0; i < 8; i++) {
mChannelUpdater.field_0x2c[i] = mOuterParam->getIntFirFilter(i);
}
mChannelUpdater.field_0x61 = 8;
}
for (u8 i = 0; i < 4; i++) {
mChannelUpdater.field_0x3c[i] = mTimedParam.mMoveParams[TIMED_IIR_Unk0 + i].mCurrentValue * 32767.0f;
}
mChannelUpdater.field_0x61 |= 0x20;
mChannelUpdater.field_0x4c = mTimedParam.mMoveParams[TIMED_Unk5].mCurrentValue * 32767.0f;
// }
}
}
/* 80281E90-80282364 .text updateTrack__Q28JASystem6TTrackFUl */
void JASystem::TTrack::updateTrack(u32) {
/* Nonmatching */
void JASystem::TTrack::updateTrack(u32 flags) {
if (field_0x37b == 4) {
return;
}
f32 pitch;
f32 vol;
f32 pan;
f32 fx_vol;
f32 dolby;
f32 pan_weight = mRegisterParam.getPanPowerParent() / 32767.0f;
if (flags & OUTERPARAM_Unk18) {
f32 unkF = mTimedParam.mMoveParams[TIMED_Unk17].mCurrentValue * 128.0f;
s8 unk = 0;
s8 delay;
OSf32tos8(&unkF, &delay);
if (delay < 0) {
unk = -delay;
delay = 0;
}
mChannelUpdater.field_0x5a[0] = unk;
mChannelUpdater.field_0x5a[1] = delay;
}
if (flags & OUTERPARAM_Tempo && mParent == NULL) {
updateTempo();
}
pitch = 1.0f;
u32 set_volume = flags & OUTERPARAM_Volume;
if (set_volume) {
vol = mTimedParam.mMoveParams[TIMED_Volume].mCurrentValue;
if (mVolumeMode == 0) {
vol *= vol;
}
if (field_0x386) {
vol = 0.0f;
}
if (mOuterParam && mOuterParam->checkOuterSwitch(OUTERPARAM_Volume)) {
vol *= mOuterParam->getVolume();
}
if (mIsPaused && (mPauseStatus & 1)) {
vol *= mTimedParam.mMoveParams[TIMED_Unk16].mCurrentValue;
}
}
u32 set_pitch = flags & OUTERPARAM_Pitch;
if (set_pitch) {
pitch = Player::pitchToCent(mTimedParam.mMoveParams[TIMED_Pitch].mCurrentValue,
mRegisterParam.field_0xe);
pitch *= mVibrate.getValue();
if (mOuterParam && mOuterParam->checkOuterSwitch(OUTERPARAM_Pitch)) {
pitch *= mOuterParam->getPitch();
}
}
u32 set_pan = flags & OUTERPARAM_Pan;
if (set_pan) {
pan = mTimedParam.mMoveParams[TIMED_Pan].mCurrentValue;
if (mOuterParam && mOuterParam->checkOuterSwitch(OUTERPARAM_Pan)) {
pan = panCalc(pan, mOuterParam->getPan(), pan_weight, mCalcTypes[0]);
}
}
u32 set_fxvol = flags & OUTERPARAM_Fxmix;
if (set_fxvol) {
fx_vol = mTimedParam.mMoveParams[TIMED_Fxmix].mCurrentValue;
if (mOuterParam && mOuterParam->checkOuterSwitch(OUTERPARAM_Fxmix)) {
fx_vol = panCalc(fx_vol, mOuterParam->getFxVol(), pan_weight, mCalcTypes[1]);
}
}
u32 set_dolby = flags & OUTERPARAM_Dolby;
if (set_dolby) {
dolby = mTimedParam.mMoveParams[TIMED_Dolby].mCurrentValue;
if (mOuterParam && mOuterParam->checkOuterSwitch(OUTERPARAM_Dolby)) {
dolby = panCalc(dolby, mOuterParam->getDolby(), pan_weight, mCalcTypes[2]);
}
}
if (flags & OUTERPARAM_IIRFilter) {
for (u8 i = 0; i < 4; i++) {
mChannelUpdater.field_0x3c[i] = mTimedParam.mMoveParams[TIMED_IIR_Unk0 + i].mCurrentValue * 32767.0f;
}
mChannelUpdater.field_0x61 |= 0x20;
}
if (mOuterParam && (flags & OUTERPARAM_FIR8Filter) && mOuterParam->checkOuterSwitch(OUTERPARAM_FIR8Filter)) {
for (u8 i = 0; i < 8; i++) {
mChannelUpdater.field_0x2c[i] = mOuterParam->getIntFirFilter(i);
}
mChannelUpdater.field_0x61 = (mChannelUpdater.field_0x61 & 0x20) + 8;
}
if (flags & OUTERPARAM_Unk6) {
mChannelUpdater.field_0x4c = mTimedParam.mMoveParams[TIMED_Unk5].mCurrentValue * 32767.0f;
}
if (mParent == NULL || (field_0x37b & 1)) {
if (set_volume) {
mChannelUpdater.field_0x18 = vol;
}
if (set_pitch) {
mChannelUpdater.field_0x1c = pitch;
}
if (set_pan) {
mChannelUpdater.field_0x20 = pan;
}
if (set_fxvol) {
mChannelUpdater.field_0x24 = fx_vol;
}
if (set_dolby) {
mChannelUpdater.field_0x28 = dolby;
}
} else {
pan_weight = mRegisterParam.getPanPowerTrack() / 32767.0f;
if (set_volume) {
mChannelUpdater.field_0x18 = mParent->mChannelUpdater.field_0x18 * vol;
}
if (set_pitch) {
mChannelUpdater.field_0x1c = mParent->mChannelUpdater.field_0x1c * pitch;
}
if (set_pan) {
mChannelUpdater.field_0x20 = panCalc(
pan, mParent->mChannelUpdater.field_0x20, pan_weight, mParentCalcTypes[0]
);
}
if (set_fxvol) {
mChannelUpdater.field_0x24 = panCalc(
fx_vol, mParent->mChannelUpdater.field_0x24, pan_weight, mParentCalcTypes[1]
);
}
if (set_dolby) {
mChannelUpdater.field_0x28 = panCalc(
dolby, mParent->mChannelUpdater.field_0x28, pan_weight, mParentCalcTypes[2]
);
}
}
}
/* 80282364-802824C0 .text updateTempo__Q28JASystem6TTrackFv */
@@ -891,8 +1109,207 @@ void JASystem::TTrack::writeRegDirect(u8 target, u16 value) {
}
/* 80283164-802836FC .text writeRegParam__Q28JASystem6TTrackFUc */
void JASystem::TTrack::writeRegParam(u8) {
void JASystem::TTrack::writeRegParam(u8 param) {
/* Nonmatching */
u8 curr_file_byte;
u8 bVar0;
u8 bVar1;
u32 iVar1;
u32 iVar2;
u32 tbl_param_3;
u32 tbl_param_1;
s16 sVar0;
s16 sVar1;
u32 extended_sVar1;
u32 tbl_return;
switch (param & 0xF) {
case 11:
iVar1 = 0;
iVar2 = 11;
break;
case 10:
curr_file_byte = *mSeqCtrl.mCurrentFilePtr++;
iVar1 = curr_file_byte & 0xC;
tbl_param_3 = (curr_file_byte >> 4) + 4;
iVar2 = 10;
break;
case 9:
curr_file_byte = *mSeqCtrl.mCurrentFilePtr++;
iVar1 = curr_file_byte & 0xC;
iVar2 = curr_file_byte & 0xF0;
if (iVar1 == 8) {
iVar1 = 16;
}
break;
default:
iVar1 = param & 0xC;
iVar2 = param & 0x3;
break;
}
bVar0 = *mSeqCtrl.mCurrentFilePtr++;
if (iVar2 == 10) {
u8 next_file_byte = *mSeqCtrl.mCurrentFilePtr++;
tbl_param_1 = readReg32(next_file_byte);
}
switch (iVar1) {
case 0:
bVar1 = *mSeqCtrl.mCurrentFilePtr++;
sVar0 = readReg16(bVar1);
break;
case 4:
sVar0 = *mSeqCtrl.mCurrentFilePtr++;
break;
case 12:
sVar0 = mSeqCtrl.read16();
break;
case 8: {
u32 byte = (u32) *mSeqCtrl.mCurrentFilePtr++;
if (byte & 0x80) {
sVar0 = byte << 8;
} else {
sVar0 = (byte << 8) | (byte << 1);
}
break;
}
case 16:
sVar0 = -1;
break;
}
sVar1 = readReg16(bVar0);
extended_sVar1 = sVar1;
switch (iVar2) {
case 0x0:
break;
case 0x1:
if (iVar1 == 4) {
sVar0 = Player::extend8to16(sVar0);
}
sVar0 += sVar1;
break;
case 0x2:
extended_sVar1 *= sVar0;
writeRegDirect(4, extended_sVar1 >> 16);
writeRegDirect(5, extended_sVar1 & 0xFFFF);
return;
case 0x3:
mRegisterParam.setFlag(sVar1 - sVar0);
return;
case 0xB:
sVar0 = extended_sVar1 - (u32)sVar0;
break;
case 0x10:
if (iVar1 == 4) {
sVar0 = Player::extend8to16(sVar0);
}
if (sVar0 < 0) {
sVar0 = (u16)sVar1 >> -sVar0;
} else {
sVar0 = (u16)sVar1 << sVar0;
}
break;
case 0x20:
if (iVar1 == 4) {
sVar0 = Player::extend8to16(sVar0);
}
if (sVar0 < 0) {
sVar0 = sVar1 >> -sVar0;
} else {
sVar0 = sVar1 << sVar0;
}
break;
case 0x30:
sVar0 &= sVar1;
break;
case 0x40:
sVar0 |= sVar1;
break;
case 0x50:
sVar0 ^= sVar1;
break;
case 0x60:
sVar0 = -sVar1;
break;
case 0x90:
tbl_return = (u32)Player::getRandomS32();
sVar0 = tbl_return % (u16)sVar0;
break;
case 0xA:
tbl_return = loadTbl(tbl_param_1, sVar0, tbl_param_3);
sVar0 = tbl_return & 0xFFFF;
break;
}
u16 reg_flags;
switch (bVar0) {
case 0:
case 1:
case 2: {
u8 val3 = sVar0 & 0xFF;
sVar0 = val3;
reg_flags = Player::extend8to16(val3);
break;
}
case 0x21: {
u8 bank = mRegisterParam.getBankNumber();
sVar0 = (bank << 8) | (sVar0 & 0xFF);
bVar0 = 6;
break;
}
case 0x20:
sVar0 = mRegisterParam.getProgramNumber() | ((s16)sVar0 << 8);
bVar0 = 6;
break;
case 0x2E:
sVar0 = (mRegisterParam.field_0x1a & 0xFF00) | (sVar0 & 0xFF);
bVar0 = 13;
break;
case 0x2F: {
s16 tmp = (mRegisterParam.field_0x1a & 0xFF);
sVar0 = tmp | (sVar0 << 8);
bVar0 = 13;
break;
}
case 0x22:
writeRegDirect(0, sVar0 >> 8);
bVar0 = 1;
sVar0 = sVar0 & 0xFF;
reg_flags = sVar0;
break;
case 0x28:
case 0x29:
case 0x2a:
case 0x2b:
mRegisterParam.setAddress(bVar0 - 0x28, tbl_return);
return;
default:
reg_flags = sVar0;
break;
}
mRegisterParam.field_0x0[bVar0] = sVar0;
mRegisterParam.setFlag(reg_flags);
switch (bVar0) {
case 6:
for (s32 i = 0; i < (s32)ARRAY_SIZE(mOscRoute); i++) {
mOscRoute[i] = 0xF;
}
break;
case 7:
mUpdateFlags |= OUTERPARAM_Pitch;
break;
case 13:
mChannelUpdater.field_0x68 = mRegisterParam.field_0x1a | 0x10000;
mChannelUpdater.field_0x6c = 0;
break;
}
}
/* 802836FC-80283720 .text readSelfPort__Q28JASystem6TTrackFi */
@@ -912,11 +1329,7 @@ int JASystem::TTrack::writePortAppDirect(u32 port, u16 value) {
if (port == 0 || port == 1) {
TIntrMgr& intrMgr = mIntrMgr;
u32 mIntrParam = 4;
if (port == 0) {
mIntrParam = 3;
}
u32 mIntrParam = port == 0 ? REQUEST_UNK_3 : REQUEST_UNK_4;
intrMgr.request(mIntrParam);
}
return 1;
@@ -965,7 +1378,6 @@ int JASystem::TTrack::readPortApp(u32 route, u16* value_out) {
/* 802838C4-80283A64 .text pause__Q28JASystem6TTrackFbb */
void JASystem::TTrack::pause(bool pause, bool pause_children) {
/* Nonmatching */
mIsPaused = pause;
if (pause) {
@@ -997,7 +1409,7 @@ void JASystem::TTrack::pause(bool pause, bool pause_children) {
}
}
mIntrMgr.request(pause ? 0 : 1);
mIntrMgr.request(pause ? REQUEST_UNK_0 : REQUEST_UNK_1);
if (pause_children) {
for (s32 i = 0; i < MAX_CHILDREN; i++) {
@@ -1156,23 +1568,3 @@ f32 JASystem::TVibrate::getValue() const {
}
return Player::pitchToCent(sin_val * mDepth, 12.0f);
}
/* 80283FE8-80284118 .text __ct__Q38JASystem6TTrack12AInnerParam_Fv */
JASystem::TTrack::AInnerParam_::AInnerParam_()
: mVolume()
, mPitch()
, mFxmix()
, mPan()
, mDolby()
, _50()
, mOsc0Width()
, mOsc0Rate()
, mOsc0Vertex()
, mOsc1Width()
, mOsc1Rate()
, mOsc1Vertex()
, mIIRs()
, _100()
, _110()
{
}
+1 -1
View File
@@ -63,7 +63,7 @@ void JASystem::TIntrMgr::timerProcess() {
if (field_0x4 != 0) {
return;
}
request(6);
request(REQUEST_UNK_6);
if (field_0x3) {
field_0x3--;
if (field_0x3) {