#ifndef CVIC656x_h
#define CVIC656x_h

#include "CLine.h"
#include "CKeyboard.h"
#include "CDisplay.h"


// TODO: VIC656x must be derived from Chip
class CVIC656x : public Clock {
public:

  CDisplay* pDisplay;
  byte* pbBitmap;

  CLine BA;              // bus available, connected to CPU.RDY

  int iLine;             // current line 0-311
  byte* pbLine;          // pointer into pbBitmap to beginning of current line
  int iXScroll;          // pixels to scroll screen right 0-7
  byte* pbLineShift;     // pbLine + iXScroll
  int iRowCounter;       // offset within an 8 pixel block from 0-7

  byte* pbVideoRAM;      // pointer to start of VIC memory
  byte* pbCharROM;       // pointer to character ROM or NULL
  byte* pbGhostByte;     // points to pbVideoRAM[0x3FFF/0x39FF]
  byte* pbVideoBase;     // pointer to video data
  byte* pbColorBase;     // pointer to color RAM
  byte* pbCharBase;      // pointer to charset
  byte* pbGraphBase;     // pointer to graphics map
  byte* pbVideoCounter;  // pointer to start of DMA line
  byte* pbColorCounter;  // pointer to start of DMA line
  byte* pbGraphCounter;  // pointer to start of DMA line
  int iVideoLatch;       // index into DMA line (0-1023 step 40)
  byte abVideoPtr[40];   // 40 video data values from last DMA
  byte abColorPtr[40];   // 40 color values from last DMA
  int aiVideoCache[40];  // for speed, contents depend from iMode

  int i4Frame;           // 4 times frame color (0x00000000-0x0F0F0F0F)
  int i4Back;            // 4 times background color (0x00000000-0x0F0F0F0F)
  int iBack;             // current background color (0x00-0x0F)
  int iBack2and1;        // multicolor backgrounds (0x1000-0x1F0F)
  byte abBackECM[4];     // extended text backgrounds (0x00000000-0x0F0F0F0F)

  int iScreenOn;         // start of visible screen (51 or 55)
  int iScreenOff;        // start of bottom frame (251 or 247)

  #define fDMA      1    // bit 0 = DMA running
  #define fDISPLAY  2    // bit 1 = character display on
  #define fFRAME    4    // bit 2 = top/bottom frame
  int iMode;             // bit 3 = bitmap mode
                         // bit 4 = extended color mode
                         // bit 5 = multicolor mode

  byte bDisplay;         // display on in current frame

  byte bYScroll;         // pixels to scroll screen down 0-7
  byte bControl1;        // control register 1
  byte bControl2;        // control register 2
  byte bAddress;         // address register

  CLine Int;             // connected to CPU.IRQ
  int iIntLine;          // raster line for interrupt (0-511)
  byte bIRR;             // Interrupt Request Register $D019
  byte bIMR;             // Interrupt Mask Register $D01A
  byte abIntFill[2];

  int aiSpriteX[8];      // sprite X positions (0-511)
  byte abSpriteY[8];     // sprite Y positions (0-255)
  byte abSpriteColor[8]; // sprite colors (0-15)
  byte abSpriteCnt[8];   // 6 bit counters from 0-62, 63 means OFF
  int aiSpriteData[8];   // fetched data to be displayed at end of line
  int aiSpriteSave[8];   // saved data for clock, $xxxxxx3F means off
  byte abCollision[664]; // buffer for sprite-sprite collisions
  pfnv apfnSprite[8];    // functions to display a sprite line
  byte bSpriteX8;        // bits 8 of sprite X positions
  byte bSSCR;            // Sprite/Sprite Collision Register $D01E
  byte bSDCR;            // Sprite/Data Collision Register $D01F
  byte bNewSDCR;         // collects data collisions for all 8 sprites
  byte bSpriteExpandX;   // sprites with double width
  byte bSpriteExpandY;   // sprites with double height
  byte bSpriteSameRow;   // flags for double height and sprite stretching
  byte bSpriteEnable;    // Sprite Enable Register $D015
  byte bSpriteBack;      // sprites with background priority
  byte bSpriteMC;        // sprites in multicolor
  byte bSpriteMC1;       // sprite multicolor 1 (0-15)
  byte bSpriteMC2;       // sprite multicolor 2 (0-15)
  byte bSprites;         // flags for sprites on in next line
  byte abSpriteFill[3];

  CLine LP;             // light pen input
  byte bLPTriggered;    // trigger only once per frame
  byte bLPX;            // raster position when LP went low
  byte bLPY;
  byte abLPFill[1];

  CVIC656x();
  virtual ~CVIC656x();

protected:

  virtual void DoInit();

public:

  void Emulate();
};

extern "C" void __cdecl ExecEvent();

#endif
