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

#define Class CC64
extern Class MSVC4Bug;


////////////////////////////////////////
// IEC clock and data input

proc(OnClockHigh)
  push ThisReg
  mov ThisReg,ECX

  mov AL,mvar(bIECIn)
  or AL,01000000b
  mov mvar(bIECIn),AL
  SetPort(mvar(IECOut), 1)

  pop ThisReg
  ret
endp


proc(OnClockLow)
  push ThisReg
  mov ThisReg,ECX

  mov AL,mvar(bIECIn)
  and AL,10111111b
  mov mvar(bIECIn),AL
  SetPort(mvar(IECOut), 1)

  pop ThisReg
  ret
endp


proc(OnDataHigh)
  push ThisReg
  mov ThisReg,ECX

  mov AL,mvar(bIECIn)
  or AL,10000000b
  mov mvar(bIECIn),AL
  SetPort(mvar(IECOut), 1)

  pop ThisReg
  ret
endp


proc(OnDataLow)
  push ThisReg
  mov ThisReg,ECX

  mov AL,mvar(bIECIn)
  and AL,01111111b
  mov mvar(bIECIn),AL
  SetPort(mvar(IECOut), 1)

  pop ThisReg
  ret
endp


////////////////////////////////////////
// IEC output

void CC64::OnIECChange(byte bState, byte bChanges) {
  __asm {
  push EBX
  push ThisReg
  mov ThisReg,ECX
  mov AL,bState
  mov AH,bChanges

  // ATN (inverted)
  test AH,00001000b
  je NoATN
  push EAX
  test AL,00001000b
  jne ATNLow
  SetHigh(mvar(ATN), 1)
  jmp ATNCont
ATNLow:
  SetLow(mvar(ATN), 1)
ATNCont:
  pop EAX
NoATN:

  // Clock (inverted)
  test AH,00010000b
  je NoClock
  push EAX
  test AL,00010000b
  jne ClockLow
  SetHigh(mvar(Clock), 2)
  jmp ClockCont
ClockLow:
  SetLow(mvar(Clock), 2)
ClockCont:
  pop EAX
NoClock:

  // Data (inverted)
  test AH,00100000b
  je NoData
  push EAX
  test AL,00100000b
  jne DataLow
  SetHigh(mvar(Data), 3)
  jmp DataCont
DataLow:
  SetLow(mvar(Data), 3)
DataCont:
  pop EAX
NoData:

  pop ThisReg
  pop EBX
  }
}


////////////////////////////////////////
// initialisation

/*
  CIECMaster IECMaster; // target for Connect()
  CLine ATN;
  CLine Clock;
  CLine Data;
  CPort IECOut;         // ATN bit 3, Clock bit 4, Data bit 5
  byte bIECIn;          // Clock bit 6, Data bit 7
  byte abIECFill[3];
*/

void CC64::InitIEC() {
  Connect(Reset, IECMaster.Reset);
  ATN.Init("ATN", this);
  Connect(ATN, IECMaster.ATN);
  Clock.Init("Clock", this);
  Clock.SetOnHigh(make_pfn(fn(OnClockHigh)));
  Clock.SetOnLow(make_pfn(fn(OnClockLow)));
  Connect(Clock, IECMaster.Clock);
  Data.Init("Data", this);
  Data.SetOnHigh(make_pfn(fn(OnDataHigh)));
  Data.SetOnLow(make_pfn(fn(OnDataLow)));
  Connect(Data, IECMaster.Data);
  IECOut.Init("IECOut", this);
  IECOut.SetOnChange((pfnbb)OnIECChange);
  IECOut.ConnectTo(pCIA2->PA);
  bIECIn = 0xFF;
}
