/*
 * DOSEMU debugger,  1995 Max Parke <mhp@light.lightlink.com>
 *
 * This is file mhpdbg.h
 *
 * changes:
 *
 *   16Sep95 Hans Lermen <lermen@elserv.ffm.fgan.de>
 */

#ifndef MHPDBG_H
#define MHPDBG_H

#include <stdarg.h>
#include <stdint.h>

#include "cpu.h"
#include "dosemu_debug.h"

// There is also an argument field shifted 8 bits left
enum dosdebug_event {
  DBG_INIT = 0,
  DBG_BOOT,
  DBG_INTx,
  DBG_TRAP,
  DBG_PRE_VM86,
  DBG_POLL,
  DBG_GPF,
  DBG_INTxDPMI,
};

#define DBGF_WAIT_ON_STARTUP            0x001
#define DBGF_INTERCEPT_LOG              0x002
#define DBGF_DISABLE_LOG_TO_FILE        0x004
#define DBGF_ALLOW_BREAKPOINT_OVERWRITE 0x008
/* removed DBGF_LOG_TO_DOSDEBUG         0x100 */
#define DBGF_LOG_TO_BREAK               0x200
#define DBGF_LOG_TEMPORARY              0x400
#define DBGF_IN_LEAVEDOS           0x40000000

int mhp_early_init(void);
void mhp_init(void);
unsigned int mhp_debug(unsigned, unsigned int, unsigned int);
void mhp_send(void);
void mhp_close(void);
void mhp_clear_all_bp(void);
void mhp_printf(const char *, ...) FORMAT(printf, 1, 2);
int mhp_getaxlist_value(int v, int mask);
int mhp_getcsip_value(void);
void mhp_modify_eip(int delta);
void mhp_intercept_log(const char *flags, int temporary);
void mhp_intercept(const char *msg, const char *logflags);
void mhp_int15_kbd_hook(Bit8u al);
void mhp_exit_intercept(int errcode);
int mhpdbg_is_stopped(void);
int mhp_usermap_move_block(uint16_t oldseg, uint16_t newseg,
                           uint16_t startoff, uint32_t blklen);
int mhp_usermap_load_gnuld(const char *fname, uint16_t origin);
void mhpdbgc_init(void);
void mhp_init_hma(void);
void mhp_reset_hma(void);
#ifdef USE_MHPDBG
int mhp_revectored(int inum);
void mhp_adjust_revectored(int inum);
#else
static inline int mhp_revectored(int inum)
{
  return 0;
}
static inline void mhp_adjust_revectored(int inum)
{
}
#endif

int vmhp_log_intercept(const char *fmt, va_list args);

#define MHP_BUFFERSIZE 8192
struct mhpdbg {
  int active;
  unsigned long flags;
  unsigned char intxxtab[32];
};

extern __TLS struct mhpdbg mhpdbg;

#ifdef MHP_PRIVATE

#define DBG_TYPE(val) ((val)&0xff)
#define DBG_ARG(val)  ((val) >> 8)
#define SRSIZE MHP_BUFFERSIZE
#define MYPORT 3456
#define IBUFS 0x100
#define MAXBP 64

void mhp_cmd(const char *);
void mhp_bpset(void);
void mhp_bpclr(void);
int mhp_bpchk(unsigned int);
int bpchk(unsigned int);
int mhp_setbp(unsigned int seekval);
int mhp_clearbp(unsigned int seekval);
void mhp_regex(const char *fmt, va_list args);

void mhpdbg_trace_init(void);

struct brkentry {
  unsigned int brkaddr;
  unsigned char opcode;
  char is_dpmi;
  char is_valid;
};

/* parameters for DOS 4Bh (EXEC) call */
struct mhpdbg_4bpar {
  unsigned short env;
  far_t commandline_ptr;
  far_t fcb1_ptr;
  far_t fcb2_ptr;
  far_t sssp;
  far_t csip;
};
static_assert(sizeof(struct mhpdbg_4bpar) == 22, "mhpdbg_4bpar size is incorrect");

#define PAR4b_addr(x) SEGOFF2LINEAR(mhpdbgc.bpload_par->x.segment, \
                                    mhpdbgc.bpload_par->x.offset)

struct mhpdbgc {
  int stopped;
  int want_to_stop;
  unsigned currcode;
  int trapcmd;
  int trapip; /* ip that we were on when we started the "tracei" command */
  int bpload;
  int bpload_bp;
  int int21_count;
  int int_handled;
  struct mhpdbg_4bpar *bpload_par;
  char bpload_cmd[128];
  char bpload_cmdline[132];
  unsigned char intxxalt[32];
  struct brkentry brktab[MAXBP];
  int bpcleared;
  int kbdbreak;
};

#if 0
extern int stop_cputime(int);
extern int restart_cputime(int);
#define MHP_STOP        {stop_cputime(0); mhpdbgc.stopped = 1;}
#define MHP_UNSTOP      {mhpdbgc.stopped = 0; restart_cputime(0);}
#else
#define MHP_STOP        mhpdbgc.stopped = 1
#define MHP_UNSTOP      mhpdbgc.stopped = 0
#endif

extern int traceloop;
extern char loopbuf[4];
extern struct mhpdbgc mhpdbgc;

#endif /* MHP_PRIVATE */

#endif /* MHPDBG_H */
