// retroDE_ps2 — DobieStation headless trace runner
//
// Minimal harness for the golden-reference harness. Loads a BIOS image,
// boots the EE in interpreter mode, runs a bounded number of frames, and
// exits. The EE instruction-fetch trace is emitted by the tap added in
// third_party/DobieStation/src/core/ee/emotion.cpp when the environment
// variable RETRODE_PS2_EE_TRACE is set to a file path.
//
// Intended for Wave 1 / Checkpoint 2 of the harness: NOP-sled BIOS,
// short run, compare first-N fetches against the RTL stub trace.
//
// Usage:
//   RETRODE_PS2_EE_TRACE=/path/to/dobie_ee.trace ./trace_runner <bios.bin> [frames]
//
// Notes:
//   - BIOS image must be exactly 4 MiB. Anything shorter is zero-padded;
//     anything longer is truncated.
//   - `frames` defaults to 1. One frame is ~4.9M EE cycles, which is far
//     more than Checkpoint 2 needs; keep it small.

#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <vector>

#include "emulator.hpp"

int main(int argc, char** argv)
{
    if (argc < 2)
    {
        std::fprintf(stderr,
                     "usage: %s <bios.bin> [frames]\n"
                     "env:   RETRODE_PS2_EE_TRACE=<path>  enable EE fetch trace\n",
                     argv[0]);
        return 2;
    }

    const char* bios_path = argv[1];
    int max_frames = (argc >= 3) ? std::atoi(argv[2]) : 1;
    if (max_frames <= 0) max_frames = 1;

    constexpr size_t BIOS_SIZE = 4 * 1024 * 1024;
    std::vector<uint8_t> bios(BIOS_SIZE, 0);

    std::ifstream f(bios_path, std::ios::binary);
    if (!f)
    {
        std::fprintf(stderr, "[trace_runner] cannot open %s\n", bios_path);
        return 2;
    }
    f.read(reinterpret_cast<char*>(bios.data()), BIOS_SIZE);
    std::fprintf(stderr, "[trace_runner] loaded %zd bytes from %s\n",
                 f.gcount(), bios_path);

    Emulator emu;
    emu.reset();
    emu.load_BIOS(bios.data());
    emu.set_ee_mode(CPU_MODE::INTERPRETER);
    emu.set_vu0_mode(CPU_MODE::INTERPRETER);
    emu.set_vu1_mode(CPU_MODE::INTERPRETER);

    for (int i = 0; i < max_frames; i++)
    {
        std::fprintf(stderr, "[trace_runner] running frame %d/%d\n",
                     i + 1, max_frames);
        emu.run();
    }

    std::fprintf(stderr, "[trace_runner] done\n");
    return 0;
}
