aboutsummaryrefslogtreecommitdiff
path: root/source/cpuexec.h
blob: 7d4008c0106af65e783d0594cd4374d73bcf4d0a (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
#include "../copyright"

#ifndef _CPUEXEC_H_
#define _CPUEXEC_H_

typedef struct
{
#ifdef __WIN32__
   void (__cdecl* S9xOpcode)();
#else
   void (*S9xOpcode)();
#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*   UNUSED1;
   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   UNUSED2;
   uint32_t   UNUSED3;
} SICPU;

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

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;
   int32_t 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 &&
         (int32_t) PPU.HTimerPosition < max &&
         (int32_t) PPU.HTimerPosition > CPU.NextEvent &&
         (!PPU.VTimerEnabled ||
         (PPU.VTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos)))
   {
      which = (int32_t) PPU.HTimerPosition < Settings.HBlankStart ? HTIMER_BEFORE_EVENT : HTIMER_AFTER_EVENT;
      max = PPU.HTimerPosition;
   }
   CPU.NextEvent = max;
   CPU.WhichEvent = which;
}

#endif