summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libgme/nes_fds_apu.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libgme/nes_fds_apu.h')
-rw-r--r--lib/rbcodec/codecs/libgme/nes_fds_apu.h116
1 files changed, 116 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libgme/nes_fds_apu.h b/lib/rbcodec/codecs/libgme/nes_fds_apu.h
new file mode 100644
index 0000000000..8dac3b721a
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_fds_apu.h
@@ -0,0 +1,116 @@
1// NES FDS sound chip emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef NES_FDS_APU_H
5#define NES_FDS_APU_H
6
7#include "blargg_common.h"
8#include "blip_buffer.h"
9
10enum { lfo_base_tempo = 8 };
11enum { fds_osc_count = 1 };
12
13enum { fds_io_addr = 0x4040 };
14enum { fds_io_size = 0x53 };
15
16enum { fds_wave_size = 0x40 };
17enum { fds_master_vol_max = 10 };
18enum { fds_vol_max = 0x20 };
19enum { fds_wave_sample_max = 0x3F };
20
21struct Nes_Fds_Apu {
22 unsigned char regs_ [fds_io_size];// last written value to registers
23 int lfo_tempo; // normally 8; adjusted by set_tempo()
24
25 int env_delay;
26 int env_speed;
27 int env_gain;
28
29 int sweep_delay;
30 int sweep_speed;
31 int sweep_gain;
32
33 int wave_pos;
34 int last_amp;
35 blip_time_t wave_fract;
36
37 int mod_fract;
38 int mod_pos;
39 int mod_write_pos;
40 unsigned char mod_wave [fds_wave_size];
41
42 // synthesis
43 blip_time_t last_time;
44 struct Blip_Buffer* output_;
45 struct Blip_Synth synth;
46};
47
48// init
49void Fds_init( struct Nes_Fds_Apu* this );
50// setup
51void Fds_set_tempo( struct Nes_Fds_Apu* this, int t );
52
53// emulation
54void Fds_reset( struct Nes_Fds_Apu* this );
55
56static inline void Fds_volume( struct Nes_Fds_Apu* this, int v )
57{
58 Synth_volume( &this->synth, (v*14) / 100 / fds_master_vol_max / fds_vol_max / fds_wave_sample_max );
59}
60
61static inline void Fds_set_output( struct Nes_Fds_Apu* this, int i, struct Blip_Buffer* b )
62{
63#if defined(ROCKBOX)
64 (void) i;
65#endif
66
67 assert( (unsigned) i < fds_osc_count );
68 this->output_ = b;
69}
70
71void Fds_run_until( struct Nes_Fds_Apu* this, blip_time_t );
72static inline void Fds_end_frame( struct Nes_Fds_Apu* this, blip_time_t end_time )
73{
74 if ( end_time > this->last_time )
75 Fds_run_until( this, end_time );
76 this->last_time -= end_time;
77 assert( this->last_time >= 0 );
78}
79
80void Fds_write_( struct Nes_Fds_Apu* this, unsigned addr, int data );
81static inline void Fds_write( struct Nes_Fds_Apu* this, blip_time_t time, unsigned addr, int data )
82{
83 Fds_run_until( this, time );
84 Fds_write_( this, addr, data );
85}
86
87static inline int Fds_read( struct Nes_Fds_Apu* this, blip_time_t time, unsigned addr )
88{
89 Fds_run_until( this, time );
90
91 int result = 0xFF;
92 switch ( addr )
93 {
94 case 0x4090:
95 result = this->env_gain;
96 break;
97
98 case 0x4092:
99 result = this->sweep_gain;
100 break;
101
102 default:
103 {
104 unsigned i = addr - fds_io_addr;
105 if ( i < fds_wave_size )
106 result = this->regs_ [i];
107 }
108 }
109
110 return result | 0x40;
111}
112
113// allow access to registers by absolute address (i.e. 0x4080)
114static inline unsigned char* regs_nes( struct Nes_Fds_Apu* this, unsigned addr ) { return &this->regs_ [addr - fds_io_addr]; }
115
116#endif