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

#define Class CVIC656x
extern Class MSVC4Bug;


/*
  Member variables for VIC interrupt handling

  COutput IRQ;           // connected to CPU.IRQ
  byte bIRR;             // Interrupt Request Register $D019
  byte bIMR;             // Interrupt Mask Register $D01A
*/

/*
  VIC Interrupt Request Register IRR $D019

  -------1 = raster line in RR/CR1 reached
  ------1- = sprite/data collision occured
  -----1-- = sprite/sprite collision occured
  ----1--- = light pen triggered
  -111---- = N/U
  1------- = IRQ line active (low)

  The bits 0-3 are flip flops. To set them back, set the corresponding
  bit to 1 and write the value into IRR.

  The bits 1 and 2 are unchanged when SSCR or SDCR have reported a collision
  yet and a new sprite collides.
*/

proc(ReadIRR)
  push ESI
  mov ESI,ECX

  // get IRQ line
  } static CLine* p;
  __asm lea EAX,mvar(Int)
  __asm mov p,EAX
  static byte b = (byte)(p->IsOutputLow() << 7);
  __asm {
  mov AL,b
  // get IRR
  or AL,mvar(bIRR)
  or AL,01110000b

  pop ESI
  ret
endp

proc(WriteIRR)
  push ESI
  mov ESI,ECX
  mov EAX,[ESP+8]

  // clear corresponding IRR bits 0-3
  not AL
  and AL,00001111b
  and AL,mvar(bIRR)
  mov mvar(bIRR),AL
  // all interrupt conditions zero?
  test AL,mvar(bIMR)
  jne AnotherIRQ
  // clear IRQ
  SetHigh(mvar(Int), 1)
AnotherIRQ:

  pop ESI
  ret 4
endp

/*
  VIC Interrupt Mask Register IMR $D01A

  -------1 = IRQ on raster line
  ------1- = IRQ on collision sprite/char
  -----1-- = IRQ on collision sprite/sprite
  ----1--- = IRQ on light pen
  1111---- = N/U
*/

proc(ReadIMR)
  push ESI
  mov ESI,ECX

  mov AL,mvar(bIMR)
  or AL,11110000b

  pop ESI
  ret
endp

proc(WriteIMR)
  push ESI
  mov ESI,ECX
  mov EAX,[ESP+8]

  and AL,00001111b
  mov mvar(bIMR),AL
  // interrupt conditions?
  test AL,mvar(bIRR)
  jne SetInt
  // clear interrupt line
  SetHigh(mvar(Int), 1)

  pop ESI
  ret 4

SetInt:
  // set interrupt line
  SetLow(mvar(Int), 1)

  pop ESI
  ret 4
endp
