//include file for dislib.asm and maybe for your module
//(c) 1998 Henrik Nebrin
//You may change the strucs to class objects if you like too.
//Remember not to change the order of the data and not
//use virutal functions in these structs/soon-to-be-classes
//You may use virtual functions in any relatives, though
#ifndef dislib_h
#define dislib_h

#include "__dislib.h"

//for dis_input_t.flags
const dword df_uppercasemnemonic=0x00001L; //MOV eax,ecx XCHG ecx,eax ETC es,ax
const dword df_uppercasereg = 0x00000002L; //EAX,ECX,EDX,EBX,ESP,EBP,ES,CS,SS,ETC
const dword df_uppercaseptr = 0x00000004L; //mov BYTE PTR [0000],00
const dword df_msd0         = 0x00000008L; //if msd is char, use a 0 (F1=0F1)
const dword df_msd0always   = 0x00000010L; //always put a 0 as msd (21h=021h)
const dword df_usebasechar  = 0x00000020L; //FF=FFh,123=123d
const dword df_uppercasebasechar=0x00040L; //if df_usebasechar: FFh=FFH
const dword df_lowercasedigitchar=0x0080L; //FF=ff
const dword df_seginsidebrack=0x00000100L; //mov al,[es:0000]
const dword df_ptrinsidebrack=0x00000200L; //mov [byte ptr 1234],00
const dword df_showsizemem   =0x00000400L; //mov al,byte ptr [esp+ebp*8+DEADBEEF]
const dword df_nobracketsdispl=0x0000800L; //mov al,[0000] -> mov al,0000
const dword df_nozerodispl  = 0x00001000L; //mov al,[bp+00] -> mov al,[bp]
const dword df_dsdispl      = 0x00002000L; //mov al,[1234] -> mov al,ds:[1234]
const dword df_memsegoverride=0x00004000L; //mov al,[bp] -> mov al,ss:[bp]
const dword df_commaspace   = 0x00008000L; //mov al,FF -> mov al, FF
const dword df_nearptr      = 0x00010000L; //jmp/call X -> jmp/call near ptr X
const dword df_farptr       = 0x00020000L; //jmp/call X:Y -> jmp call far ptr X:Y
const dword df_noshort      = 0x00040000L; //jmp short X -> jmp X
const dword df_noptr        = 0x00080000L; //word ptr [0] -> word [0] also jmp/call
const dword df_nomemsize    = 0x00100000L; //word ptr [0] -> [0]
const dword df_usescale1    = 0x00200000L; //[ecx] -> [ecx*1] ([ecx]=index,not base)
const dword df_nobracketsmem= 0x00400000L; //[bp+si] -> bp+si (not if only displ!)
const dword df_tabafterrep  = 0x00800000L; //rep movsd -> rep    movsd
const dword df_showsegmemsize=0x01000000L; //mov es,[0] -> mov es,word ptr [0]
const dword df_basecharifneeded=0x2000000L;//1D -> 1Dh 09 -> 09 0A -> 0Ah
const dword df_fewdigits    = 0x04000000L; //0013 -> 13
const dword df_attsyntax    = 0x08000000L; //mov al,ah -> movb %ah,%al
const dword df_Cnumbers     = 0x10000000L; //1234h -> 0x1234
const dword df_noopnamesizeatt=0x20000000L;//movb %al,%cl -> mov %al,%cl (only
                                           // if one of the operands is a reg!)
struct dis_input_t;
typedef __cdecl int (*checkoperand_t)(dis_input_t &,dis_operand_t &,char *&string);

struct dis_input_t {
    __dis_input_t __dis_input;          //will be changed in dis:procptr
    dword flags;
#if sizeof (int) == 4
  #if sizeof (void (*)(void)) == 6
    //
    //   check one operand in an instruction before we print it in a string
    //
    //   returns !0=you printed something in the string and advanced it
    //   past the last character
    //   returns 0=you didn't do a thing
    //
    checkoperand_t _checkoperand [1];
    byte __res[2];
  #elseif sizeof (void (*)(void)) == 4
    checkoperand_t _checkoperand [2];
  #elseif sizeof (void (*)(void)) == 8
    checkoperand_t _checkoperand [1];
  #else
    checkoperand_t _checkoperand [2]; //BC++ FUCK
//    #err
  #endif
#else
  #if sizeof (void (*)(void)) == 4
    //
    //   check one operand in an instruction before we print it in a string
    //
    //   returns !0=you printed something in the string and advanced it
    //   past the last character
    //   returns 0=you didn't do a thing
    //
    checkoperand_t _checkoperand [1];
  #else
    checkoperand_t _checkoperand [2];
  #endif
#endif
    byte octalbasechar;
    byte tabsize;
    byte numberbase;                    //dis_changenumberbase must change it!
    byte maxdigitsbyte;                 //max # of digits in a byte,
    byte maxdigitsword;                 // word or dword for this numberbase.
    byte maxdigitsdword;                // CHANGED BY dis_changenumberbase only
    byte res[2];
    inline dis_input_t (checkoperand_t chkop,dword Flags=0,byte obase='o',byte tsize=8,byte nbase=0x10);
    __cdecl int checkoperand (dis_input_t &di,dis_operand_t &_do,char *&string) {return (_checkoperand[0](di,_do,string));}
  };

#if sizeof (dis_input_t) & 3
  #err
#endif

//disassemble one instruction and print it in a string
//returns 0=not ok,!0=ok
extern "C" __cdecl unsigned int dis (dis_input_t &,char *string);
//print one instruction (but __dis () has already been called)
//returns !0
extern "C" __cdecl unsigned int dis_printinstruction (dis_input_t &,char *string);
//change the number base and update maxdigitsbyte/word/dword
extern "C" __cdecl void dis_changenumberbase (dis_input_t &,byte);

inline dis_input_t::dis_input_t (checkoperand_t chkop,dword Flags,byte obase,byte tsize,byte nbase)
    : flags (Flags), octalbasechar (obase), tabsize (tsize) {
    _checkoperand[0] = chkop;
    dis_changenumberbase (*this,nbase);
  };

#endif
