// // Generated by dtk // Translation Unit: JASTrack.cpp // #include "JSystem/JSystem.h" // IWYU pragma: keep #include "JSystem/JAudio/JASTrack.h" #include "JSystem/JAudio/JASBankMgr.h" #include "JSystem/JAudio/JASCalc.h" #include "JSystem/JAudio/JASCallback.h" #include "JSystem/JAudio/JASChannel.h" #include "JSystem/JAudio/JASChGlobal.h" #include "JSystem/JAudio/JASPlayer.h" #include "JSystem/JAudio/JASSystemHeap.h" #include "JSystem/JAudio/JASRate.h" #include "JSystem/JKernel/JKRSolidHeap.h" #include "JSystem/JUtility/JUTAssert.h" /* 80280960-80280A34 .text __ct__Q28JASystem6TTrackFv */ JASystem::TTrack::TTrack() { mParent = NULL; field_0x364 = 0.0f; field_0x368 = 0.0f; field_0x36c = 0; mUpdateFlags = 0; field_0x374 = 0; field_0x376 = 0x78; field_0x378 = 0x78; mTranspose = 0; field_0x37b = 0; mPauseStatus = 0; mVolumeMode = 0; field_0x37e = 0; mIsPaused = 0; field_0x386 = 0; field_0x387 = 0; field_0x388 = 0; field_0x389 = 0; mChannelUpdater.init(); for (int i = 0; i < 12; i++) { field_0x304[i] = Player::sAdsTable[i]; } Calc::bzero(&mTimedParam, sizeof(TimedParam_)); } /* 80280A34-80280A80 .text __ct__Q38JASystem6TTrack11TimedParam_Fv */ JASystem::TTrack::TimedParam_::TimedParam_() {} /* 80280A80-80280C10 .text init__Q28JASystem6TTrackFv */ void JASystem::TTrack::init() { mSeqCtrl.init(); mTrackPort.init(); mIntrMgr.init(); mNoteMgr.init(); mChannelUpdater.initAllocChannel(0); initTimed(); mRegisterParam.init(); mOscRoute[0] = 0x0f; field_0x2cc[0] = Player::sEnvelopeDef; mOscRoute[1] = 0x0f; field_0x2cc[1] = Player::sEnvelopeDef; mParent = NULL; for (int i = 0; i < 16; i++) { mChildren[i] = NULL; } if (mOuterParam) { mOuterParam->initExtBuffer(); } field_0x364 = 0.0f; field_0x368 = 1.0f; field_0x36c = 0; mVibrate.init(); mUpdateFlags = 0; field_0x374 = 0; field_0x376 = 0x78; field_0x378 = 0x30; updateTempo(); mTranspose = 0; field_0x37b = 0; mPauseStatus = 10; mVolumeMode = 0; field_0x37e = 0; for (int i = 0; i < 3; i++) { mCalcTypes[i] = 0; mParentCalcTypes[i] = 0; mChannelUpdater.mCalcTypes[i] = 0x0d; } mIsPaused = 0; field_0x386 = 0; field_0x387 = 1; field_0x388 = 0; } /* 80280C10-80280D0C .text inherit__Q28JASystem6TTrackFv */ void JASystem::TTrack::inherit() { if (!mParent) { return; } field_0x376 = mParent->field_0x376; field_0x388 = 0; field_0x368 = mParent->field_0x368; field_0x378 = mParent->field_0x378; field_0x387 = mParent->field_0x387; mIsPaused = mParent->mIsPaused; mPauseStatus = mParent->mPauseStatus; mVolumeMode = mParent->mVolumeMode; field_0x386 = mParent->field_0x386; if (field_0x37b & 2) { return; } mRegisterParam.inherit(mParent->mRegisterParam); for (int i = 0; i < 3; i++) { mCalcTypes[i] = mParent->mCalcTypes[i]; mParentCalcTypes[i] = mParent->mParentCalcTypes[i]; mChannelUpdater.mCalcTypes[i] = mParent->mChannelUpdater.mCalcTypes[i]; } } u16 (*JASystem::TTrack::sCallBackFunc)(JASystem::TTrack*, u16); JASystem::TSeqParser JASystem::TTrack::sParser; JASystem::TTrack* JASystem::TTrack::sFreeList; /* 80280D0C-80280F80 .text mainProc__Q28JASystem6TTrackFv */ s8 JASystem::TTrack::mainProc() { int r31 = 0; if (field_0x388 && mParent) { f32 tmp = field_0x376; tmp /= mParent->field_0x376; if (tmp > 1.0f) { tmp = 1.0f; } field_0x364 += tmp; if (field_0x364 < 1.0f) { return 0; } field_0x364 -= 1.0f; } if (mParent && mChannelUpdater.field_0x0) { TChannel* channel = mChannelUpdater.getListHead(0); if (channel) { mParent->mChannelUpdater.addListHead(channel, 0); channel->field_0x4 = &mParent->mChannelUpdater; mChannelUpdater.field_0x0--; mParent->mChannelUpdater.field_0x0++; } } mIntrMgr.request(REQUEST_UNK_7); mIntrMgr.timerProcess(); tryInterrupt(); if (mIsPaused == 0 || (mPauseStatus & 2) == 0) { // TODO: figure out how to remove gotos. maybe inlines. if (mSeqCtrl.getWait() == -1) { if (checkNoteStop(0)) { mSeqCtrl.wait(0); } else { goto lab_19c; } } if (mSeqCtrl.getWait() > 0) { if (mSeqCtrl.waitCountDown()) { mNoteMgr.endProcess(); } else { goto lab_19c; } } r31 = sParser.parseSeq(this); lab_19c: updateTimedParam(); } updateSeq(0, false); if (r31 < 0) { return -1; } for (int i = 0; i < 16; i++) { TTrack* child = mChildren[i]; if (child && child->field_0x37e) { JUT_ASSERT(276, this == child->mParent); if (child->mainProc() == -1) { child->close(); mChildren[i] = NULL; } } } return 0; } /* 80280F80-80280FA8 .text setInterrupt__Q28JASystem6TTrackFUs */ void JASystem::TTrack::setInterrupt(u16 param_1) { mIntrMgr.request(param_1); } /* 80280FA8-80281004 .text tryInterrupt__Q28JASystem6TTrackFv */ bool JASystem::TTrack::tryInterrupt() { if (mSeqCtrl.mPreviousFilePtr) { return false; } void* var1 = mIntrMgr.checkIntr(); if (var1 == NULL) { return false; } return mSeqCtrl.callIntr(var1); } /* 80281004-8028100C .text assignExtBuffer__Q28JASystem6TTrackFPQ38JASystem6TTrack11TOuterParam */ void JASystem::TTrack::assignExtBuffer(TOuterParam* param_1) { mOuterParam = param_1; } /* 8028100C-80281050 .text releaseChannelAll__Q28JASystem6TTrackFv */ void JASystem::TTrack::releaseChannelAll() { if (mParent) { mParent->mChannelUpdater.receiveAllChannels(&mChannelUpdater); } else { TGlobalChannel::releaseAll(&mChannelUpdater); } } /* 80281050-80281088 .text flushAll__Q28JASystem6TTrackFv */ void JASystem::TTrack::flushAll() { mChannelUpdater.stopAll(); mChannelUpdater.stopAllRelease(); } /* 80281088-80281138 .text moveFreeChannel__Q28JASystem6TTrackFPQ28JASystem11TChannelMgrPQ28JASystem11TChannelMgri */ int JASystem::TTrack::moveFreeChannel(TChannelMgr* param_1, TChannelMgr* param_2, int param_3) { if (param_3 < 0) { u32 r31 = param_1->field_0x0; param_2->receiveAllChannels(param_1); return r31; } for (int i = 0; i < param_3; i++) { if (!param_1->field_0x0) { break; } TChannel* channel = param_1->getListHead(0); if (!channel) { break; } param_1->field_0x0--; param_2->addListHead(channel, 0); param_2->field_0x0++; } return 0; } /* 80281138-802811DC .text initTimed__Q28JASystem6TTrackFv */ void JASystem::TTrack::initTimed() { for (u8 i = 0; i < 18; i++) { mTimedParam.mMoveParams[i].mMoveTime = 0.0f; mTimedParam.mMoveParams[i].mCurrentValue = 1.0f; mTimedParam.mMoveParams[i].mTargetValue = 1.0f; } mTimedParam.mMoveParams[1].mCurrentValue = 0.0f; mTimedParam.mMoveParams[1].mTargetValue = 0.0f; mTimedParam.mMoveParams[3].mCurrentValue = 0.5f; mTimedParam.mMoveParams[3].mTargetValue = 0.5f; mTimedParam.mMoveParams[16].mCurrentValue = 0.5f; mTimedParam.mMoveParams[16].mTargetValue = 0.5f; mTimedParam.mMoveParams[17].mCurrentValue = 0.0f; mTimedParam.mMoveParams[17].mTargetValue = 0.0f; mTimedParam.mMoveParams[2].mCurrentValue = 0.0f; mTimedParam.mMoveParams[2].mTargetValue = 0.0f; mTimedParam.mMoveParams[4].mCurrentValue = 0.0f; mTimedParam.mMoveParams[4].mTargetValue = 0.0f; for (u8 i = 1; i < 4; i++) { mTimedParam.mMoveParams[i + 12].mCurrentValue = 0.0f; mTimedParam.mMoveParams[i + 12].mTargetValue = 0.0f; } mTimedParam.mMoveParams[5].mCurrentValue = 0.0f; mTimedParam.mMoveParams[5].mTargetValue = 0.0f; } static void dummy() { OSReport("i >= 0"); OSReport("i < 3"); } /* 802811DC-80281258 .text connectBus__Q28JASystem6TTrackFii */ void JASystem::TTrack::connectBus(int line, int param_2) { JUT_ASSERT(486, line < (6)); mChannelUpdater.field_0x4e[line] = param_2; } /* 80281258-802814AC .text noteOn__Q28JASystem6TTrackFUclllUl */ int JASystem::TTrack::noteOn(u8 param_1, s32 param_2, s32 param_3, s32 param_4, u32 param_5) { if (field_0x386 && (mPauseStatus & 0x40)) { return -1; } noteOff(param_1, 0); TChannelMgr* r31 = &mChannelUpdater; TTrack* parent = mParent; while (r31->field_0x0 == 0 || r31->field_0x8 == 0) { if (!parent) { r31 = &mChannelUpdater; break; } r31 = &parent->mChannelUpdater; parent = parent->mParent; } if (field_0x37b == 4) { JUT_ASSERT(527, mParent != NULL); if (r31 != &mParent->mChannelUpdater) { if (moveFreeChannel(r31, &mParent->mChannelUpdater, 1) != 1) { OSReport("in Player (NOTE-MODE) ... ボイス借用に失敗しました!! (%d)\n", r31->field_0x0); } r31 = &mParent->mChannelUpdater; } } else if (r31 != &mChannelUpdater) { if (moveFreeChannel(r31, &mChannelUpdater, 1) != 1) { OSReport("in Player ボイス借用に失敗しました!! (%d)\n", r31->field_0x0); } r31 = &mChannelUpdater; } u8 bankNum = mRegisterParam.getBankNumber(); u8 physNum = BankMgr::getPhysicalNumber(bankNum); u8 progNum = mRegisterParam.getProgramNumber(); TChannel* channel = BankMgr::noteOn(r31, physNum, progNum, param_2, param_3, param_4); if (!channel) { return -1; } mNoteMgr.setChannel(param_1, channel); channel->field_0xe8 = param_5; channel->setPanPower(mRegisterParam.getPanPowerBank(), mRegisterParam.getPanPowerExt(), mRegisterParam.getPanPowerOsc(), 0.0f); overwriteOsc(channel); if (field_0x374) { channel->directReleaseOsc(0, field_0x374); } return 0; } /* 802814AC-802815DC .text overwriteOsc__Q28JASystem6TTrackFPQ28JASystem8TChannel */ void JASystem::TTrack::overwriteOsc(TChannel* param_1) { u32 r28; for (int i = 0; i < 2; i++) { u32 var1 = mOscRoute[i]; if (var1 == 0x0f) { continue; } r28 = var1 & 3; if (var1 & 8) { if (!param_1->isOsc(r28)) { JUT_WARN(593, "%s", "cannot copy osc"); continue; } param_1->copyOsc(r28, &field_0x2cc[i]); } else if (var1 & 4) { s16* var4 = field_0x2cc[i].rel_table; if (!param_1->isOsc(r28)) { JUT_WARN(603, "%s", "cannot copy osc"); continue; } param_1->copyOsc(r28, &field_0x2cc[i]); field_0x2cc[i].rel_table = var4; } param_1->overwriteOsc(r28, &field_0x2cc[i]); } } /* 802815DC-8028165C .text noteOff__Q28JASystem6TTrackFUcUs */ bool JASystem::TTrack::noteOff(u8 param_1, u16 param_2) { TChannel* channel = mNoteMgr.getChannel(param_1); if (!channel) { return false; } if (param_2 == 0) { channel->stop(0); } else { channel->stop(param_2); } mNoteMgr.releaseChannel(param_1); return true; } /* 8028165C-802816C4 .text gateOn__Q28JASystem6TTrackFUclll */ int JASystem::TTrack::gateOn(u8 param_1, s32 param_2, s32 param_3, s32 param_4) { TChannel* channel = mNoteMgr.getChannel(param_1); if (!channel) { return -1; } BankMgr::gateOn(channel, param_2, param_3, param_4); return 0; } /* 802816C4-80281708 .text checkNoteStop__Q28JASystem6TTrackFl */ bool JASystem::TTrack::checkNoteStop(s32 param_1) { TChannel* channel = mNoteMgr.getChannel(param_1); if (channel == NULL) { return true; } if (channel->field_0x1 == 0xff) { return true; } return false; } /* 80281708-802817E4 .text oscSetupFull__Q28JASystem6TTrackFUcUlUl */ void JASystem::TTrack::oscSetupFull(u8 param_1, u32 param_2, u32 param_3) { bool r8 = (param_1 & 0x10) ? true : false; u8 r7 = param_1 & 0x0f; bool r0 = (param_1 & 0x80) ? true : false; bool r9 = (param_1 & 0x40) ? true : false; bool r10 = (param_1 & 0x20) ? true : false; if (r0) { field_0x2cc[r8] = Player::sEnvelopeDef; field_0x2cc[r8].field_0x0 = r7; switch (r7) { case 1: field_0x2cc[r8].field_0x14 = 1.0f; break; } } if (r9) { if (param_2 == 0) { field_0x2cc[r8].table = NULL; } field_0x2cc[r8].table = (s16*)(mSeqCtrl.mRawFilePtr + param_2); } if (!r10) { return; } if (param_3 == 0) { field_0x2cc[r8].rel_table = Player::sRelTable; } field_0x2cc[r8].rel_table = (s16*)(mSeqCtrl.mRawFilePtr + param_3); } /* 802817E4-80281850 .text oscSetupSimpleEnv__Q28JASystem6TTrackFUcUl */ void JASystem::TTrack::oscSetupSimpleEnv(u8 param_1, u32 param_2) { switch (param_1) { case 0: field_0x2cc[0] = Player::sEnvelopeDef; field_0x2cc[0].table = (s16*)(mSeqCtrl.mRawFilePtr + param_2); break; case 1: field_0x2cc[0].rel_table = (s16*)(mSeqCtrl.mRawFilePtr + param_2); break; } } /* 80281850-80281900 .text updateOscParam__Q28JASystem6TTrackFif */ void JASystem::TTrack::updateOscParam(int param_1, f32 param_2) { switch (param_1) { case 6: field_0x2cc[0].field_0x10 = param_2; break; case 7: field_0x2cc[0].field_0x4 = param_2; break; case 8: field_0x2cc[0].field_0x14 = param_2; break; case 9: field_0x2cc[1].field_0x10 = param_2; break; case 10: field_0x2cc[1].field_0x4 = param_2; break; case 11: field_0x2cc[1].field_0x14 = param_2; break; default: JUT_ASSERT(753, false); break; } } /* 80281900-802819D0 .text oscSetupSimple__Q28JASystem6TTrackFUc */ void JASystem::TTrack::oscSetupSimple(u8 param_1) { switch (param_1) { case 0: field_0x2cc[1] = Player::sVibratoDef; break; case 1: field_0x2cc[0] = Player::sTremoroDef; break; case 2: field_0x2cc[1] = Player::sTremoroDef; break; } } /* 802819D0-80281AA4 .text updateTimedParam__Q28JASystem6TTrackFv */ void JASystem::TTrack::updateTimedParam() { for (s32 i = 0; i < TIMED_PARAMS; i++) { MoveParam_& param = mTimedParam.mMoveParams[i]; if (param.mMoveTime > 0.0f) { param.mCurrentValue += param.mMoveAmount; param.mMoveTime -= 1.0f; if (i <= 5 || i >= 11) { mUpdateFlags |= (1 << i); } else { updateOscParam(i, param.mCurrentValue); } } } mUpdateFlags |= 2; } /* 80281AA4-80281E90 .text updateTrackAll__Q28JASystem6TTrackFv */ void JASystem::TTrack::updateTrackAll() { if (field_0x37b == 4) { return; } f32 pitch; f32 vol; f32 pan; f32 fx_vol; f32 dolby; f32 pan_weight = (f32)mRegisterParam.getPanPowerParent() / 0x7FFF; mChannelUpdater.field_0x68 = mRegisterParam.field_0x1a | 0x10000; mChannelUpdater.field_0x6c = 0; f32 delayF = mTimedParam.mMoveParams[TIMED_Unk17].mCurrentValue * 128.0f; s8 delay; s8 unk = 0; OSf32tos8(&delayF, &delay); if (delay < 0) { unk = -delay; delay = 0; } 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 = (f32)mRegisterParam.getPanPowerTrack() / 0x7FFF; 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 * 0x7FFF; } mChannelUpdater.field_0x61 |= 0x20; mChannelUpdater.field_0x4c = mTimedParam.mMoveParams[TIMED_Unk5].mCurrentValue * 0x7FFF; } } /* 80281E90-80282364 .text updateTrack__Q28JASystem6TTrackFUl */ 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 = (f32)mRegisterParam.getPanPowerParent() / 0x7FFF; 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 * 0x7FFF; } 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 * 0x7FFF; } 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 = (f32)mRegisterParam.getPanPowerTrack() / 0x7FFF; 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 */ void JASystem::TTrack::updateTempo() { if (mParent == NULL) { field_0x368 = (f32) field_0x378; field_0x368 *= field_0x376; field_0x368 /= Kernel::getDacRate(); field_0x368 *= (4.0f / 3.0f); if (mOuterParam != NULL && mOuterParam->checkOuterSwitch(OUTERPARAM_Tempo)) { field_0x368 *= mOuterParam->getTempo(); } } else { field_0x368 = mParent->field_0x368; field_0x378 = mParent->field_0x378; } for (s32 i = 0; i < MAX_CHILDREN; i++) { TTrack* child = mChildren[i]; if (child && child->field_0x37e) { JUT_ASSERT(1159, this == child->mParent); child->updateTempo(); } } } /* 802824C0-802825A0 .text updateSeq__Q28JASystem6TTrackFUlb */ void JASystem::TTrack::updateSeq(u32 flags, bool update_children) { u32 new_flags = flags | mUpdateFlags; if (mOuterParam) { new_flags |= mOuterParam->getOuterUpdate(); mOuterParam->setOuterUpdate(0); } mVibrate.incCounter(); mUpdateFlags = 0; if (new_flags != 0) { updateTrack(new_flags); } for (s32 i = 0; i < MAX_CHILDREN; i++) { TTrack* child = mChildren[i]; if (child && child->field_0x37e) { if (update_children) { child->updateSeq(new_flags, update_children); } else { child->mUpdateFlags |= new_flags; } } } } /* 802825A0-8028265C .text seqTimeToDspTime__Q28JASystem6TTrackFlUc */ int JASystem::TTrack::seqTimeToDspTime(s32 param_1, u8 param_2) { f32 f1 = ((f32)param_1 * (f32)param_2) / 100.0f; if (field_0x387) { f1 /= field_0x368; } else { f1 = 120.0f * f1; f1 /= field_0x378; if (Kernel::getOutputRate() == 0) { f1 = (f1 * Kernel::getSubFrames()) / 10.0f; } } return f1; } /* 8028265C-8028278C .text setParam__Q28JASystem6TTrackFifi */ void JASystem::TTrack::setParam(int target, f32 target_value, int move_time) { JUT_ASSERT(1236, target >= 0); JUT_ASSERT(1237, target < TIMED_PARAMS); MoveParam_& param = mTimedParam.mMoveParams[target]; param.mTargetValue = target_value; if (move_time <= 0) { param.mCurrentValue = param.mTargetValue; param.mMoveAmount = 0.0f; param.mMoveTime = 1.0f; } else { param.mMoveAmount = (param.mTargetValue - param.mCurrentValue) / move_time; param.mMoveTime = move_time; } } /* 8028278C-802827F0 .text setSeqData__Q28JASystem6TTrackFPUcli */ bool JASystem::TTrack::setSeqData(u8* param_1, s32, int) { init(); field_0x37b = 3; mSeqCtrl.start(param_1, 0); updateTrackAll(); field_0x37e = 2; return true; } /* 802827F0-802828A8 .text startSeq__Q28JASystem6TTrackFv */ bool JASystem::TTrack::startSeq() { switch (field_0x37e) { case 0: // Not ready OSReport("in Player StartSeq: 準備ができていません\n"); return false; case 1: // Already started OSReport("in Player StartSeq: 既に動作中です\n"); return false; case 3: // Stopping OSReport("in Player StartSeq: 停止中です\n"); return false; case 2: field_0x37e = 1; break; } Kernel::registerSubFrameCallback(rootCallback, this); return true; } /* 802828A8-80282908 .text stopSeq__Q28JASystem6TTrackFv */ bool JASystem::TTrack::stopSeq() { switch (field_0x37e) { case 0: break; case 2: field_0x37e = 0; if (field_0x389 != 0 && this != NULL) { delete this; } break; default: field_0x37e = 3; break; } return true; } /* 80282908-80282944 .text stopSeqMain__Q28JASystem6TTrackFv */ void JASystem::TTrack::stopSeqMain() { updateSeq(0, 1); close(); } /* 80282944-802829DC .text noteOffAll__Q28JASystem6TTrackFv */ void JASystem::TTrack::noteOffAll() { if (mParent == NULL) { for (u8 i = 0; i < 8; i++) { noteOff(i, 10); } } else { for (u8 i = 0; i < 8; i++) { noteOff(i, 0); } } mNoteMgr.init(); } /* 802829DC-80282A90 .text close__Q28JASystem6TTrackFv */ int JASystem::TTrack::close() { if (field_0x37e == 0) { return 0; } noteOffAll(); field_0x37e = 0; for (s32 i = 0; i < MAX_CHILDREN; i++) { if (mChildren[i]) { mChildren[i]->close(); mChildren[i] = NULL; } } field_0x386 = 0; releaseChannelAll(); if (field_0x389 != 0 && this != NULL) { delete this; } return 0; } /* 80282A90-80282B44 .text muteTrack__Q28JASystem6TTrackFb */ void JASystem::TTrack::muteTrack(bool mute) { field_0x386 = mute; mUpdateFlags |= 1; if (field_0x386 && (mPauseStatus & 0x20)) { for (u8 i = 0; i < 8; i++) { noteOff(i, 10); } } for (s32 i = 0; i < MAX_CHILDREN; i++) { if (mChildren[i]) { mChildren[i]->muteTrack(mute); } } } /* 80282B44-80282B84 .text start__Q28JASystem6TTrackFPvUl */ bool JASystem::TTrack::start(void* param_1, u32 param_2) { mSeqCtrl.start(param_1, param_2); field_0x37e = 1; updateTrackAll(); return false; } /* 80282B84-80282CE8 .text openChild__Q28JASystem6TTrackFUcUc */ JASystem::TTrack* JASystem::TTrack::openChild(u8 trk_no, u8 param_2) { JUT_ASSERT(1448, trk_no < MAX_CHILDREN); if (mChildren[(int)trk_no]) { mChildren[(int)trk_no]->close(); mChildren[(int)trk_no] = NULL; } TTrack* new_track = new TTrack(); if (new_track == NULL) { // Not enough JASTracks. JUT_WARN(1459, "%s", "JASTrackが足りません。\n"); return NULL; } new_track->init(); new_track->field_0x389 = 1; new_track->mParent = this; new_track->field_0x37b = param_2; u32 top_nibble = field_0x36c & 0xf0000000; if (top_nibble >= 0x70000000) { // "JASTrack:openTrack: The hierarchy exceeds 8 levels and an invalid track ID is generated.\n" OSReport("JASTrack:openTrack: 階層が8段階を超えてしまい、不正なトラックIDが生成されました\n"); } new_track->field_0x36c = (top_nibble + 0x10000000) | (((field_0x36c) << 4 | ((u32) trk_no)) & 0x0FFFFFFF); mChildren[(int)trk_no] = new_track; new_track->inherit(); return new_track; } /* 80282CE8-80282D80 .text loadTbl__Q28JASystem6TTrackFUlUlUl */ int JASystem::TTrack::loadTbl(u32 param_1, u32 param_2, u32 param_3) { u32 param_2_times_three; switch (param_3) { case 4: return mSeqCtrl.mRawFilePtr[param_1 + param_2]; case 5: return mSeqCtrl.get16(param_1 + param_2 * 2); case 6: // Doing (param_2 * 3) causes a multiply instruction instead of a shift // and add. param_2_times_three = param_2; param_2_times_three += param_2 * 2; return mSeqCtrl.get24(param_1 + param_2_times_three); case 7: return mSeqCtrl.get32(param_1 + param_2 * 4); case 8: return mSeqCtrl.get32(param_1 + param_2); } } /* 80282D80-80282DC0 .text exchangeRegisterValue__Q28JASystem6TTrackFUc */ int JASystem::TTrack::exchangeRegisterValue(u8 target) { if (target < 0x40) { return readReg32(target); } u8 index = target - 0x40; return mTrackPort.mValue[index]; } /* 80282DC0-80282ED4 .text readReg32__Q28JASystem6TTrackFUc */ u32 JASystem::TTrack::readReg32(u8 target) { u32 result; switch(target) { case 0x28: case 0x29: case 0x2a: case 0x2b: result = mRegisterParam.getAddress(target - 0x28); break; case 0x23: result = readReg16(0x4) << 16; result |= readReg16(0x5); break; default: result = readReg16(target); break; } return result; } /* 80282ED4-802830AC .text readReg16__Q28JASystem6TTrackFUc */ u16 JASystem::TTrack::readReg16(u8 target) { JUT_ASSERT(1553, target != TRegisterParam::PARAM_REG_XY); JUT_ASSERT(1554, target < TRegisterParam::PARAM_REG_AR0 || target > TRegisterParam::PARAM_REG_AR3); int i; u16 result; switch (target) { case 0x20: result = mRegisterParam.getBankNumber(); break; case 0x21: result = mRegisterParam.getProgramNumber(); break; case 0x22: result = readReg16(0) << 8; result |= readReg16(1); break; case 0x2C: result = 0; for (i = MAX_CHILDREN - 1; i >= 0; i--) { result <<= 1; if (mChildren[i] && mChildren[i]->field_0x37e != 0) { result |= 1; } } break; case 0x2D: result = 0; for (i = 7; i >= 0; i--) { result <<= 1; result |= checkNoteStop(i); } break; case 0x30: result = mSeqCtrl.getLoopCount(); break; default: result = mRegisterParam.field_0x0[target]; break; } return result; } /* 802830AC-80283164 .text writeRegDirect__Q28JASystem6TTrackFUcUs */ void JASystem::TTrack::writeRegDirect(u8 target, u16 value) { u16 r4; u8 val_u8; switch (target) { case 0: case 1: case 2: val_u8 = value & 0xFF; value = val_u8; r4 = Player::extend8to16(val_u8); break; case 0x20: case 0x21: return; case 0x22: writeRegDirect(0, value >> 8); target = 1; r4 = value; value = value & 0xFF; break; default: r4 = value; break; } mRegisterParam.field_0x0[target] = value; mRegisterParam.setFlag(r4); } /* 80283164-802836FC .text writeRegParam__Q28JASystem6TTrackFUc */ void JASystem::TTrack::writeRegParam(u8 param) { 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; } // Bug: reg_flags is uninitialized in several of these cases. 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 */ u16 JASystem::TTrack::readSelfPort(int param_1) { return mTrackPort.readImport(param_1); } /* 80283720-80283744 .text writeSelfPort__Q28JASystem6TTrackFiUs */ void JASystem::TTrack::writeSelfPort(int param_1, u16 param_2) { mTrackPort.writeExport(param_1, param_2); } /* 80283744-802837AC .text writePortAppDirect__Q28JASystem6TTrackFUlUs */ int JASystem::TTrack::writePortAppDirect(u32 port, u16 value) { mTrackPort.writeImport(port, value); if (port == 0 || port == 1) { mIntrMgr.request(port == 0 ? REQUEST_UNK_3 : REQUEST_UNK_4); } return 1; } /* 802837AC-802837E4 .text readPortAppDirect__Q28JASystem6TTrackFUlPUs */ int JASystem::TTrack::readPortAppDirect(u32 port, u16* read_ptr) { *read_ptr = mTrackPort.readExport(port); return 1; } /* 802837E4-8028381C .text routeTrack__Q28JASystem6TTrackFUl */ JASystem::TTrack* JASystem::TTrack::routeTrack(u32 route) { TTrack* owning_track = this; u32 depth = route >> 28; for (u32 i = 0; i < depth; i++) { owning_track = owning_track->mChildren[route & 0xF]; if (owning_track == NULL) { return NULL; } route >>= 4; } return owning_track; } /* 8028381C-80283870 .text writePortApp__Q28JASystem6TTrackFUlUs */ int JASystem::TTrack::writePortApp(u32 route, u16 value) { TTrack* track = routeTrack(route); if (track == NULL) { return 0; } return track->writePortAppDirect((route >> 16) & 0xFF, value); } /* 80283870-802838C4 .text readPortApp__Q28JASystem6TTrackFUlPUs */ int JASystem::TTrack::readPortApp(u32 route, u16* value_out) { TTrack* track = routeTrack(route); if (track == NULL) { return 0; } return track->readPortAppDirect((route >> 16) & 0xFF, value_out); } /* 802838C4-80283A64 .text pause__Q28JASystem6TTrackFbb */ void JASystem::TTrack::pause(bool pause, bool pause_children) { mIsPaused = pause; if (pause) { if (mPauseStatus & 1) { mUpdateFlags |= 1; } if (mPauseStatus & 0x4) { for (u8 i = 0; i < 8; i++) { noteOff(i, 10); } } if (mPauseStatus & 0x8) { for (s32 i = 0; i < 8; i++) { TChannel* channel = mNoteMgr.getChannel(i); if (channel) { channel->setPauseFlag(1); } } } } else { mUpdateFlags |= 1; for (s32 i = 0; i < 8; i++) { TChannel* channel = mNoteMgr.getChannel(i); if (channel) { channel->setPauseFlag(0); } } } mIntrMgr.request(pause ? REQUEST_UNK_0 : REQUEST_UNK_1); if (pause_children) { for (s32 i = 0; i < MAX_CHILDREN; i++) { TTrack* child = mChildren[i]; if (child && child->field_0x37e) { JUT_ASSERT(2109, this == child->mParent); child->pause(pause, true); } } } } /* 80283A64-80283AB4 .text getTranspose__Q28JASystem6TTrackCFv */ int JASystem::TTrack::getTranspose() const { if (mParent != NULL) { return mParent->getTranspose() + mTranspose; } return mTranspose; } /* 80283AB4-80283AF0 .text setTempo__Q28JASystem6TTrackFUs */ void JASystem::TTrack::setTempo(u16 tempo) { field_0x376 = tempo; if (mParent == NULL) { updateTempo(); } else { field_0x388 = 1; } } /* 80283AF0-80283B20 .text setTimebase__Q28JASystem6TTrackFUs */ void JASystem::TTrack::setTimebase(u16 timeBase) { field_0x378 = timeBase; if (mParent == NULL) { updateTempo(); } } /* 80283B20-80283BBC .text panCalc__Q28JASystem6TTrackFfffUc */ f32 JASystem::TTrack::panCalc(f32 a, f32 b, f32 weight, u8 type) { switch (type) { case 0: return a; case 1: return b; case 2: return a * (1.0f - weight) + (b * weight); } JUT_ASSERT(2150, false); return 0.0f; } /* 80283BBC-80283C9C .text rootCallback__Q28JASystem6TTrackFPv */ s32 JASystem::TTrack::rootCallback(void* user_data) { TTrack* track = (TTrack*)user_data; if (track == NULL) { return -1; } if (track->field_0x37e == 0) { return -1; } if (track->field_0x37e == 3) { track->stopSeqMain(); return -1; } track->field_0x364 += track->field_0x368; if (track->field_0x364 < 1.0f) { track->updateSeq(0, true); } else { while (track->field_0x364 >= 1.0f) { track->field_0x364 -= 1.0f; if (track->mainProc() == -1) { track->stopSeqMain(); return -1; } } } return 0; } /* 80283C9C-80283CE8 .text registerSeqCallback__Q28JASystem6TTrackFPFPQ28JASystem6TTrackUs_Us */ void JASystem::TTrack::registerSeqCallback(u16 (*param_1)(TTrack*, u16)) { if (sCallBackFunc) { OSReport("in Player ... overwrite callback\n"); } sCallBackFunc = param_1; } /* 80283CE8-80283E9C .text newMemPool__Q28JASystem6TTrackFi */ void JASystem::TTrack::newMemPool(int param_1) { TTrack* runner = (TTrack*)new (JASDram, 0) u8[sizeof(TTrack)]; JUT_ASSERT(2218, runner); TOuterParam* outer = new (JASDram, 0) TOuterParam(); JUT_ASSERT(2220, outer); runner->assignExtBuffer(outer); sFreeList = runner; for (int i = 1; i < param_1; i++) { runner->next = (TTrack*)new (JASDram, 0) u8[sizeof(TTrack)]; JUT_ASSERT(2228, runner->next); TOuterParam* outer = new (JASDram, 0) TOuterParam(); JUT_ASSERT(2230, outer); runner->next->assignExtBuffer(outer); runner = runner->next; } runner->next = NULL; } /* 80283E9C-80283ECC .text __ct__Q28JASystem8TVibrateFv */ JASystem::TVibrate::TVibrate() { init(); } /* 80283ECC-80283EE4 .text init__Q28JASystem8TVibrateFv */ void JASystem::TVibrate::init() { mPitch = 1.0f / 18.0f; mDepth = 0.0f; field_0x0 = 0.0f; } /* 80283EE4-80283F18 .text incCounter__Q28JASystem8TVibrateFv */ void JASystem::TVibrate::incCounter() { field_0x0 += mPitch; if (!(field_0x0 >= 4.0)) { return; } field_0x0 -= 4.0f; } /* 80283F18-80283FD0 .text getValue__Q28JASystem8TVibrateCFv */ f32 JASystem::TVibrate::getValue() const { if (mDepth == 0.0f) { return 1.0f; } f32 value = field_0x0; bool flag = false; if (value < 2.0) { if (!(value < 1.0)) { value = 2.0f - value; } } else { flag = true; if (value < 3.0) { value = value - 2.0f; } else { value = 4.0f - value; } } f32 sin_val = Calc::sinfT(value); if (flag) { sin_val = -sin_val; } return Player::pitchToCent(sin_val * mDepth, 12.0f); }