#ifndef PSX_RUNTIME_INTERNAL_H
#define PSX_RUNTIME_INTERNAL_H

#include "psx_runtime.h"

#if defined(_WIN32) && defined(OPENPETE_RECOMP_MODULE_BUILD)
#  define OPENPETE_ABI_DATA __declspec(dllimport)
#else
#  define OPENPETE_ABI_DATA
#endif

#ifdef __cplusplus
extern "C" {
#endif

void psx_runtime_init(CPUState* cpu);

void psx_runtime_load(uint32_t addr, const uint8_t* data, uint32_t size);

void psx_mmio_trace_enable(int enable);

void psx_install_crash_handler(void);

void call_by_address(CPUState* cpu, uint32_t addr);

int psx_override_dispatch(CPUState* cpu, uint32_t addr);

void psx_syscall(CPUState* cpu, uint32_t code);

void gte_execute(CPUState* cpu, uint32_t cmd);

OPENPETE_ABI_DATA extern uint32_t openpete_gte_caller_pc;

uint32_t gte_read_data(CPUState* cpu, uint8_t reg);
uint32_t gte_read_ctrl(CPUState* cpu, uint8_t reg);
void     gte_write_data(CPUState* cpu, uint8_t reg, uint32_t val);
void     gte_write_ctrl(CPUState* cpu, uint8_t reg, uint32_t val);

uint8_t* psx_get_ram(void);

uint8_t* psx_get_scratch(void);

void diag_track_gp1(uint32_t cmd);

OPENPETE_ABI_DATA extern uint32_t psx_runtime_g_sony_image_base;

extern int openpete_no_lod;

extern uint8_t psx_runtime_native_cone_pass;

extern uint8_t psx_runtime_native_dist_pass;

void psx_runtime_dist_gate_lower(int32_t v);

void psx_runtime_dist_gate_upper(int32_t v);

int32_t psx_runtime_cone_widen_permoby(int32_t mac1_abs, int32_t a2,
                                       int32_t mac3, int32_t a3);

int32_t psx_runtime_cone_widen_shaded(int32_t mac1_abs, int32_t mac3);

uint32_t psx_runtime_vstream_moby(uint32_t rt);
uint32_t psx_runtime_vstream_halved(uint32_t rt);

void psx_runtime_mwasdrawn_clear_store(CPUState* cpu, uint32_t addr, uint32_t val);
void psx_runtime_mwasdrawn_store(CPUState* cpu, uint32_t addr, uint32_t val);
void psx_runtime_part_drawn_store(CPUState* cpu, uint32_t addr, uint32_t val);

int32_t psx_runtime_part_cull_sx1(int32_t a, int32_t b);
int32_t psx_runtime_part_cull_sx2(int32_t a, int32_t b);
int32_t psx_runtime_part_cull_4vert(int32_t v);
int32_t psx_runtime_sparkle_canon_sx(void);

extern uint8_t psx_runtime_native_part_pass;

extern int64_t openpete_canonical_sx0_q16;
extern int64_t openpete_canonical_sx1_q16;
extern int64_t openpete_canonical_sx2_q16;

void openpete_diag_cone_dump(void* cpu,
                             int32_t mac1_abs,
                             int32_t mac3,
                             uint8_t native_pass);

void openpete_envvert_probe(void* cpu, uint32_t w0, uint32_t w1,
                            uint32_t s1, uint32_t s7, uint32_t t8,
                            uint32_t t9);

int      psx_runtime_register_region(uint32_t psx_base,
                                     uint32_t size,
                                     void*    host_buffer);

void     psx_runtime_unregister_region(uint32_t psx_base);

int      psx_runtime_resolve_region(uint32_t psx_addr,
                                    void**   out_host,
                                    uint32_t* out_remaining);

int      psx_runtime_region_host_to_vaddr(const void* host,
                                          uint32_t* out_vaddr);

uint32_t psx_runtime_canonicalize(uint32_t addr);

uint32_t psx_runtime_region_count(void);

#ifdef __cplusplus
}
#endif

#endif
