summaryrefslogtreecommitdiff
path: root/apps/codecs/libgme/nes_oscs.h
blob: 8d7f4ae817b352e6da981df4ff50571fdba5b959 (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
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
// Private oscillators used by Nes_Apu

// Nes_Snd_Emu 0.1.8
#ifndef NES_OSCS_H
#define NES_OSCS_H

#include "blargg_common.h"
#include "blip_buffer.h"
#include "nes_cpu.h"

struct Nes_Apu;

struct Nes_Osc
{
	unsigned char regs [4];
	bool reg_written [4];
	struct Blip_Buffer* output;
	int length_counter;// length counter (0 if unused by oscillator)
	int delay;      // delay until next (potential) transition
	int last_amp;   // last amplitude oscillator was outputting
};

void Osc_clock_length( struct Nes_Osc* this, int halt_mask );
static inline int Osc_period( struct Nes_Osc* this ) 
{
	return (this->regs [3] & 7) * 0x100 + (this->regs [2] & 0xFF);
}

static inline void Osc_reset( struct Nes_Osc* this ) 
{
	this->delay = 0;
	this->last_amp = 0;
}

static inline int Osc_update_amp( struct Nes_Osc* this, int amp ) 
{
	int delta = amp - this->last_amp;
	this->last_amp = amp;
	return delta;
}

// Nes_Square

enum { negate_flag = 0x08 };
enum { shift_mask = 0x07 };
enum { square_phase_range = 8 };

typedef struct Blip_Synth Synth;
	
struct Nes_Square
{
	struct Nes_Osc osc;
	int envelope;
	int env_delay;
	int phase;
	int sweep_delay;
		
	Synth* synth; // shared between squares
};

static inline void Square_set_synth( struct Nes_Square* this, Synth* s ) { this->synth = s; }
	
void Square_clock_sweep( struct Nes_Square* this, int adjust );
void Square_run( struct Nes_Square* this, nes_time_t, nes_time_t );

static inline void Square_reset( struct Nes_Square* this ) 
{
	this->sweep_delay = 0;
	this->envelope = 0;
	this->env_delay = 0;
	Osc_reset( &this->osc );
}

void Square_clock_envelope( struct Nes_Square* this );
int Square_volume( struct Nes_Square* this );
		
// Nes_Triangle

enum { Triangle_phase_range = 16 };
	
struct Nes_Triangle
{
	struct Nes_Osc osc;
		
	int phase;
	int linear_counter;
	struct Blip_Synth synth;
};

void Triangle_run( struct Nes_Triangle* this, nes_time_t, nes_time_t );
void Triangle_clock_linear_counter( struct Nes_Triangle* this );

static inline void Triangle_reset( struct Nes_Triangle* this )
{
	this->linear_counter = 0;
	this->phase = 1;
	Osc_reset( &this->osc );
}

// Nes_Noise
struct Nes_Noise
{
	struct Nes_Osc osc;
	
	int envelope;
	int env_delay;
	int noise;
	struct Blip_Synth synth;
};

void Noise_clock_envelope( struct Nes_Noise* this );
int Noise_volume( struct Nes_Noise* this );
void Noise_run( struct Nes_Noise* this, nes_time_t, nes_time_t );

static inline void Noise_reset( struct Nes_Noise* this )
{
	this->noise = 1 << 14;
	this->envelope = 0;
	this->env_delay = 0;
	Osc_reset( &this->osc );
}

// Nes_Dmc

enum { loop_flag = 0x40 };
	
struct Nes_Dmc
{
	struct Nes_Osc osc;
		
	int address;    // address of next byte to read
	int period;
	int buf;
	int bits_remain;
	int bits;
	bool buf_full;
	bool silence;
	
	int dac;
	
	nes_time_t next_irq;
	bool irq_enabled;
	bool irq_flag;
	bool pal_mode;
	bool nonlinear;
	
 	int (*prg_reader)( void*, addr_t ); // needs to be initialized to prg read function
	void* prg_reader_data;
	
	struct Nes_Apu* apu;
	
	struct Blip_Synth synth;
};

void Dmc_start( struct Nes_Dmc* this );
void Dmc_write_register( struct Nes_Dmc* this, int, int );
void Dmc_run( struct Nes_Dmc* this, nes_time_t, nes_time_t );
void Dmc_recalc_irq( struct Nes_Dmc* this );
void Dmc_fill_buffer( struct Nes_Dmc* this );
void Dmc_reload_sample( struct Nes_Dmc* this );
void Dmc_reset( struct Nes_Dmc* this );

int Dmc_count_reads( struct Nes_Dmc* this, nes_time_t, nes_time_t* );

#endif