1
2// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/libs/
3
4#include "Nes_Namco.h"
5
6/* Copyright (C) 2003-2005 Shay Green. This module is free software; you
7can redistribute it and/or modify it under the terms of the GNU Lesser
8General Public License as published by the Free Software Foundation; either
9version 2.1 of the License, or (at your option) any later version. This
10module is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
13more details. You should have received a copy of the GNU Lesser General
14Public License along with this module; if not, write to the Free Software
15Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
17#include BLARGG_SOURCE_BEGIN
18
19Nes_Namco::Nes_Namco()
20{
21 output( NULL );
22 volume( 1.0 );
23 reset();
24}
25
26Nes_Namco::~Nes_Namco()
27{
28}
29
30void Nes_Namco::reset()
31{
32 addr_reg = 0;
33
34 int i;
35 for ( i = 0; i < reg_count; i++ )
36 reg [i] = 0;
37
38 for ( i = 0; i < osc_count; i++ )
39 {
40 Namco_Osc& osc = oscs [i];
41 osc.delay = 0;
42 osc.last_amp = 0;
43 osc.wave_pos = 0;
44 }
45}
46
47void Nes_Namco::output( Blip_Buffer* buf )
48{
49 for ( int i = 0; i < osc_count; i++ )
50 osc_output( i, buf );
51}
52
53BOOST::uint8_t& Nes_Namco::access()
54{
55 int addr = addr_reg & 0x7f;
56 if ( addr_reg & 0x80 )
57 addr_reg = (addr + 1) | 0x80;
58 return reg [addr];
59}
60
61/*
62void Nes_Namco::reflect_state( Tagged_Data& data )
63{
64 reflect_int16( data, 'ADDR', &addr_reg );
65
66 static const char hex [17] = "0123456789ABCDEF";
67 int i;
68 for ( i = 0; i < reg_count; i++ )
69 reflect_int16( data, 'RG\0\0' + hex [i >> 4] * 0x100 + hex [i & 15], &reg [i] );
70
71 for ( i = 0; i < osc_count; i++ )
72 {
73 reflect_int32( data, 'DLY0' + i, &oscs [i].delay );
74 reflect_int16( data, 'POS0' + i, &oscs [i].wave_pos );
75 }
76}
77*/
78
79void Nes_Namco::end_frame( cpu_time_t time )
80{
81 if ( time > last_time )
82 run_until( time );
83
84 last_time -= time;
85 assert( last_time >= 0 );
86}
87
88#include BLARGG_ENABLE_OPTIMIZER
89
90void Nes_Namco::run_until( cpu_time_t nes_end_time )
91{
92 int active_oscs = ((reg [0x7f] >> 4) & 7) + 1;
93 for ( int i = osc_count - active_oscs; i < osc_count; i++ )
94 {
95 Namco_Osc& osc = oscs [i];
96 Blip_Buffer* output = osc.output;
97 if ( !output )
98 continue;
99
100 Blip_Buffer::resampled_time_t time =
101 output->resampled_time( last_time ) + osc.delay;
102 Blip_Buffer::resampled_time_t end_time = output->resampled_time( nes_end_time );
103 osc.delay = 0;
104 if ( time < end_time )
105 {
106 const BOOST::uint8_t* osc_reg = &reg [i * 8 + 0x40];
107 if ( !(osc_reg [4] & 0xe0) )
108 continue;
109
110 int volume = osc_reg [7] & 15;
111 if ( !volume )
112 continue;
113
114 long freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0];
115 if ( !freq )
116 continue;
117 Blip_Buffer::resampled_time_t period =
118 output->resampled_duration( 983040 ) / freq * active_oscs;
119
120 int wave_size = (8 - ((osc_reg [4] >> 2) & 7)) * 4;
121 if ( !wave_size )
122 continue;
123
124 int last_amp = osc.last_amp;
125 int wave_pos = osc.wave_pos;
126
127 do
128 {
129 // read wave sample
130 int addr = wave_pos + osc_reg [6];
131 int sample = reg [addr >> 1];
132 wave_pos++;
133 if ( addr & 1 )
134 sample >>= 4;
135 sample = (sample & 15) * volume;
136
137 // output impulse if amplitude changed
138 int delta = sample - last_amp;
139 if ( delta )
140 {
141 last_amp = sample;
142 synth.offset_resampled( time, delta, output );
143 }
144
145 // next sample
146 time += period;
147 if ( wave_pos >= wave_size )
148 wave_pos = 0;
149 }
150 while ( time < end_time );
151
152 osc.wave_pos = wave_pos;
153 osc.last_amp = last_amp;
154 }
155 osc.delay = time - end_time;
156 }
157
158 last_time = nes_end_time;
159}
160
161