mirror of
https://github.com/zeldaret/tww.git
synced 2026-05-27 16:12:54 -04:00
396 lines
14 KiB
C++
396 lines
14 KiB
C++
//
|
|
// Generated by dtk
|
|
// Translation Unit: d_vibration.cpp
|
|
//
|
|
|
|
#include "d/dolzel.h" // IWYU pragma: keep
|
|
#include "d/d_vibration.h"
|
|
#include "d/d_com_inf_game.h"
|
|
#include "d/d_camera.h"
|
|
#include "m_Do/m_Do_controller_pad.h"
|
|
#include "SSystem/SComponent/c_math.h"
|
|
#include "JSystem/JUtility/JUTGamePad.h"
|
|
|
|
#define RESET_FRAME -99
|
|
#define PATTERN_OFF -1
|
|
#define MAX_MOTOR_QUAKE_FRAME 900
|
|
|
|
#define MASK_CAMERA_SHAKE 0x3E
|
|
#define FLAG_MOTOR_SHAKE 0x1
|
|
|
|
|
|
namespace {
|
|
u8* makedata(u16 dst[4], u32 pattern, s32 length) {
|
|
/* Makes a rumble pattern in the format used by startPatternedRumble */
|
|
dst[0] = length;
|
|
dst[1] = pattern >> 16;
|
|
dst[2] = pattern;
|
|
dst[3] = 0;
|
|
return (u8*)dst;
|
|
}
|
|
|
|
u32 rollshift(u32 pattern, s32 patt_len, s32 cur_idx) {
|
|
s32 loop_num = cur_idx/patt_len;
|
|
s32 loop_start = loop_num * patt_len;
|
|
s32 pos_in_loop = cur_idx - loop_start;
|
|
|
|
u32 lo = pattern >> pos_in_loop;
|
|
u32 hi = pattern << (patt_len - pos_in_loop);
|
|
|
|
return lo | hi;
|
|
}
|
|
|
|
u32 makebits(u32 pattern, s32 patt_len, s32 numbits) {
|
|
/* Extends a pattern to numbits bits by looping it */
|
|
int i;
|
|
u32 masked = pattern & -1 << (0x20 - patt_len);
|
|
pattern = masked;
|
|
for (i = patt_len; i < numbits; i += patt_len){
|
|
pattern = masked | pattern >> patt_len;
|
|
}
|
|
return pattern;
|
|
}
|
|
|
|
u32 randombit(s32 rounds, s32 patt_len) {
|
|
/* Makes a random rumble pattern by enabling up to rounds random bits */
|
|
u32 pattern = 0;
|
|
for (int i = 0; i < rounds; i++){
|
|
pattern |= ((1 << 30) >> (u32)(patt_len * cM_rnd()));
|
|
}
|
|
return pattern;
|
|
}
|
|
};
|
|
|
|
/* 8009C73C-8009CCCC .text Run__12dVibration_cFv */
|
|
int dVibration_c::Run() {
|
|
mRumbleState = RUMBLE_STATE_RUNNING;
|
|
#if VERSION == VERSION_DEMO
|
|
if (dComIfGs_getOptVibration() != 1U)
|
|
#else
|
|
if (dComIfGs_checkOptVibration() != 1U)
|
|
#endif
|
|
{
|
|
mMotor.mShock.mPatternIdx = mMotor.mQuake.mPatternIdx = PATTERN_OFF;
|
|
mMotor.mShock.mCurrentFrame = mMotor.mQuake.mCurrentFrame = RESET_FRAME;
|
|
}
|
|
if (mCamera.mShock.mCurrentFrame == 0 || mCamera.mQuake.mCurrentFrame == 0){
|
|
u32 rumble = 0;
|
|
if (mCamera.mShock.mPatternIdx == PATTERN_OFF){
|
|
mCamera.mShock.mCurrentFrame = RESET_FRAME;
|
|
} else if (mCamera.mShock.mCurrentFrame >= 0) {
|
|
rumble |= RUMBLE_SHOCK;
|
|
}
|
|
if (mCamera.mQuake.mPatternIdx == PATTERN_OFF) {
|
|
mCamera.mQuake.mCurrentFrame = RESET_FRAME;
|
|
} else if (mCamera.mQuake.mCurrentFrame >= 0){
|
|
rumble |= RUMBLE_QUAKE;
|
|
}
|
|
|
|
s32 length, pattern, bits;
|
|
switch (rumble) {
|
|
case RUMBLE_SHOCK: /* branch e0 */
|
|
length = mCamera.mShock.mLength;
|
|
pattern = mCamera.mShock.mPattern;
|
|
pattern |= randombit(mCamera.mShock.mRounds, length);
|
|
dCam_getBody()->StartShake(length, (u8*)(&pattern), mCamera.mShock.mFlags, mCamera.mShock.mCoord.norm());
|
|
break;
|
|
case RUMBLE_QUAKE: /* branch 12c */
|
|
length = mCamera.mQuake.mLength;
|
|
pattern = rollshift(mCamera.mQuake.mPattern, length, mFrameIdx);
|
|
pattern |= randombit(mCamera.mQuake.mRounds, length);
|
|
dCam_getBody()->StartShake(length, (u8*)(&pattern), mCamera.mQuake.mFlags, mCamera.mQuake.mCoord.norm());
|
|
break;
|
|
case RUMBLE_SHOCK | RUMBLE_QUAKE: /* branch 184 */
|
|
pattern = mCamera.mShock.mPattern << mCamera.mShock.mCurrentFrame;
|
|
length = mCamera.mShock.mLength - mCamera.mShock.mCurrentFrame;
|
|
bits = makebits(mCamera.mQuake.mPattern, mCamera.mQuake.mLength, length);
|
|
pattern |= rollshift(bits, length, mFrameIdx);
|
|
pattern |= randombit((mCamera.mShock.mRounds > mCamera.mQuake.mRounds)? mCamera.mShock.mRounds : mCamera.mQuake.mRounds, length);
|
|
|
|
dCam_getBody()->StartShake(length, (u8*)(&pattern), mCamera.mShock.mFlags|mCamera.mQuake.mFlags,
|
|
cXyz(mCamera.mShock.mCoord + mCamera.mQuake.mCoord).norm());
|
|
mCamera.mShock.mCurrentFrame = mCamera.mQuake.mCurrentFrame = 0;
|
|
break;
|
|
default: /* branch 254 */
|
|
dCam_getBody()->StopShake();
|
|
break;
|
|
}
|
|
}
|
|
if (mMotor.mQuake.mCurrentFrame >= MAX_MOTOR_QUAKE_FRAME){
|
|
g_mDoCPd_gamePad[0]->stopMotorWave();
|
|
g_mDoCPd_gamePad[0]->stopMotor();
|
|
mMotor.mQuake.mCurrentFrame = -1;
|
|
}
|
|
|
|
if (mMotor.mShock.mCurrentFrame == 0 || mMotor.mQuake.mCurrentFrame == 0){
|
|
u32 rumble = 0;
|
|
if (mMotor.mShock.mPatternIdx == PATTERN_OFF){
|
|
mMotor.mShock.mCurrentFrame = RESET_FRAME;
|
|
} else if (mMotor.mShock.mCurrentFrame >= 0){
|
|
rumble |= RUMBLE_SHOCK;
|
|
}
|
|
if (mMotor.mQuake.mPatternIdx == PATTERN_OFF){
|
|
mMotor.mQuake.mCurrentFrame = RESET_FRAME;
|
|
} else if (mMotor.mQuake.mCurrentFrame >= 0){
|
|
rumble |= RUMBLE_QUAKE;
|
|
}
|
|
|
|
static u16 data[4];
|
|
u8* pBuf;
|
|
s32 pattern, loopLen, bits;
|
|
switch (rumble) {
|
|
case RUMBLE_SHOCK: /* branch 324 */
|
|
loopLen = mMotor.mShock.mLength;
|
|
pattern = mMotor.mShock.mPattern;
|
|
pattern |= randombit(mMotor.mShock.mRounds, loopLen);
|
|
mMotor.mShock.mStopFrame = loopLen;
|
|
pBuf = makedata(data, pattern, loopLen);
|
|
g_mDoCPd_gamePad[0]->startMotorWave(pBuf, JUTGamePad::CRumble::LOOP_ONCE, 60);
|
|
break;
|
|
case RUMBLE_QUAKE: /* branch 374 */
|
|
loopLen = mMotor.mQuake.mLength;
|
|
pattern = rollshift(mMotor.mQuake.mPattern, loopLen, mFrameIdx);
|
|
pattern |= randombit(mMotor.mQuake.mRounds, loopLen);
|
|
mMotor.mQuake.mStopFrame = INT32_MAX;
|
|
pBuf = makedata(data, pattern, loopLen);
|
|
g_mDoCPd_gamePad[0]->startMotorWave(pBuf, JUTGamePad::CRumble::LOOP_FOREVER, 60);
|
|
break;
|
|
case RUMBLE_SHOCK | RUMBLE_QUAKE: /* branch 3d8 */
|
|
pattern = mMotor.mShock.mPattern << mMotor.mShock.mCurrentFrame;
|
|
loopLen = mMotor.mShock.mLength - mMotor.mShock.mCurrentFrame;
|
|
|
|
bits = makebits(mMotor.mQuake.mPattern, mMotor.mQuake.mLength, loopLen);
|
|
pattern |= rollshift(bits, loopLen, mFrameIdx);
|
|
pattern |= randombit((mMotor.mShock.mRounds > mMotor.mQuake.mRounds)? mMotor.mShock.mRounds : mMotor.mQuake.mRounds, loopLen);
|
|
|
|
mMotor.mShock.mStopFrame = mMotor.mQuake.mStopFrame = loopLen;
|
|
mMotor.mShock.mCurrentFrame = mMotor.mQuake.mCurrentFrame = 0;
|
|
|
|
pBuf = makedata(data, pattern, loopLen);
|
|
g_mDoCPd_gamePad[0]->startMotorWave(pBuf, JUTGamePad::CRumble::LOOP_ONCE, 60);
|
|
break;
|
|
default: /* branch 474 */
|
|
g_mDoCPd_gamePad[0]->stopMotorWave();
|
|
g_mDoCPd_gamePad[0]->stopMotor();
|
|
mMotor.mShock.mStopFrame = mMotor.mQuake.mStopFrame = RESET_FRAME;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (mCamera.mShock.mCurrentFrame >= -1){
|
|
mCamera.mShock.mCurrentFrame += 1;
|
|
if (mCamera.mShock.mCurrentFrame > mCamera.mShock.mLength){
|
|
mCamera.mShock.mCurrentFrame = 0;
|
|
mCamera.mShock.mPatternIdx = PATTERN_OFF;
|
|
}
|
|
}
|
|
if (mMotor.mShock.mCurrentFrame >= -1){
|
|
mMotor.mShock.mCurrentFrame += 1;
|
|
if (mMotor.mShock.mCurrentFrame > mMotor.mShock.mStopFrame){
|
|
mMotor.mShock.mCurrentFrame = 0;
|
|
mMotor.mShock.mPatternIdx = PATTERN_OFF;
|
|
}
|
|
}
|
|
if (mCamera.mQuake.mCurrentFrame >= -1){
|
|
mCamera.mQuake.mCurrentFrame += 1;
|
|
if (mCamera.mQuake.mCurrentFrame > mCamera.mQuake.mLength){
|
|
mCamera.mQuake.mCurrentFrame = 0;
|
|
}
|
|
}
|
|
if (mMotor.mQuake.mCurrentFrame >= -1){
|
|
mMotor.mQuake.mCurrentFrame += 1;
|
|
if (mMotor.mQuake.mCurrentFrame > mMotor.mQuake.mStopFrame){
|
|
mMotor.mQuake.mCurrentFrame = 0;
|
|
}
|
|
}
|
|
mFrameIdx += 1;
|
|
return 1;
|
|
}
|
|
|
|
/* 8009CCCC-8009CD6C .text StartShock__12dVibration_cFii4cXyz */
|
|
bool dVibration_c::StartShock(int patt_idx, int flags, cXyz coord) {
|
|
/* Starts shock pattern from the registered [MC]S_patt global constants */
|
|
bool ret = false;
|
|
|
|
if (flags & MASK_CAMERA_SHAKE){
|
|
mCamera.mShock.mPatternIdx = patt_idx;
|
|
mCamera.mShock.mCurrentFrame = 0;
|
|
mCamera.mShock.mFlags = flags;
|
|
mCamera.mShock.mCoord = coord;
|
|
|
|
mCamera.mShock.mPattern = CS_patt[patt_idx].pattern;
|
|
mCamera.mShock.mLength = CS_patt[patt_idx].length;
|
|
mCamera.mShock.mRounds = CS_patt[patt_idx].rounds;
|
|
ret = true;
|
|
}
|
|
|
|
if (flags & FLAG_MOTOR_SHAKE){
|
|
mMotor.mShock.mPatternIdx = patt_idx;
|
|
mMotor.mShock.mCurrentFrame = 0;
|
|
|
|
mMotor.mShock.mPattern = MS_patt[patt_idx].pattern;
|
|
mMotor.mShock.mLength = MS_patt[patt_idx].length;
|
|
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* 8009CD6C-8009CE1C .text StartQuake__12dVibration_cFii4cXyz */
|
|
bool dVibration_c::StartQuake(int patt_idx, int flags, cXyz coord) {
|
|
/* Starts quake pattern from the registered [MC]Q_patt global constants */
|
|
bool ret = false;
|
|
|
|
if (flags & MASK_CAMERA_SHAKE){
|
|
mCamera.mQuake.mPatternIdx = patt_idx;
|
|
mCamera.mQuake.mCurrentFrame = 0;
|
|
mCamera.mQuake.mFlags = flags;
|
|
mCamera.mQuake.mCoord = coord;
|
|
|
|
mCamera.mQuake.mPattern = CQ_patt[patt_idx].pattern;
|
|
mCamera.mQuake.mLength = CQ_patt[patt_idx].length;
|
|
mCamera.mQuake.mRounds = CQ_patt[patt_idx].rounds;
|
|
ret = true;
|
|
}
|
|
|
|
if (flags & FLAG_MOTOR_SHAKE){
|
|
mMotor.mQuake.mPatternIdx = patt_idx;
|
|
mMotor.mQuake.mCurrentFrame = 0;
|
|
|
|
mMotor.mQuake.mPattern = MQ_patt[patt_idx].pattern;
|
|
mMotor.mQuake.mLength = MQ_patt[patt_idx].length;
|
|
mMotor.mQuake.mRounds = CQ_patt[patt_idx].rounds;
|
|
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* 8009CE1C-8009CF84 .text StartQuake__12dVibration_cFPCUcii4cXyz */
|
|
bool dVibration_c::StartQuake(u8 const *pattern, int rounds, int flags, cXyz coord) {
|
|
/* Starts quake pattern from an arbitrary bit pattern */
|
|
bool ret = false;
|
|
int pattLen = (pattern[0] << 8) | pattern[1];
|
|
s32 bits =
|
|
(pattern[pattLen >= 1 ? 2 : 0]) << 24
|
|
| (pattern[pattLen >= 9 ? 3 : 0]) << 16
|
|
| (pattern[pattLen >= 17 ? 4 : 0]) << 8
|
|
| (pattern[pattLen >= 25 ? 5 : 0]) << 0
|
|
;
|
|
|
|
|
|
if (flags & MASK_CAMERA_SHAKE){
|
|
mCamera.mQuake.mPatternIdx = 0;
|
|
mCamera.mQuake.mCurrentFrame = 0;
|
|
mCamera.mQuake.mFlags = flags;
|
|
mCamera.mQuake.mCoord = coord;
|
|
|
|
mCamera.mQuake.mPattern = makebits(bits, pattern[1], 32);
|
|
mCamera.mQuake.mLength = 32;
|
|
mCamera.mQuake.mRounds = rounds;
|
|
ret = true;
|
|
}
|
|
|
|
if (flags & FLAG_MOTOR_SHAKE){
|
|
mMotor.mQuake.mPatternIdx = 0;
|
|
mMotor.mQuake.mCurrentFrame = 0;
|
|
|
|
mMotor.mQuake.mPattern = makebits(bits, pattern[1], 32);
|
|
mMotor.mQuake.mLength = 32;
|
|
mMotor.mQuake.mRounds = rounds;
|
|
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* 8009CF84-8009CFEC .text StopQuake__12dVibration_cFi */
|
|
int dVibration_c::StopQuake(int flags) {
|
|
int ret = FALSE;
|
|
if (flags & MASK_CAMERA_SHAKE) {
|
|
mCamera.mQuake.mFlags &= ~flags;
|
|
if (mCamera.mQuake.mFlags == 0) {
|
|
mCamera.mQuake.mPatternIdx = PATTERN_OFF;
|
|
}
|
|
mCamera.mQuake.mCurrentFrame = 0;
|
|
ret = TRUE;
|
|
}
|
|
if ((flags & FLAG_MOTOR_SHAKE) && mMotor.mQuake.mPatternIdx != PATTERN_OFF) {
|
|
mMotor.mQuake.mPatternIdx = PATTERN_OFF;
|
|
mMotor.mQuake.mCurrentFrame = 0;
|
|
ret = TRUE;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* 8009CFEC-8009D044 .text Kill__12dVibration_cFv */
|
|
void dVibration_c::Kill() {
|
|
g_mDoCPd_gamePad[0]->stopMotorWaveHard();
|
|
g_mDoCPd_gamePad[0]->stopMotorHard();
|
|
setDefault();
|
|
}
|
|
|
|
/* 8009D044-8009D06C .text CheckQuake__12dVibration_cFv */
|
|
bool dVibration_c::CheckQuake() {
|
|
return mCamera.mQuake.mPatternIdx != PATTERN_OFF || mMotor.mQuake.mPatternIdx != PATTERN_OFF;
|
|
}
|
|
|
|
/* 8009D06C-8009D0AC .text setDefault__12dVibration_cFv */
|
|
void dVibration_c::setDefault() {
|
|
mMotor.mShock.mPatternIdx = PATTERN_OFF;
|
|
mCamera.mShock.mPatternIdx = PATTERN_OFF;
|
|
mMotor.mQuake.mPatternIdx = PATTERN_OFF;
|
|
mCamera.mQuake.mPatternIdx = PATTERN_OFF;
|
|
mMotor.mShock.mCurrentFrame = RESET_FRAME;
|
|
mCamera.mShock.mCurrentFrame = RESET_FRAME;
|
|
mMotor.mQuake.mCurrentFrame = RESET_FRAME;
|
|
mCamera.mQuake.mCurrentFrame = RESET_FRAME;
|
|
mMotor.mQuake.mStopFrame = RESET_FRAME;
|
|
mMotor.mShock.mStopFrame = RESET_FRAME;
|
|
mRumbleState = RUMBLE_STATE_WAITING;
|
|
mFrameIdx = 0;
|
|
}
|
|
|
|
/* 8009D0AC-8009D0CC .text Init__12dVibration_cFv */
|
|
void dVibration_c::Init() {
|
|
setDefault();
|
|
}
|
|
|
|
/* 8009D0CC-8009D188 .text Pause__12dVibration_cFv */
|
|
void dVibration_c::Pause() {
|
|
if (mRumbleState == RUMBLE_STATE_PAUSED){
|
|
return;
|
|
}
|
|
#if VERSION > VERSION_DEMO
|
|
if (mMotor.mShock.mPatternIdx != PATTERN_OFF || mMotor.mQuake.mPatternIdx != PATTERN_OFF)
|
|
#endif
|
|
{
|
|
g_mDoCPd_gamePad[0]->stopMotorWaveHard();
|
|
g_mDoCPd_gamePad[0]->stopMotorHard();
|
|
}
|
|
mCamera.mShock.mPatternIdx = mMotor.mShock.mPatternIdx = PATTERN_OFF;
|
|
mCamera.mShock.mCurrentFrame = mMotor.mShock.mCurrentFrame = RESET_FRAME;
|
|
if (mCamera.mQuake.mPatternIdx != PATTERN_OFF){
|
|
mCamera.mQuake.mCurrentFrame = 0;
|
|
}
|
|
if (mMotor.mQuake.mPatternIdx != PATTERN_OFF){
|
|
mMotor.mQuake.mCurrentFrame = 0;
|
|
}
|
|
mRumbleState = RUMBLE_STATE_PAUSED;
|
|
}
|
|
|
|
#if VERSION > VERSION_DEMO
|
|
/* 8009D188-8009D1C4 .text __ct__12dVibration_cFv */
|
|
dVibration_c::dVibration_c() {
|
|
setDefault();
|
|
}
|
|
|
|
/* 8009D1C4-8009D220 .text __dt__12dVibration_cFv */
|
|
dVibration_c::~dVibration_c() {
|
|
Kill();
|
|
}
|
|
#endif
|