diff --git a/bsnes/Makefile b/bsnes/Makefile index 88a4caaf..3b20cc03 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -2,7 +2,7 @@ include nall/Makefile snes := snes gameboy := gameboy profile := compatibility -ui := ui-gameboy +ui := ui # compiler c := $(compiler) -std=gnu99 diff --git a/bsnes/gameboy/apu/apu.cpp b/bsnes/gameboy/apu/apu.cpp index 2b5ce1dd..87c90d95 100755 --- a/bsnes/gameboy/apu/apu.cpp +++ b/bsnes/gameboy/apu/apu.cpp @@ -21,23 +21,24 @@ void APU::main() { scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); } - if((counter & 8191) == 0) { //512hz - if(sequencer == 0 || sequencer == 2 || sequencer == 4 || sequencer == 6) { //256hz + if(sequencer_base == 0) { //512hz + if(sequencer_step == 0 || sequencer_step == 2 || sequencer_step == 4 || sequencer_step == 6) { //256hz square1.clock_length(); square2.clock_length(); wave.clock_length(); noise.clock_length(); } - if(sequencer == 2 || sequencer == 6) { //128hz + if(sequencer_step == 2 || sequencer_step == 6) { //128hz square1.clock_sweep(); } - if(sequencer == 7) { //64hz + if(sequencer_step == 7) { //64hz square1.clock_envelope(); square2.clock_envelope(); noise.clock_envelope(); } - sequencer = (sequencer + 1) & 7; + sequencer_step++; } + sequencer_base++; square1.run(); square2.run(); @@ -46,9 +47,6 @@ void APU::main() { master.run(); system.interface->audio_sample(master.center, master.left, master.right); - - if(++counter == 4194304) counter = 0; - if(++clock >= 0) co_switch(scheduler.active_thread = cpu.thread); } } @@ -58,8 +56,8 @@ void APU::power() { for(unsigned n = 0xff10; n <= 0xff3f; n++) bus.mmio[n] = this; foreach(n, mmio_data) n = 0x00; - counter = 0; - sequencer = 0; + sequencer_base = 0; + sequencer_step = 0; square1.power(); square2.power(); diff --git a/bsnes/gameboy/apu/apu.hpp b/bsnes/gameboy/apu/apu.hpp index 935d92fe..7218415c 100755 --- a/bsnes/gameboy/apu/apu.hpp +++ b/bsnes/gameboy/apu/apu.hpp @@ -6,8 +6,8 @@ struct APU : Processor, MMIO { #include "master/master.hpp" uint8 mmio_data[48]; - unsigned counter; - unsigned sequencer; + uint13 sequencer_base; + uint3 sequencer_step; Square1 square1; Square2 square2; diff --git a/bsnes/gameboy/apu/master/master.cpp b/bsnes/gameboy/apu/master/master.cpp index 591d52d6..c2df5ccd 100755 --- a/bsnes/gameboy/apu/master/master.cpp +++ b/bsnes/gameboy/apu/master/master.cpp @@ -1,15 +1,26 @@ #ifdef APU_CPP void APU::Master::run() { - signed sample = 0, channels = 4; + if(enable == false) { + center = 0; + left = 0; + right = 0; + return; + } + + signed sample = 0, channels; sample += apu.square1.output; sample += apu.square2.output; sample += apu.wave.output; sample += apu.noise.output; - sample /= channels; - if(sample < -32768) sample = -32768; - if(sample > +32767) sample = +32767; - center = sample; + sample >>= 2; + center = sclamp<16>(sample); + + if(left_enable == false && right_enable == false) { + left = center; + right = center; + return; + } sample = 0; channels = 0; @@ -18,17 +29,16 @@ void APU::Master::run() { if(channel3_left_enable) { sample += apu.wave.output; channels++; } if(channel4_left_enable) { sample += apu.noise.output; channels++; } if(channels) sample /= channels; - left = sample; + left = sclamp<16>(sample); switch(left_volume) { - case 0: left *= 0.125; break; - case 1: left *= 0.250; break; - case 2: left *= 0.375; break; - case 3: left *= 0.500; break; - case 4: left *= 0.625; break; - case 5: left *= 0.750; break; - case 6: left *= 0.875; break; - case 7: left *= 1.000; break; + case 0: left >>= 3; break; // 12.5% + case 1: left >>= 2; break; // 25.0% + case 2: left = (left >> 2) + (left >> 3); break; // 37.5% + case 3: left >>= 1; break; // 50.0% + case 4: left = (left >> 1) + (left >> 3); break; // 62.5% + case 5: left -= (left >> 2); break; // 75.0% + case 6: left -= (left >> 3); break; // 87.5% } if(left_enable == false) left = 0; @@ -39,30 +49,18 @@ void APU::Master::run() { if(channel3_right_enable) { sample += apu.wave.output; channels++; } if(channel4_right_enable) { sample += apu.noise.output; channels++; } if(channels) sample /= channels; - right = sample; + right = sclamp<16>(sample); switch(right_volume) { - case 0: right *= 0.125; break; - case 1: right *= 0.250; break; - case 2: right *= 0.375; break; - case 3: right *= 0.500; break; - case 4: right *= 0.625; break; - case 5: right *= 0.750; break; - case 6: right *= 0.875; break; - case 7: right *= 1.000; break; + case 0: right >>= 3; break; // 12.5% + case 1: right >>= 2; break; // 25.0% + case 2: right = (right >> 2) + (right >> 3); break; // 37.5% + case 3: right >>= 1; break; // 50.0% + case 4: right = (right >> 1) + (right >> 3); break; // 62.5% + case 5: right -= (right >> 2); break; // 75.0% + case 6: right -= (right >> 3); break; // 87.5% } if(right_enable == false) right = 0; - - if(left_enable == false && right_enable == false) { - left = center; - right = center; - } - - if(enable == false) { - center = 0; - left = 0; - right = 0; - } } void APU::Master::write(unsigned r, uint8 data) { diff --git a/bsnes/gameboy/apu/serialization.cpp b/bsnes/gameboy/apu/serialization.cpp index e781d5a4..c04dc533 100755 --- a/bsnes/gameboy/apu/serialization.cpp +++ b/bsnes/gameboy/apu/serialization.cpp @@ -2,8 +2,8 @@ void APU::serialize(serializer &s) { s.array(mmio_data); - s.integer(counter); - s.integer(sequencer); + s.integer(sequencer_base); + s.integer(sequencer_step); square1.serialize(s); square2.serialize(s); diff --git a/bsnes/gameboy/apu/wave/wave.cpp b/bsnes/gameboy/apu/wave/wave.cpp index 449c99df..bce6f444 100755 --- a/bsnes/gameboy/apu/wave/wave.cpp +++ b/bsnes/gameboy/apu/wave/wave.cpp @@ -12,12 +12,7 @@ void APU::Wave::run() { if(enable == false) sample = 0; output = (sample * 4369) - 32768; - switch(volume) { - case 0: output *= 0.00; break; - case 1: output *= 1.00; break; - case 2: output *= 0.50; break; - case 3: output *= 0.25; break; - } + output >>= volume; } void APU::Wave::clock_length() { @@ -38,7 +33,12 @@ void APU::Wave::write(unsigned r, uint8 data) { } if(r == 2) { - volume = (data >> 5) & 3; + switch((data >> 5) & 3) { + case 0: volume = 16; break; // 0% + case 1: volume = 0; break; //100% + case 2: volume = 1; break; // 50% + case 3: volume = 2; break; // 25% + } } if(r == 3) { diff --git a/bsnes/gameboy/cpu/cpu.cpp b/bsnes/gameboy/cpu/cpu.cpp index 0b30ba1f..b78aac8b 100755 --- a/bsnes/gameboy/cpu/cpu.cpp +++ b/bsnes/gameboy/cpu/cpu.cpp @@ -94,7 +94,7 @@ void CPU::interrupt_exec(uint16 pc) { } void CPU::power() { - create(Main, 4 * 1024 * 1024); + create(Main, 4194304); for(unsigned n = 0xc000; n <= 0xdfff; n++) bus.mmio[n] = this; //WRAM for(unsigned n = 0xe000; n <= 0xfdff; n++) bus.mmio[n] = this; //WRAM (mirror) diff --git a/bsnes/gameboy/cpu/timing/timing.cpp b/bsnes/gameboy/cpu/timing/timing.cpp index 215e8977..f771466c 100755 --- a/bsnes/gameboy/cpu/timing/timing.cpp +++ b/bsnes/gameboy/cpu/timing/timing.cpp @@ -1,13 +1,9 @@ //4194304hz (4 * 1024 * 1024) + //70224 clocks/frame // 456 clocks/scanline // 154 scanlines/frame -//4194304 / 4096 = 1024 -//4194304 / 262144 = 16 -//4194304 / 65536 = 64 -//4394304 / 16384 = 256 - #ifdef CPU_CPP #include "opcode.cpp" @@ -17,8 +13,8 @@ void CPU::add_clocks(unsigned clocks) { scheduler.exit(Scheduler::ExitReason::StepEvent); status.clock += clocks; - if(status.clock >= 4 * 1024 * 1024) { - status.clock -= 4 * 1024 * 1024; + if(status.clock >= 4194304) { + status.clock -= 4194304; cartridge.mbc3.second(); } diff --git a/bsnes/gameboy/gameboy.hpp b/bsnes/gameboy/gameboy.hpp index 9a47a5ba..eac830c2 100755 --- a/bsnes/gameboy/gameboy.hpp +++ b/bsnes/gameboy/gameboy.hpp @@ -5,7 +5,7 @@ namespace GameBoy { namespace Info { static const char Name[] = "bgameboy"; - static const char Version[] = "000.16"; + static const char Version[] = "000.17"; static unsigned SerializerVersion = 1; } } @@ -33,12 +33,38 @@ namespace GameBoy { typedef uint32_t uint32; typedef uint64_t uint64; - typedef int_t< 4> int4; - typedef int_t<15> int15; - + typedef uint_t< 1> uint1; + typedef uint_t< 2> uint2; + typedef uint_t< 3> uint3; typedef uint_t< 4> uint4; + typedef uint_t< 5> uint5; + typedef uint_t< 6> uint6; + typedef uint_t< 7> uint7; + + typedef uint_t< 9> uint9; + typedef uint_t<10> uint10; + typedef uint_t<11> uint11; + typedef uint_t<12> uint12; + typedef uint_t<13> uint13; + typedef uint_t<14> uint14; typedef uint_t<15> uint15; + typedef uint_t<17> uint17; + typedef uint_t<18> uint18; + typedef uint_t<19> uint19; + typedef uint_t<20> uint20; + typedef uint_t<21> uint21; + typedef uint_t<22> uint22; + typedef uint_t<23> uint23; + typedef uint_t<24> uint24; + typedef uint_t<25> uint25; + typedef uint_t<26> uint26; + typedef uint_t<27> uint27; + typedef uint_t<28> uint28; + typedef uint_t<29> uint29; + typedef uint_t<30> uint30; + typedef uint_t<31> uint31; + template alwaysinline bool within(uint16 addr) { static const uint16 mask = ~(hi ^ lo); diff --git a/bsnes/gameboy/lcd/lcd.cpp b/bsnes/gameboy/lcd/lcd.cpp index 78e85ea2..7d12d321 100755 --- a/bsnes/gameboy/lcd/lcd.cpp +++ b/bsnes/gameboy/lcd/lcd.cpp @@ -190,7 +190,7 @@ void LCD::render_obj() { } void LCD::power() { - create(Main, 4 * 1024 * 1024); + create(Main, 4194304); for(unsigned n = 0x8000; n <= 0x9fff; n++) bus.mmio[n] = this; //VRAM for(unsigned n = 0xff40; n <= 0xff4b; n++) bus.mmio[n] = this; //MMIO diff --git a/bsnes/snes/audio/audio.cpp b/bsnes/snes/audio/audio.cpp index 4b2f6861..eaea1c63 100755 --- a/bsnes/snes/audio/audio.cpp +++ b/bsnes/snes/audio/audio.cpp @@ -24,8 +24,8 @@ void Audio::sample(int16 left, int16 right) { system.interface->audio_sample(left, right); } else { dsp_buffer[dsp_wroffset] = ((uint16)left << 0) + ((uint16)right << 16); - dsp_wroffset = (dsp_wroffset + 1) & 32767; - dsp_length = (dsp_length + 1) & 32767; + dsp_wroffset = (dsp_wroffset + 1) & buffer_mask; + dsp_length = (dsp_length + 1) & buffer_mask; flush(); } } @@ -50,8 +50,8 @@ void Audio::coprocessor_sample(int16 left, int16 right) { r_frac = r_step - first; cop_buffer[cop_wroffset] = (output_left << 0) + (output_right << 16); - cop_wroffset = (cop_wroffset + 1) & 32767; - cop_length = (cop_length + 1) & 32767; + cop_wroffset = (cop_wroffset + 1) & buffer_mask; + cop_length = (cop_length + 1) & buffer_mask; flush(); } @@ -63,8 +63,8 @@ void Audio::flush() { uint32 dsp_sample = dsp_buffer[dsp_rdoffset]; uint32 cop_sample = cop_buffer[cop_rdoffset]; - dsp_rdoffset = (dsp_rdoffset + 1) & 32767; - cop_rdoffset = (cop_rdoffset + 1) & 32767; + dsp_rdoffset = (dsp_rdoffset + 1) & buffer_mask; + cop_rdoffset = (cop_rdoffset + 1) & buffer_mask; dsp_length--; cop_length--; diff --git a/bsnes/snes/audio/audio.hpp b/bsnes/snes/audio/audio.hpp index 3cd522fa..29d6dbae 100755 --- a/bsnes/snes/audio/audio.hpp +++ b/bsnes/snes/audio/audio.hpp @@ -8,7 +8,8 @@ public: private: bool coprocessor; - uint32 dsp_buffer[32768], cop_buffer[32768]; + enum : unsigned { buffer_size = 32768, buffer_mask = buffer_size - 1 }; + uint32 dsp_buffer[buffer_size], cop_buffer[buffer_size]; unsigned dsp_rdoffset, cop_rdoffset; unsigned dsp_wroffset, cop_wroffset; unsigned dsp_length, cop_length; diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index f3498ee9..cc1ed8dd 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -1,7 +1,7 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "075.05"; + static const char Version[] = "075.06"; static const unsigned SerializerVersion = 18; } } diff --git a/bsnes/ui-gameboy/main.cpp b/bsnes/ui-gameboy/main.cpp index e614b8ac..5dfca13c 100755 --- a/bsnes/ui-gameboy/main.cpp +++ b/bsnes/ui-gameboy/main.cpp @@ -38,7 +38,7 @@ void Application::main(int argc, char **argv) { audio.driver("ALSA"); #endif audio.set(Audio::Handle, (uintptr_t)mainWindow.viewport.handle()); - audio.set(Audio::Synchronize, true); + audio.set(Audio::Synchronize, false); audio.set(Audio::Volume, 100U); audio.set(Audio::Latency, 80U); audio.set(Audio::Frequency, 44100U);