Browse code

Update snes9x code from 1.53 to 1.6.0.

Notable differences from upstream:
* Did not use the same #include setup for the new byuu apu and instead chose to do things more traditionally, as the latter is also much easier to deal with in Visual Studio than just including .cpp files into other .cpp files...
* MSU1 support not included (I see no need for this in a plugin meant to be used for original SNES music).
* The dynamic rate control on the APU not included (I also see no need for it in this plugin).
* The extra resamplers I added in were removed as the original hermite resampler was folded into a single non-inhertiable resampler.
* Bits of cleanup.

Naram Qashat authored on 2021/04/19 21:20:36
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,236 +0,0 @@
1
-// SNES SPC-700 APU emulator
2
-
3
-// snes_spc 0.9.0
4
-#pragma once
5
-
6
-#include "SPC_DSP.h"
7
-#include "blargg_endian.h"
8
-
9
-// (n ? n : 256)
10
-template<typename T> inline T IF_0_THEN_256(const T &n) { return static_cast<uint8_t>(n - 1) + 1; }
11
-
12
-struct SNES_SPC
13
-{
14
-public:
15
-	// Must be called once before using
16
-	void init();
17
-
18
-	// Sample pairs generated per second
19
-	enum { sample_rate = 32000 };
20
-
21
-	// Emulator use
22
-
23
-	// Sets IPL ROM data. Library does not include ROM data. Most SPC music files
24
-	// don't need ROM, but a full emulator must provide this.
25
-	enum { rom_size = 0x40 };
26
-	void init_rom(const uint8_t rom[rom_size]);
27
-
28
-	// Sets destination for output samples
29
-	typedef short sample_t;
30
-	void set_output(sample_t *out, int out_size);
31
-
32
-	// Number of samples written to output since last set
33
-	int sample_count() const;
34
-
35
-	// Resets SPC to power-on state. This resets your output buffer, so you must
36
-	// call set_output() after this.
37
-	void reset();
38
-
39
-	// Emulates pressing reset switch on SNES. This resets your output buffer, so
40
-	// you must call set_output() after this.
41
-	void soft_reset();
42
-
43
-	// 1024000 SPC clocks per second, sample pair every 32 clocks
44
-	typedef int time_t;
45
-	enum { clock_rate = 1024000 };
46
-	enum { clocks_per_sample = 32 };
47
-
48
-	// Emulated port read/write at specified time
49
-	enum { port_count = 4 };
50
-	int read_port(time_t, int port);
51
-	void write_port(time_t, int port, int data);
52
-
53
-	// Runs SPC to end_time and starts a new time frame at 0
54
-	void end_frame(time_t end_time);
55
-
56
-	// Sound control
57
-
58
-	// Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events).
59
-	// Reduces emulation accuracy.
60
-	enum { voice_count = 8 };
61
-	void mute_voices(int mask);
62
-
63
-	// If true, prevents channels and global volumes from being phase-negated.
64
-	// Only supported by fast DSP.
65
-	void disable_surround(bool disable = true );
66
-
67
-	// Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc.
68
-	enum { tempo_unit = 0x100 };
69
-	void set_tempo(int);
70
-
71
-	// SPC music files
72
-
73
-	// Clears echo region. Useful after loading an SPC as many have garbage in echo.
74
-	void clear_echo();
75
-
76
-	// Plays for count samples and write samples to out. Discards samples if out
77
-	// is NULL. Count must be a multiple of 2 since output is stereo.
78
-	void play(int count, sample_t *out);
79
-
80
-	// Skips count samples. Several times faster than play() when using fast DSP.
81
-	void skip(int count);
82
-
83
-	//// Snes9x Accessor
84
-
85
-	void spc_allow_time_overflow(bool);
86
-
87
-	void dsp_set_stereo_switch(int);
88
-	uint8_t dsp_reg_value(int, int);
89
-	int dsp_envx_value(int);
90
-
91
-public:
92
-	// Time relative to m_spc_time. Speeds up code a bit by eliminating need to
93
-	// constantly add m_spc_time to time from CPU. CPU uses time that ends at
94
-	// 0 to eliminate reloading end time every instruction. It pays off.
95
-	typedef int rel_time_t;
96
-
97
-	struct Timer
98
-	{
99
-		rel_time_t next_time; // time of next event
100
-		int prescaler;
101
-		int period;
102
-		int divider;
103
-		bool enabled;
104
-		int counter;
105
-	};
106
-	enum { reg_count = 0x10 };
107
-	enum { timer_count = 3 };
108
-	enum { extra_size = SPC_DSP::extra_size };
109
-
110
-private:
111
-	SPC_DSP dsp;
112
-
113
-	struct state_t
114
-	{
115
-		Timer timers[timer_count];
116
-
117
-		uint8_t smp_regs[2][reg_count];
118
-
119
-		struct
120
-		{
121
-			int pc;
122
-			int a;
123
-			int x;
124
-			int y;
125
-			int psw;
126
-			int sp;
127
-		} cpu_regs;
128
-
129
-		rel_time_t dsp_time;
130
-		time_t spc_time;
131
-
132
-		int tempo;
133
-
134
-		int extra_clocks;
135
-		sample_t *buf_begin;
136
-		const sample_t *buf_end;
137
-		sample_t *extra_pos;
138
-		sample_t extra_buf[extra_size];
139
-
140
-		bool rom_enabled;
141
-		uint8_t rom[rom_size];
142
-		uint8_t hi_ram[rom_size];
143
-
144
-		unsigned char cycle_table[256];
145
-
146
-		struct
147
-		{
148
-			// padding to neutralize address overflow
149
-			union
150
-			{
151
-				uint8_t padding1[0x100];
152
-				uint16_t align; // makes compiler align data for 16-bit access
153
-			} padding1[1];
154
-			uint8_t ram[0x10000];
155
-			uint8_t padding2[0x100];
156
-		} ram;
157
-	};
158
-	state_t m;
159
-
160
-	enum { rom_addr = 0xFFC0 };
161
-
162
-	enum { skipping_time = 127 };
163
-
164
-	// Value that padding should be filled with
165
-	enum { cpu_pad_fill = 0xFF };
166
-
167
-	enum
168
-	{
169
-		r_test = 0x0,
170
-		r_control = 0x1,
171
-		r_dspaddr = 0x2,
172
-		r_dspdata = 0x3,
173
-		r_cpuio0 = 0x4,
174
-		r_cpuio1 = 0x5,
175
-		r_cpuio2 = 0x6,
176
-		r_cpuio3 = 0x7,
177
-		r_f8 = 0x8,
178
-		r_f9 = 0x9,
179
-		r_t0target = 0xA,
180
-		r_t1target = 0xB,
181
-		r_t2target = 0xC,
182
-		r_t0out = 0xD,
183
-		r_t1out = 0xE,
184
-		r_t2out = 0xF
185
-	};
186
-
187
-	void timers_loaded();
188
-	void enable_rom(bool enable);
189
-	void reset_buf();
190
-	void save_extra();
191
-	void load_regs(const uint8_t in[reg_count]);
192
-	void ram_loaded();
193
-	void regs_loaded();
194
-	void reset_time_regs();
195
-	void reset_common(int timer_counter_init);
196
-
197
-	Timer *run_timer_(Timer *t, rel_time_t);
198
-	Timer *run_timer(Timer *t, rel_time_t);
199
-	void RUN_DSP(rel_time_t);
200
-	int dsp_read(rel_time_t);
201
-	void dsp_write(int data, rel_time_t);
202
-	void cpu_write_smp_reg_(int data, rel_time_t, int addr);
203
-	void cpu_write_smp_reg(int data, rel_time_t, int addr);
204
-	void cpu_write_high(int data, int i, rel_time_t);
205
-	void cpu_write(int data, int addr, rel_time_t);
206
-	int cpu_read_smp_reg(int i, rel_time_t);
207
-	int cpu_read(int addr, rel_time_t);
208
-	unsigned CPU_mem_bit(const uint8_t *pc, rel_time_t);
209
-
210
-	bool check_echo_access(int addr);
211
-	uint8_t *run_until_(time_t end_time);
212
-
213
-	// Snes9x timing hack
214
-	bool allow_time_overflow;
215
-};
216
-
217
-inline int SNES_SPC::sample_count() const { return (this->m.extra_clocks >> 5) * 2; }
218
-
219
-inline int SNES_SPC::read_port(time_t t, int port)
220
-{
221
-	assert(static_cast<unsigned>(port) < port_count);
222
-	return this->run_until_(t)[port];
223
-}
224
-
225
-inline void SNES_SPC::write_port(time_t t, int port, int data)
226
-{
227
-	assert(static_cast<unsigned>(port) < port_count);
228
-	this->run_until_(t)[0x10 + port] = data;
229
-	this->m.ram.ram[0xF4 + port] = data;
230
-}
231
-
232
-inline void SNES_SPC::mute_voices(int mask) { this->dsp.mute_voices(mask); }
233
-
234
-inline void SNES_SPC::disable_surround(bool disable) { this->dsp.disable_surround(disable); }
235
-
236
-inline void SNES_SPC::spc_allow_time_overflow(bool allow) { this->allow_time_overflow = allow; }
Browse code

