aboutsummaryrefslogtreecommitdiff
path: root/source/cpuexec.h
blob: 82de07fa8812b81cea6ce58d3b3548e139af21f3 (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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "../copyright"

#ifndef _CPUEXEC_H_
#define _CPUEXEC_H_

typedef struct
{
#ifdef __WIN32__
   void (__cdecl* S9xOpcode)(void);
#else
   void (*S9xOpcode)(void);
#endif
} SOpcodes;

#include "ppu.h"
#include "memmap.h"
#include "65c816.h"

#define DO_HBLANK_CHECK_SFX() \
    if (CPU.Cycles >= CPU.NextEvent) \
   S9xDoHBlankProcessing_SFX ();

#define DO_HBLANK_CHECK_NoSFX() \
    if (CPU.Cycles >= CPU.NextEvent) \
   S9xDoHBlankProcessing_NoSFX ();


typedef struct
{
   uint8_t*  Speed;
   SOpcodes* S9xOpcodes;
   SRegisters Registers;
   uint8_t  _Carry;
   uint8_t  _Zero;
   uint8_t  _Negative;
   uint8_t  _Overflow;
   bool  CPUExecuting;
   uint32_t ShiftedPB;
   uint32_t ShiftedDB;
   uint32_t Frame;
   uint32_t Scanline;
   uint32_t FrameAdvanceCount;
} SICPU;

void S9xMainLoop(void);
void S9xReset(void);
void S9xSoftReset(void);
void S9xDoHBlankProcessing_SFX();
void S9xDoHBlankProcessing_NoSFX();
void S9xClearIRQ(uint32_t);
void S9xSetIRQ(uint32_t);

extern SOpcodes S9xOpcodesE1 [256];
extern SOpcodes S9xOpcodesM1X1 [256];
extern SOpcodes S9xOpcodesM1X0 [256];
extern SOpcodes S9xOpcodesM0X1 [256];
extern SOpcodes S9xOpcodesM0X0 [256];

extern SICPU ICPU;

static inline void S9xUnpackStatus()
{
   ICPU._Zero = (ICPU.Registers.PL & Zero) == 0;
   ICPU._Negative = (ICPU.Registers.PL & Negative);
   ICPU._Carry = (ICPU.Registers.PL & Carry);
   ICPU._Overflow = (ICPU.Registers.PL & Overflow) >> 6;
}

static inline void S9xPackStatus()
{
   ICPU.Registers.PL &= ~(Zero | Negative | Carry | Overflow);
   ICPU.Registers.PL |= ICPU._Carry | ((ICPU._Zero == 0) << 1) |
                        (ICPU._Negative & 0x80) | (ICPU._Overflow << 6);
}

static inline void CLEAR_IRQ_SOURCE(uint32_t M)
{
   CPU.IRQActive &= ~M;
   if (!CPU.IRQActive)
      CPU.Flags &= ~IRQ_PENDING_FLAG;
}

static inline void S9xFixCycles()
{
   if (CheckEmulation())
      ICPU.S9xOpcodes = S9xOpcodesE1;
   else if (CheckMemory())
   {
      if (CheckIndex())
         ICPU.S9xOpcodes = S9xOpcodesM1X1;
      else
         ICPU.S9xOpcodes = S9xOpcodesM1X0;
   }
   else
   {
      if (CheckIndex())
         ICPU.S9xOpcodes = S9xOpcodesM0X1;
      else
         ICPU.S9xOpcodes = S9xOpcodesM0X0;
   }
}

static inline void S9xReschedule()
{
   uint8_t which;
   long max;

   if (CPU.WhichEvent == HBLANK_START_EVENT ||
         CPU.WhichEvent == HTIMER_AFTER_EVENT)
   {
      which = HBLANK_END_EVENT;
      max = Settings.H_Max;
   }
   else
   {
      which = HBLANK_START_EVENT;
      max = Settings.HBlankStart;
   }

   if (PPU.HTimerEnabled &&
         (long) PPU.HTimerPosition < max &&
         (long) PPU.HTimerPosition > CPU.NextEvent &&
         (!PPU.VTimerEnabled ||
          (PPU.VTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos)))
   {
      which = (long) PPU.HTimerPosition < Settings.HBlankStart ?
              HTIMER_BEFORE_EVENT : HTIMER_AFTER_EVENT;
      max = PPU.HTimerPosition;
   }
   CPU.NextEvent = max;
   CPU.WhichEvent = which;
}

#endif