
//
//A simple test program for dislib to make sure they work in the C++ world
//
//    /zi is debugging info in the .obj files
//    Remember to use the same model in both the .asm files and .cc files!!!
//    tasm /dmdl=small /dClib /mx/zi dislib.asm
//    tasm /dmdl=small /dClib /mx/zi __dislib.asm
//    bcc -P -4 -Z -02 -ms -v distest.cc dislib.obj __dislib.obj
//    distest>te
//    edit te
//
//    windows 95 version (bcc32 v5.0)
//    tasm /dClib /mx/t/zi dislib32.asm
//    tasm /dClib /mx/t/zi __disl32.asm
//    bcc32 -tW -lV4.0 -P -5 -Z -O2 -v distest.cc dislib32.obj __disl32.obj
//

#ifdef __WIN32__
  #include <windows.h>
  #define near
  #define far
#else
  #include <iostream.h>
  #include <dos.h>
#endif
#include <string.h>

#include "dislib.h"

#ifdef UNICODE
  #NoUnicodePlease
#endif

#ifdef __WIN32__
static unsigned int len;
#else
static unsigned int seg,len;
#endif

//This procedure will be called each time __dis () wants a byte
//__dis_input is the input you used when you called __dis ()
static int __cdecl getbyte (__dis_input_t &__dis_input) {
    if (len--) {
  #ifdef __WIN32__
        int b = *(unsigned char *)__dis_input.eip;
  #else
        int b = *(unsigned char far *)MK_FP (seg,__dis_input.eip);
  #endif
        ++__dis_input.eip;
        return (b);
      }
    else return (0x0100);
  };

//checkoperand () should check an operand and decide if it will add a debugging
//name to the string instead of just printing offsets/numbers. It's called for
//all operands (including registers). dis_input is the same dis_input you
//used when you called dis (), dis_operand is one of the operands in
//dis_input (dis_input.__dis_input.opcode.op[0-2]), string is start of the
//string where we should print a name. string is the same string you used
//as input to dis (but it may not have the same offset, since dis ()
//might've printed something in it, like the opcode name)
static int __cdecl checkoperand (dis_input_t &,dis_operand_t &dis_operand,char *&string) {
    if (dis_operand.ismem ()) {
        strcpy (string,"memory");   //assume all offsets are called memory
        string += strlen (string);  //We MUST do this
        return (1); //did something
      }
    else return (0);//didn't do a thing
  };

static void near startmain (void) {
  };

static void near endmain (void);

static dis_input_t dis_input (&checkoperand);

#ifdef __WIN32__
LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM);
int __stdcall WinMain (HINSTANCE hInstance,HINSTANCE,PSTR,int iCmdShow) {
#else
int __cdecl main (int,char **,char **) {
#endif
    dis_input.flags = df_usebasechar|df_nozerodispl;
    dis_input.__dis_input._getbyte[0]=&getbyte;
    dis_input.__dis_input.eip = unsigned (&startmain);
    dis_input.__dis_input.codesize =
  #ifdef __WIN32__
    0x20;
  #else
    0x10;
  #endif
    dis_input.__dis_input.flags = 0x00000000;
    dis_input.__dis_input.cputype = __discpu_intel;
#ifdef __WIN32__
    WNDCLASSEX wndclass;
    wndclass.cbSize           = sizeof (WNDCLASSEX);
    wndclass.style            = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc      = WndProc;
    wndclass.cbClsExtra       =
    wndclass.cbWndExtra       = 0;
    wndclass.hInstance        = hInstance;
    wndclass.hIcon            = NULL;
    wndclass.hCursor          = NULL;
    wndclass.hbrBackground    = (HBRUSH) GetStockObject (WHITE_BRUSH);
    wndclass.lpszMenuName     = NULL;
    static const char szClassName [] = "TestClass";
    wndclass.lpszClassName    = szClassName;
    wndclass.hIconSm          = NULL;

    RegisterClassEx (&wndclass);
    HWND hWnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW,
                                szClassName,"Example of dislib",
                                WS_OVERLAPPEDWINDOW,
                                CW_USEDEFAULT,CW_USEDEFAULT,
                                CW_USEDEFAULT,CW_USEDEFAULT,
                                NULL,NULL,hInstance,NULL);
    ShowWindow (hWnd,iCmdShow);

    MSG msg;
    while (GetMessage (&msg,NULL,0,0)) {
        DispatchMessage (&msg);
      };
    return msg.wParam;
#else
    seg = FP_SEG (&startmain);
    len = FP_OFF (&endmain) - FP_OFF (&startmain);
    if (!__dis (dis_input.__dis_input))  //just decode an instruction
      return (0);
    char string [0x0200];
    dis_printinstruction (dis_input,string);  //print a decoded instruction
    cout << "        " << string << endl;
    while (dis (dis_input,string))      //decode and print an instruction
      cout << "        " << string << endl;
    return (0);
#endif
  };

static void near endmain (void) {
  };

#ifdef __WIN32__
LRESULT CALLBACK WndProc (HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) {
    static cyChar,nRows;

    const FONT = ANSI_FIXED_FONT;

    switch (uMsg) {
      case WM_PAINT: {
          PAINTSTRUCT ps;
          HDC hdc = BeginPaint (hWnd,&ps);
          SelectObject (hdc,GetStockObject (FONT));
          dis_input.__dis_input.eip = unsigned (startmain);
          len = unsigned (&endmain) - unsigned (&startmain);
          char szString [0x0200];
          szString [0] = szString [1] = szString [2] = szString [3] =
          szString [4] = szString [5] = szString [6] = szString [7] = ' ';
          for (int i = 0; i < nRows; i++) {
              if (dis (dis_input,szString+8))
                TextOut (hdc,0,i*cyChar,szString,strlen (szString));
            };
          EndPaint (hWnd,&ps);
          return (0);
        };

      case WM_CREATE: {
          TEXTMETRIC tm;
          HDC hdc = GetDC (hWnd);
          SelectObject (hdc,GetStockObject (FONT));
          GetTextMetrics (hdc,&tm);
          ReleaseDC (hWnd,hdc);
          cyChar = tm.tmHeight + tm.tmExternalLeading;
          return (0);
        };

      case WM_SIZE:
        nRows = (HIWORD(lParam)+cyChar-1)/cyChar;
        return (0);

      case WM_DESTROY:
        PostQuitMessage (0);
        return (0);

      default:
        return (DefWindowProc (hWnd,uMsg,wParam,lParam));
      };
  };
#endif
