Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/wiki/What-is-LittlePiggyTracker.md
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ ARPG 4050: loops between original pitch, +4 semitones, +0 semitones, + 5 semiton

## HOP aabb

**play position will jump to the next phrase in a chain, jumping directly at position bb in the phrase.**
**play position will jump to the next phrase in a chain, jumping directly at position bb in the phrase, unless bb = FF, in which case the channel will be stopped**

- hop is instant: instrument triggers and commands on the same row will be run.
- no effect on instruments
Expand Down
46 changes: 38 additions & 8 deletions sources/Application/Player/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,26 @@ bool Player::ProcessChannelCommand(int channel, FourCC cmd, ushort param) {
} else {
gr->SetGroove(channel, param);
}
} break;
case I_CMD_HOP: {
bool channel_stop = (param & 0xFF) == 0xFF;
if (channel_stop) {
// Stop current channel
mixer_->StopChannel(channel);

// If all channels are stopped, stop the song if in song mode.
if (GetSequencerMode() == SM_SONG) {
bool all_channels_stopped = true;
for (int c = 0; c < SONG_CHANNEL_COUNT; c++) {
all_channels_stopped &= !mixer_->IsChannelPlaying(c);
}
if (all_channels_stopped) {
Stop();
}
} else {
liveQueueingMode_[channel] = QM_NONE;
}
}
} break;
case I_CMD_STOP: {
switch (GetSequencerMode()) {
Expand Down Expand Up @@ -882,14 +902,24 @@ void Player::playCursorPosition(int channel) {
int Player::getChannelHop(int channel, int pos) {

int phrase = viewData_->currentPlayPhrase_[channel];
FourCC cc = viewData_->song_->phrase_->cmd1_[phrase * 16 + pos];
if (cc == I_CMD_HOP) {
return (viewData_->song_->phrase_->param1_[phrase * 16 + pos]) & 0xF;
}
cc = viewData_->song_->phrase_->cmd2_[phrase * 16 + pos];
if (cc == I_CMD_HOP) {
return (viewData_->song_->phrase_->param2_[phrase * 16 + pos]) & 0xF;
}

Phrase *song_phrase = viewData_->song_->phrase_;
FourCC cc[] = {song_phrase->cmd1_[phrase * 16 + pos],
song_phrase->cmd2_[phrase * 16 + pos]};
int param[] = {song_phrase->param1_[phrase * 16 + pos],
song_phrase->param2_[phrase * 16 + pos]};

// First hop takes precedence.
for(int i = 0; i < 2; i++)
if (cc[i] == I_CMD_HOP) {
int arg = param[i] & 0xFF;
if (arg != 0xFF)
return arg & 0xF;
else
// 'Hop stop' deferred to command processing stage.
return -1;
}

return -1;
}

Expand Down
Loading