* Fixes for gcc and clang (while they can compile the code, the DLLs made aren't functional, but oh well).

* [2SF] Used more up-to-date asmjit, despite the ugly looking code.

Naram Qashat authored on 2014/09/17 19:51:45
Showing 1 changed files
... ...
@@ -230,7 +230,7 @@ inline void SNES_SPC::write_port(time_t t, int port, int data)
230 230
 }
231 231
 
232 232
 inline void SNES_SPC::mute_voices(int mask) { this->dsp.mute_voices(mask); }
233
-	
233
+
234 234
 inline void SNES_SPC::disable_surround(bool disable) { this->dsp.disable_surround(disable); }
235 235
 
236 236
 inline void SNES_SPC::spc_allow_time_overflow(bool allow) { this->allow_time_overflow = allow; }
Browse code

A few more cases of using #pragma once instead of include guards.

Naram Qashat authored on 2014/09/08 14:51:19
Showing 1 changed files
... ...
@@ -1,8 +1,7 @@
1 1
 // SNES SPC-700 APU emulator
2 2
 
3 3
 // snes_spc 0.9.0
4
-#ifndef SNES_SPC_H
5
-#define SNES_SPC_H
4
+#pragma once
6 5
 
7 6
 #include "SPC_DSP.h"
8 7
 #include "blargg_endian.h"
