#include <EDK.h>
#include "General.h"
#include "CIECDisasm.h"

#define Class CIECDisasm
extern Class MSVC4Bug;


////////////////////////////////////////////////////////////////////////////////
// causes redraw when lines change

static void Invalidate() {

  CIECDisasm* p;
  __asm mov p,ThisReg;
  
  InvalidateRect(p->hwnd, NULL, FALSE);
}


proc(OnATNHigh)
  push ThisReg
  mov ThisReg,ECX
  call Invalidate
  pop ThisReg
  ret
endp


proc(OnATNLow)
  push ThisReg
  mov ThisReg,ECX
  call Invalidate
  pop ThisReg
  ret
endp


proc(OnClockHigh)
  push ThisReg
  mov ThisReg,ECX
  call Invalidate
  pop ThisReg
  ret
endp


proc(OnClockLow)
  push ThisReg
  mov ThisReg,ECX
  call Invalidate
  pop ThisReg
  ret
endp


proc(OnDataHigh)
  push ThisReg
  mov ThisReg,ECX
  call Invalidate
  pop ThisReg
  ret
endp


proc(OnDataLow)
  push ThisReg
  mov ThisReg,ECX
  call Invalidate
  pop ThisReg
  ret
endp


////////////////////////////////////////////////////////////////////////////////
// window procedure

LRESULT CALLBACK CIECDisasmWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

  CIECDisasm* p = (CIECDisasm*)GetWindowLong(hwnd, 0);

  switch (uMsg) {

  case WM_PAINT: 
    {
      PAINTSTRUCT ps;
      HDC hdc = BeginPaint(hwnd, &ps);

      SelectObject(hdc, GetStockObject(ANSI_FIXED_FONT));

      int iATN = 0;
      int iClock = 0;
      int iData = 0;
      __asm {
        push ThisReg
        mov ThisReg,p
        TestHigh(mvar(ATN))
        jne ATNLow
        mov iATN,1
      ATNLow:
        TestHigh(mvar(Clock))
        jne ClockLow
        mov iClock,1
      ClockLow:
        TestHigh(mvar(Data))
        jne DataLow
        mov iData,1
      DataLow:
        pop ThisReg
      }

      const char aacState[2][5] = {
        "Low ", "High"
      };
      char ac[20];
      int i;
      i = sprintf(ac, "ATN   : %s", aacState[iATN]);
      TextOut(hdc, 0, 0, ac, i);
      i = sprintf(ac, "Clock : %s", aacState[iClock]);
      TextOut(hdc, 0, 10, ac, i);
      i = sprintf(ac, "Data  : %s", aacState[iData]);
      TextOut(hdc, 0, 20, ac, i);

      EndPaint(hwnd, &ps);
      return 0;
    }

  case WM_CREATE:
    {
      p = (CIECDisasm*)((LPCREATESTRUCT)lParam)->lpCreateParams;
      SetWindowLong(hwnd, 0, (long)p);

      break;
    }
  
  }
  return DefWindowProc(hwnd, uMsg, wParam, lParam);
}


////////////////////////////////////////////////////////////////////////////////
// constructor

/*
  HWND hwnd;

  CLine ATN;
  CLine Clock;
  CLine Data;
*/


CIECDisasm::CIECDisasm(CIECMaster* pIECMaster) {

  static flag fClassRegistered = FALSE;
  if (!fClassRegistered) {
    WNDCLASS wc;
    wc.style = 0;
    wc.lpfnWndProc = CIECDisasmWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 4;
    wc.hInstance = ghinst;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "CIECDisasm";
    fClassRegistered = RegisterClass(&wc) != NULL;
  }

  ATN.Init("ATN", this);
  ATN.SetOnHigh(make_pfn(fn(OnATNHigh)));
  ATN.SetOnLow(make_pfn(fn(OnATNLow)));
  Clock.Init("Clock", this);
  Clock.SetOnHigh(make_pfn(fn(OnClockHigh)));
  Clock.SetOnHigh(make_pfn(fn(OnClockLow)));
  Data.Init("Data", this);
  Data.SetOnHigh(make_pfn(fn(OnDataHigh)));
  Data.SetOnLow(make_pfn(fn(OnDataLow)));

  Connect(ATN, pIECMaster->ATN);
  Connect(Clock, pIECMaster->Clock);
  Connect(Data, pIECMaster->Data);

  hwnd = CreateWindow("CIECDisasm", "IEC Bus", WS_POPUP	| WS_CAPTION, 640 - 16 * 8, 480 - 150 - 54, 16 * 8, 54, ghwnd, NULL, ghinst, this);
  ShowWindow(hwnd, SW_SHOWNORMAL);
  UpdateWindow(hwnd);
}
