Skip to content

Commit

Permalink
Merge pull request #3319 from EasyRPG-NewFeatures/CallCommand-Updates
Browse files Browse the repository at this point in the history
Maniac Patch - CallCommand Update
  • Loading branch information
Ghabry authored Jan 16, 2025
2 parents 6acddd9 + 6fee86c commit a557aa6
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 8 deletions.
68 changes: 60 additions & 8 deletions src/game_interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5242,23 +5242,75 @@ bool Game_Interpreter::CommandManiacCallCommand(lcf::rpg::EventCommand const& co
return true;
}

enum class ProcessingMode {
Constant = 0, // 0 and 1: Parameters read from variables
Variable = 1,
//VariableIndirect = 2, // Somehow not implemented by ManiacPatch
Inline = 3, // Parameters are directly provided by the command
Expression = 4 // Like 3, but the parameters are calculated from expressions
};

std::vector<int32_t> values;

// Create command with basic parameters
lcf::rpg::EventCommand cmd;
cmd.code = ValueOrVariableBitfield(com.parameters[0], 0, com.parameters[1]);

cmd.string = lcf::DBString(CommandStringOrVariableBitfield(com, 0, 3, 4));

int arr_begin = ValueOrVariableBitfield(com.parameters[0], 1, com.parameters[2]);
int arr_length = ValueOrVariableBitfield(com.parameters[0], 2, com.parameters[3]);
// Determine processing mode
auto processing_mode = static_cast<ProcessingMode>((com.parameters[0] >> 4) & 0b1111);

std::vector<int32_t> output_args;
if (arr_length > 0) {
output_args.reserve(arr_length);
for (int i = 0; i < arr_length; ++i) {
output_args.push_back(Main_Data::game_variables->Get(arr_begin + i));
switch (processing_mode) {
case ProcessingMode::Constant:
case ProcessingMode::Variable: {
int start_index = ValueOrVariable(static_cast<int>(processing_mode), com.parameters[2]);
int length = ValueOrVariableBitfield(com.parameters[0], 2, com.parameters[3]);

for (int i = 0; i < length; ++i) {
values.push_back(Main_Data::game_variables->Get(start_index + i));
}
break;
}
case ProcessingMode::Inline: {
int value_index = 5; // Start of the values
int mode_index = com.parameters[2]; // Mode of the values
int length = com.parameters[3];

for (int i = 0; i < length; ++i) {
// The mode is the typical 4 bit packing
// Always 4 modes (16 bit) are packing into one parameter
// Then the mode_index increments
if (i != 0 && i % 4 == 0) {
++mode_index;
}

cmd.parameters = lcf::DBArray<int32_t>(output_args.begin(), output_args.end());
values.push_back(ValueOrVariableBitfield(com, mode_index, i % 4, value_index + i));
}
break;
}
case ProcessingMode::Expression: {
values = ManiacPatch::ParseExpressions(MakeSpan(com.parameters).subspan(5), *this);
break;
}
default:
Output::Warning("Call Command: Unsupported Processing Mode: {}", static_cast<int>(processing_mode));
return true;
}

// Finalize command parameters
cmd.parameters = lcf::DBArray<int32_t>(values.begin(), values.end());

// Debug output
/*Output::Warning("Processing mode: {}", static_cast<int>(processing_mode));
Output::Warning("Command code: {}", cmd.code);
Output::Warning("Command string: {}", cmd.string);
std::string params_str;
for (const auto& param : values) {
params_str += " " + std::to_string(param);
}
Output::Warning("Command parameters:{}", params_str);
Output::Info("--------------------\n");*/

// Our implementation pushes a new frame containing the command instead of invoking it directly.
// This is incompatible to Maniacs but has a better compatibility with our code.
Expand Down
30 changes: 30 additions & 0 deletions src/maniac_patch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ int Process(std::vector<int32_t>::iterator& it, std::vector<int32_t>::iterator e
Output::Warning("Maniac: Expression actor args {} != 2", imm2);
return 0;
}
imm3 = Process(it, end, ip);
return ControlVariables::Actor(Process(it, end, ip), imm3);
case Fn::Party:
if (imm2 != 2) {
Expand Down Expand Up @@ -570,6 +571,35 @@ int32_t ManiacPatch::ParseExpression(Span<const int32_t> op_codes, const Game_Ba
return Process(beg, ops.end(), interpreter);
}

std::vector<int32_t> ManiacPatch::ParseExpressions(Span<const int32_t> op_codes, const Game_BaseInterpreterContext& interpreter) {
std::vector<int32_t> ops;
for (auto& o : op_codes) {
auto uo = static_cast<uint32_t>(o);
ops.push_back(static_cast<int32_t>(uo & 0x000000FF));
ops.push_back(static_cast<int32_t>((uo & 0x0000FF00) >> 8));
ops.push_back(static_cast<int32_t>((uo & 0x00FF0000) >> 16));
ops.push_back(static_cast<int32_t>((uo & 0xFF000000) >> 24));
}

if (ops.empty()) {
return {};
}

auto it = ops.begin();

std::vector<int32_t> results;

while (true) {
results.push_back(Process(it, ops.end(), interpreter));

if (it == ops.end() || static_cast<Op>(*it) == Op::Null) {
break;
}
}

return results;
}

std::array<bool, 50> ManiacPatch::GetKeyRange() {
std::array<Input::Keys::InputKey, 50> keys = {
Input::Keys::A,
Expand Down
3 changes: 3 additions & 0 deletions src/maniac_patch.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <array>
#include <cstdint>
#include <vector>
#include "span.h"

#include "game_strings.h"
Expand All @@ -29,6 +30,8 @@ class Game_BaseInterpreterContext;

namespace ManiacPatch {
int32_t ParseExpression(Span<const int32_t> op_codes, const Game_BaseInterpreterContext& interpreter);
std::vector<int32_t> ParseExpressions(Span<const int32_t> op_codes, const Game_BaseInterpreterContext& interpreter);


std::array<bool, 50> GetKeyRange();

Expand Down

0 comments on commit a557aa6

Please sign in to comment.