// Find code that WRITES to RAM 0xD0000E49 — to identify what this byte represents
//@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;

public class FindWriterOfE49 extends GhidraScript {

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

        // Scan ASW region for instructions that store/load 0xD0000E49 (and adjacent bytes)
        Address asw_a = af.getAddress("80040000");
        Address asw_b = af.getAddress("800FFEFF");
        AddressSet aswSet = new AddressSet(asw_a, asw_b);

        // Also search 0xD0000E48..0xD0000E4F (the dword containing E49)
        String[] targets = {"0xd0000e49", "0xd0000e48", "0xd0000e4a", "0xd0000e4b",
                            "0xd0000e4c", "0xd0000e4d", "0xd0000e4e", "0xd0000e4f"};

        for (String tgt : targets) {
            println("\n=== Instructions referencing " + tgt + " ===");
            InstructionIterator it = listing.getInstructions(aswSet, true);
            int count = 0;
            while (it.hasNext()) {
                Instruction ins = it.next();
                String s = ins.toString();
                if (s.contains(tgt) || s.contains(tgt.toUpperCase())) {
                    Function func = fm.getFunctionContaining(ins.getAddress());
                    String fname = (func != null) ? func.getName() : "<no-func>";
                    String fent = (func != null) ? "0x"+func.getEntryPoint() : "n/a";
                    println(String.format("  0x%s [%s @ %s]: %s", ins.getAddress(), fname, fent, s));
                    count++;
                    if (count > 30) { println("  ...truncated"); break; }
                }
            }
        }

        // Now look for the function that WRITES (st.*) to 0xD0000E49 and decompile it
        println("\n=== Looking for WRITER of 0xD0000E49 ===");
        InstructionIterator it = listing.getInstructions(aswSet, true);
        Address writerSite = null;
        while (it.hasNext()) {
            Instruction ins = it.next();
            String s = ins.toString();
            if ((s.startsWith("st.")) && (s.contains("0xd0000e49") || s.contains("0xD0000E49"))) {
                println(String.format("  STORE @ 0x%s: %s", ins.getAddress(), s));
                if (writerSite == null) writerSite = ins.getAddress();
            }
        }

        if (writerSite != null) {
            Function func = fm.getFunctionContaining(writerSite);
            if (func != null) {
                println(String.format("\n=== DECOMPILE function containing first writer (%s @ 0x%s) ===",
                        func.getName(), func.getEntryPoint()));
                DecompInterface decomp = new DecompInterface();
                decomp.openProgram(currentProgram);
                DecompileResults res = decomp.decompileFunction(func, 60, monitor);
                if (res.decompileCompleted()) {
                    println(res.getDecompiledFunction().getC());
                }
                decomp.dispose();
            } else {
                // Show instructions around writer
                println("\n=== Code around writer site (no func) ===");
                long site = writerSite.getOffset();
                for (long off = site - 0x40; off < site + 0x10; off++) {
                    Address a = af.getAddress(Long.toHexString(off));
                    Instruction i = listing.getInstructionAt(a);
                    if (i != null) {
                        String mark = (off == site) ? "  <<<<< STORE" : "";
                        println(String.format("  0x%s: %s%s", a, i.toString(), mark));
                        off += i.getLength() - 1;
                    }
                }
            }
        }

        println("\nDONE");
    }
}
