// Find where the cruise master gate at 0xD000197A bit 0 is set
//@category Analysis

import java.util.ArrayList;
import java.util.List;
import ghidra.app.script.GhidraScript;
import ghidra.app.decompiler.DecompInterface;
import ghidra.app.decompiler.DecompileResults;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionManager;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.listing.InstructionIterator;
import ghidra.program.model.listing.Listing;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceIterator;
import ghidra.program.model.symbol.ReferenceManager;

public class FindMasterGate extends GhidraScript {

    private List<Reference> collect(ReferenceManager refMgr, Address a) {
        List<Reference> list = new ArrayList<>();
        ReferenceIterator it = refMgr.getReferencesTo(a);
        while (it.hasNext()) list.add(it.next());
        return list;
    }

    @Override
    public void run() throws Exception {
        AddressFactory af = currentProgram.getAddressFactory();
        FunctionManager fm = currentProgram.getFunctionManager();
        Listing listing = currentProgram.getListing();
        ReferenceManager refMgr = currentProgram.getReferenceManager();

        // Find all instructions that reference 0xD000197A (the master gate byte)
        long aswStart = 0x80040000L;
        long aswEnd   = 0x800FFEFFL;
        Address asw_a = af.getAddress(Long.toHexString(aswStart));
        Address asw_b = af.getAddress(Long.toHexString(aswEnd));
        AddressSet aswSet = new AddressSet(asw_a, asw_b);

        println("=== Instructions referencing 0xD000197A (cruise master gate) ===");
        InstructionIterator allIns = listing.getInstructions(aswSet, true);
        while (allIns.hasNext()) {
            Instruction ins = allIns.next();
            String s = ins.toString();
            if (s.contains("d000197a") || s.contains("D000197A")) {
                Function func = fm.getFunctionContaining(ins.getAddress());
                String fname = (func != null) ? func.getName() : "<no-func>";
                String fent = (func != null) ? func.getEntryPoint().toString() : "n/a";
                println(String.format("  0x%s [%s @ 0x%s]: %s", ins.getAddress(), fname, fent, s));
            }
        }

        // Also: find xrefs to 0xD000197A via Ghidra reference manager
        println("\n=== xrefs to 0xD000197A ===");
        Address gateAddr = af.getAddress("d000197a");
        List<Reference> refs = collect(refMgr, gateAddr);
        for (Reference r : refs) {
            Address from = r.getFromAddress();
            Function func = fm.getFunctionContaining(from);
            String fname = (func != null) ? func.getName() : "<no-func>";
            Instruction ins = listing.getInstructionAt(from);
            String insStr = (ins != null) ? ins.toString() : "<no-ins>";
            println(String.format("  from 0x%s in [%s] type=%s  insn=%s",
                    from, fname, r.getReferenceType().getName(), insStr));
        }

        println("\nDONE");
    }
}
