summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/nes_defs.h
blob: 0abe5b4666e51bf210c030f59436932707399eb4 (plain) (blame)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// license:GPL-2.0+
// copyright-holders:Matthew Conte
/*****************************************************************************

  MAME/MESS NES APU CORE

  Based on the Nofrendo/Nosefart NES N2A03 sound emulation core written by
  Matthew Conte (matt@conte.com) and redesigned for use in MAME/MESS by
  Who Wants to Know? (wwtk@mail.com)

  This core is written with the advise and consent of Matthew Conte and is
  released under the GNU Public License.  This core is freely available for
  use in any freeware project, subject to the following terms:

  Any modifications to this code must be duly noted in the source and
  approved by Matthew Conte and myself prior to public submission.

 *****************************************************************************

   NES_DEFS.H

   NES APU internal type definitions and constants.

 *****************************************************************************/

#ifndef MAME_SOUND_NES_DEFS_H
#define MAME_SOUND_NES_DEFS_H

#pragma once


/* APU type */
struct apu_t
{
	/* REGULAR TYPE DEFINITIONS */
	typedef int8_t          int8;
	typedef int16_t         int16;
	typedef int32_t         int32;
	typedef uint8_t         uint8;
	typedef uint16_t        uint16;
	typedef uint32_t        uint32;


	/* CHANNEL TYPE DEFINITIONS */

	/* Square Wave */
	struct square_t
	{
		square_t()
		{
			for (auto & elem : regs)
				elem = 0;
		}

		uint8 regs[4];
		int vbl_length = 0;
		int freq = 0;
		float phaseacc = 0.0;
		float output_vol = 0.0;
		float env_phase = 0.0;
		float sweep_phase = 0.0;
		uint8 adder = 0;
		uint8 env_vol = 0;
		bool enabled = false;
	};

	/* Triangle Wave */
	struct triangle_t
	{
		triangle_t()
		{
			for (auto & elem : regs)
				elem = 0;
		}

		uint8 regs[4]; /* regs[1] unused */
		int linear_length = 0;
		int vbl_length = 0;
		int write_latency = 0;
		float phaseacc = 0.0;
		float output_vol = 0.0;
		uint8 adder = 0;
		bool counter_started = false;
		bool enabled = false;
	};

	/* Noise Wave */
	struct noise_t
	{
		noise_t()
		{
			for (auto & elem : regs)
				elem = 0;
		}

		uint8 regs[4]; /* regs[1] unused */
		int cur_pos = 0;
		int vbl_length = 0;
		float phaseacc = 0.0;
		float output_vol = 0.0;
		float env_phase = 0.0;
		uint8 env_vol = 0;
		bool enabled = false;
	};

	/* DPCM Wave */
	struct dpcm_t
	{
		dpcm_t()
		{
			for (auto & elem : regs)
				elem = 0;
		}

		uint8 regs[4];
		uint32 address = 0;
		uint32 length = 0;
		int bits_left = 0;
		float phaseacc = 0.0;
		float output_vol = 0.0;
		uint8 cur_byte = 0;
		bool enabled = false;
		bool irq_occurred = false;
		signed char vol = 0;
	};


	/* REGISTER DEFINITIONS */
	static constexpr unsigned WRA0    = 0x00;
	static constexpr unsigned WRA1    = 0x01;
	static constexpr unsigned WRA2    = 0x02;
	static constexpr unsigned WRA3    = 0x03;
	static constexpr unsigned WRB0    = 0x04;
	static constexpr unsigned WRB1    = 0x05;
	static constexpr unsigned WRB2    = 0x06;
	static constexpr unsigned WRB3    = 0x07;
	static constexpr unsigned WRC0    = 0x08;
	static constexpr unsigned WRC2    = 0x0A;
	static constexpr unsigned WRC3    = 0x0B;
	static constexpr unsigned WRD0    = 0x0C;
	static constexpr unsigned WRD2    = 0x0E;
	static constexpr unsigned WRD3    = 0x0F;
	static constexpr unsigned WRE0    = 0x10;
	static constexpr unsigned WRE1    = 0x11;
	static constexpr unsigned WRE2    = 0x12;
	static constexpr unsigned WRE3    = 0x13;
	static constexpr unsigned SMASK   = 0x15;
	static constexpr unsigned IRQCTRL = 0x17;

	static constexpr unsigned NOISE_LONG     = 0x4000;
	static constexpr unsigned NOISE_SHORT    = 93;


	apu_t()
	{
		memset(regs, 0, sizeof(regs));
	}

	/* Sound channels */
	square_t   squ[2];
	triangle_t tri;
	noise_t    noi;
	dpcm_t     dpcm;

	/* APU registers */
	unsigned char regs[0x18];

	/* Sound pointers */
	void *buffer = nullptr;

#ifdef USE_QUEUE

	static constexpr unsigned QUEUE_SIZE = 0x2000;
	static constexpr unsigned QUEUE_MAX  = QUEUE_SIZE - 1;

	struct queue_t
	{
		queue_t() { }

		int pos = 0;
		unsigned char reg = 0, val = 0;
	};

	/* Event queue */
	queue_t queue[QUEUE_SIZE];
	int head, tail;

#else

	int buf_pos = 0;

#endif

	int step_mode = 0;
};

/* CONSTANTS */

/* vblank length table used for squares, triangle, noise */
static const apu_t::uint8 vbl_length[32] =
{
	5, 127, 10, 1, 19,  2, 40,  3, 80,  4, 30,  5, 7,  6, 13,  7,
	6,   8, 12, 9, 24, 10, 48, 11, 96, 12, 36, 13, 8, 14, 16, 15
};

/* frequency limit of square channels */
static const int freq_limit[8] =
{
	0x3FF, 0x555, 0x666, 0x71C, 0x787, 0x7C1, 0x7E0, 0x7F0,
};

/* table of noise frequencies */
static const int noise_freq[16] =
{
	4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 2046
};

/* dpcm transfer freqs */
static const int dpcm_clocks[16] =
{
	428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 85, 72, 54
};

/* ratios of pos/neg pulse for square waves */
/* 2/16 = 12.5%, 4/16 = 25%, 8/16 = 50%, 12/16 = 75% */
static const int duty_lut[4] =
{
	2, 4, 8, 12
};

#endif // MAME_SOUND_NES_DEFS_H