1 // Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
2 
3 #include "Nsf_Emu.h"
4 
5 #include "blargg_endian.h"
6 #include <string.h>
7 #include <stdio.h>
8 
9 #if !NSF_EMU_APU_ONLY
10 	#include "Nes_Namco_Apu.h"
11 	#include "Nes_Vrc6_Apu.h"
12 	#include "Nes_Fme7_Apu.h"
13 #endif
14 
15 /* Copyright (C) 2003-2006 Shay Green. This module is free software; you
16 can redistribute it and/or modify it under the terms of the GNU Lesser
17 General Public License as published by the Free Software Foundation; either
18 version 2.1 of the License, or (at your option) any later version. This
19 module is distributed in the hope that it will be useful, but WITHOUT ANY
20 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
22 details. You should have received a copy of the GNU Lesser General Public
23 License along with this module; if not, write to the Free Software Foundation,
24 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
25 
26 #include "blargg_source.h"
27 
28 int const vrc6_flag  = 0x01;
29 int const namco_flag = 0x10;
30 int const fme7_flag  = 0x20;
31 
32 long const clock_divisor = 12;
33 
34 Nsf_Emu::equalizer_t const Nsf_Emu::nes_eq     =
35 	Music_Emu::make_equalizer( -1.0, 80 );
36 Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq =
37 	Music_Emu::make_equalizer( -15.0, 80 );
38 
pcm_read(void * emu,nes_addr_t addr)39 int Nsf_Emu::pcm_read( void* emu, nes_addr_t addr )
40 {
41 	return *((Nsf_Emu*) emu)->cpu::get_code( addr );
42 }
43 
Nsf_Emu()44 Nsf_Emu::Nsf_Emu()
45 {
46 	vrc6  = 0;
47 	namco = 0;
48 	fme7  = 0;
49 
50 	set_type( gme_nsf_type );
51 	set_silence_lookahead( 6 );
52 	apu.dmc_reader( pcm_read, this );
53 	Music_Emu::set_equalizer( nes_eq );
54 	set_gain( 1.4 );
55 	memset( unmapped_code, Nes_Cpu::bad_opcode, sizeof unmapped_code );
56 }
57 
~Nsf_Emu()58 Nsf_Emu::~Nsf_Emu() { unload(); }
59 
unload()60 void Nsf_Emu::unload()
61 {
62 	#if !NSF_EMU_APU_ONLY
63 	{
64 		delete vrc6;
65 		vrc6  = 0;
66 
67 		delete namco;
68 		namco = 0;
69 
70 		delete fme7;
71 		fme7  = 0;
72 	}
73 	#endif
74 
75 	rom.clear();
76 	Music_Emu::unload();
77 }
78 
79 // Track info
80 
copy_nsf_fields(Nsf_Emu::header_t const & h,track_info_t * out)81 static void copy_nsf_fields( Nsf_Emu::header_t const& h, track_info_t* out )
82 {
83 	GME_COPY_FIELD( h, out, game );
84 	GME_COPY_FIELD( h, out, author );
85 	GME_COPY_FIELD( h, out, copyright );
86 	if ( h.chip_flags )
87 		Gme_File::copy_field_( out->system, "Famicom" );
88 }
89 
track_info_(track_info_t * out,int) const90 blargg_err_t Nsf_Emu::track_info_( track_info_t* out, int ) const
91 {
92 	copy_nsf_fields( header_, out );
93 	return 0;
94 }
95 
check_nsf_header(void const * header)96 static blargg_err_t check_nsf_header( void const* header )
97 {
98 	if ( memcmp( header, "NESM\x1A", 5 ) )
99 		return gme_wrong_file_type;
100 	return 0;
101 }
102 
103 struct Nsf_File : Gme_Info_
104 {
105 	Nsf_Emu::header_t h;
106 
Nsf_FileNsf_File107 	Nsf_File() { set_type( gme_nsf_type ); }
108 
load_Nsf_File109 	blargg_err_t load_( Data_Reader& in )
110 	{
111 		blargg_err_t err = in.read( &h, Nsf_Emu::header_size );
112 		if ( err )
113 			return (err == in.eof_error ? gme_wrong_file_type : err);
114 
115 		if ( h.chip_flags & ~(namco_flag | vrc6_flag | fme7_flag) )
116 			set_warning( "Uses unsupported audio expansion hardware" );
117 
118 		set_track_count( h.track_count );
119 		return check_nsf_header( &h );
120 	}
121 
track_info_Nsf_File122 	blargg_err_t track_info_( track_info_t* out, int ) const
123 	{
124 		copy_nsf_fields( h, out );
125 		return 0;
126 	}
127 };
128 
new_nsf_emu()129 static Music_Emu* new_nsf_emu () { return BLARGG_NEW Nsf_Emu ; }
new_nsf_file()130 static Music_Emu* new_nsf_file() { return BLARGG_NEW Nsf_File; }
131 
132 static gme_type_t_ const gme_nsf_type_ = { "Nintendo NES", 0, &new_nsf_emu, &new_nsf_file, "NSF", 1 };
133 gme_type_t const gme_nsf_type = &gme_nsf_type_;
134 
135 
136 // Setup
137 
set_tempo_(double t)138 void Nsf_Emu::set_tempo_( double t )
139 {
140 	unsigned playback_rate = get_le16( header_.ntsc_speed );
141 	unsigned standard_rate = 0x411A;
142 	clock_rate_ = 1789772.72727;
143 	play_period = 262 * 341L * 4 - 2; // two fewer PPU clocks every four frames
144 
145 	if ( pal_only )
146 	{
147 		play_period   = 33247 * clock_divisor;
148 		clock_rate_   = 1662607.125;
149 		standard_rate = 0x4E20;
150 		playback_rate = get_le16( header_.pal_speed );
151 	}
152 
153 	if ( !playback_rate )
154 		playback_rate = standard_rate;
155 
156 	if ( playback_rate != standard_rate || t != 1.0 )
157 		play_period = long (playback_rate * clock_rate_ / (1000000.0 / clock_divisor * t));
158 
159 	apu.set_tempo( t );
160 }
161 
init_sound()162 blargg_err_t Nsf_Emu::init_sound()
163 {
164 	if ( header_.chip_flags & ~(namco_flag | vrc6_flag | fme7_flag) )
165 		set_warning( "Uses unsupported audio expansion hardware" );
166 
167 	{
168 		#define APU_NAMES "Square 1", "Square 2", "Triangle", "Noise", "DMC"
169 
170 		int const count = Nes_Apu::osc_count;
171 		static const char* const apu_names [count] = { APU_NAMES };
172 		set_voice_count( count );
173 		set_voice_names( apu_names );
174 
175 	}
176 
177 	static int const types [] = {
178 		wave_type  | 1, wave_type  | 2, wave_type | 0,
179 		noise_type | 0, mixed_type | 1,
180 		wave_type  | 3, wave_type  | 4, wave_type | 5,
181 		wave_type  | 6, wave_type  | 7, wave_type | 8, wave_type | 9,
182 		wave_type  |10, wave_type  |11, wave_type |12, wave_type |13
183 	};
184 	set_voice_types( types ); // common to all sound chip configurations
185 
186 	double adjusted_gain = gain();
187 
188 	#if NSF_EMU_APU_ONLY
189 	{
190 		if ( header_.chip_flags )
191 			set_warning( "Uses unsupported audio expansion hardware" );
192 	}
193 	#else
194 	{
195 		if ( header_.chip_flags & (namco_flag | vrc6_flag | fme7_flag) )
196 			set_voice_count( Nes_Apu::osc_count + 3 );
197 
198 		if ( header_.chip_flags & namco_flag )
199 		{
200 			namco = BLARGG_NEW Nes_Namco_Apu;
201 			CHECK_ALLOC( namco );
202 			adjusted_gain *= 0.75;
203 
204 			int const count = Nes_Apu::osc_count + Nes_Namco_Apu::osc_count;
205 			static const char* const names [count] = {
206 				APU_NAMES,
207 				"Wave 1", "Wave 2", "Wave 3", "Wave 4",
208 				"Wave 5", "Wave 6", "Wave 7", "Wave 8"
209 			};
210 			set_voice_count( count );
211 			set_voice_names( names );
212 		}
213 
214 		if ( header_.chip_flags & vrc6_flag )
215 		{
216 			vrc6 = BLARGG_NEW Nes_Vrc6_Apu;
217 			CHECK_ALLOC( vrc6 );
218 			adjusted_gain *= 0.75;
219 
220 			{
221 				int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count;
222 				static const char* const names [count] = {
223 					APU_NAMES,
224 					"Saw Wave", "Square 3", "Square 4"
225 				};
226 				set_voice_count( count );
227 				set_voice_names( names );
228 			}
229 
230 			if ( header_.chip_flags & namco_flag )
231 			{
232 				int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count +
233 						Nes_Namco_Apu::osc_count;
234 				static const char* const names [count] = {
235 					APU_NAMES,
236 					"Saw Wave", "Square 3", "Square 4",
237 					"Wave 1", "Wave 2", "Wave 3", "Wave 4",
238 					"Wave 5", "Wave 6", "Wave 7", "Wave 8"
239 				};
240 				set_voice_count( count );
241 				set_voice_names( names );
242 			}
243 		}
244 
245 		if ( header_.chip_flags & fme7_flag )
246 		{
247 			fme7 = BLARGG_NEW Nes_Fme7_Apu;
248 			CHECK_ALLOC( fme7 );
249 			adjusted_gain *= 0.75;
250 
251 			int const count = Nes_Apu::osc_count + Nes_Fme7_Apu::osc_count;
252 			static const char* const names [count] = {
253 				APU_NAMES,
254 				"Square 3", "Square 4", "Square 5"
255 			};
256 			set_voice_count( count );
257 			set_voice_names( names );
258 		}
259 
260 		if ( namco ) namco->volume( adjusted_gain );
261 		if ( vrc6  ) vrc6 ->volume( adjusted_gain );
262 		if ( fme7  ) fme7 ->volume( adjusted_gain );
263 	}
264 	#endif
265 
266 	apu.volume( adjusted_gain );
267 
268 	return 0;
269 }
270 
load_(Data_Reader & in)271 blargg_err_t Nsf_Emu::load_( Data_Reader& in )
272 {
273 	assert( offsetof (header_t,unused [4]) == header_size );
274 	RETURN_ERR( rom.load( in, header_size, &header_, 0 ) );
275 
276 	set_track_count( header_.track_count );
277 	RETURN_ERR( check_nsf_header( &header_ ) );
278 
279 	if ( header_.vers != 1 )
280 		set_warning( "Unknown file version" );
281 
282 	// sound and memory
283 	blargg_err_t err = init_sound();
284 	if ( err )
285 		return err;
286 
287 	// set up data
288 	nes_addr_t load_addr = get_le16( header_.load_addr );
289 	init_addr = get_le16( header_.init_addr );
290 	play_addr = get_le16( header_.play_addr );
291 	if ( !load_addr ) load_addr = rom_begin;
292 	if ( !init_addr ) init_addr = rom_begin;
293 	if ( !play_addr ) play_addr = rom_begin;
294 	if ( load_addr < rom_begin || init_addr < rom_begin )
295 	{
296 		const char* w = warning();
297 		if ( !w )
298 			w = "Corrupt file (invalid load/init/play address)";
299 		return w;
300 	}
301 
302 	rom.set_addr( load_addr % bank_size );
303 	int total_banks = rom.size() / bank_size;
304 
305 	// bank switching
306 	int first_bank = (load_addr - rom_begin) / bank_size;
307 	for ( int i = 0; i < bank_count; i++ )
308 	{
309 		unsigned bank = i - first_bank;
310 		if ( bank >= (unsigned) total_banks )
311 			bank = 0;
312 		initial_banks [i] = bank;
313 
314 		if ( header_.banks [i] )
315 		{
316 			// bank-switched
317 			memcpy( initial_banks, header_.banks, sizeof initial_banks );
318 			break;
319 		}
320 	}
321 
322 	pal_only = (header_.speed_flags & 3) == 1;
323 
324 	#if !NSF_EMU_EXTRA_FLAGS
325 		header_.speed_flags = 0;
326 	#endif
327 
328 	set_tempo( tempo() );
329 
330 	return setup_buffer( (long) (clock_rate_ + 0.5) );
331 }
332 
update_eq(blip_eq_t const & eq)333 void Nsf_Emu::update_eq( blip_eq_t const& eq )
334 {
335 	apu.treble_eq( eq );
336 
337 	#if !NSF_EMU_APU_ONLY
338 	{
339 		if ( namco ) namco->treble_eq( eq );
340 		if ( vrc6  ) vrc6 ->treble_eq( eq );
341 		if ( fme7  ) fme7 ->treble_eq( eq );
342 	}
343 	#endif
344 }
345 
set_voice(int i,Blip_Buffer * buf,Blip_Buffer *,Blip_Buffer *)346 void Nsf_Emu::set_voice( int i, Blip_Buffer* buf, Blip_Buffer*, Blip_Buffer* )
347 {
348 	if ( i < Nes_Apu::osc_count )
349 	{
350 		apu.osc_output( i, buf );
351 		return;
352 	}
353 	i -= Nes_Apu::osc_count;
354 
355 	#if !NSF_EMU_APU_ONLY
356 	{
357 		if ( fme7 && i < Nes_Fme7_Apu::osc_count )
358 		{
359 			fme7->osc_output( i, buf );
360 			return;
361 		}
362 
363 		if ( vrc6 )
364 		{
365 			if ( i < Nes_Vrc6_Apu::osc_count )
366 			{
367 				// put saw first
368 				if ( --i < 0 )
369 					i = 2;
370 				vrc6->osc_output( i, buf );
371 				return;
372 			}
373 			i -= Nes_Vrc6_Apu::osc_count;
374 		}
375 
376 		if ( namco && i < Nes_Namco_Apu::osc_count )
377 		{
378 			namco->osc_output( i, buf );
379 			return;
380 		}
381 	}
382 	#endif
383 }
384 
385 // Emulation
386 
387 // see nes_cpu_io.h for read/write functions
388 
cpu_write_misc(nes_addr_t addr,int data)389 void Nsf_Emu::cpu_write_misc( nes_addr_t addr, int data )
390 {
391 	#if !NSF_EMU_APU_ONLY
392 	{
393 		if ( namco )
394 		{
395 			switch ( addr )
396 			{
397 			case Nes_Namco_Apu::data_reg_addr:
398 				namco->write_data( time(), data );
399 				return;
400 
401 			case Nes_Namco_Apu::addr_reg_addr:
402 				namco->write_addr( data );
403 				return;
404 			}
405 		}
406 
407 		if ( addr >= Nes_Fme7_Apu::latch_addr && fme7 )
408 		{
409 			switch ( addr & Nes_Fme7_Apu::addr_mask )
410 			{
411 			case Nes_Fme7_Apu::latch_addr:
412 				fme7->write_latch( data );
413 				return;
414 
415 			case Nes_Fme7_Apu::data_addr:
416 				fme7->write_data( time(), data );
417 				return;
418 			}
419 		}
420 
421 		if ( vrc6 )
422 		{
423 			unsigned reg = addr & (Nes_Vrc6_Apu::addr_step - 1);
424 			unsigned osc = unsigned (addr - Nes_Vrc6_Apu::base_addr) / Nes_Vrc6_Apu::addr_step;
425 			if ( osc < Nes_Vrc6_Apu::osc_count && reg < Nes_Vrc6_Apu::reg_count )
426 			{
427 				vrc6->write_osc( time(), osc, reg, data );
428 				return;
429 			}
430 		}
431 	}
432 	#endif
433 
434 	// unmapped write
435 
436 	#ifndef NDEBUG
437 	{
438 		// some games write to $8000 and $8001 repeatedly
439 		if ( addr == 0x8000 || addr == 0x8001 ) return;
440 
441 		// probably namco sound mistakenly turned on in mck
442 		if ( addr == 0x4800 || addr == 0xF800 ) return;
443 
444 		// memory mapper?
445 		if ( addr == 0xFFF8 ) return;
446 
447 		debug_printf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data );
448 	}
449 	#endif
450 }
451 
start_track_(int track)452 blargg_err_t Nsf_Emu::start_track_( int track )
453 {
454 	RETURN_ERR( Classic_Emu::start_track_( track ) );
455 
456 	memset( low_mem, 0, sizeof low_mem );
457 	memset( sram,    0, sizeof sram );
458 
459 	cpu::reset( unmapped_code ); // also maps low_mem
460 	cpu::map_code( sram_addr, sizeof sram, sram );
461 	for ( int i = 0; i < bank_count; ++i )
462 		cpu_write( bank_select_addr + i, initial_banks [i] );
463 
464 	apu.reset( pal_only, (header_.speed_flags & 0x20) ? 0x3F : 0 );
465 	apu.write_register( 0, 0x4015, 0x0F );
466 	apu.write_register( 0, 0x4017, (header_.speed_flags & 0x10) ? 0x80 : 0 );
467 	#if !NSF_EMU_APU_ONLY
468 	{
469 		if ( namco ) namco->reset();
470 		if ( vrc6  ) vrc6 ->reset();
471 		if ( fme7  ) fme7 ->reset();
472 	}
473 	#endif
474 
475 	play_ready = 4;
476 	play_extra = 0;
477 	next_play = play_period / clock_divisor;
478 
479 	saved_state.pc = badop_addr;
480 	low_mem [0x1FF] = (badop_addr - 1) >> 8;
481 	low_mem [0x1FE] = (badop_addr - 1) & 0xFF;
482 	r.sp = 0xFD;
483 	r.pc = init_addr;
484 	r.a  = track;
485 	r.x  = pal_only;
486 
487 	return 0;
488 }
489 
run_clocks(blip_time_t & duration,int)490 blargg_err_t Nsf_Emu::run_clocks( blip_time_t& duration, int )
491 {
492 	set_time( 0 );
493 	while ( time() < duration )
494 	{
495 		nes_time_t end = min( (blip_time_t) next_play, duration );
496 		end = min( end, time() + 32767 ); // allows CPU to use 16-bit time delta
497 		if ( cpu::run( end ) )
498 		{
499 			if ( r.pc != badop_addr )
500 			{
501 				set_warning( "Emulation error (illegal instruction)" );
502 				r.pc++;
503 			}
504 			else
505 			{
506 				play_ready = 1;
507 				if ( saved_state.pc != badop_addr )
508 				{
509 					cpu::r = saved_state;
510 					saved_state.pc = badop_addr;
511 				}
512 				else
513 				{
514 					set_time( end );
515 				}
516 			}
517 		}
518 
519 		if ( time() >= next_play )
520 		{
521 			nes_time_t period = (play_period + play_extra) / clock_divisor;
522 			play_extra = play_period - period * clock_divisor;
523 			next_play += period;
524 			if ( play_ready && !--play_ready )
525 			{
526 				check( saved_state.pc == badop_addr );
527 				if ( r.pc != badop_addr )
528 					saved_state = cpu::r;
529 
530 				r.pc = play_addr;
531 				low_mem [0x100 + r.sp--] = (badop_addr - 1) >> 8;
532 				low_mem [0x100 + r.sp--] = (badop_addr - 1) & 0xFF;
533 				GME_FRAME_HOOK( this );
534 			}
535 		}
536 	}
537 
538 	if ( cpu::error_count() )
539 	{
540 		cpu::clear_error_count();
541 		set_warning( "Emulation error (illegal instruction)" );
542 	}
543 
544 	duration = time();
545 	next_play -= duration;
546 	check( next_play >= 0 );
547 	if ( next_play < 0 )
548 		next_play = 0;
549 
550 	apu.end_frame( duration );
551 
552 	#if !NSF_EMU_APU_ONLY
553 	{
554 		if ( namco ) namco->end_frame( duration );
555 		if ( vrc6  ) vrc6 ->end_frame( duration );
556 		if ( fme7  ) fme7 ->end_frame( duration );
557 	}
558 	#endif
559 
560 	return 0;
561 }
562