mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-22 04:43:39 +02:00
Update to v105 release.
byuu says: This release provides several major improvements to Mega Drive emulation which enhances compatibility a good deal. It also includes important Super Famicom mosaic emulation improvements, plus a much-needed SuperFX save state issue fix. Changelog (since v104): - higan: many improvements to Emulator::Interface to support forks/frontends - higan: refreshed program icon - icarus: new program icon - Game Boy Advance: slight emulation speedup over v104 - Game Boy Advance: synchronize APU FIFO updates better - Mega Drive: added automatic region detection [hex_usr] - Mega Drive: support 8-bit SRAM - Game Boy Advance: fixed bug when changing to THUMB mode via MSR [MerryMage] - Master System: fix bug in backdrop color and background 0 priority [hex_usr] - Mega Drive: backgrounds always update output priority bit [Cydrak] - Mega Drive: emulated interlaced video output - Mega Drive: emulated shadow/highlight mode [Cydrak] - Super Famicom: auto joypad polling clears the shift register when starting - Super Famicom: added new low-entropy RAM initialization mode to more closely match hardware - Game Boy Advance: rumble will now time out after being left on for 500ms - ruby: improved rumble support in udev input driver [ma_rysia] - M68K: `move.b (a7)[+/-]` adjust a7 by two - M68K: illegal/lineA/lineF opcodes do not modify the stack register - Mega Drive: emulate VIP status bit - uPD7725: improved emulation of OV1/S1 flags [byuu, AWJ, Lord Nightmare] - uPD7725: improved handling of DP, RP updates [Jonas Quinn] - Super Famicom: improved emulation of mosaic effects in hires, interlace, and offset-per-tile modes [byuu, Cydrak] - ruby: improved Direct3D exclusive mode monitor selection [Cydrak] - Super Famicom: fixed save state bug affecting SuperFX games [Cydrak] - Mega Drive: added workaround for Clang compiler bug; allowing this core to work on macOS [Cydrak, Sintendo] - higan: hotkeys now also trigger when the main window lacks focus yet higan is set to allow input on focus loss - higan: fixed an edge case where `int16_t` ↔ `double` audio conversion could possibly result in overflows - higan: fixed a crash on macOS when choosing quit from the application menu [ncbncb] Changelog (since the previous WIP): - higan: restored `make console=true` - tomoko: if you allow input when main window focus is lost, hotkeys can now be triggered without focus as well - hiro/cocoa: fix crash on exit from menu [ncbncb] - ruby: smarter `double` → `int16_t` conversion to prevent underflow/overflow
This commit is contained in:
@@ -54,8 +54,9 @@ struct AudioALSA : Audio {
|
||||
auto output(const double samples[]) -> void {
|
||||
if(!ready()) return;
|
||||
|
||||
_buffer[_offset++] = uint16_t(samples[0] * 32768.0) << 0 | uint16_t(samples[1] * 32768.0) << 16;
|
||||
if(_offset < _periodSize) return;
|
||||
_buffer[_offset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0;
|
||||
_buffer[_offset] |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16;
|
||||
if(++_offset < _periodSize) return;
|
||||
|
||||
snd_pcm_sframes_t available;
|
||||
do {
|
||||
|
@@ -33,7 +33,9 @@ struct AudioAO : Audio {
|
||||
}
|
||||
|
||||
auto output(const double samples[]) -> void {
|
||||
uint32_t sample = uint16_t(samples[0] * 32768.0) << 0 | uint16_t(samples[1] * 32768.0) << 16;
|
||||
uint32_t sample = 0;
|
||||
sample |= (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0;
|
||||
sample |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16;
|
||||
ao_play(_interface, (char*)&sample, 4);
|
||||
}
|
||||
|
||||
|
@@ -208,30 +208,30 @@ private:
|
||||
|
||||
switch(_sampleFormat) {
|
||||
case ASIOSTInt16LSB: {
|
||||
*(int16_t*)buffer = samples[n] * double(1 << 15);
|
||||
*(uint16_t*)buffer = (uint16_t)sclamp<16>(samples[n] * (32768.0 - 1.0));
|
||||
break;
|
||||
}
|
||||
|
||||
case ASIOSTInt24LSB: {
|
||||
int value = samples[n] * double(1 << 23);
|
||||
buffer[0] = value >> 0;
|
||||
buffer[1] = value >> 8;
|
||||
auto value = (uint32_t)sclamp<24>(samples[n] * (256.0 * 32768.0 - 1.0));
|
||||
buffer[0] = value >> 0;
|
||||
buffer[1] = value >> 8;
|
||||
buffer[2] = value >> 16;
|
||||
break;
|
||||
}
|
||||
|
||||
case ASIOSTInt32LSB: {
|
||||
*(int32_t*)buffer = samples[n] * double(1 << 31);
|
||||
*(uint32_t*)buffer = (uint32_t)sclamp<32>(samples[n] * (65536.0 * 32768.0 - 1.0));
|
||||
break;
|
||||
}
|
||||
|
||||
case ASIOSTFloat32LSB: {
|
||||
*(float*)buffer = samples[n];
|
||||
*(float*)buffer = max(-1.0, min(+1.0, samples[n]));
|
||||
break;
|
||||
}
|
||||
|
||||
case ASIOSTFloat64LSB: {
|
||||
*(double*)buffer = samples[n];
|
||||
*(double*)buffer = max(-1.0, min(+1.0, samples[n]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -70,8 +70,9 @@ struct AudioDirectSound : Audio {
|
||||
auto output(const double samples[]) -> void {
|
||||
if(!ready()) return;
|
||||
|
||||
_buffer[_offset++] = uint16_t(samples[0] * 32768.0) << 0 | uint16_t(samples[1] * 32768.0) << 16;
|
||||
if(_offset < _period) return;
|
||||
_buffer[_offset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0;
|
||||
_buffer[_offset] |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16;
|
||||
if(++_offset < _period) return;
|
||||
_offset = 0;
|
||||
|
||||
if(_blocking) {
|
||||
|
@@ -61,8 +61,8 @@ struct AudioOpenAL : Audio {
|
||||
}
|
||||
|
||||
auto output(const double samples[]) -> void {
|
||||
_buffer[_bufferLength] = int16_t(samples[0] * 32768.0) << 0;
|
||||
_buffer[_bufferLength] |= int16_t(samples[1] * 32768.0) << 16;
|
||||
_buffer[_bufferLength] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0;
|
||||
_buffer[_bufferLength] |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16;
|
||||
if(++_bufferLength < _bufferSize) return;
|
||||
|
||||
ALuint alBuffer = 0;
|
||||
|
@@ -77,7 +77,7 @@ struct AudioOSS : Audio {
|
||||
auto output(const double samples[]) -> void {
|
||||
if(!ready()) return;
|
||||
for(auto n : range(_channels)) {
|
||||
int16_t sample = samples[n] * 32768.0;
|
||||
auto sample = (uint16_t)sclamp<16>(samples[n] * 32767.0);
|
||||
auto unused = write(_fd, &sample, 2);
|
||||
}
|
||||
}
|
||||
|
@@ -46,8 +46,9 @@ struct AudioPulseAudio : Audio {
|
||||
|
||||
auto output(const double samples[]) -> void {
|
||||
pa_stream_begin_write(_stream, (void**)&_buffer, &_period);
|
||||
_buffer[_offset++] = uint16_t(samples[0] * 32768.0) << 0 | uint16_t(samples[1] * 32768.0) << 16;
|
||||
if((_offset + 1) * pa_frame_size(&_specification) <= _period) return;
|
||||
_buffer[_offset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0;
|
||||
_buffer[_offset] |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16;
|
||||
if((++_offset + 1) * pa_frame_size(&_specification) <= _period) return;
|
||||
|
||||
while(true) {
|
||||
if(_first) {
|
||||
|
@@ -36,8 +36,9 @@ struct AudioPulseAudioSimple : Audio {
|
||||
auto output(const double samples[]) -> void {
|
||||
if(!ready()) return;
|
||||
|
||||
_buffer[_offset++] = uint16_t(samples[0] * 32768.0) << 0 | uint16_t(samples[1] * 32768.0) << 16;
|
||||
if(_offset >= 64) {
|
||||
_buffer[_offset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0;
|
||||
_buffer[_offset] |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16;
|
||||
if(++_offset >= 64) {
|
||||
int error;
|
||||
pa_simple_write(_interface, (const void*)_buffer, _offset * sizeof(uint32_t), &error);
|
||||
_offset = 0;
|
||||
|
@@ -205,16 +205,16 @@ private:
|
||||
}
|
||||
|
||||
if(_mode == 1 && _precision == 16) {
|
||||
auto output = (int16_t*)buffer;
|
||||
for(uint n : range(_channels)) *output++ = int16_t(samples[n] * 32768.0);
|
||||
auto output = (uint16_t*)buffer;
|
||||
for(uint n : range(_channels)) *output++ = (uint16_t)sclamp<16>(samples[n] * (32768.0 - 1.0));
|
||||
buffer = (uint8_t*)output;
|
||||
} else if(_mode == 1 && _precision == 32) {
|
||||
auto output = (int32_t*)buffer;
|
||||
for(uint n : range(_channels)) *output++ = int32_t(samples[n] * 65536.0 * 32768.0);
|
||||
auto output = (uint32_t*)buffer;
|
||||
for(uint n : range(_channels)) *output++ = (uint32_t)sclamp<32>(samples[n] * (65536.0 * 32768.0 - 1.0));
|
||||
buffer = (uint8_t*)output;
|
||||
} else if(_mode == 3 && _precision == 32) {
|
||||
auto output = (float*)buffer;
|
||||
for(uint n : range(_channels)) *output++ = float(samples[n]);
|
||||
for(uint n : range(_channels)) *output++ = float(max(-1.0, min(+1.0, samples[n])));
|
||||
buffer = (uint8_t*)output;
|
||||
} else {
|
||||
//output silence for unsupported sample formats
|
||||
|
@@ -59,8 +59,9 @@ struct AudioXAudio2 : Audio, public IXAudio2VoiceCallback {
|
||||
}
|
||||
|
||||
auto output(const double samples[]) -> void {
|
||||
_buffer[_bufferIndex * _period + _bufferOffset++] = uint16_t(samples[0] * 32768.0) << 0 | uint16_t(samples[1] * 32768.0) << 16;
|
||||
if(_bufferOffset < _period) return;
|
||||
_buffer[_bufferIndex * _period + _bufferOffset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0;
|
||||
_buffer[_bufferIndex * _period + _bufferOffset] |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16;
|
||||
if(++_bufferOffset < _period) return;
|
||||
_bufferOffset = 0;
|
||||
|
||||
if(_bufferQueue == _bufferCount - 1) {
|
||||
|
Reference in New Issue
Block a user