diff --git a/bsnes/gameboy/apu/apu.cpp b/bsnes/gameboy/apu/apu.cpp index 9875e0e4..be3a4e77 100755 --- a/bsnes/gameboy/apu/apu.cpp +++ b/bsnes/gameboy/apu/apu.cpp @@ -47,7 +47,9 @@ void APU::main() { master.run(); interface->audioSample(master.center, master.left, master.right); - if(++clock >= 0) co_switch(scheduler.active_thread = cpu.thread); + + clock += 1 * cpu.frequency; + if(clock >= 0) co_switch(scheduler.active_thread = cpu.thread); } } diff --git a/bsnes/gameboy/apu/master/master.cpp b/bsnes/gameboy/apu/master/master.cpp index 54667357..bd0a247e 100755 --- a/bsnes/gameboy/apu/master/master.cpp +++ b/bsnes/gameboy/apu/master/master.cpp @@ -1,11 +1,6 @@ #ifdef APU_CPP void APU::Master::run() { - static int16_t volume[] = { - -16384, -14336, -12288, -10240, -8192, -6144, -4096, -2048, - +2048, +4096, +6144, +8192, +10240, +12288, +14336, +16384, - }; - if(enable == false) { center = 0; left = 0; @@ -13,22 +8,19 @@ void APU::Master::run() { return; } - signed sample = 0, channels; + signed sample = 0; sample += apu.square1.output; sample += apu.square2.output; sample += apu.wave.output; sample += apu.noise.output; - sample >>= 2; - center = volume[sample]; + center = (sample * 512) - 16384; sample = 0; - channels = 0; - if(channel1_left_enable) { sample += apu.square1.output; channels++; } - if(channel2_left_enable) { sample += apu.square2.output; channels++; } - if(channel3_left_enable) { sample += apu.wave.output; channels++; } - if(channel4_left_enable) { sample += apu.noise.output; channels++; } - if(channels) sample /= channels; - left = volume[sample]; + if(channel1_left_enable) sample += apu.square1.output; + if(channel2_left_enable) sample += apu.square2.output; + if(channel3_left_enable) sample += apu.wave.output; + if(channel4_left_enable) sample += apu.noise.output; + left = (sample * 512) - 16384; switch(left_volume) { case 0: left >>= 3; break; // 12.5% @@ -42,13 +34,11 @@ void APU::Master::run() { } sample = 0; - channels = 0; - if(channel1_right_enable) { sample += apu.square1.output; channels++; } - if(channel2_right_enable) { sample += apu.square2.output; channels++; } - if(channel3_right_enable) { sample += apu.wave.output; channels++; } - if(channel4_right_enable) { sample += apu.noise.output; channels++; } - if(channels) sample /= channels; - right = volume[sample]; + if(channel1_right_enable) sample += apu.square1.output; + if(channel2_right_enable) sample += apu.square2.output; + if(channel3_right_enable) sample += apu.wave.output; + if(channel4_right_enable) sample += apu.noise.output; + right = (sample * 512) - 16384; switch(right_volume) { case 0: right >>= 3; break; // 12.5% diff --git a/bsnes/gameboy/cpu/core/core.cpp b/bsnes/gameboy/cpu/core/core.cpp index 30a747f1..2f3601ac 100755 --- a/bsnes/gameboy/cpu/core/core.cpp +++ b/bsnes/gameboy/cpu/core/core.cpp @@ -574,6 +574,8 @@ void CPU::op_stop() { if(status.speed_switch) { status.speed_switch = 0; status.speed_double ^= 1; + frequency = 4 * 1024 * 1024; + if(status.speed_double) frequency *= 2; return; } status.stop = true; diff --git a/bsnes/gameboy/cpu/mmio/mmio.cpp b/bsnes/gameboy/cpu/mmio/mmio.cpp index d3104103..58fc4f03 100755 --- a/bsnes/gameboy/cpu/mmio/mmio.cpp +++ b/bsnes/gameboy/cpu/mmio/mmio.cpp @@ -219,7 +219,7 @@ void CPU::mmio_write(uint16 addr, uint8 data) { if(status.dma_mode == 0) do { bus.write(status.dma_target++, bus.read(status.dma_source++)); - add_clocks(4); + add_clocks(4 << status.speed_double); } while(--status.dma_length); return; } diff --git a/bsnes/gameboy/cpu/timing/opcode.cpp b/bsnes/gameboy/cpu/timing/opcode.cpp index db6c721f..5774670b 100755 --- a/bsnes/gameboy/cpu/timing/opcode.cpp +++ b/bsnes/gameboy/cpu/timing/opcode.cpp @@ -2,20 +2,20 @@ void CPU::op_io() { cycle_edge(); - add_clocks(4 >> status.speed_double); + add_clocks(4); } uint8 CPU::op_read(uint16 addr) { cycle_edge(); uint8 r = bus.read(addr); - add_clocks(4 >> status.speed_double); + add_clocks(4); return r; } void CPU::op_write(uint16 addr, uint8 data) { cycle_edge(); bus.write(addr, data); - add_clocks(4 >> status.speed_double); + add_clocks(4); } void CPU::cycle_edge() { diff --git a/bsnes/gameboy/cpu/timing/timing.cpp b/bsnes/gameboy/cpu/timing/timing.cpp index 54e17f08..cc5e3abd 100755 --- a/bsnes/gameboy/cpu/timing/timing.cpp +++ b/bsnes/gameboy/cpu/timing/timing.cpp @@ -8,7 +8,7 @@ void CPU::add_clocks(unsigned clocks) { system.clocks_executed += clocks; - scheduler.exit(Scheduler::ExitReason::StepEvent); + if(system.sgb()) scheduler.exit(Scheduler::ExitReason::StepEvent); status.clock += clocks; if(status.clock >= 4 * 1024 * 1024) { @@ -23,10 +23,10 @@ void CPU::add_clocks(unsigned clocks) { if((status.clock & 511) == 0) timer_8192hz(); if((status.clock & 1023) == 0) timer_4096hz(); - lcd.clock -= clocks; + lcd.clock -= clocks * lcd.frequency; if(lcd.clock <= 0) co_switch(scheduler.active_thread = lcd.thread); - apu.clock -= clocks; + apu.clock -= clocks * apu.frequency; if(apu.clock <= 0) co_switch(scheduler.active_thread = apu.thread); } diff --git a/bsnes/gameboy/lcd/cgb.cpp b/bsnes/gameboy/lcd/cgb.cpp index 6d552070..c29230b3 100755 --- a/bsnes/gameboy/lcd/cgb.cpp +++ b/bsnes/gameboy/lcd/cgb.cpp @@ -2,17 +2,17 @@ void LCD::cgb_render() { for(unsigned n = 0; n < 160; n++) { - line[n] = 0x0000; + line[n] = 0x7fff; origin[n] = Origin::None; } - if(status.display_enable == true) { + if(status.display_enable) { cgb_render_bg(); - if(status.window_display_enable == true) cgb_render_window(); - if(status.obj_enable == true) cgb_render_ob(); + if(status.window_display_enable) cgb_render_window(); + if(status.ob_enable) cgb_render_ob(); } - uint16_t *output = screen + status.ly * 160; + uint16 *output = screen + status.ly * 160; for(unsigned n = 0; n < 160; n++) output[n] = line[n]; interface->lcdScanline(); } @@ -107,7 +107,7 @@ void LCD::cgb_render_window() { //0x08: VRAM bank# //0x07: palette# void LCD::cgb_render_ob() { - const unsigned Height = (status.obj_size == 0 ? 8 : 16); + const unsigned Height = (status.ob_size == 0 ? 8 : 16); unsigned sprite[10], sprites = 0; //find first ten sprites on this scanline diff --git a/bsnes/gameboy/lcd/dmg.cpp b/bsnes/gameboy/lcd/dmg.cpp index ff293eae..d8e6d98e 100755 --- a/bsnes/gameboy/lcd/dmg.cpp +++ b/bsnes/gameboy/lcd/dmg.cpp @@ -6,13 +6,13 @@ void LCD::dmg_render() { origin[n] = Origin::None; } - if(status.display_enable == true) { - if(status.bg_enable == true) dmg_render_bg(); - if(status.window_display_enable == true) dmg_render_window(); - if(status.obj_enable == true) dmg_render_ob(); + if(status.display_enable) { + if(status.bg_enable) dmg_render_bg(); + if(status.window_display_enable) dmg_render_window(); + if(status.ob_enable) dmg_render_ob(); } - uint16_t *output = screen + status.ly * 160; + uint16 *output = screen + status.ly * 160; for(unsigned n = 0; n < 160; n++) output[n] = line[n]; interface->lcdScanline(); } @@ -76,7 +76,7 @@ void LCD::dmg_render_window() { //0x20: horizontal flip //0x10: palette# void LCD::dmg_render_ob() { - const unsigned Height = (status.obj_size == 0 ? 8 : 16); + const unsigned Height = (status.ob_size == 0 ? 8 : 16); unsigned sprite[10], sprites = 0; //find first ten sprites on this scanline diff --git a/bsnes/gameboy/lcd/lcd.cpp b/bsnes/gameboy/lcd/lcd.cpp index b53132a8..7a3607c6 100755 --- a/bsnes/gameboy/lcd/lcd.cpp +++ b/bsnes/gameboy/lcd/lcd.cpp @@ -41,7 +41,7 @@ void LCD::main() { } void LCD::add_clocks(unsigned clocks) { - clock += clocks; + clock += clocks * cpu.frequency; if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) { co_switch(scheduler.active_thread = cpu.thread); } @@ -127,8 +127,8 @@ void LCD::power() { status.window_display_enable = 0; status.bg_tiledata_select = 0; status.bg_tilemap_select = 0; - status.obj_size = 0; - status.obj_enable = 0; + status.ob_size = 0; + status.ob_enable = 0; status.bg_enable = 0; status.interrupt_lyc = 0; diff --git a/bsnes/gameboy/lcd/lcd.hpp b/bsnes/gameboy/lcd/lcd.hpp index 9fe752d5..f1b88115 100755 --- a/bsnes/gameboy/lcd/lcd.hpp +++ b/bsnes/gameboy/lcd/lcd.hpp @@ -11,8 +11,8 @@ struct LCD : Processor, MMIO { bool window_display_enable; bool bg_tiledata_select; bool bg_tilemap_select; - bool obj_size; - bool obj_enable; + bool ob_size; + bool ob_enable; bool bg_enable; //$ff41 STAT diff --git a/bsnes/gameboy/lcd/mmio/mmio.cpp b/bsnes/gameboy/lcd/mmio/mmio.cpp index 1e0e3197..5b20fe70 100755 --- a/bsnes/gameboy/lcd/mmio/mmio.cpp +++ b/bsnes/gameboy/lcd/mmio/mmio.cpp @@ -14,8 +14,8 @@ uint8 LCD::mmio_read(uint16 addr) { | (status.window_display_enable << 5) | (status.bg_tiledata_select << 4) | (status.bg_tilemap_select << 3) - | (status.obj_size << 2) - | (status.obj_enable << 1) + | (status.ob_size << 2) + | (status.ob_enable << 1) | (status.bg_enable << 0); } @@ -104,8 +104,8 @@ void LCD::mmio_write(uint16 addr, uint8 data) { status.window_display_enable = data & 0x20; status.bg_tiledata_select = data & 0x10; status.bg_tilemap_select = data & 0x08; - status.obj_size = data & 0x04; - status.obj_enable = data & 0x02; + status.ob_size = data & 0x04; + status.ob_enable = data & 0x02; status.bg_enable = data & 0x01; return; } diff --git a/bsnes/gameboy/lcd/serialization.cpp b/bsnes/gameboy/lcd/serialization.cpp index 45b66de2..df4752aa 100755 --- a/bsnes/gameboy/lcd/serialization.cpp +++ b/bsnes/gameboy/lcd/serialization.cpp @@ -23,8 +23,8 @@ void LCD::serialize(serializer &s) { s.integer(status.window_display_enable); s.integer(status.bg_tiledata_select); s.integer(status.bg_tilemap_select); - s.integer(status.obj_size); - s.integer(status.obj_enable); + s.integer(status.ob_size); + s.integer(status.ob_enable); s.integer(status.bg_enable); s.integer(status.interrupt_lyc); diff --git a/bsnes/phoenix/windows/platform.cpp b/bsnes/phoenix/windows/platform.cpp index 44d9efa2..560adc6d 100755 --- a/bsnes/phoenix/windows/platform.cpp +++ b/bsnes/phoenix/windows/platform.cpp @@ -299,6 +299,7 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM //mmi->ptMinTrackSize.x = 256 + window.p.frameMargin().width; //mmi->ptMinTrackSize.y = 256 + window.p.frameMargin().height; //return TRUE; + break; } case WM_ERASEBKGND: { @@ -320,6 +321,7 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM SetBkColor((HDC)wparam, window.p.brushColor); return (INT_PTR)window.p.brush; } + break; } case WM_COMMAND: { @@ -378,6 +380,7 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM } } } + break; } case WM_NOTIFY: { @@ -412,6 +415,7 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM if(listView.onActivate) listView.onActivate(); } } + break; } case WM_HSCROLL: @@ -481,6 +485,8 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM if(verticalSlider.onChange) verticalSlider.onChange(); } } + + break; } } diff --git a/bsnes/ui/config/config.cpp b/bsnes/ui/config/config.cpp index bf18c8e5..0dfbf267 100755 --- a/bsnes/ui/config/config.cpp +++ b/bsnes/ui/config/config.cpp @@ -24,7 +24,9 @@ Config::Config() { attach(audio.synchronize = true, "Audio::Synchronize"); attach(audio.mute = false, "Audio::Mute"); attach(audio.volume = 100, "Audio::Volume"); + attach(audio.latency = 60, "Audio::Latency"); + attach(audio.frequency = 48000, "Audio::Frequency::Native"); attach(audio.frequencyNES = 1789772, "Audio::Frequency::NES"); attach(audio.frequencySNES = 32000, "Audio::Frequency::SNES"); attach(audio.frequencyGameBoy = 4194304, "Audio::Frequency::GameBoy"); diff --git a/bsnes/ui/config/config.hpp b/bsnes/ui/config/config.hpp index 96e88f4a..a6c62163 100755 --- a/bsnes/ui/config/config.hpp +++ b/bsnes/ui/config/config.hpp @@ -24,7 +24,9 @@ struct Config : public configuration { bool synchronize; bool mute; unsigned volume; + unsigned latency; + unsigned frequency; unsigned frequencyNES; unsigned frequencySNES; unsigned frequencyGameBoy; diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index dfbb1986..43176054 100755 --- a/bsnes/ui/main.cpp +++ b/bsnes/ui/main.cpp @@ -27,7 +27,7 @@ void Application::run() { } Application::Application(int argc, char **argv) { - title = "bsnes v083.06"; + title = "bsnes v083.07"; application = this; quit = false; @@ -80,8 +80,8 @@ Application::Application(int argc, char **argv) { audio.driver(config->audio.driver); audio.set(Audio::Handle, mainWindow->viewport.handle()); audio.set(Audio::Synchronize, config->audio.synchronize); - audio.set(Audio::Latency, 60u); - audio.set(Audio::Frequency, 48000u); + audio.set(Audio::Latency, config->audio.latency); + audio.set(Audio::Frequency, config->audio.frequency); audio.init(); dspaudio.setPrecision(16);