summaryrefslogtreecommitdiffstats
path: root/lib/rbcodec/codecs/cRSID/C64/VIC.c
blob: 1f9f736bbef9d8c96fc1720458822f8d2daf615d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

//VIC-II emulation


void cRSID_createVICchip (cRSID_C64instance* C64, cRSID_VICinstance* VIC, unsigned short baseaddress) {
 VIC->C64 = C64;
 VIC->ChipModel = 0;
 VIC->BaseAddress = baseaddress;
 VIC->BasePtrWR = &C64->IObankWR[baseaddress]; VIC->BasePtrRD = &C64->IObankRD[baseaddress];
 cRSID_initVICchip (VIC);
}


void cRSID_initVICchip (cRSID_VICinstance* VIC) {
 unsigned char i;
 for (i=0; i<0x3F; ++i) VIC->BasePtrWR[i] = VIC->BasePtrRD[i] = 0x00;
 VIC->RowCycleCnt=0;
}


static inline char cRSID_emulateVIC (cRSID_VICinstance* VIC, char cycles) {

 unsigned short RasterRow;

 enum VICregisters { CONTROL = 0x11, RASTERROWL = 0x12, INTERRUPT = 0x19, INTERRUPT_ENABLE = 0x1A };

 enum ControlBitVal { RASTERROWMSB = 0x80, DISPLAY_ENABLE = 0x10, ROWS = 0x08, YSCROLL_MASK = 0x07 };

 enum InterruptBitVal { VIC_IRQ = 0x80, RASTERROW_MATCH_IRQ = 0x01 };


 VIC->RowCycleCnt += cycles;
 if (VIC->RowCycleCnt >= VIC->RasterRowCycles) {
  VIC->RowCycleCnt -= VIC->RasterRowCycles;

  RasterRow = ( (VIC->BasePtrRD[CONTROL]&RASTERROWMSB) << 1 ) + VIC->BasePtrRD[RASTERROWL];
  ++RasterRow; if (RasterRow >= VIC->RasterLines) RasterRow = 0;
  VIC->BasePtrRD[CONTROL] = ( VIC->BasePtrRD[CONTROL] & ~RASTERROWMSB ) | ((RasterRow&0x100)>>1);
  VIC->BasePtrRD[RASTERROWL] = RasterRow & 0xFF;

  if (VIC->BasePtrWR[INTERRUPT_ENABLE] & RASTERROW_MATCH_IRQ) {
   if ( RasterRow == ( (VIC->BasePtrWR[CONTROL]&RASTERROWMSB) << 1 ) + VIC->BasePtrWR[RASTERROWL] ) {
    VIC->BasePtrRD[INTERRUPT] |= VIC_IRQ | RASTERROW_MATCH_IRQ;
   }
  }

 }

 return VIC->BasePtrRD[INTERRUPT] & VIC_IRQ;
}


static inline void cRSID_acknowledgeVICrasterIRQ (cRSID_VICinstance* VIC) {
 enum VICregisters { INTERRUPT = 0x19 };
 enum InterruptBitVal { VIC_IRQ = 0x80, RASTERROW_MATCH_IRQ = 0x01 };
 //An 1 is to be written into the IRQ-flag (bit0) of $d019 to clear it and deassert IRQ signal
 //if (VIC->BasePtrWR[INTERRUPT] & RASTERROW_MATCH_IRQ) { //acknowledge raster-interrupt by writing to $d019 bit0?
 //But oftentimes INC/LSR/etc. RMW commands are used to acknowledge VIC IRQ, they work on real
 //CPU because it writes the unmodified original value itself to memory before writing the modified there
  VIC->BasePtrWR[INTERRUPT] &= ~RASTERROW_MATCH_IRQ; //prepare for next acknowledge-detection
  VIC->BasePtrRD[INTERRUPT] &= ~(VIC_IRQ | RASTERROW_MATCH_IRQ); //remove IRQ flag and state
 //}
}