1/* PR tree-optimization/34046 */
2/* Origin: dcb <dcb314@hotmail.com> */
3
4typedef unsigned char bool8;
5typedef unsigned char uint8_t;
6typedef unsigned short int uint16_t;
7typedef unsigned int uint32_t;
8typedef uint8_t uint8;
9typedef uint16_t uint16;
10typedef uint32_t uint32;
11
12struct SIAPU
13{
14    uint8 *PC;
15    uint8 *RAM;
16    uint8 Bit;
17    uint32 Address;
18    uint8 *WaitAddress1;
19    uint8 *WaitAddress2;
20    uint8 _Carry;
21};
22
23struct SAPU
24{
25    bool8 ShowROM;
26    uint8 OutPorts [4];
27    uint8 ExtraRAM [64];
28    uint16 TimerTarget [3];
29};
30
31struct SAPU APU;
32struct SIAPU IAPU;
33
34void S9xSetAPUControl (uint8 byte);
35void S9xSetAPUDSP (uint8 byte);
36uint8 S9xGetAPUDSP ();
37
38uint8 S9xAPUGetByte (uint32 Address)
39{
40  Address &= 0xffff;
41
42  if (Address <= 0xff && Address >= 0xf0)
43    {
44      if (Address >= 0xf4 && Address <= 0xf7)
45	{
46	  IAPU.WaitAddress2 = IAPU.WaitAddress1;
47	  IAPU.WaitAddress1 = IAPU.PC;
48	  return (IAPU.RAM [Address]);
49	}
50      else if (Address == 0xf3)
51	return (S9xGetAPUDSP ());
52
53      if (Address >= 0xfd)
54	{
55	  IAPU.WaitAddress2 = IAPU.WaitAddress1;
56	  IAPU.WaitAddress1 = IAPU.PC;
57	  uint8 t = IAPU.RAM [Address];
58	  IAPU.RAM [Address] = 0;
59	  return (t);
60	}
61
62      return (IAPU.RAM [Address]);
63    }
64 else
65   return (IAPU.RAM [Address]);
66}
67
68void S9xAPUSetByte (uint8 byte, uint32 Address)
69{
70  Address &= 0xffff;
71
72  if (Address <= 0xff && Address >= 0xf0)
73    {
74      if (Address == 0xf3)
75	S9xSetAPUDSP (byte);
76      else if (Address >= 0xf4 && Address <= 0xf7)
77	APU.OutPorts [Address - 0xf4] = byte;
78      else if (Address == 0xf1)
79	S9xSetAPUControl (byte);
80      else if (Address < 0xfd)
81	{
82	  IAPU.RAM [Address] = byte;
83	  if (Address >= 0xfa)
84	    {
85	      if (byte == 0)
86		APU.TimerTarget [Address - 0xfa] = 0x100;
87	      else
88		APU.TimerTarget [Address - 0xfa] = byte;
89	    }
90	}
91    }
92  else
93    {
94      if (Address < 0xffc0)
95	IAPU.RAM [Address] = byte;
96      else
97	{
98	  APU.ExtraRAM [Address - 0xffc0] = byte;
99	  if (!APU.ShowROM)
100	    IAPU.RAM [Address] = byte;
101	}
102    }
103}
104
105void ApuCA ()
106{
107  IAPU.Address = *(uint16 *) (IAPU.PC + 1);
108  IAPU.Bit = (uint8)(IAPU.Address >> 13);
109  if ((IAPU._Carry))
110    S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) | (1 << IAPU.Bit), IAPU.Address);
111  else
112    S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) & ~(1 << IAPU.Bit), IAPU.Address);
113}
114