diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 535f2129..720bf4ad 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "103.23"; + static const string Version = "103.24"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/gb/cartridge/mbc6/mbc6.cpp b/higan/gb/cartridge/mbc6/mbc6.cpp index 4529e74c..df672bcb 100644 --- a/higan/gb/cartridge/mbc6/mbc6.cpp +++ b/higan/gb/cartridge/mbc6/mbc6.cpp @@ -3,18 +3,62 @@ auto Cartridge::MBC6::read(uint16 address) -> uint8 { return cartridge.rom.read(address.bits(0,13)); } - if((address & 0xc000) == 0x4000) { //$4000-7fff - return cartridge.rom.read(io.rom.bank << 14 | address.bits(0,13)); + if((address & 0xe000) == 0x4000) { //$4000-5fff + return cartridge.rom.read(io.rom.bank[0] << 13 | address.bits(0,12)); + } + + if((address & 0xe000) == 0x6000) { //$6000-7fff + return cartridge.rom.read(io.rom.bank[1] << 13 | address.bits(0,12)); + } + + if((address & 0xf000) == 0xa000) { //$a000-afff + if(!io.ram.enable) return 0xff; + return cartridge.ram.read(io.ram.bank[0] << 12 | address.bits(0,11)); + } + + if((address & 0xf000) == 0xb000) { //$b000-bfff + if(!io.ram.enable) return 0xff; + return cartridge.ram.read(io.ram.bank[1] << 12 | address.bits(0,11)); } return 0xff; } auto Cartridge::MBC6::write(uint16 address, uint8 data) -> void { - if((address & 0xf000) == 0x2000) { //$2000-2fff - io.rom.bank = data; + if((address & 0xfc00) == 0x0000) { + io.ram.enable = data.bits(0,3) == 0xa; return; } + + if((address & 0xfc00) == 0x0400) { + io.ram.bank[0] = data; + return; + } + + if((address & 0xfc00) == 0x0800) { + io.ram.bank[1] = data; + return; + } + + if((address & 0xf800) == 0x2000) { + io.rom.bank[0] = data; + return; + } + + if((address & 0xf800) == 0x3000) { + io.rom.bank[1] = data; + return; + } + + if((address & 0xf000) == 0xa000) { //$a000-afff + if(!io.ram.enable) return; + return cartridge.ram.write(io.ram.bank[0] << 12 | address.bits(0,11), data); + } + + if((address & 0xf000) == 0xb000) { //$b000-bfff + if(!io.ram.enable) return; + return cartridge.ram.write(io.ram.bank[1] << 12 | address.bits(0,11), data); + } } auto Cartridge::MBC6::power() -> void { @@ -22,4 +66,9 @@ auto Cartridge::MBC6::power() -> void { } auto Cartridge::MBC6::serialize(serializer& s) -> void { + s.integer(io.rom.bank[0]); + s.integer(io.rom.bank[1]); + s.integer(io.ram.enable); + s.integer(io.ram.bank[0]); + s.integer(io.ram.bank[1]); } diff --git a/higan/gb/cartridge/mbc6/mbc6.hpp b/higan/gb/cartridge/mbc6/mbc6.hpp index e2212b86..927b872a 100644 --- a/higan/gb/cartridge/mbc6/mbc6.hpp +++ b/higan/gb/cartridge/mbc6/mbc6.hpp @@ -6,7 +6,11 @@ struct MBC6 : Mapper { struct IO { struct ROM { - uint8 bank = 0x01; + uint8 bank[2]; } rom; + struct RAM { + uint1 enable; + uint8 bank[2]; + } ram; } io; } mbc6; diff --git a/higan/gb/cartridge/mbc7/mbc7.cpp b/higan/gb/cartridge/mbc7/mbc7.cpp index fdd29505..4494bd22 100644 --- a/higan/gb/cartridge/mbc7/mbc7.cpp +++ b/higan/gb/cartridge/mbc7/mbc7.cpp @@ -3,7 +3,7 @@ auto Cartridge::MBC7::read(uint16 address) -> uint8 { return cartridge.rom.read(address.bits(0,13)); } - if((address & 0xc000) == 0x0000) { //$4000-7fff + if((address & 0xc000) == 0x4000) { //$4000-7fff return cartridge.rom.read(io.rom.bank << 14 | address.bits(0,13)); } @@ -15,8 +15,8 @@ auto Cartridge::MBC7::read(uint16 address) -> uint8 { case 3: return io.accelerometer.x.bits(8,15); case 4: return io.accelerometer.y.bits(0, 7); case 5: return io.accelerometer.y.bits(8,15); - case 6: return io.accelerometer.z.bits(0, 7); - case 7: return io.accelerometer.z.bits(8,15); + case 6: return 0x00; //z? + case 7: return 0xff; //z? case 8: return 0xff; } @@ -78,4 +78,9 @@ auto Cartridge::MBC7::power() -> void { } auto Cartridge::MBC7::serialize(serializer& s) -> void { + s.integer(io.rom.bank); + s.integer(io.ram.enable[0]); + s.integer(io.ram.enable[1]); + s.integer(io.accelerometer.x); + s.integer(io.accelerometer.y); } diff --git a/higan/gb/cartridge/mbc7/mbc7.hpp b/higan/gb/cartridge/mbc7/mbc7.hpp index 851ee67f..c32df17c 100644 --- a/higan/gb/cartridge/mbc7/mbc7.hpp +++ b/higan/gb/cartridge/mbc7/mbc7.hpp @@ -14,7 +14,6 @@ struct MBC7 : Mapper { struct Accelerometer { uint16 x = 0x8000; uint16 y = 0x8000; - uint16 z = 0xff00; //unused } accelerometer; } io; } mbc7; diff --git a/higan/gb/cpu/timing.cpp b/higan/gb/cpu/timing.cpp index 71e619f9..c4e7e206 100644 --- a/higan/gb/cpu/timing.cpp +++ b/higan/gb/cpu/timing.cpp @@ -76,8 +76,8 @@ auto CPU::hblank() -> void { if(status.dmaMode == 1 && status.dmaLength && ppu.status.ly < 144) { for(auto n : range(16)) { writeDMA(status.dmaTarget++, readDMA(status.dmaSource++)); + status.dmaLength--; + if(n & 1) step(1 << status.speedDouble); } - step(8 << status.speedDouble); - status.dmaLength -= 16; } } diff --git a/higan/gb/ppu/cgb.cpp b/higan/gb/ppu/cgb.cpp index 14dd9a57..c6b2bc5c 100644 --- a/higan/gb/ppu/cgb.cpp +++ b/higan/gb/ppu/cgb.cpp @@ -37,7 +37,6 @@ auto PPU::readTileCGB(bool select, uint x, uint y, uint& attr, uint& data) -> vo auto PPU::scanlineCGB() -> void { px = 0; - if(!enabled()) return; const uint Height = (status.obSize == 0 ? 8 : 16); sprites = 0; @@ -69,24 +68,22 @@ auto PPU::runCGB() -> void { ob.priority = 0; uint color = 0x7fff; - if(enabled()) { - runBackgroundCGB(); - if(status.windowDisplayEnable) runWindowCGB(); - if(status.obEnable) runObjectsCGB(); + runBackgroundCGB(); + if(status.windowDisplayEnable) runWindowCGB(); + if(status.obEnable) runObjectsCGB(); - if(ob.palette == 0) { - color = bg.color; - } else if(bg.palette == 0) { - color = ob.color; - } else if(status.bgEnable == 0) { - color = ob.color; - } else if(bg.priority) { - color = bg.color; - } else if(ob.priority) { - color = ob.color; - } else { - color = bg.color; - } + if(ob.palette == 0) { + color = bg.color; + } else if(bg.palette == 0) { + color = ob.color; + } else if(status.bgEnable == 0) { + color = ob.color; + } else if(bg.priority) { + color = bg.color; + } else if(ob.priority) { + color = ob.color; + } else { + color = bg.color; } uint32* output = screen + status.ly * 160 + px++; diff --git a/higan/gb/ppu/dmg.cpp b/higan/gb/ppu/dmg.cpp index 3619796e..10c3ff46 100644 --- a/higan/gb/ppu/dmg.cpp +++ b/higan/gb/ppu/dmg.cpp @@ -19,7 +19,6 @@ auto PPU::readTileDMG(bool select, uint x, uint y, uint& data) -> void { auto PPU::scanlineDMG() -> void { px = 0; - if(!enabled()) return; const uint Height = (status.obSize == 0 ? 8 : 16); sprites = 0; @@ -60,20 +59,18 @@ auto PPU::runDMG() -> void { ob.palette = 0; uint color = 0; - if(enabled()) { - if(status.bgEnable) runBackgroundDMG(); - if(status.windowDisplayEnable) runWindowDMG(); - if(status.obEnable) runObjectsDMG(); + if(status.bgEnable) runBackgroundDMG(); + if(status.windowDisplayEnable) runWindowDMG(); + if(status.obEnable) runObjectsDMG(); - if(ob.palette == 0) { - color = bg.color; - } else if(bg.palette == 0) { - color = ob.color; - } else if(ob.priority) { - color = ob.color; - } else { - color = bg.color; - } + if(ob.palette == 0) { + color = bg.color; + } else if(bg.palette == 0) { + color = ob.color; + } else if(ob.priority) { + color = ob.color; + } else { + color = bg.color; } uint32* output = screen + status.ly * 160 + px++; diff --git a/higan/gb/ppu/io.cpp b/higan/gb/ppu/io.cpp index b07617ca..738c22f6 100644 --- a/higan/gb/ppu/io.cpp +++ b/higan/gb/ppu/io.cpp @@ -113,7 +113,7 @@ auto PPU::writeIO(uint16 addr, uint8 data) -> void { } if(addr == 0xff40) { //LCDC - if(!status.displayEnable && (data & 0x80)) { + if(status.displayEnable && !data.bit(7)) { status.ly = 0; status.lx = 0; diff --git a/higan/gb/ppu/ppu.cpp b/higan/gb/ppu/ppu.cpp index 6d6d90b3..43939ea5 100644 --- a/higan/gb/ppu/ppu.cpp +++ b/higan/gb/ppu/ppu.cpp @@ -8,13 +8,13 @@ PPU ppu; #include "cgb.cpp" #include "serialization.cpp" -auto PPU::enabled() const -> bool { return status.displayEnable; } - auto PPU::Enter() -> void { while(true) scheduler.synchronize(), ppu.main(); } auto PPU::main() -> void { + if(!status.displayEnable) return step(456); + status.lx = 0; if(Model::SuperGameBoy()) superGameBoy->lcdScanline(); @@ -30,7 +30,7 @@ auto PPU::main() -> void { } mode(0); - if(enabled()) cpu.hblank(); + cpu.hblank(); step(204); } else { mode(1); @@ -40,7 +40,7 @@ auto PPU::main() -> void { status.ly++; if(status.ly == 144) { - if(enabled()) cpu.raise(CPU::Interrupt::Vblank); + cpu.raise(CPU::Interrupt::Vblank); scheduler.exit(Scheduler::Event::Frame); } diff --git a/higan/gb/ppu/ppu.hpp b/higan/gb/ppu/ppu.hpp index d7e6cb5d..c85394a5 100644 --- a/higan/gb/ppu/ppu.hpp +++ b/higan/gb/ppu/ppu.hpp @@ -1,6 +1,4 @@ struct PPU : Thread, MMIO { - auto enabled() const -> bool; - static auto Enter() -> void; auto main() -> void; auto mode(uint) -> void; diff --git a/higan/md/controller/control-pad/control-pad.cpp b/higan/md/controller/control-pad/control-pad.cpp new file mode 100644 index 00000000..42c93a52 --- /dev/null +++ b/higan/md/controller/control-pad/control-pad.cpp @@ -0,0 +1,29 @@ +ControlPad::ControlPad(uint port) : Controller(port) { +} + +auto ControlPad::readData() -> uint8 { + uint6 data; + + if(select == 0) { + data.bit(0) = platform->inputPoll(port, ID::Device::ControlPad, Up); + data.bit(1) = platform->inputPoll(port, ID::Device::ControlPad, Down); + data.bits(2,3) = ~0; + data.bit(4) = platform->inputPoll(port, ID::Device::ControlPad, A); + data.bit(5) = platform->inputPoll(port, ID::Device::ControlPad, Start); + } else { + data.bit(0) = platform->inputPoll(port, ID::Device::ControlPad, Up); + data.bit(1) = platform->inputPoll(port, ID::Device::ControlPad, Down); + data.bit(2) = platform->inputPoll(port, ID::Device::ControlPad, Left); + data.bit(3) = platform->inputPoll(port, ID::Device::ControlPad, Right); + data.bit(4) = platform->inputPoll(port, ID::Device::ControlPad, B); + data.bit(5) = platform->inputPoll(port, ID::Device::ControlPad, C); + } + + data = ~data; + return latch << 7 | select << 6 | data; +} + +auto ControlPad::writeData(uint8 data) -> void { + select = data.bit(6); + latch = data.bit(7); +} diff --git a/higan/md/controller/gamepad/gamepad.hpp b/higan/md/controller/control-pad/control-pad.hpp similarity index 62% rename from higan/md/controller/gamepad/gamepad.hpp rename to higan/md/controller/control-pad/control-pad.hpp index 59becc9e..406456c3 100644 --- a/higan/md/controller/gamepad/gamepad.hpp +++ b/higan/md/controller/control-pad/control-pad.hpp @@ -1,13 +1,13 @@ -struct Gamepad : Controller { +struct ControlPad : Controller { enum : uint { Up, Down, Left, Right, A, B, C, Start, }; - Gamepad(uint port); + ControlPad(uint port); auto readData() -> uint8 override; auto writeData(uint8 data) -> void override; - boolean select; - boolean latch; + uint1 select = 1; + uint1 latch; }; diff --git a/higan/md/controller/controller.cpp b/higan/md/controller/controller.cpp index 61d440fd..f612fb38 100644 --- a/higan/md/controller/controller.cpp +++ b/higan/md/controller/controller.cpp @@ -5,7 +5,8 @@ namespace MegaDrive { ControllerPort controllerPort1; ControllerPort controllerPort2; ControllerPort extensionPort; -#include "gamepad/gamepad.cpp" +#include "control-pad/control-pad.cpp" +#include "fighting-pad/fighting-pad.cpp" Controller::Controller(uint port) : port(port) { if(!handle()) create(Controller::Enter, 1); @@ -37,7 +38,8 @@ auto ControllerPort::connect(uint deviceID) -> void { switch(deviceID) { default: case ID::Device::None: device = new Controller(port); break; - case ID::Device::Gamepad: device = new Gamepad(port); break; + case ID::Device::ControlPad: device = new ControlPad(port); break; + case ID::Device::FightingPad: device = new FightingPad(port); break; } cpu.peripherals.reset(); diff --git a/higan/md/controller/controller.hpp b/higan/md/controller/controller.hpp index 399a92d3..3ab12802 100644 --- a/higan/md/controller/controller.hpp +++ b/higan/md/controller/controller.hpp @@ -3,7 +3,7 @@ struct Controller : Thread { virtual ~Controller(); static auto Enter() -> void; - auto main() -> void; + virtual auto main() -> void; virtual auto readData() -> uint8 { return 0xff; } virtual auto writeData(uint8 data) -> void {} @@ -30,4 +30,5 @@ extern ControllerPort controllerPort1; extern ControllerPort controllerPort2; extern ControllerPort extensionPort; -#include "gamepad/gamepad.hpp" +#include "control-pad/control-pad.hpp" +#include "fighting-pad/fighting-pad.hpp" diff --git a/higan/md/controller/fighting-pad/fighting-pad.cpp b/higan/md/controller/fighting-pad/fighting-pad.cpp new file mode 100644 index 00000000..0bc5fc4e --- /dev/null +++ b/higan/md/controller/fighting-pad/fighting-pad.cpp @@ -0,0 +1,66 @@ +FightingPad::FightingPad(uint port) : Controller(port) { + create(Controller::Enter, 1'000'000); +} + +auto FightingPad::main() -> void { + if(timeout) { + timeout--; + } else { + counter = 0; + } + step(1); + synchronize(cpu); +} + +auto FightingPad::readData() -> uint8 { + uint6 data; + + if(select == 0) { + if(counter == 0 || counter == 1 || counter == 4) { + data.bit(0) = platform->inputPoll(port, ID::Device::FightingPad, Up); + data.bit(1) = platform->inputPoll(port, ID::Device::FightingPad, Down); + data.bits(2,3) = ~0; + } + + if(counter == 2) { + data.bits(0,3) = ~0; //controller type detection + } + + if(counter == 3) { + data.bits(0,3) = 0; + } + + data.bit(4) = platform->inputPoll(port, ID::Device::FightingPad, A); + data.bit(5) = platform->inputPoll(port, ID::Device::FightingPad, Start); + } else { + if(counter == 0 || counter == 1 || counter == 2 || counter == 4) { + data.bit(0) = platform->inputPoll(port, ID::Device::FightingPad, Up); + data.bit(1) = platform->inputPoll(port, ID::Device::FightingPad, Down); + data.bit(2) = platform->inputPoll(port, ID::Device::FightingPad, Left); + data.bit(3) = platform->inputPoll(port, ID::Device::FightingPad, Right); + data.bit(4) = platform->inputPoll(port, ID::Device::FightingPad, B); + data.bit(5) = platform->inputPoll(port, ID::Device::FightingPad, C); + } + + if(counter == 3) { + data.bit(0) = platform->inputPoll(port, ID::Device::FightingPad, Z); + data.bit(1) = platform->inputPoll(port, ID::Device::FightingPad, Y); + data.bit(2) = platform->inputPoll(port, ID::Device::FightingPad, X); + data.bit(3) = platform->inputPoll(port, ID::Device::FightingPad, Mode); + data.bits(4,5) = 0; + } + } + + data = ~data; + return latch << 7 | select << 6 | data; +} + +auto FightingPad::writeData(uint8 data) -> void { + if(!select && data.bit(6)) { //0->1 transition + if(++counter == 5) counter = 0; + } + + select = data.bit(6); + latch = data.bit(7); + timeout = 1600; //~1.6ms +} diff --git a/higan/md/controller/fighting-pad/fighting-pad.hpp b/higan/md/controller/fighting-pad/fighting-pad.hpp new file mode 100644 index 00000000..fcd3f42b --- /dev/null +++ b/higan/md/controller/fighting-pad/fighting-pad.hpp @@ -0,0 +1,16 @@ +struct FightingPad : Controller { + enum : uint { + Up, Down, Left, Right, A, B, C, X, Y, Z, Mode, Start, + }; + + FightingPad(uint port); + auto main() -> void override; + + auto readData() -> uint8 override; + auto writeData(uint8 data) -> void override; + + uint1 select = 1; + uint1 latch; + uint3 counter; + uint32 timeout; +}; diff --git a/higan/md/controller/gamepad/gamepad.cpp b/higan/md/controller/gamepad/gamepad.cpp deleted file mode 100644 index b9703bf9..00000000 --- a/higan/md/controller/gamepad/gamepad.cpp +++ /dev/null @@ -1,30 +0,0 @@ -Gamepad::Gamepad(uint port) : Controller(port) { -} - -auto Gamepad::readData() -> uint8 { - uint6 data; - - if(select == 0) { - data.bit(0) = platform->inputPoll(port, ID::Device::Gamepad, Up); - data.bit(1) = platform->inputPoll(port, ID::Device::Gamepad, Down); - data.bit(2) = 1; - data.bit(3) = 1; - data.bit(4) = platform->inputPoll(port, ID::Device::Gamepad, A); - data.bit(5) = platform->inputPoll(port, ID::Device::Gamepad, Start); - } else { - data.bit(0) = platform->inputPoll(port, ID::Device::Gamepad, Up); - data.bit(1) = platform->inputPoll(port, ID::Device::Gamepad, Down); - data.bit(2) = platform->inputPoll(port, ID::Device::Gamepad, Left); - data.bit(3) = platform->inputPoll(port, ID::Device::Gamepad, Right); - data.bit(4) = platform->inputPoll(port, ID::Device::Gamepad, B); - data.bit(5) = platform->inputPoll(port, ID::Device::Gamepad, C); - } - - data = ~data; - return latch << 7 | select << 6 | data; -} - -auto Gamepad::writeData(uint8 data) -> void { - select = data.bit(6); - latch = data.bit(7); -} diff --git a/higan/md/interface/interface.cpp b/higan/md/interface/interface.cpp index 5ed75279..ca7860f2 100644 --- a/higan/md/interface/interface.cpp +++ b/higan/md/interface/interface.cpp @@ -26,7 +26,7 @@ Interface::Interface() { extensionPort.devices.append(device); } - { Device device{ID::Device::Gamepad, "Gamepad"}; + { Device device{ID::Device::ControlPad, "Control Pad"}; device.inputs.append({0, "Up" }); device.inputs.append({0, "Down" }); device.inputs.append({0, "Left" }); @@ -39,6 +39,23 @@ Interface::Interface() { controllerPort2.devices.append(device); } + { Device device{ID::Device::FightingPad, "Fighting Pad"}; + device.inputs.append({0, "Up" }); + device.inputs.append({0, "Down" }); + device.inputs.append({0, "Left" }); + device.inputs.append({0, "Right"}); + device.inputs.append({0, "A" }); + device.inputs.append({0, "B" }); + device.inputs.append({0, "C" }); + device.inputs.append({0, "X" }); + device.inputs.append({0, "Y" }); + device.inputs.append({0, "Z" }); + device.inputs.append({0, "Mode" }); + device.inputs.append({0, "Start"}); + controllerPort1.devices.append(device); + controllerPort2.devices.append(device); + } + ports.append(move(controllerPort1)); ports.append(move(controllerPort2)); ports.append(move(extensionPort)); diff --git a/higan/md/interface/interface.hpp b/higan/md/interface/interface.hpp index 664af71a..dc70a8ba 100644 --- a/higan/md/interface/interface.hpp +++ b/higan/md/interface/interface.hpp @@ -14,7 +14,8 @@ struct ID { struct Device { enum : uint { None, - Gamepad, + ControlPad, + FightingPad, };}; }; diff --git a/higan/processor/m68k/instructions.cpp b/higan/processor/m68k/instructions.cpp index 9285bdbc..27d4aa9e 100644 --- a/higan/processor/m68k/instructions.cpp +++ b/higan/processor/m68k/instructions.cpp @@ -1131,12 +1131,17 @@ auto M68K::instructionSWAP(DataRegister with) -> void { } auto M68K::instructionTAS(EffectiveAddress with) -> void { -//auto data = read(with); -//write(with, data | 0x80); + uint32 data; - //Mega Drive models 1&2 have a bug that prevents TAS write cycle from completing - //this bugged behavior is required for certain software to function correctly - auto data = read(with); + if(with.mode == DataRegisterDirect) { + data = read(with); + write(with, data | 0x80); + } else { + //Mega Drive models 1&2 have a bug that prevents TAS write from taking effect + //this bugged behavior is required for certain software to function correctly + data = read(with); + step(4); + } r.c = 0; r.v = 0; diff --git a/hiro/windows/desktop.cpp b/hiro/windows/desktop.cpp index 2a5f56fb..04e67020 100644 --- a/hiro/windows/desktop.cpp +++ b/hiro/windows/desktop.cpp @@ -1,17 +1,17 @@ -#if defined(Hiro_Desktop) - -namespace hiro { - -auto pDesktop::size() -> Size { - return {GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN)}; -} - -auto pDesktop::workspace() -> Geometry { - RECT rc; - SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); - return {rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top}; -} - -} - -#endif +#if defined(Hiro_Desktop) + +namespace hiro { + +auto pDesktop::size() -> Size { + return {GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN)}; +} + +auto pDesktop::workspace() -> Geometry { + RECT rc; + SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); + return {rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top}; +} + +} + +#endif diff --git a/hiro/windows/mouse.cpp b/hiro/windows/mouse.cpp index 89898ad8..63c3ffdc 100644 --- a/hiro/windows/mouse.cpp +++ b/hiro/windows/mouse.cpp @@ -1,22 +1,22 @@ -#if defined(Hiro_Mouse) - -namespace hiro { - -auto pMouse::position() -> Position { - POINT point{0}; - GetCursorPos(&point); - return {point.x, point.y}; -} - -auto pMouse::pressed(Mouse::Button button) -> bool { - switch(button) { - case Mouse::Button::Left: return GetAsyncKeyState(VK_LBUTTON) & 0x8000; - case Mouse::Button::Middle: return GetAsyncKeyState(VK_MBUTTON) & 0x8000; - case Mouse::Button::Right: return GetAsyncKeyState(VK_RBUTTON) & 0x8000; - } - return false; -} - -} - -#endif +#if defined(Hiro_Mouse) + +namespace hiro { + +auto pMouse::position() -> Position { + POINT point{}; + GetCursorPos(&point); + return {point.x, point.y}; +} + +auto pMouse::pressed(Mouse::Button button) -> bool { + switch(button) { + case Mouse::Button::Left: return GetAsyncKeyState(VK_LBUTTON) & 0x8000; + case Mouse::Button::Middle: return GetAsyncKeyState(VK_MBUTTON) & 0x8000; + case Mouse::Button::Right: return GetAsyncKeyState(VK_RBUTTON) & 0x8000; + } + return false; +} + +} + +#endif diff --git a/ruby/audio/alsa.cpp b/ruby/audio/alsa.cpp index d3185635..aec30061 100644 --- a/ruby/audio/alsa.cpp +++ b/ruby/audio/alsa.cpp @@ -6,11 +6,27 @@ struct AudioALSA : Audio { auto ready() -> bool { return _ready; } + auto information() -> Information { + Information information; + information.devices = queryDevices(); + information.frequencies = {44100.0, 48000.0, 96000.0}; + information.latencies = {20, 40, 60, 80, 100}; + information.channels = {2}; + return information; + } + + auto device() -> string { return _device; } auto blocking() -> bool { return _blocking; } auto channels() -> uint { return 2; } auto frequency() -> double { return _frequency; } auto latency() -> uint { return _latency; } + auto setDevice(string device) -> bool { + if(_device == device) return true; + _device = device; + return initialize(); + } + auto setBlocking(bool blocking) -> bool { if(_blocking == blocking) return true; _blocking = blocking; @@ -76,7 +92,9 @@ private: auto initialize() -> bool { terminate(); - if(snd_pcm_open(&_interface, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) return terminate(), false; + string device = "default"; + if(queryDevices().find(_device)) device = _device; + if(snd_pcm_open(&_interface, device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) return terminate(), false; uint rate = (uint)_frequency; uint bufferTime = _latency * 1000; @@ -122,10 +140,29 @@ private: if(_buffer) { delete[] _buffer; _buffer = nullptr; - } + } + } + + auto queryDevices() -> string_vector { + string_vector devices; + + const char** list; + if(snd_device_name_hint(-1, "pcm", (void***)&list) == 0) { + uint index = 0; + while(list[index]) { + const char* deviceName = snd_device_name_get_hint(list[index], "NAME"); + if(deviceName) devices.append(deviceName); + free(deviceName); + index++; + } + } + + snd_device_name_free_hint((void**)list); + return devices; } bool _ready = false; + string _device; bool _blocking = true; double _frequency = 48000.0; uint _latency = 40; diff --git a/ruby/audio/ao.cpp b/ruby/audio/ao.cpp index e34da4c2..3afa0b2e 100644 --- a/ruby/audio/ao.cpp +++ b/ruby/audio/ao.cpp @@ -44,6 +44,7 @@ struct AudioAO : Audio { format.channels = 2; format.rate = (uint)_frequency; format.byte_format = AO_FMT_LITTLE; + format.matrix = nullptr; ao_info* information = ao_driver_info(driverID); if(!information) return false; diff --git a/ruby/ruby.hpp b/ruby/ruby.hpp index 1d48ba57..798b4550 100644 --- a/ruby/ruby.hpp +++ b/ruby/ruby.hpp @@ -63,7 +63,7 @@ struct Audio { virtual ~Audio() = default; virtual auto ready() -> bool { return true; } - virtual auto information() -> Information { return {{"None"}, {48000.0}, {0}, {2}}; } + virtual auto information() -> Information { return {{"Default"}, {48000.0}, {0}, {2}}; } virtual auto exclusive() -> bool { return false; } virtual auto context() -> uintptr { return 0; } diff --git a/ruby/video/cgl.cpp b/ruby/video/cgl.cpp index d97fddd2..c6b63c8b 100644 --- a/ruby/video/cgl.cpp +++ b/ruby/video/cgl.cpp @@ -127,7 +127,7 @@ private: return _ready = true; } - auto term() -> void { + auto terminate() -> void { _ready = false; OpenGL::terminate();