cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

Gb_Oscs.cpp (14767B)


      1// Gb_Snd_Emu 0.2.0. http://www.slack.net/~ant/
      2
      3#include "Gb_Apu.h"
      4
      5/* Copyright (C) 2003-2007 Shay Green. This module is free software; you
      6can redistribute it and/or modify it under the terms of the GNU Lesser
      7General Public License as published by the Free Software Foundation; either
      8version 2.1 of the License, or (at your option) any later version. This
      9module is distributed in the hope that it will be useful, but WITHOUT ANY
     10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
     12details. You should have received a copy of the GNU Lesser General Public
     13License along with this module; if not, write to the Free Software Foundation,
     14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
     15
     16#include "blargg_source.h"
     17
     18bool const cgb_02 = false; // enables bug in early CGB units that causes problems in some games
     19bool const cgb_05 = false; // enables CGB-05 zombie behavior
     20
     21int const trigger_mask   = 0x80;
     22int const length_enabled = 0x40;
     23
     24void Gb_Osc::reset()
     25{
     26	output   = 0;
     27	last_amp = 0;
     28	delay    = 0;
     29	phase    = 0;
     30	enabled  = false;
     31}
     32
     33inline void Gb_Osc::update_amp( blip_time_t time, int new_amp )
     34{
     35	output->set_modified();
     36	int delta = new_amp - last_amp;
     37	if ( delta )
     38	{
     39		last_amp = new_amp;
     40		med_synth->offset( time, delta, output );
     41	}
     42}
     43
     44// Units
     45
     46void Gb_Osc::clock_length()
     47{
     48	if ( (regs [4] & length_enabled) && length_ctr )
     49	{
     50		if ( --length_ctr <= 0 )
     51			enabled = false;
     52	}
     53}
     54
     55inline int Gb_Env::reload_env_timer()
     56{
     57	int raw = regs [2] & 7;
     58	env_delay = (raw ? raw : 8);
     59	return raw;
     60}
     61
     62void Gb_Env::clock_envelope()
     63{
     64	if ( env_enabled && --env_delay <= 0 && reload_env_timer() )
     65	{
     66		int v = volume + (regs [2] & 0x08 ? +1 : -1);
     67		if ( 0 <= v && v <= 15 )
     68			volume = v;
     69		else
     70			env_enabled = false;
     71	}
     72}
     73
     74inline void Gb_Sweep_Square::reload_sweep_timer()
     75{
     76	sweep_delay = (regs [0] & period_mask) >> 4;
     77	if ( !sweep_delay )
     78		sweep_delay = 8;
     79}
     80
     81void Gb_Sweep_Square::calc_sweep( bool update )
     82{
     83	int const shift = regs [0] & shift_mask;
     84	int const delta = sweep_freq >> shift;
     85	sweep_neg = (regs [0] & 0x08) != 0;
     86	int const freq = sweep_freq + (sweep_neg ? -delta : delta);
     87
     88	if ( freq > 0x7FF )
     89	{
     90		enabled = false;
     91	}
     92	else if ( shift && update )
     93	{
     94		sweep_freq = freq;
     95
     96		regs [3] = freq & 0xFF;
     97		regs [4] = (regs [4] & ~0x07) | (freq >> 8 & 0x07);
     98	}
     99}
    100
    101void Gb_Sweep_Square::clock_sweep()
    102{
    103	if ( --sweep_delay <= 0 )
    104	{
    105		reload_sweep_timer();
    106		if ( sweep_enabled && (regs [0] & period_mask) )
    107		{
    108			calc_sweep( true  );
    109			calc_sweep( false );
    110		}
    111	}
    112}
    113
    114int Gb_Wave::access( unsigned addr ) const
    115{
    116	if ( enabled && mode != Gb_Apu::mode_agb )
    117	{
    118		addr = phase & (bank_size - 1);
    119		if ( mode == Gb_Apu::mode_dmg )
    120		{
    121			addr++;
    122			if ( delay > clk_mul )
    123				return -1; // can only access within narrow time window while playing
    124		}
    125		addr >>= 1;
    126	}
    127	return addr & 0x0F;
    128}
    129
    130// write_register
    131
    132int Gb_Osc::write_trig( int frame_phase, int max_len, int old_data )
    133{
    134	int data = regs [4];
    135
    136	if ( (frame_phase & 1) && !(old_data & length_enabled) && length_ctr )
    137	{
    138		if ( (data & length_enabled) || cgb_02 )
    139			length_ctr--;
    140	}
    141
    142	if ( data & trigger_mask )
    143	{
    144		enabled = true;
    145		if ( !length_ctr )
    146		{
    147			length_ctr = max_len;
    148			if ( (frame_phase & 1) && (data & length_enabled) )
    149				length_ctr--;
    150		}
    151	}
    152
    153	if ( !length_ctr )
    154		enabled = false;
    155
    156	return data & trigger_mask;
    157}
    158
    159inline void Gb_Env::zombie_volume( int old, int data )
    160{
    161	int v = volume;
    162	if ( mode == Gb_Apu::mode_agb || cgb_05 )
    163	{
    164		// CGB-05 behavior, very close to AGB behavior as well
    165		if ( (old ^ data) & 8 )
    166		{
    167			if ( !(old & 8) )
    168			{
    169				v++;
    170				if ( old & 7 )
    171					v++;
    172			}
    173
    174			v = 16 - v;
    175		}
    176		else if ( (old & 0x0F) == 8 )
    177		{
    178			v++;
    179		}
    180	}
    181	else
    182	{
    183		// CGB-04&02 behavior, very close to MGB behavior as well
    184		if ( !(old & 7) && env_enabled )
    185			v++;
    186		else if ( !(old & 8) )
    187			v += 2;
    188
    189		if ( (old ^ data) & 8 )
    190			v = 16 - v;
    191	}
    192	volume = v & 0x0F;
    193}
    194
    195bool Gb_Env::write_register( int frame_phase, int reg, int old, int data )
    196{
    197	int const max_len = 64;
    198
    199	switch ( reg )
    200	{
    201	case 1:
    202		length_ctr = max_len - (data & (max_len - 1));
    203		break;
    204
    205	case 2:
    206		if ( !dac_enabled() )
    207			enabled = false;
    208
    209		zombie_volume( old, data );
    210
    211		if ( (data & 7) && env_delay == 8 )
    212		{
    213			env_delay = 1;
    214			clock_envelope(); // TODO: really happens at next length clock
    215		}
    216		break;
    217
    218	case 4:
    219		if ( write_trig( frame_phase, max_len, old ) )
    220		{
    221			volume = regs [2] >> 4;
    222			reload_env_timer();
    223			env_enabled = true;
    224			if ( frame_phase == 7 )
    225				env_delay++;
    226			if ( !dac_enabled() )
    227				enabled = false;
    228			return true;
    229		}
    230	}
    231	return false;
    232}
    233
    234bool Gb_Square::write_register( int frame_phase, int reg, int old_data, int data )
    235{
    236	bool result = Gb_Env::write_register( frame_phase, reg, old_data, data );
    237	if ( result )
    238		delay = (delay & (4 * clk_mul - 1)) + period();
    239	return result;
    240}
    241
    242inline void Gb_Noise::write_register( int frame_phase, int reg, int old_data, int data )
    243{
    244	if ( Gb_Env::write_register( frame_phase, reg, old_data, data ) )
    245	{
    246		phase = 0x7FFF;
    247		delay += 8 * clk_mul;
    248	}
    249}
    250
    251inline void Gb_Sweep_Square::write_register( int frame_phase, int reg, int old_data, int data )
    252{
    253	if ( reg == 0 && sweep_enabled && sweep_neg && !(data & 0x08) )
    254		enabled = false; // sweep negate disabled after used
    255
    256	if ( Gb_Square::write_register( frame_phase, reg, old_data, data ) )
    257	{
    258		sweep_freq = frequency();
    259		sweep_neg = false;
    260		reload_sweep_timer();
    261		sweep_enabled = (regs [0] & (period_mask | shift_mask)) != 0;
    262		if ( regs [0] & shift_mask )
    263			calc_sweep( false );
    264	}
    265}
    266
    267void Gb_Wave::corrupt_wave()
    268{
    269	int pos = ((phase + 1) & (bank_size - 1)) >> 1;
    270	if ( pos < 4 )
    271		wave_ram [0] = wave_ram [pos];
    272	else
    273		for ( int i = 4; --i >= 0; )
    274			wave_ram [i] = wave_ram [(pos & ~3) + i];
    275}
    276
    277inline void Gb_Wave::write_register( int frame_phase, int reg, int old_data, int data )
    278{
    279	int const max_len = 256;
    280
    281	switch ( reg )
    282	{
    283	case 0:
    284		if ( !dac_enabled() )
    285			enabled = false;
    286		break;
    287
    288	case 1:
    289		length_ctr = max_len - data;
    290		break;
    291
    292	case 4:
    293		bool was_enabled = enabled;
    294		if ( write_trig( frame_phase, max_len, old_data ) )
    295		{
    296			if ( !dac_enabled() )
    297				enabled = false;
    298			else if ( mode == Gb_Apu::mode_dmg && was_enabled &&
    299					(unsigned) (delay - 2 * clk_mul) < 2 * clk_mul )
    300				corrupt_wave();
    301
    302			phase = 0;
    303			delay    = period() + 6 * clk_mul;
    304		}
    305	}
    306}
    307
    308void Gb_Apu::write_osc( int index, int reg, int old_data, int data )
    309{
    310	reg -= index * 5;
    311	switch ( index )
    312	{
    313	case 0: square1.write_register( frame_phase, reg, old_data, data ); break;
    314	case 1: square2.write_register( frame_phase, reg, old_data, data ); break;
    315	case 2: wave   .write_register( frame_phase, reg, old_data, data ); break;
    316	case 3: noise  .write_register( frame_phase, reg, old_data, data ); break;
    317	}
    318}
    319
    320// Synthesis
    321
    322void Gb_Square::run( blip_time_t time, blip_time_t end_time )
    323{
    324	// Calc duty and phase
    325	static byte const duty_offsets [4] = { 1, 1, 3, 7 };
    326	static byte const duties       [4] = { 1, 2, 4, 6 };
    327	int const duty_code = regs [1] >> 6;
    328	int duty_offset = duty_offsets [duty_code];
    329	int duty = duties [duty_code];
    330	if ( mode == Gb_Apu::mode_agb )
    331	{
    332		// AGB uses inverted duty
    333		duty_offset -= duty;
    334		duty = 8 - duty;
    335	}
    336	int ph = (this->phase + duty_offset) & 7;
    337
    338	// Determine what will be generated
    339	int vol = 0;
    340	Blip_Buffer* const out = this->output;
    341	if ( out )
    342	{
    343		int amp = dac_off_amp;
    344		if ( dac_enabled() )
    345		{
    346			if ( enabled )
    347				vol = this->volume;
    348
    349			amp = -dac_bias;
    350			if ( mode == Gb_Apu::mode_agb )
    351				amp = -(vol >> 1);
    352
    353			// Play inaudible frequencies as constant amplitude
    354			if ( frequency() >= 0x7FA && delay < 32 * clk_mul )
    355			{
    356				amp += (vol * duty) >> 3;
    357				vol = 0;
    358			}
    359
    360			if ( ph < duty )
    361			{
    362				amp += vol;
    363				vol = -vol;
    364			}
    365		}
    366		update_amp( time, amp );
    367	}
    368
    369	// Generate wave
    370	time += delay;
    371	if ( time < end_time )
    372	{
    373		int const per = this->period();
    374		if ( !vol )
    375		{
    376			// Maintain phase when not playing
    377			int count = (end_time - time + per - 1) / per;
    378			ph += count; // will be masked below
    379			time += (blip_time_t) count * per;
    380		}
    381		else
    382		{
    383			// Output amplitude transitions
    384			int delta = vol;
    385			do
    386			{
    387				ph = (ph + 1) & 7;
    388				if ( ph == 0 || ph == duty )
    389				{
    390					good_synth->offset_inline( time, delta, out );
    391					delta = -delta;
    392				}
    393				time += per;
    394			}
    395			while ( time < end_time );
    396
    397			if ( delta != vol )
    398				last_amp -= delta;
    399		}
    400		this->phase = (ph - duty_offset) & 7;
    401	}
    402	delay = time - end_time;
    403}
    404
    405// Quickly runs LFSR for a large number of clocks. For use when noise is generating
    406// no sound.
    407static unsigned run_lfsr( unsigned s, unsigned mask, int count )
    408{
    409	bool const optimized = true; // set to false to use only unoptimized loop in middle
    410
    411	// optimization used in several places:
    412	// ((s & (1 << b)) << n) ^ ((s & (1 << b)) << (n + 1)) = (s & (1 << b)) * (3 << n)
    413
    414	if ( mask == 0x4000 && optimized )
    415	{
    416		if ( count >= 32767 )
    417			count %= 32767;
    418
    419		// Convert from Fibonacci to Galois configuration,
    420		// shifted left 1 bit
    421		s ^= (s & 1) * 0x8000;
    422
    423		// Each iteration is equivalent to clocking LFSR 255 times
    424		while ( (count -= 255) > 0 )
    425			s ^= ((s & 0xE) << 12) ^ ((s & 0xE) << 11) ^ (s >> 3);
    426		count += 255;
    427
    428		// Each iteration is equivalent to clocking LFSR 15 times
    429		// (interesting similarity to single clocking below)
    430		while ( (count -= 15) > 0 )
    431			s ^= ((s & 2) * (3 << 13)) ^ (s >> 1);
    432		count += 15;
    433
    434		// Remaining singles
    435		while ( --count >= 0 )
    436			s = ((s & 2) * (3 << 13)) ^ (s >> 1);
    437
    438		// Convert back to Fibonacci configuration
    439		s &= 0x7FFF;
    440	}
    441	else if ( count < 8 || !optimized )
    442	{
    443		// won't fully replace upper 8 bits, so have to do the unoptimized way
    444		while ( --count >= 0 )
    445			s = (s >> 1 | mask) ^ (mask & (0 - ((s - 1) & 2)));
    446	}
    447	else
    448	{
    449		if ( count > 127 )
    450		{
    451			count %= 127;
    452			if ( !count )
    453				count = 127; // must run at least once
    454		}
    455
    456		// Need to keep one extra bit of history
    457		s = s << 1 & 0xFF;
    458
    459		// Convert from Fibonacci to Galois configuration,
    460		// shifted left 2 bits
    461		s ^= (s & 2) * 0x80;
    462
    463		// Each iteration is equivalent to clocking LFSR 7 times
    464		// (interesting similarity to single clocking below)
    465		while ( (count -= 7) > 0 )
    466			s ^= ((s & 4) * (3 << 5)) ^ (s >> 1);
    467		count += 7;
    468
    469		// Remaining singles
    470		while ( --count >= 0 )
    471			s = ((s & 4) * (3 << 5)) ^ (s >> 1);
    472
    473		// Convert back to Fibonacci configuration and
    474		// repeat last 8 bits above significant 7
    475		s = (s << 7 & 0x7F80) | (s >> 1 & 0x7F);
    476	}
    477
    478	return s;
    479}
    480
    481void Gb_Noise::run( blip_time_t time, blip_time_t end_time )
    482{
    483	// Determine what will be generated
    484	int vol = 0;
    485	Blip_Buffer* const out = this->output;
    486	if ( out )
    487	{
    488		int amp = dac_off_amp;
    489		if ( dac_enabled() )
    490		{
    491			if ( enabled )
    492				vol = this->volume;
    493
    494			amp = -dac_bias;
    495			if ( mode == Gb_Apu::mode_agb )
    496				amp = -(vol >> 1);
    497
    498			if ( !(phase & 1) )
    499			{
    500				amp += vol;
    501				vol = -vol;
    502			}
    503		}
    504
    505		// AGB negates final output
    506		if ( mode == Gb_Apu::mode_agb )
    507		{
    508			vol = -vol;
    509			amp    = -amp;
    510		}
    511
    512		update_amp( time, amp );
    513	}
    514
    515	// Run timer and calculate time of next LFSR clock
    516	static byte const period1s [8] = { 1, 2, 4, 6, 8, 10, 12, 14 };
    517	int const period1 = period1s [regs [3] & 7] * clk_mul;
    518	{
    519		int extra = (end_time - time) - delay;
    520		int const per2 = this->period2();
    521		time += delay + ((divider ^ (per2 >> 1)) & (per2 - 1)) * period1;
    522
    523		int count = (extra < 0 ? 0 : (extra + period1 - 1) / period1);
    524		divider = (divider - count) & period2_mask;
    525		delay = count * period1 - extra;
    526	}
    527
    528	// Generate wave
    529	if ( time < end_time )
    530	{
    531		unsigned const mask = this->lfsr_mask();
    532		unsigned bits = this->phase;
    533
    534		int per = period2( period1 * 8 );
    535		if ( period2_index() >= 0xE )
    536		{
    537			time = end_time;
    538		}
    539		else if ( !vol )
    540		{
    541			// Maintain phase when not playing
    542			int count = (end_time - time + per - 1) / per;
    543			time += (blip_time_t) count * per;
    544			bits = run_lfsr( bits, ~mask, count );
    545		}
    546		else
    547		{
    548			// Output amplitude transitions
    549			int delta = -vol;
    550			do
    551			{
    552				unsigned changed = bits + 1;
    553				bits = bits >> 1 & mask;
    554				if ( changed & 2 )
    555				{
    556					bits |= ~mask;
    557					delta = -delta;
    558					med_synth->offset_inline( time, delta, out );
    559				}
    560				time += per;
    561			}
    562			while ( time < end_time );
    563
    564			if ( delta == vol )
    565				last_amp += delta;
    566		}
    567		this->phase = bits;
    568	}
    569}
    570
    571void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
    572{
    573	// Calc volume
    574	static byte const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 };
    575	int const volume_shift = 2;
    576	int const volume_idx = regs [2] >> 5 & (agb_mask | 3); // 2 bits on DMG/CGB, 3 on AGB
    577	int const volume_mul = volumes [volume_idx];
    578
    579	// Determine what will be generated
    580	int playing = false;
    581	Blip_Buffer* const out = this->output;
    582	if ( out )
    583	{
    584		int amp = dac_off_amp;
    585		if ( dac_enabled() )
    586		{
    587			// Play inaudible frequencies as constant amplitude
    588			amp = 8 << 4; // really depends on average of all samples in wave
    589
    590			// if delay is larger, constant amplitude won't start yet
    591			if ( frequency() <= 0x7FB || delay > 15 * clk_mul )
    592			{
    593				if ( volume_mul )
    594					playing = (int) enabled;
    595
    596				amp = (sample_buf << (phase << 2 & 4) & 0xF0) * playing;
    597			}
    598
    599			amp = ((amp * volume_mul) >> (volume_shift + 4)) - dac_bias;
    600		}
    601		update_amp( time, amp );
    602	}
    603
    604	// Generate wave
    605	time += delay;
    606	if ( time < end_time )
    607	{
    608		byte const* wave = this->wave_ram;
    609
    610		// wave size and bank
    611		int const size20_mask = 0x20;
    612		int const flags = regs [0] & agb_mask;
    613		int const wave_mask = (flags & size20_mask) | 0x1F;
    614		int swap_banks = 0;
    615		if ( flags & bank40_mask )
    616		{
    617			swap_banks = flags & size20_mask;
    618			wave += bank_size/2 - (swap_banks >> 1);
    619		}
    620
    621		int ph = this->phase ^ swap_banks;
    622		ph = (ph + 1) & wave_mask; // pre-advance
    623
    624		int const per = this->period();
    625		if ( !playing )
    626		{
    627			// Maintain phase when not playing
    628			int count = (end_time - time + per - 1) / per;
    629			ph += count; // will be masked below
    630			time += (blip_time_t) count * per;
    631		}
    632		else
    633		{
    634			// Output amplitude transitions
    635			int lamp = this->last_amp + dac_bias;
    636			do
    637			{
    638				// Extract nybble
    639				int nybble = wave [ph >> 1] << (ph << 2 & 4) & 0xF0;
    640				ph = (ph + 1) & wave_mask;
    641
    642				// Scale by volume
    643				int amp = (nybble * volume_mul) >> (volume_shift + 4);
    644
    645				int delta = amp - lamp;
    646				if ( delta )
    647				{
    648					lamp = amp;
    649					med_synth->offset_inline( time, delta, out );
    650				}
    651				time += per;
    652			}
    653			while ( time < end_time );
    654			this->last_amp = lamp - dac_bias;
    655		}
    656		ph = (ph - 1) & wave_mask; // undo pre-advance and mask position
    657
    658		// Keep track of last byte read
    659		if ( enabled )
    660			sample_buf = wave [ph >> 1];
    661
    662		this->phase = ph ^ swap_banks; // undo swapped banks
    663	}
    664	delay = time - end_time;
    665}