use crate::gml::Code;
use crate::gml::assembly::assemble_instructions;
use crate::gml::insert_instructions;
use crate::gml::instruction::InstanceType;
use crate::gml::instruction::Instruction;
use crate::gml::instruction::VariableType;
use crate::prelude::*;
use crate::wad::elem::variable::Variable;
pub fn toggle(data: &mut GMData, enable: bool) -> Result<()> {
log::debug!("Detected Deltarune Chapter 1/2/4");
let code_ref: GMRef<Code> = data
.codes
.ref_by_name("gml_Object_obj_initializer2_Create_0", &data.strings)?;
super::replace_debug(data, code_ref, enable, InstanceType::Global)?;
if !enable
|| data
.codes
.by_name("gml_Script_scr_flag_name_get", &data.strings)
.is_err()
{
return Ok(());
}
let code_ref = data
.codes
.ref_by_name("gml_GlobalScript_scr_flag_get", &data.strings)?;
let code = data.codes.by_ref(code_ref)?;
let index: u32 = find_insertion_point(data, code)?;
let assembly: &str = r#"
push.s "flagname"
conv.s.v
call variable_global_exists 1
conv.v.b
not.b
bf 5
push.s ""
conv.s.v
ret
"#;
let insertion: Vec<Instruction> = assemble_instructions(assembly, data)?;
let code = data.codes.by_ref_mut(code_ref)?;
insert_instructions(&mut code.instructions, index, &insertion)?;
bail!(
"TODO: debug activation for deltarune is currently broken (need to fix child gml_Script \
execution offsets)"
);
}
fn find_insertion_point(data: &GMData, code: &Code) -> Result<u32> {
for i in 0..code.instructions.len() {
let instr = &code.instructions[i];
let Some(code_variable) = instr.variable() else {
continue;
};
let variable: &Variable = data.variables.by_ref(code_variable.variable)?;
let var_name = data.strings.by_ref(variable.name)?;
if var_name != "flagname" {
continue;
}
let ref_type = code_variable.variable_type;
if ref_type != VariableType::Array {
bail!("Expected array access for global.flagname, got {ref_type:?}");
}
let pred = |i: &Instruction| matches!(i, Instruction::BranchUnless { .. });
let branch_index = code.instructions[..i].iter().rposition(pred);
let idx = branch_index.ok_or("No branch instruction before global.flagname push")?;
if i - idx > 8 {
bail!("Could not find a branch near (before) global.flagname push");
}
return Ok(idx as u32 + 1);
}
Err(err!("Could not find global.flagname push"))
}