diff options
Diffstat (limited to 'apps/codecs/libgme/nes_apu.h')
-rw-r--r-- | apps/codecs/libgme/nes_apu.h | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/apps/codecs/libgme/nes_apu.h b/apps/codecs/libgme/nes_apu.h new file mode 100644 index 0000000000..6a2c2805e1 --- /dev/null +++ b/apps/codecs/libgme/nes_apu.h | |||
@@ -0,0 +1,134 @@ | |||
1 | // NES 2A03 APU sound chip emulator | ||
2 | |||
3 | // Nes_Snd_Emu 0.1.8 | ||
4 | #ifndef NES_APU_H | ||
5 | #define NES_APU_H | ||
6 | |||
7 | #include "blargg_common.h" | ||
8 | #include "nes_oscs.h" | ||
9 | |||
10 | enum { apu_status_addr = 0x4015 }; | ||
11 | enum { apu_osc_count = 5 }; | ||
12 | enum { apu_no_irq = INT_MAX / 2 + 1 }; | ||
13 | enum { apu_irq_waiting = 0 }; | ||
14 | |||
15 | enum { apu_io_addr = 0x4000 }; | ||
16 | enum { apu_io_size = 0x18 }; | ||
17 | |||
18 | struct apu_state_t; | ||
19 | |||
20 | struct Nes_Apu { | ||
21 | nes_time_t last_dmc_time; | ||
22 | int osc_enables; | ||
23 | |||
24 | struct Nes_Osc* oscs [apu_osc_count]; | ||
25 | struct Nes_Square square1; | ||
26 | struct Nes_Square square2; | ||
27 | struct Nes_Noise noise; | ||
28 | struct Nes_Triangle triangle; | ||
29 | struct Nes_Dmc dmc; | ||
30 | |||
31 | double tempo_; | ||
32 | nes_time_t last_time; // has been run until this time in current frame | ||
33 | nes_time_t earliest_irq_; | ||
34 | nes_time_t next_irq; | ||
35 | int frame_period; | ||
36 | int frame_delay; // cycles until frame counter runs next | ||
37 | int frame; // current frame (0-3) | ||
38 | int frame_mode; | ||
39 | bool irq_flag; | ||
40 | |||
41 | void (*irq_notifier_)( void* user_data ); | ||
42 | void* irq_data; | ||
43 | |||
44 | Synth square_synth; // shared by squares | ||
45 | }; | ||
46 | |||
47 | // Init Nes apu | ||
48 | void Apu_init( struct Nes_Apu* this ); | ||
49 | |||
50 | // Set buffer to generate all sound into, or disable sound if NULL | ||
51 | void Apu_output( struct Nes_Apu* this, struct Blip_Buffer* ) ICODE_ATTR; | ||
52 | |||
53 | // All time values are the number of cpu clock cycles relative to the | ||
54 | // beginning of the current time frame. Before resetting the cpu clock | ||
55 | // count, call end_frame( last_cpu_time ). | ||
56 | |||
57 | // Write to register (0x4000-0x4017, except 0x4014 and 0x4016) | ||
58 | void Apu_write_register( struct Nes_Apu* this, nes_time_t, addr_t, int data ) ICODE_ATTR; | ||
59 | |||
60 | // Read from status register at 0x4015 | ||
61 | int Apu_read_status( struct Nes_Apu* this, nes_time_t ) ICODE_ATTR; | ||
62 | |||
63 | // Run all oscillators up to specified time, end current time frame, then | ||
64 | // start a new time frame at time 0. Time frames have no effect on emulation | ||
65 | // and each can be whatever length is convenient. | ||
66 | void Apu_end_frame( struct Nes_Apu* this, nes_time_t ) ICODE_ATTR; | ||
67 | |||
68 | // Additional optional features (can be ignored without any problem) | ||
69 | |||
70 | // Reset internal frame counter, registers, and all oscillators. | ||
71 | // Use PAL timing if pal_timing is true, otherwise use NTSC timing. | ||
72 | // Set the DMC oscillator's initial DAC value to initial_dmc_dac without | ||
73 | // any audible click. | ||
74 | void Apu_reset( struct Nes_Apu* this, bool pal_mode, int initial_dmc_dac ); | ||
75 | |||
76 | // Adjust frame period | ||
77 | void Apu_set_tempo( struct Nes_Apu* this, double ); | ||
78 | |||
79 | // Set overall volume (default is 1.0) | ||
80 | void Apu_volume( struct Nes_Apu* this, double ); | ||
81 | |||
82 | // Run DMC until specified time, so that any DMC memory reads can be | ||
83 | // accounted for (i.e. inserting cpu wait states). | ||
84 | void Apu_run_until( struct Nes_Apu* this, nes_time_t ) ICODE_ATTR; | ||
85 | |||
86 | // Set sound output of specific oscillator to buffer. If buffer is NULL, | ||
87 | // the specified oscillator is muted and emulation accuracy is reduced. | ||
88 | // The oscillators are indexed as follows: 0) Square 1, 1) Square 2, | ||
89 | // 2) Triangle, 3) Noise, 4) DMC. | ||
90 | static inline void Apu_osc_output( struct Nes_Apu* this, int osc, struct Blip_Buffer* buf ) | ||
91 | { | ||
92 | assert( (unsigned) osc < apu_osc_count ); | ||
93 | this->oscs [osc]->output = buf; | ||
94 | } | ||
95 | |||
96 | // Set memory reader callback used by DMC oscillator to fetch samples. | ||
97 | // When callback is invoked, 'user_data' is passed unchanged as the | ||
98 | // first parameter. | ||
99 | static inline void Apu_dmc_reader( struct Nes_Apu* this, int (*func)( void*, addr_t ), void* user_data ) | ||
100 | { | ||
101 | this->dmc.prg_reader_data = user_data; | ||
102 | this->dmc.prg_reader = func; | ||
103 | } | ||
104 | |||
105 | // Set IRQ time callback that is invoked when the time of earliest IRQ | ||
106 | // may have changed, or NULL to disable. When callback is invoked, | ||
107 | // 'user_data' is passed unchanged as the first parameter. | ||
108 | static inline void Apu_irq_notifier( struct Nes_Apu* this, void (*func)( void* user_data ), void* user_data ) | ||
109 | { | ||
110 | this->irq_notifier_ = func; | ||
111 | this->irq_data = user_data; | ||
112 | } | ||
113 | |||
114 | // Count number of DMC reads that would occur if 'run_until( t )' were executed. | ||
115 | // If last_read is not NULL, set *last_read to the earliest time that | ||
116 | // 'count_dmc_reads( time )' would result in the same result. | ||
117 | static inline int Apu_count_dmc_reads( struct Nes_Apu* this, nes_time_t time, nes_time_t* last_read ) | ||
118 | { | ||
119 | return Dmc_count_reads( &this->dmc, time, last_read ); | ||
120 | } | ||
121 | |||
122 | static inline nes_time_t Dmc_next_read_time( struct Nes_Dmc* this ) | ||
123 | { | ||
124 | if ( this->osc.length_counter == 0 ) | ||
125 | return apu_no_irq; // not reading | ||
126 | |||
127 | return this->apu->last_dmc_time + this->osc.delay + (long) (this->bits_remain - 1) * this->period; | ||
128 | } | ||
129 | |||
130 | // Time when next DMC memory read will occur | ||
131 | static inline nes_time_t Apu_next_dmc_read_time( struct Nes_Apu* this ) { return Dmc_next_read_time( &this->dmc ); } | ||
132 | void Apu_irq_changed( struct Nes_Apu* this ) ICODE_ATTR; | ||
133 | |||
134 | #endif | ||