... ...
@@ -235,5 +234,3 @@ inline void SNES_SPC::mute_voices(int mask) { this->dsp.mute_voices(mask); }
235 234
 inline void SNES_SPC::disable_surround(bool disable) { this->dsp.disable_surround(disable); }
236 235
 
237 236
 inline void SNES_SPC::spc_allow_time_overflow(bool allow) { this->allow_time_overflow = allow; }
238
-
239
-#endif
Browse code

[SNSF] Massive code cleanup, as well as removing as much unused code/variables as possible.

Naram Qashat authored on 2013/05/23 06:02:16
Showing 1 changed files
... ...
@@ -7,32 +7,28 @@
7 7
 #include "SPC_DSP.h"
8 8
 #include "blargg_endian.h"
9 9
 
10
-#ifdef DEBUGGER
11
-#include "snes9x.h"
12
-#include "display.h"
13
-#include "debug.h"
14
-#endif
10
+// (n ? n : 256)
11
+template<typename T> inline T IF_0_THEN_256(const T &n) { return static_cast<uint8_t>(n - 1) + 1; }
15 12
 
16
-struct SNES_SPC {
13
+struct SNES_SPC
14
+{
17 15
 public:
18
-	typedef BOOST::uint8_t uint8_t;
19
-	
20 16
 	// Must be called once before using
21
-	blargg_err_t init();
22
-	
17
+	void init();
18
+
23 19
 	// Sample pairs generated per second
24 20
 	enum { sample_rate = 32000 };
25
-	
26
-// Emulator use
27
-	
21
+
22
+	// Emulator use
23
+
28 24
 	// Sets IPL ROM data. Library does not include ROM data. Most SPC music files
29 25
 	// don't need ROM, but a full emulator must provide this.
30 26
 	enum { rom_size = 0x40 };
31
-	void init_rom( uint8_t const rom [rom_size] );
27
+	void init_rom(const uint8_t rom[rom_size]);
32 28
 
33 29
 	// Sets destination for output samples
34 30
 	typedef short sample_t;
35
-	void set_output( sample_t* out, int out_size );
31
+	void set_output(sample_t *out, int out_size);
36 32
 
37 33
 	// Number of samples written to output since last set
38 34
 	int sample_count() const;
... ...
@@ -49,126 +45,78 @@ public:
49 45
 	typedef int time_t;
50 46
 	enum { clock_rate = 1024000 };
51 47
 	enum { clocks_per_sample = 32 };
52
-	
48
+
53 49
 	// Emulated port read/write at specified time
54 50
 	enum { port_count = 4 };
55
-	int  read_port ( time_t, int port );
56
-	void write_port( time_t, int port, int data );
51
+	int read_port(time_t, int port);
52
+	void write_port(time_t, int port, int data);
57 53
 
58 54
 	// Runs SPC to end_time and starts a new time frame at 0
59
-	void end_frame( time_t end_time );
60
-	
61
-// Sound control
62
-	
55
+	void end_frame(time_t end_time);
56
+
57
+	// Sound control
58
+
63 59
 	// Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events).
64 60
 	// Reduces emulation accuracy.
65 61
 	enum { voice_count = 8 };
66
-	void mute_voices( int mask );
67
-	
62
+	void mute_voices(int mask);
63
+
68 64
 	// If true, prevents channels and global volumes from being phase-negated.
69 65
 	// Only supported by fast DSP.
70
-	void disable_surround( bool disable = true );
71
-	
66
+	void disable_surround(bool disable = true );
67
+
72 68
 	// Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc.
73 69
 	enum { tempo_unit = 0x100 };
74
-	void set_tempo( int );
70
+	void set_tempo(int);
75 71
 
76
-// SPC music files
72
+	// SPC music files
77 73
 
78
-	// Loads SPC data into emulator
79
-	enum { spc_min_file_size = 0x10180 };
80
-	enum { spc_file_size     = 0x10200 };
81
-	blargg_err_t load_spc( void const* in, long size );
82
-	
83 74
 	// Clears echo region. Useful after loading an SPC as many have garbage in echo.
84 75
 	void clear_echo();
85 76
 
86 77
 	// Plays for count samples and write samples to out. Discards samples if out
87 78
 	// is NULL. Count must be a multiple of 2 since output is stereo.
88
-	blargg_err_t play( int count, sample_t* out );
89
-	
90
-	// Skips count samples. Several times faster than play() when using fast DSP.
91
-	blargg_err_t skip( int count );
92
-	
93
-// State save/load (only available with accurate DSP)
94
-
95
-#if !SPC_NO_COPY_STATE_FUNCS
96
-	// Saves/loads state
97
-	enum { state_size = 68 * 1024L }; // maximum space needed when saving
98
-	typedef SPC_DSP::copy_func_t copy_func_t;
99
-	void copy_state( unsigned char** io, copy_func_t );
100
-	
101
-	// Writes minimal header to spc_out
102
-	static void init_header( void* spc_out );
103
-
104
-	// Saves emulator state as SPC file data. Writes spc_file_size bytes to spc_out.
105
-	// Does not set up SPC header; use init_header() for that.
106
-	void save_spc( void* spc_out );
107
-
108
-	// Returns true if new key-on events occurred since last check. Useful for
109
-	// trimming silence while saving an SPC.
110
-	bool check_kon();
111
-#endif
79
+	void play(int count, sample_t *out);
112 80
 
113
-//// Snes9x Accessor
81
+	// Skips count samples. Several times faster than play() when using fast DSP.
82
+	void skip(int count);
114 83
 
115
-	void	spc_allow_time_overflow( bool );
84
+	//// Snes9x Accessor
116 85
 
117
-	void    dsp_set_spc_snapshot_callback(void (*callback)());
118
-	void    dsp_dump_spc_snapshot();
119
-	void    dsp_set_stereo_switch( int );
120
-	uint8_t dsp_reg_value( int, int );
121
-	int     dsp_envx_value( int );
86
+	void spc_allow_time_overflow(bool);
122 87
 
123
-//// Snes9x Debugger
124
-
125
-#ifdef DEBUGGER
126
-	void	debug_toggle_trace();
127
-	bool    debug_is_enabled();
128
-	void	debug_do_trace( int, int, int, uint8_t const *, uint8_t *, int, int, int, int );
129
-	void	debug_op_print( char *, int, int, int, uint8_t const *, uint8_t *, int, int, int, int );
130
-	void	debug_io_print( char * );
131
-#endif
88
+	void dsp_set_stereo_switch(int);
89
+	uint8_t dsp_reg_value(int, int);
90
+	int dsp_envx_value(int);
132 91
 
133 92
 public:
134
-	BLARGG_DISABLE_NOTHROW
135
-	
136
-	typedef BOOST::uint16_t uint16_t;
137
-	
138 93
 	// Time relative to m_spc_time. Speeds up code a bit by eliminating need to
139 94
 	// constantly add m_spc_time to time from CPU. CPU uses time that ends at
140 95
 	// 0 to eliminate reloading end time every instruction. It pays off.
141 96
 	typedef int rel_time_t;
142
-	
97
+
143 98
 	struct Timer
144 99
 	{
145 100
 		rel_time_t next_time; // time of next event
146 101
 		int prescaler;
147 102
 		int period;
148 103
 		int divider;
149
-		int enabled;
104
+		bool enabled;
150 105
 		int counter;
151 106
 	};
152 107
 	enum { reg_count = 0x10 };
153 108
 	enum { timer_count = 3 };
154 109
 	enum { extra_size = SPC_DSP::extra_size };
155
-	
156
-	enum { signature_size = 35 };
157
-	
110
+
158 111
 private:
159 112
 	SPC_DSP dsp;
160
-	
161
-	#if SPC_LESS_ACCURATE
162
-		static signed char const reg_times_ [256];
163
-		signed char reg_times [256];
164
-	#endif
165
-	
113
+
166 114
 	struct state_t
167 115
 	{
168
-		Timer timers [timer_count];
169
-		
170
-		uint8_t smp_regs [2] [reg_count];
171
-		
116
+		Timer timers[timer_count];
117
+
118
+		uint8_t smp_regs[2][reg_count];
119
+
172 120
 		struct
173 121
 		{
174 122
 			int pc;
... ...
@@ -178,139 +126,114 @@ private:
178 126
 			int psw;
179 127
 			int sp;
180 128
 		} cpu_regs;
181
-		
182
-		rel_time_t  dsp_time;
183
-		time_t      spc_time;
184
-		bool        echo_accessed;
185
-		
186
-		int         tempo;
187
-		int         skipped_kon;
188
-		int         skipped_koff;
189
-		const char* cpu_error;
190
-		
191
-		int         extra_clocks;
192
-		sample_t*   buf_begin;
193
-		sample_t const* buf_end;
194
-		sample_t*   extra_pos;
195
-		sample_t    extra_buf [extra_size];
196
-		
197
-		int         rom_enabled;
198
-		uint8_t     rom    [rom_size];
199
-		uint8_t     hi_ram [rom_size];
200
-		
201
-		unsigned char cycle_table [256];
202
-		
129
+
130
+		rel_time_t dsp_time;
131
+		time_t spc_time;
132
+
133
+		int tempo;
134
+
135
+		int extra_clocks;
136
+		sample_t *buf_begin;
137
+		const sample_t *buf_end;
138
+		sample_t *extra_pos;
139
+		sample_t extra_buf[extra_size];
140
+
141
+		bool rom_enabled;
142
+		uint8_t rom[rom_size];
143
+		uint8_t hi_ram[rom_size];
144
+
145
+		unsigned char cycle_table[256];
146
+
203 147
 		struct
204 148
 		{
205 149
 			// padding to neutralize address overflow
206
-			union {
207
-				uint8_t padding1 [0x100];
150
+			union
151
+			{
152
+				uint8_t padding1[0x100];
208 153
 				uint16_t align; // makes compiler align data for 16-bit access
209
-			} padding1 [1];
210
-			uint8_t ram      [0x10000];
211
-			uint8_t padding2 [0x100];
154
+			} padding1[1];
155
+			uint8_t ram[0x10000];
156
+			uint8_t padding2[0x100];
212 157
 		} ram;
213 158
 	};
214 159
 	state_t m;
215
-	
160
+
216 161
 	enum { rom_addr = 0xFFC0 };
217
-	
162
+
218 163
 	enum { skipping_time = 127 };
219
-	
164
+
220 165
 	// Value that padding should be filled with
221 166
 	enum { cpu_pad_fill = 0xFF };
222
-	
223
-	enum {
224
-        r_test     = 0x0, r_control  = 0x1,
225
-        r_dspaddr  = 0x2, r_dspdata  = 0x3,
226
-        r_cpuio0   = 0x4, r_cpuio1   = 0x5,
227
-        r_cpuio2   = 0x6, r_cpuio3   = 0x7,
228
-        r_f8       = 0x8, r_f9       = 0x9,
229
-        r_t0target = 0xA, r_t1target = 0xB, r_t2target = 0xC,
230
-        r_t0out    = 0xD, r_t1out    = 0xE, r_t2out    = 0xF
167
+
168
+	enum
169
+	{
170
+		r_test = 0x0,
171
+		r_control = 0x1,
172
+		r_dspaddr = 0x2,
173
+		r_dspdata = 0x3,
174
+		r_cpuio0 = 0x4,
175
+		r_cpuio1 = 0x5,
176
+		r_cpuio2 = 0x6,
177
+		r_cpuio3 = 0x7,
178
+		r_f8 = 0x8,
179
+		r_f9 = 0x9,
180
+		r_t0target = 0xA,
181
+		r_t1target = 0xB,
182
+		r_t2target = 0xC,
183
+		r_t0out = 0xD,
184
+		r_t1out = 0xE,
185
+		r_t2out = 0xF
231 186
 	};
232
-	
187
+
233 188
 	void timers_loaded();
234
-	void enable_rom( int enable );
189
+	void enable_rom(bool enable);
235 190
 	void reset_buf();
236 191
 	void save_extra();
237
-	void load_regs( uint8_t const in [reg_count] );
192
+	void load_regs(const uint8_t in[reg_count]);
238 193
 	void ram_loaded();
239 194
 	void regs_loaded();
240 195
 	void reset_time_regs();
241
-	void reset_common( int timer_counter_init );
242
-	
243
-	Timer* run_timer_      ( Timer* t, rel_time_t );
244
-	Timer* run_timer       ( Timer* t, rel_time_t );
245
-	int dsp_read           ( rel_time_t );
246
-	void dsp_write         ( int data, rel_time_t );
247
-	void cpu_write_smp_reg_( int data, rel_time_t, int addr );
248
-	void cpu_write_smp_reg ( int data, rel_time_t, int addr );
249
-	void cpu_write_high    ( int data, int i, rel_time_t );
250
-	void cpu_write         ( int data, int addr, rel_time_t );
251
-	int cpu_read_smp_reg   ( int i, rel_time_t );
252
-	int cpu_read           ( int addr, rel_time_t );
253
-	unsigned CPU_mem_bit   ( uint8_t const* pc, rel_time_t );
254
-	
255
-	bool check_echo_access ( int addr );
256
-	uint8_t* run_until_( time_t end_time );
257
-	
258
-	struct spc_file_t
259
-	{
260
-		char    signature [signature_size];
261
-		uint8_t has_id666;
262
-		uint8_t version;
263
-		uint8_t pcl, pch;
264
-		uint8_t a;
265
-		uint8_t x;
266
-		uint8_t y;
267
-		uint8_t psw;
268
-		uint8_t sp;
269
-		char    text [212];
270
-		uint8_t ram [0x10000];
271
-		uint8_t dsp [128];
272
-		uint8_t unused [0x40];
273
-		uint8_t ipl_rom [0x40];
274
-	};
275
-
276
-	static char const signature [signature_size + 1];
277
-	
278
-	void save_regs( uint8_t out [reg_count] );
279
-
280
-// Snes9x timing hack
196
+	void reset_common(int timer_counter_init);
197
+
198
+	Timer *run_timer_(Timer *t, rel_time_t);
199
+	Timer *run_timer(Timer *t, rel_time_t);
200
+	void RUN_DSP(rel_time_t);
201
+	int dsp_read(rel_time_t);
202
+	void dsp_write(int data, rel_time_t);
203
+	void cpu_write_smp_reg_(int data, rel_time_t, int addr);
204
+	void cpu_write_smp_reg(int data, rel_time_t, int addr);
205
+	void cpu_write_high(int data, int i, rel_time_t);
206
+	void cpu_write(int data, int addr, rel_time_t);
207
+	int cpu_read_smp_reg(int i, rel_time_t);
208
+	int cpu_read(int addr, rel_time_t);
209
+	unsigned CPU_mem_bit(const uint8_t *pc, rel_time_t);
210
+
211
+	bool check_echo_access(int addr);
212
+	uint8_t *run_until_(time_t end_time);
213
+
214
+	// Snes9x timing hack
281 215
 	bool allow_time_overflow;
282
-// Snes9x debugger
283
-#ifdef DEBUGGER
284
-	FILE *apu_trace;
285
-	bool debug_trace;
286
-#endif
287 216
 };
288 217
 
289
-#include <assert.h>
290
-
291
-inline int SNES_SPC::sample_count() const { return (m.extra_clocks >> 5) * 2; }
218
+inline int SNES_SPC::sample_count() const { return (this->m.extra_clocks >> 5) * 2; }
292 219
 
293
-inline int SNES_SPC::read_port( time_t t, int port )
220
+inline int SNES_SPC::read_port(time_t t, int port)
294 221
 {
295
-	assert( (unsigned) port < port_count );
296
-	return run_until_( t ) [port];
222
+	assert(static_cast<unsigned>(port) < port_count);
223
+	return this->run_until_(t)[port];
297 224
 }
298 225
 
299
-inline void SNES_SPC::write_port( time_t t, int port, int data )
226
+inline void SNES_SPC::write_port(time_t t, int port, int data)
300 227
 {
301
-	assert( (unsigned) port < port_count );
302
-	run_until_( t ) [0x10 + port] = data;
303
-	m.ram.ram [0xF4 + port] = data;
228
+	assert(static_cast<unsigned>(port) < port_count);
229
+	this->run_until_(t)[0x10 + port] = data;
230
+	this->m.ram.ram[0xF4 + port] = data;
304 231
 }
305 232
 
306
-inline void SNES_SPC::mute_voices( int mask ) { dsp.mute_voices( mask ); }
233
+inline void SNES_SPC::mute_voices(int mask) { this->dsp.mute_voices(mask); }
307 234
 	
308
-inline void SNES_SPC::disable_surround( bool disable ) { dsp.disable_surround( disable ); }
309
-
310
-#if !SPC_NO_COPY_STATE_FUNCS
311
-inline bool SNES_SPC::check_kon() { return dsp.check_kon(); }
312
-#endif
235
+inline void SNES_SPC::disable_surround(bool disable) { this->dsp.disable_surround(disable); }
313 236
 
314
-inline void SNES_SPC::spc_allow_time_overflow( bool allow ) { allow_time_overflow = allow; }
237
+inline void SNES_SPC::spc_allow_time_overflow(bool allow) { this->allow_time_overflow = allow; }
315 238
 
316 239
 #endif
Browse code

Import actual code.

Naram Qashat authored on 2013/03/26 02:41:19
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,316 @@
1
+// SNES SPC-700 APU emulator
2
+
3
+// snes_spc 0.9.0
4
+#ifndef SNES_SPC_H
5
+#define SNES_SPC_H
6
+
7
+#include "SPC_DSP.h"
8
+#include "blargg_endian.h"
9
+
10
+#ifdef DEBUGGER
11
+#include "snes9x.h"
12
+#include "display.h"
13
+#include "debug.h"
14
+#endif
15
+
16
+struct SNES_SPC {
17
+public:
18
+	typedef BOOST::uint8_t uint8_t;
19
+	
20
+	// Must be called once before using
21
+	blargg_err_t init();
22
+	
23
+	// Sample pairs generated per second
24
+	enum { sample_rate = 32000 };
25
+	
26
+// Emulator use
27
+	
28
+	// Sets IPL ROM data. Library does not include ROM data. Most SPC music files
29
+	// don't need ROM, but a full emulator must provide this.
30
+	enum { rom_size = 0x40 };
31
+	void init_rom( uint8_t const rom [rom_size] );
32
+
33
+	// Sets destination for output samples
34
+	typedef short sample_t;
35
+	void set_output( sample_t* out, int out_size );
36
+
37
+	// Number of samples written to output since last set
38
+	int sample_count() const;
39
+
40
+	// Resets SPC to power-on state. This resets your output buffer, so you must
41
+	// call set_output() after this.
42
+	void reset();
43
+
44
+	// Emulates pressing reset switch on SNES. This resets your output buffer, so
45
+	// you must call set_output() after this.
46
+	void soft_reset();
47
+
48
+	// 1024000 SPC clocks per second, sample pair every 32 clocks
49
+	typedef int time_t;
50
+	enum { clock_rate = 1024000 };
51
+	enum { clocks_per_sample = 32 };
52
+	
53
+	// Emulated port read/write at specified time
54
+	enum { port_count = 4 };
55
+	int  read_port ( time_t, int port );
56
+	void write_port( time_t, int port, int data );
57
+
58
+	// Runs SPC to end_time and starts a new time frame at 0
59
+	void end_frame( time_t end_time );
60
+	
61
+// Sound control
62
+	
63
+	// Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events).
64
+	// Reduces emulation accuracy.
65
+	enum { voice_count = 8 };
66
+	void mute_voices( int mask );
67
+	
68
+	// If true, prevents channels and global volumes from being phase-negated.
69
+	// Only supported by fast DSP.
70
+	void disable_surround( bool disable = true );
71
+	
72
+	// Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc.
73
+	enum { tempo_unit = 0x100 };
74
+	void set_tempo( int );
75
+
76
+// SPC music files
77
+
78
+	// Loads SPC data into emulator
79
+	enum { spc_min_file_size = 0x10180 };
80
+	enum { spc_file_size     = 0x10200 };
81
+	blargg_err_t load_spc( void const* in, long size );
82
+	
83
+	// Clears echo region. Useful after loading an SPC as many have garbage in echo.
84
+	void clear_echo();
85
+
86
+	// Plays for count samples and write samples to out. Discards samples if out
87
+	// is NULL. Count must be a multiple of 2 since output is stereo.
88
+	blargg_err_t play( int count, sample_t* out );
89
+	
90
+	// Skips count samples. Several times faster than play() when using fast DSP.
91
+	blargg_err_t skip( int count );
92
+	
93
+// State save/load (only available with accurate DSP)
94
+
95
+#if !SPC_NO_COPY_STATE_FUNCS
96
+	// Saves/loads state
97
+	enum { state_size = 68 * 1024L }; // maximum space needed when saving
98
+	typedef SPC_DSP::copy_func_t copy_func_t;
99
+	void copy_state( unsigned char** io, copy_func_t );
100
+	
101
+	// Writes minimal header to spc_out
102
+	static void init_header( void* spc_out );
103
+
104
+	// Saves emulator state as SPC file data. Writes spc_file_size bytes to spc_out.
105
+	// Does not set up SPC header; use init_header() for that.
106
+	void save_spc( void* spc_out );
107
+
108
+	// Returns true if new key-on events occurred since last check. Useful for
109
+	// trimming silence while saving an SPC.
110
+	bool check_kon();
111
+#endif
112
+
113
+//// Snes9x Accessor
114
+
115
+	void	spc_allow_time_overflow( bool );
116
+
117
+	void    dsp_set_spc_snapshot_callback(void (*callback)());
118
+	void    dsp_dump_spc_snapshot();
119
+	void    dsp_set_stereo_switch( int );
120
+	uint8_t dsp_reg_value( int, int );
121
+	int     dsp_envx_value( int );
122
+
123
+//// Snes9x Debugger
124
+
125
+#ifdef DEBUGGER
126
+	void	debug_toggle_trace();
127
+	bool    debug_is_enabled();
128
+	void	debug_do_trace( int, int, int, uint8_t const *, uint8_t *, int, int, int, int );
129
+	void	debug_op_print( char *, int, int, int, uint8_t const *, uint8_t *, int, int, int, int );
130
+	void	debug_io_print( char * );
131
+#endif
132
+
133
+public:
134
+	BLARGG_DISABLE_NOTHROW
135
+	
136
+	typedef BOOST::uint16_t uint16_t;
137
+	
138
+	// Time relative to m_spc_time. Speeds up code a bit by eliminating need to
139
+	// constantly add m_spc_time to time from CPU. CPU uses time that ends at
140
+	// 0 to eliminate reloading end time every instruction. It pays off.
141
+	typedef int rel_time_t;
142
+	
143
+	struct Timer
144
+	{
145
+		rel_time_t next_time; // time of next event
146
+		int prescaler;
147
+		int period;
148
+		int divider;
149
+		int enabled;
150
+		int counter;
151
+	};
152
+	enum { reg_count = 0x10 };
153
+	enum { timer_count = 3 };
154
+	enum { extra_size = SPC_DSP::extra_size };
155
+	
156
+	enum { signature_size = 35 };
157
+	
158
+private:
159
+	SPC_DSP dsp;
160
+	
161
+	#if SPC_LESS_ACCURATE
162
+		static signed char const reg_times_ [256];
163
+		signed char reg_times [256];
164
+	#endif
165
+	
166
+	struct state_t
167
+	{
168
+		Timer timers [timer_count];
169
+		
170
+		uint8_t smp_regs [2] [reg_count];
171
+		
172
+		struct
173
+		{
174
+			int pc;
175
+			int a;
176
+			int x;
177
+			int y;
178
+			int psw;
179
+			int sp;
180
+		} cpu_regs;
181
+		
182
+		rel_time_t  dsp_time;
183
+		time_t      spc_time;
184
+		bool        echo_accessed;
185
+		
186
+		int         tempo;
187
+		int         skipped_kon;
188
+		int         skipped_koff;
189
+		const char* cpu_error;
190
+		
191
+		int         extra_clocks;
192
+		sample_t*   buf_begin;
193
+		sample_t const* buf_end;
194
+		sample_t*   extra_pos;
195
+		sample_t    extra_buf [extra_size];
196
+		
197
+		int         rom_enabled;
198
+		uint8_t     rom    [rom_size];
199
+		uint8_t     hi_ram [rom_size];
200
+		
201
+		unsigned char cycle_table [256];
202
+		
203
+		struct
204
+		{
205
+			// padding to neutralize address overflow
206
+			union {
207
+				uint8_t padding1 [0x100];
208
+				uint16_t align; // makes compiler align data for 16-bit access
209
+			} padding1 [1];
210
+			uint8_t ram      [0x10000];
211
+			uint8_t padding2 [0x100];
212
+		} ram;
213
+	};
214
+	state_t m;
215
+	
216
+	enum { rom_addr = 0xFFC0 };
217
+	
218
+	enum { skipping_time = 127 };
219
+	
220
+	// Value that padding should be filled with
221
+	enum { cpu_pad_fill = 0xFF };
222
+	
223
+	enum {
224
+        r_test     = 0x0, r_control  = 0x1,
225
+        r_dspaddr  = 0x2, r_dspdata  = 0x3,
226
+        r_cpuio0   = 0x4, r_cpuio1   = 0x5,
227
+        r_cpuio2   = 0x6, r_cpuio3   = 0x7,
228
+        r_f8       = 0x8, r_f9       = 0x9,
229
+        r_t0target = 0xA, r_t1target = 0xB, r_t2target = 0xC,
230
+        r_t0out    = 0xD, r_t1out    = 0xE, r_t2out    = 0xF
231
+	};
232
+	
233
+	void timers_loaded();
234
+	void enable_rom( int enable );
235
+	void reset_buf();
236
+	void save_extra();
237
+	void load_regs( uint8_t const in [reg_count] );
238
+	void ram_loaded();
239
+	void regs_loaded();
240
+	void reset_time_regs();
241
+	void reset_common( int timer_counter_init );
242
+	
243
+	Timer* run_timer_      ( Timer* t, rel_time_t );
244
+	Timer* run_timer       ( Timer* t, rel_time_t );
245
+	int dsp_read           ( rel_time_t );
246
+	void dsp_write         ( int data, rel_time_t );
247
+	void cpu_write_smp_reg_( int data, rel_time_t, int addr );
248
+	void cpu_write_smp_reg ( int data, rel_time_t, int addr );
249
+	void cpu_write_high    ( int data, int i, rel_time_t );
250
+	void cpu_write         ( int data, int addr, rel_time_t );
251
+	int cpu_read_smp_reg   ( int i, rel_time_t );
252
+	int cpu_read           ( int addr, rel_time_t );
253
+	unsigned CPU_mem_bit   ( uint8_t const* pc, rel_time_t );
254
+	
255
+	bool check_echo_access ( int addr );
256
+	uint8_t* run_until_( time_t end_time );
257
+	
258
+	struct spc_file_t
259
+	{
260
+		char    signature [signature_size];
261
+		uint8_t has_id666;
262
+		uint8_t version;
263
+		uint8_t pcl, pch;
264
+		uint8_t a;
265
+		uint8_t x;
266
+		uint8_t y;
267
+		uint8_t psw;
268
+		uint8_t sp;
269
+		char    text [212];
270
+		uint8_t ram [0x10000];
271
+		uint8_t dsp [128];
272
+		uint8_t unused [0x40];
273
+		uint8_t ipl_rom [0x40];
274
+	};
275
+
276
+	static char const signature [signature_size + 1];
277
+	
278
+	void save_regs( uint8_t out [reg_count] );
279
+
280
+// Snes9x timing hack
281
+	bool allow_time_overflow;
282
+// Snes9x debugger
283
+#ifdef DEBUGGER
284
+	FILE *apu_trace;
285
+	bool debug_trace;
286
+#endif
287
+};
288
+
289
+#include <assert.h>
290
+
291
+inline int SNES_SPC::sample_count() const { return (m.extra_clocks >> 5) * 2; }
292
+
293
+inline int SNES_SPC::read_port( time_t t, int port )
294
+{
295
+	assert( (unsigned) port < port_count );
296
+	return run_until_( t ) [port];
297
+}
298
+
299
+inline void SNES_SPC::write_port( time_t t, int port, int data )
300
+{
301
+	assert( (unsigned) port < port_count );
302
+	run_until_( t ) [0x10 + port] = data;
303
+	m.ram.ram [0xF4 + port] = data;
304
+}
305
+
306
+inline void SNES_SPC::mute_voices( int mask ) { dsp.mute_voices( mask ); }
307
+	
308
+inline void SNES_SPC::disable_surround( bool disable ) { dsp.disable_surround( disable ); }
309
+
310
+#if !SPC_NO_COPY_STATE_FUNCS
311
+inline bool SNES_SPC::check_kon() { return dsp.check_kon(); }
312
+#endif
313
+
314
+inline void SNES_SPC::spc_allow_time_overflow( bool allow ) { allow_time_overflow = allow; }
315
+
316
+#endif