aboutsummaryrefslogtreecommitdiff
path: root/source/sa1.h
blob: 6679a1c4d601d033e69ae2a4fe0f4fa081c602f3 (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 _sa1_h_
#define _sa1_h_

#include "memmap.h"
#include "cpuexec.h"
#include <retro_inline.h>

typedef struct
{
   uint8_t   PB;
   uint8_t   DB;
   pair      P;
   pair      A;
   pair      D;
   pair      S;
   pair      X;
   pair      Y;
   uint16_t  PC;
} SSA1Registers;

typedef struct
{
   SOpcodes*     S9xOpcodes;
   uint8_t       _Carry;
   uint8_t       _Zero;
   uint8_t       _Negative;
   uint8_t       _Overflow;
   bool          CPUExecuting;
   uint32_t      ShiftedPB;
   uint32_t      ShiftedDB;
   uint32_t      Flags;
   bool          Executing;
   bool          NMIActive;
   uint8_t       IRQActive;
   bool          WaitingForInterrupt;
   bool          Waiting;
   uint8_t*      PC;
   uint8_t*      PCBase;
   uint8_t*      BWRAM;
   uint8_t*      PCAtOpcodeStart;
   uint8_t*      WaitAddress;
   uint32_t      WaitCounter;
   uint8_t*      WaitByteAddress1;
   uint8_t*      WaitByteAddress2;
   uint8_t*      Map      [MEMMAP_NUM_BLOCKS];
   uint8_t*      WriteMap [MEMMAP_NUM_BLOCKS];
   int16_t       op1;
   int16_t       op2;
   int           arithmetic_op; // For savestate compatibility can't change to int32_t
   int64_t       sum;
   bool          overflow;
   uint8_t       VirtualBitmapFormat;
   uint8_t       in_char_dma;
   uint8_t       variable_bit_pos;
   SSA1Registers Registers;
} SSA1;

#define SA1CheckZero()      (SA1._Zero == 0)
#define SA1CheckCarry()     (SA1._Carry)
#define SA1CheckIRQ()       (SA1.Registers.PL & IRQ)
#define SA1CheckDecimal()   (SA1.Registers.PL & Decimal)
#define SA1CheckIndex()     (SA1.Registers.PL & IndexFlag)
#define SA1CheckMemory()    (SA1.Registers.PL & MemoryFlag)
#define SA1CheckOverflow()  (SA1._Overflow)
#define SA1CheckNegative()  (SA1._Negative & 0x80)
#define SA1CheckEmulation() (SA1.Registers.P.W & Emulation)

#define SA1ClearFlags(f) (SA1.Registers.P.W &= ~(f))
#define SA1SetFlags(f)   (SA1.Registers.P.W |=  (f))
#define SA1CheckFlag(f)  (SA1.Registers.PL & (f))

uint8_t S9xSA1GetByte(uint32_t);
uint16_t S9xSA1GetWord(uint32_t);
void S9xSA1SetByte(uint8_t, uint32_t);
void S9xSA1SetWord(uint16_t, uint32_t);
void S9xSA1SetPCBase(uint32_t);
uint8_t S9xGetSA1(uint32_t);
void S9xSetSA1(uint8_t, uint32_t);

extern SOpcodes S9xSA1OpcodesE1   [256];
extern SOpcodes S9xSA1OpcodesM1X1 [256];
extern SOpcodes S9xSA1OpcodesM1X0 [256];
extern SOpcodes S9xSA1OpcodesM0X1 [256];
extern SOpcodes S9xSA1OpcodesM0X0 [256];
extern SSA1 SA1;

void S9xSA1MainLoop(void);
void S9xSA1Init(void);
void S9xFixSA1AfterSnapshotLoad(void);

#define SNES_IRQ_SOURCE     (1 << 7)
#define TIMER_IRQ_SOURCE    (1 << 6)
#define DMA_IRQ_SOURCE      (1 << 5)

static INLINE void S9xSA1UnpackStatus(void)
{
   SA1._Zero = (SA1.Registers.PL & Zero) == 0;
   SA1._Negative = (SA1.Registers.PL & Negative);
   SA1._Carry = (SA1.Registers.PL & Carry);
   SA1._Overflow = (SA1.Registers.PL & Overflow) >> 6;
}

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

static INLINE void S9xSA1FixCycles(void)
{
   if (SA1CheckEmulation())
      SA1.S9xOpcodes = S9xSA1OpcodesE1;
   else if (SA1CheckMemory())
   {
      if (SA1CheckIndex())
         SA1.S9xOpcodes = S9xSA1OpcodesM1X1;
      else
         SA1.S9xOpcodes = S9xSA1OpcodesM1X0;
   }
   else
   {
      if (SA1CheckIndex())
         SA1.S9xOpcodes = S9xSA1OpcodesM0X1;
      else
         SA1.S9xOpcodes = S9xSA1OpcodesM0X0;
   }
}
#endif