d_snd_bgm_mml_parser_base

This commit is contained in:
robojumper
2025-06-29 16:16:52 +02:00
parent a6c218e654
commit d36d8ac2ac
5 changed files with 799 additions and 14 deletions
+2
View File
@@ -2700,10 +2700,12 @@ d/snd/d_snd_bgm_sound.cpp:
d/snd/d_snd_bgm_data_mgr.cpp:
.text start:0x8037BA70 end:0x8037C518 align:16
.data start:0x80549148 end:0x80549158
.sdata start:0x805742F0 end:0x805742F8
d/snd/d_snd_bgm_mml_parser_base.cpp:
.text start:0x8037C520 end:0x8037D014 align:16
.data start:0x80549158 end:0x80549168
d/snd/d_snd_bgm_mml_parsers.cpp:
.text start:0x8037D020 end:0x8037D800 align:16
+13 -13
View File
@@ -20798,18 +20798,18 @@ fn_8037C370 = .text:0x8037C370; // type:function size:0x34
fn_8037C3B0 = .text:0x8037C3B0; // type:function size:0x58
fn_8037C410 = .text:0x8037C410; // type:function size:0x60
setHarpPitchSeqVars = .text:0x8037C470; // type:function size:0xA8
fn_8037C520 = .text:0x8037C520; // type:function size:0x20
fn_8037C540 = .text:0x8037C540; // type:function size:0x34
fn_8037C580 = .text:0x8037C580; // type:function size:0x98
fn_8037C620 = .text:0x8037C620; // type:function size:0x1E0
dSndMmlParser__Parse = .text:0x8037C800; // type:function size:0x4F0
dSndMmlParser__CommandProc = .text:0x8037CCF0; // type:function size:0x18C
dSndMmlParser__Read16 = .text:0x8037CE80; // type:function size:0x24
dSndMmlParser__Read24 = .text:0x8037CEB0; // type:function size:0x38
dSndMmlParser__ReadVar = .text:0x8037CEF0; // type:function size:0x30
dSndMmlParser__ReadArg = .text:0x8037CF20; // type:function size:0xD8
fn_8037D000 = .text:0x8037D000; // type:function size:0x4
fn_8037D010 = .text:0x8037D010; // type:function size:0x4
__ct__18dSndBgmMmlParser_cFPQ34nw4r3snd18SoundArchivePlayerPQ34nw4r3snd12SoundArchive = .text:0x8037C520; // type:function size:0x20
initTrack__18dSndBgmMmlParser_cFlUl = .text:0x8037C540; // type:function size:0x34
loadAndParse__18dSndBgmMmlParser_cFUlUlb = .text:0x8037C580; // type:function size:0x98
readTracks__18dSndBgmMmlParser_cFUlUlb = .text:0x8037C620; // type:function size:0x1E0
Parse__18dSndBgmMmlParser_cCFP12dBgmMmlTrack = .text:0x8037C800; // type:function size:0x4F0
CommandProc___18dSndBgmMmlParser_cCFP12dBgmMmlTrackUlll = .text:0x8037CCF0; // type:function size:0x18C
Read16__18dSndBgmMmlParser_cCFPPCUc = .text:0x8037CE80; // type:function size:0x24
Read24__18dSndBgmMmlParser_cCFPPCUc = .text:0x8037CEB0; // type:function size:0x38
ReadVar__18dSndBgmMmlParser_cCFPPCUc = .text:0x8037CEF0; // type:function size:0x30
ReadArg__18dSndBgmMmlParser_cCFPPCUcQ218dSndBgmMmlParser_c10SeqArgType = .text:0x8037CF20; // type:function size:0xD8
CommandProc__18dSndBgmMmlParser_cCFUliUlll = .text:0x8037D000; // type:function size:0x4
NoteOnCommandProc__18dSndBgmMmlParser_cCFUliiil = .text:0x8037D010; // type:function size:0x4
fn_8037D020 = .text:0x8037D020; // type:function size:0x64
fn_8037D090 = .text:0x8037D090; // type:function size:0xE8
fn_8037D180 = .text:0x8037D180; // type:function size:0x84
@@ -38042,7 +38042,7 @@ lbl_80549088 = .data:0x80549088; // type:object size:0x34
lbl_805490BC = .data:0x805490BC; // type:object size:0x44
lbl_80549100 = .data:0x80549100; // type:object size:0x48
lbl_80549148 = .data:0x80549148; // type:object size:0x10
lbl_80549158 = .data:0x80549158; // type:object size:0x10
__vt__18dSndBgmMmlParser_c = .data:0x80549158; // type:object size:0x10
lbl_80549168 = .data:0x80549168; // type:object size:0x10
lbl_80549178 = .data:0x80549178; // type:object size:0x10
lbl_80549188 = .data:0x80549188; // type:object size:0x10
+1 -1
View File
@@ -758,7 +758,7 @@ config.libs = [
Object(NonMatching, "d/snd/d_snd_bgm_sound_battle_callbacks.cpp"),
Object(NonMatching, "d/snd/d_snd_bgm_sound.cpp"),
Object(NonMatching, "d/snd/d_snd_bgm_data_mgr.cpp"),
Object(NonMatching, "d/snd/d_snd_bgm_mml_parser_base.cpp"),
Object(Matching, "d/snd/d_snd_bgm_mml_parser_base.cpp"),
Object(NonMatching, "d/snd/d_snd_bgm_mml_parsers.cpp"),
Object(NonMatching, "d/snd/d_snd_small_effect_mgr.cpp"),
Object(NonMatching, "d/snd/d_snd_harp_mgr.cpp"),
+203
View File
@@ -0,0 +1,203 @@
#ifndef D_SND_BGM_MML_PARSER_BASE_H
#define D_SND_BGM_MML_PARSER_BASE_H
#include "common.h"
#include "nw4r/snd/snd_SoundArchive.h"
#include "nw4r/snd/snd_SoundArchivePlayer.h"
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2cdd6
struct dBgmMmlCallStack
{
bool loopFlag; // size 0x01, offset 0x00
u8 loopCount; // size 0x01, offset 0x01
/* 2 bytes padding */
byte_t const *address; // size 0x04, offset 0x04
}; // size 0x08
/**
* Size: 0x28
*/
struct dBgmMmlTrack {
/* 0x00 */ const byte_t *currentAddr;
/* 0x04 */ u8 mTrackNo;
/* 0x05 */ bool mTrackUsed;
/* 0x06 */ u8 cmpFlag;
/* 0x08 */ s32 wait;
/* 0x0C */ dBgmMmlCallStack callStack[3];
/* 0x24 */ s32 callStackDepth;
};
/**
* @brief Parses harp key data
*
* Partial copy of nw4r::snd::detail::MmlParser
*/
class dSndBgmMmlParser_c {
private:
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2d70c
// Swapped - or maybe just returns a boolean
enum ParseResult {
PARSE_RESULT_FINISH,
PARSE_RESULT_CONTINUE,
};
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x31279
enum SeqArgType {
SEQ_ARG_NONE,
SEQ_ARG_U8,
SEQ_ARG_S16,
SEQ_ARG_VMIDI,
SEQ_ARG_RANDOM,
SEQ_ARG_VARIABLE,
};
enum MmlCommand {
MML_CMD_MIN = 0x80, // <80 -> MML note, not a command
MML_CMD_MAX = 0xff,
MML_CMD_MASK = 0x80,
MML_CMD_SET_MASK = 0xf0,
MML_WAIT = 0x80,
MML_SET_PRGNO,
MML_OPEN_TRACK = 0x88,
MML_JUMP,
MML_CALL,
MML_ARG_1_RANDOM = 0xa0,
MML_ARG_1_VARIABLE,
MML_EXEC_IF,
MML_ARG_2_S16,
MML_ARG_2_RANDOM,
MML_ARG_2_VARIABLE,
MML_SET_TIMEBASE = 0xb0,
MML_SET_ENV_HOLD,
MML_SET_MONOPHONIC,
MML_SET_TRACK_VELOCITY_RANGE,
MML_SET_BIQUAD_TYPE,
MML_SET_BIQUAD_VALUE,
MML_SET_PAN = 0xc0,
MML_SET_TRACK_VOLUME,
MML_SET_PLAYER_VOLUME,
MML_SET_TRANSPOSE,
MML_SET_PITCH_BEND,
MML_SET_BEND_RANGE,
MML_SET_PRIORITY,
MML_SET_NOTE_WAIT,
MML_SET_TIE,
MML_SET_PORTAMENTO,
MML_SET_LFO_DEPTH,
MML_SET_LFO_SPEED,
MML_SET_LFO_TARGET,
MML_SET_LFO_RANGE,
MML_SET_PORTASPEED,
MML_SET_PORTATIME,
MML_SET_ATTACK = 0xd0,
MML_SET_DECAY,
MML_SET_SUSTAIN,
MML_SET_RELEASE,
MML_LOOP_START,
MML_SET_TRACK_VOLUME2,
MML_PRINT_VAR,
MML_SET_SURROUND_PAN,
MML_SET_LPF_FREQ,
MML_SET_FX_SEND_A,
MML_SET_FX_SEND_B,
MML_SET_MAIN_SEND,
MML_SET_INIT_PAN,
MML_SET_MUTE,
MML_SET_FX_SEND_C,
MML_SET_DAMPER,
MML_SET_LFO_DELAY = 0xe0,
MML_SET_TEMPO,
MML_SET_E2,
MML_SET_SWEEP_PITCH,
MML_RESET_ADSR = 0xfb,
MML_LOOP_END,
MML_RET,
MML_ALLOC_TRACK,
MML_EOF
};
enum MmlExCommand {
MML_EX_COMMAND = 0xf0,
MML_EX_CMD_MAX = 0xffff,
MML_EX_ARITHMETIC = 0x80,
MML_EX_SET = 0x80,
MML_EX_APL,
MML_EX_AMI,
MML_EX_AMU,
MML_EX_ADV,
MML_EX_ALS,
MML_EX_RND,
MML_EX_AAD,
MML_EX_AOR,
MML_EX_AER,
MML_EX_ACO,
MML_EX_AMD,
MML_EX_LOGIC = 0x90,
MML_EX_EQ = 0x90,
MML_EX_GE,
MML_EX_GT,
MML_EX_LE,
MML_EX_LT,
MML_EX_NE,
MML_EX_USERPROC = 0xe0,
};
public:
dSndBgmMmlParser_c(nw4r::snd::SoundArchivePlayer *player, nw4r::snd::SoundArchive *archive);
virtual void CommandProc(u32 trackNo, int wait, u32 command, s32 commandArg1, s32 commandArg2) const;
virtual void NoteOnCommandProc(u32 trackNo, int wait, int key, int velocity, s32 length) const;
protected:
bool loadAndParse(u32 soundId, u32 trackMask, bool noJumps);
private:
bool readTracks(u32 soundId, u32 trackMask, bool noJumps);
void initTrack(s32 trackNo, u32 offset);
ParseResult Parse(dBgmMmlTrack *track) const;
void CommandProc_(dBgmMmlTrack *track, u32 command, s32 commandArg1, s32 commandArg2) const;
u8 ReadByte(byte_t const **ptr) const {
return *(*ptr)++;
}
u16 Read16(byte_t const **ptr) const;
u32 Read24(byte_t const **ptr) const;
s32 ReadVar(byte_t const **ptr) const;
s32 ReadArg(byte_t const **ptr, SeqArgType argType) const;
// static members
public:
static int const TEMPO_MAX = 1023;
static int const TEMPO_MIN = 0;
static int const CALL_STACK_DEPTH = 3;
static int const SURROUND_PAN_CENTER;
static int const PAN_CENTER = 64;
private:
static bool mPrintVarEnabledFlag;
// members
private:
/* vtable */ // size 0x04, offset 0x00
/* 0x04 */ u8 field_0x04;
/* 0x08 */ nw4r::snd::SoundArchivePlayer *mpPlayer;
/* 0x0C */ nw4r::snd::SoundArchive *mpArchive;
/* 0x10 */ const byte_t *baseAddr;
/* 0x14 */ dBgmMmlTrack mTracks[16];
}; // size 0x04
#endif
+580
View File
@@ -0,0 +1,580 @@
#include "d/snd/d_snd_bgm_mml_parser_base.h"
#include "common.h"
#include "nw4r/snd/snd_SeqFile.h"
#include "nw4r/snd/snd_SoundArchive.h"
#include "nw4r/snd/snd_SoundArchivePlayer.h"
dSndBgmMmlParser_c::dSndBgmMmlParser_c(nw4r::snd::SoundArchivePlayer *player, nw4r::snd::SoundArchive *archive)
: field_0x04(0), mpPlayer(player), mpArchive(archive) {}
void dSndBgmMmlParser_c::initTrack(s32 trackNo, u32 offset) {
dBgmMmlTrack &trackParam = mTracks[trackNo];
trackParam.currentAddr = baseAddr + offset;
trackParam.mTrackNo = trackNo;
trackParam.mTrackUsed = true;
trackParam.cmpFlag = 0;
trackParam.wait = 0;
trackParam.callStackDepth = 0;
}
bool dSndBgmMmlParser_c::loadAndParse(u32 soundId, u32 trackMask, bool noJumps) {
if (!readTracks(soundId, trackMask, noJumps)) {
return false;
}
for (int i = 0; i < 16; i++) {
if (mTracks[i].mTrackUsed) {
while (Parse(&mTracks[i]) != PARSE_RESULT_FINISH) {}
}
}
return true;
}
bool dSndBgmMmlParser_c::readTracks(u32 soundId, u32 trackMask, bool noJumps) {
nw4r::snd::SoundArchivePlayer *player = mpPlayer;
nw4r::snd::SoundArchive *archive = mpArchive;
field_0x04 = noJumps;
nw4r::snd::SoundArchive::SoundInfo info;
if (!archive->ReadSoundInfo(soundId, &info)) {
return false;
}
if (archive->GetSoundType(soundId) != nw4r::snd::SoundArchive::SOUND_TYPE_SEQ) {
return false;
}
const void *addr = player->detail_GetFileAddress(info.fileId);
if (addr == nullptr) {
return false;
}
nw4r::snd::detail::SeqFileReader reader(addr);
baseAddr = (const byte_t *)reader.GetBaseAddress();
for (int i = 0; i < 16; i++) {
mTracks[i].mTrackUsed = false;
}
initTrack(0, 0);
const byte_t *ptr = baseAddr;
bool endReached = false;
for (int i = 0; i < 20; i++) {
u32 cmd = ReadByte(&ptr);
switch (cmd) {
case MML_ALLOC_TRACK:
Read16(&ptr);
break;
case MML_OPEN_TRACK: {
u8 trackNo = ReadByte(&ptr);
u32 offset = Read24(&ptr);
if (((trackMask >> trackNo) & 1) != 0) {
initTrack(trackNo, offset);
}
break;
}
case MML_SET_TIMEBASE:
ptr += 1;
break;
default:
endReached = true;
break;
}
if (endReached) {
mTracks[0].currentAddr = ptr - 1;
break;
}
}
if (!endReached) {
return false;
}
if ((trackMask & 1) == 0) {
mTracks[0].mTrackUsed = false;
}
return true;
}
// clang-format off
// modified from nw4r::snd - some changes I had to make to make it match might be fake
dSndBgmMmlParser_c::ParseResult dSndBgmMmlParser_c::Parse(dBgmMmlTrack *track) const {
dBgmMmlTrack &trackParam = *track;
// Had to move these up for regswaps - maybe fake
s32 commandArg1;
s32 commandArg2;
SeqArgType argType;
SeqArgType argType2 = SEQ_ARG_NONE;
bool useArgType = false;
bool doExecCommand = true;
u32 cmd = ReadByte(&trackParam.currentAddr);
if (cmd == MML_EXEC_IF)
{
cmd = ReadByte(&trackParam.currentAddr);
doExecCommand = trackParam.cmpFlag != false;
}
if (cmd == MML_ARG_2_S16)
{
cmd = ReadByte(&trackParam.currentAddr);
argType2 = SEQ_ARG_S16;
}
else if (cmd == MML_ARG_2_RANDOM)
{
cmd = ReadByte(&trackParam.currentAddr);
argType2 = SEQ_ARG_RANDOM;
}
else if (cmd == MML_ARG_2_VARIABLE)
{
cmd = ReadByte(&trackParam.currentAddr);
argType2 = SEQ_ARG_VARIABLE;
}
if (cmd == MML_ARG_1_RANDOM)
{
cmd = ReadByte(&trackParam.currentAddr);
argType = SEQ_ARG_RANDOM;
useArgType = true;
}
else if (cmd == MML_ARG_1_VARIABLE)
{
cmd = ReadByte(&trackParam.currentAddr);
argType = SEQ_ARG_VARIABLE;
useArgType = true;
}
if (!(cmd & MML_CMD_MASK))
{
// MML note data, not a command
u8 velocity = ReadByte(&trackParam.currentAddr);
s32 length = ReadArg(&trackParam.currentAddr,
useArgType ? argType : SEQ_ARG_VMIDI);
if (!doExecCommand)
return PARSE_RESULT_CONTINUE;
int key = cmd;
NoteOnCommandProc(trackParam.mTrackNo, trackParam.wait, key, velocity,
length > 0 ? length : -1);
}
else
{
// MML command
commandArg1 = 0;
commandArg2 = 0;
switch (cmd & MML_CMD_SET_MASK)
{
case 0x80:
{
switch (cmd)
{
case MML_WAIT:
{
s32 arg = ReadArg(&trackParam.currentAddr,
useArgType ? argType : SEQ_ARG_VMIDI);
if (doExecCommand)
trackParam.wait += arg;
}
break;
case MML_SET_PRGNO:
commandArg1 = ReadArg(&trackParam.currentAddr,
useArgType ? argType : SEQ_ARG_VMIDI);
if (doExecCommand)
CommandProc_(track, cmd, commandArg1, commandArg2);
break;
case MML_OPEN_TRACK:
{
// Had to change u8 -> u32 for regswaps - maybe fake
u32 trackNo = ReadByte(&trackParam.currentAddr);
u32 offset = Read24(&trackParam.currentAddr);
if (doExecCommand)
{
commandArg1 = trackNo;
commandArg2 = offset;
CommandProc_(track, cmd, commandArg1, commandArg2);
}
}
break;
case MML_JUMP:
case MML_CALL:
{
u32 offset = Read24(&trackParam.currentAddr);
if (doExecCommand)
{
commandArg1 = offset;
CommandProc_(track, cmd, commandArg1, commandArg2);
}
}
break;
}
break;
}
case 0xb0:
case 0xc0:
case 0xd0:
{
u8 arg = ReadArg(&trackParam.currentAddr,
useArgType ? argType : SEQ_ARG_U8);
if (argType2 != SEQ_ARG_NONE)
{
commandArg2 =
ReadArg(&trackParam.currentAddr, argType2);
}
if (!doExecCommand)
break;
switch (cmd)
{
case MML_SET_TRANSPOSE:
case MML_SET_PITCH_BEND:
commandArg1 = *reinterpret_cast<s8 *>(&arg);
break;
default:
commandArg1 = *reinterpret_cast<u8 *>(&arg);
break;
}
CommandProc_(track, cmd, commandArg1, commandArg2);
break;
}
case 0x90:
if (doExecCommand)
CommandProc_(track, cmd, commandArg1, commandArg2);
break;
case 0xe0:
commandArg1 =
static_cast<s16>(ReadArg(&trackParam.currentAddr,
useArgType ? argType : SEQ_ARG_S16));
if (doExecCommand)
CommandProc_(track, cmd, commandArg1, commandArg2);
break;
case 0xf0:
{
switch (cmd)
{
case MML_ALLOC_TRACK:
Read16(&trackParam.currentAddr);
NW4RPanicMessage_Line(
312, "seq: must use alloctrack in startup code");
break;
case MML_EOF:
if (doExecCommand)
return PARSE_RESULT_FINISH;
break;
case MML_EX_COMMAND:
{
u32 cmdex = ReadByte(&trackParam.currentAddr);
switch (cmdex & MML_CMD_SET_MASK)
{
case MML_EX_USERPROC:
commandArg1 = static_cast<u16>(
ReadArg(&trackParam.currentAddr,
useArgType ? argType : SEQ_ARG_S16));
if (doExecCommand)
{
CommandProc_(track, (cmd << 8) + cmdex, commandArg1,
commandArg2);
}
break;
case MML_EX_ARITHMETIC:
case MML_EX_LOGIC:
commandArg1 = ReadByte(&trackParam.currentAddr);
commandArg2 = static_cast<s16>(
ReadArg(&trackParam.currentAddr,
useArgType ? argType : SEQ_ARG_S16));
if (doExecCommand)
{
CommandProc_(track, (cmd << 8) + cmdex, commandArg1,
commandArg2);
}
break;
}
}
ATTR_FALLTHROUGH;
default:
if (doExecCommand)
CommandProc_(track, cmd, commandArg1, commandArg2);
break;
}
}
break;
case 0xa0:
NW4RPanicMessage_Line(392, "Invalid seqdata command: %d", cmd);
break;
}
}
return PARSE_RESULT_CONTINUE;
}
// very stripped down from nw4r::snd
void dSndBgmMmlParser_c::CommandProc_(dBgmMmlTrack *track, u32 command, s32 commandArg1, s32 commandArg2) const {
dBgmMmlTrack &trackParam = *track;
switch (command)
{
case MML_JUMP:
if (field_0x04 == 0)
trackParam.currentAddr = baseAddr + commandArg1;
break;
case MML_CALL:
{
if (trackParam.callStackDepth >= CALL_STACK_DEPTH)
{
NW4RWarningMessage_Line(665,
"nw4r::snd::MmlParser: cannot \'call\' "
"because already too deep");
break;
}
dBgmMmlCallStack *callStack =
&trackParam.callStack[trackParam.callStackDepth];
callStack->address = trackParam.currentAddr;
callStack->loopFlag = false;
trackParam.callStackDepth++;
trackParam.currentAddr = baseAddr + commandArg1;
break;
}
case MML_RET:
{
dBgmMmlCallStack *tmp; // needed for lbzu
dBgmMmlCallStack *callStack = nullptr;
while (trackParam.callStackDepth > 0)
{
tmp = &trackParam.callStack[--trackParam.callStackDepth];
if (!tmp->loopFlag)
{
callStack = tmp;
break;
}
}
if (!callStack)
{
NW4RWarningMessage_Line(
688,
"nw4r::snd::MmlParser: unmatched sequence command \'ret\'");
break;
}
trackParam.currentAddr = callStack->address;
}
break;
case MML_LOOP_START:
{
if (trackParam.callStackDepth >= CALL_STACK_DEPTH)
{
NW4RWarningMessage_Line(
698, "nw4r::snd::MmlParser: cannot \'loop_start\' because "
"already too deep");
break;
}
dBgmMmlCallStack *callStack =
&trackParam.callStack[trackParam.callStackDepth];
callStack->address = trackParam.currentAddr;
callStack->loopFlag = true;
callStack->loopCount = commandArg1;
trackParam.callStackDepth++;
}
break;
case MML_LOOP_END:
{
if (trackParam.callStackDepth <= 0)
{
NW4RWarningMessage_Line(713, "nw4r::snd::MmlParser: unmatched "
"sequence command \'loop_end\'");
break;
}
dBgmMmlCallStack *callStack =
&trackParam.callStack[trackParam.callStackDepth - 1];
if (!callStack->loopFlag)
{
NW4RWarningMessage_Line(719, "nw4r::snd::MmlParser: unmatched "
"sequence command \'loop_end\'");
break;
}
u8 loop_count = callStack->loopCount;
if (loop_count && --loop_count == 0)
{
trackParam.callStackDepth--;
}
else
{
callStack->loopCount = loop_count;
trackParam.currentAddr = callStack->address;
}
}
break;
}
CommandProc(track->mTrackNo, track->wait, command, commandArg1, commandArg2);
}
// copied from nw4r::snd start
u16 dSndBgmMmlParser_c::Read16(byte_t const **ptr) const
{
u16 ret = ReadByte(ptr);
ret <<= 8;
ret |= ReadByte(ptr);
return ret;
}
u32 dSndBgmMmlParser_c::Read24(byte_t const **ptr) const
{
u32 ret = ReadByte(ptr);
ret <<= 8;
ret |= ReadByte(ptr);
ret <<= 8;
ret |= ReadByte(ptr);
return ret;
}
s32 dSndBgmMmlParser_c::ReadVar(byte_t const **ptr) const
{
s32 ret = 0;
byte_t b;
for (int i = 0;; i++)
{
NW4RAssert_Line(940, i < 4);
b = ReadByte(ptr);
ret <<= 7;
ret |= b & 0x7f;
if (!(b & 0x80))
break;
}
return ret;
}
s32 dSndBgmMmlParser_c::ReadArg(byte_t const **ptr,
SeqArgType argType) const
{
s32 var;
switch (argType)
{
case SEQ_ARG_U8:
var = ReadByte(ptr);
break;
case SEQ_ARG_S16:
var = Read16(ptr);
break;
case SEQ_ARG_VMIDI:
var = ReadVar(ptr);
break;
case SEQ_ARG_VARIABLE:
{
var = ReadByte(ptr);
/*
u8 varNo = ReadByte(ptr);
s16 const volatile *varPtr = GetVariablePtr(player, track, varNo);
// ERRATUM: if varPtr is not valid then ReadArg returns garbage
if (varPtr)
var = *varPtr;
*/
}
break;
case SEQ_ARG_RANDOM:
{
s32 rand;
s16 min = Read16(ptr);
s16 max = Read16(ptr);
rand = nw4r::snd::detail::Util::CalcRandom();
rand *= max - min + 1;
rand >>= 16;
rand += min;
var = rand;
}
break;
}
return var;
}
// clang-format on
void dSndBgmMmlParser_c::CommandProc(u32 trackNo, int wait, u32 command, s32 commandArg1, s32 commandArg2) const {
// noop
}
void dSndBgmMmlParser_c::NoteOnCommandProc(u32 trackNo, int wait, int key, int velocity, s32 length) const {
// noop
}