diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 2c9a5648..535f2129 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.22"; + static const string Version = "103.23"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/gb/cartridge/cartridge.cpp b/higan/gb/cartridge/cartridge.cpp index b07bd81b..37dbcab5 100644 --- a/higan/gb/cartridge/cartridge.cpp +++ b/higan/gb/cartridge/cartridge.cpp @@ -9,6 +9,8 @@ Cartridge cartridge; #include "mbc2/mbc2.cpp" #include "mbc3/mbc3.cpp" #include "mbc5/mbc5.cpp" +#include "mbc6/mbc6.cpp" +#include "mbc7/mbc7.cpp" #include "mmm01/mmm01.cpp" #include "huc1/huc1.cpp" #include "huc3/huc3.cpp" @@ -51,10 +53,16 @@ auto Cartridge::load() -> bool { if(mapperID == "MBC2" ) mapper = &mbc2; if(mapperID == "MBC3" ) mapper = &mbc3; if(mapperID == "MBC5" ) mapper = &mbc5; + if(mapperID == "MBC6" ) mapper = &mbc6; + if(mapperID == "MBC7" ) mapper = &mbc7; if(mapperID == "MMM01") mapper = &mmm01; if(mapperID == "HuC1" ) mapper = &huc1; if(mapperID == "HuC3" ) mapper = &huc3; if(mapperID == "TAMA" ) mapper = &tama; + if(!mapper) mapper = &mbc0; + + accelerometer = (bool)document["board/accelerometer"]; + rumble = (bool)document["board/rumble"]; rom.size = max(0x4000, document["board/rom/size"].natural()); rom.data = (uint8*)memory::allocate(rom.size, 0xff); diff --git a/higan/gb/cartridge/cartridge.hpp b/higan/gb/cartridge/cartridge.hpp index 06e5655f..c5cd7cc7 100644 --- a/higan/gb/cartridge/cartridge.hpp +++ b/higan/gb/cartridge/cartridge.hpp @@ -42,6 +42,8 @@ private: virtual auto serialize(serializer&) -> void = 0; }; Mapper* mapper = nullptr; + bool accelerometer = false; + bool rumble = false; #include "mbc0/mbc0.hpp" #include "mbc1/mbc1.hpp" @@ -49,6 +51,8 @@ private: #include "mbc2/mbc2.hpp" #include "mbc3/mbc3.hpp" #include "mbc5/mbc5.hpp" + #include "mbc6/mbc6.hpp" + #include "mbc7/mbc7.hpp" #include "mmm01/mmm01.hpp" #include "huc1/huc1.hpp" #include "huc3/huc3.hpp" diff --git a/higan/gb/cartridge/mbc5/mbc5.cpp b/higan/gb/cartridge/mbc5/mbc5.cpp index b3b4b404..a4d8785b 100644 --- a/higan/gb/cartridge/mbc5/mbc5.cpp +++ b/higan/gb/cartridge/mbc5/mbc5.cpp @@ -32,6 +32,7 @@ auto Cartridge::MBC5::write(uint16 address, uint8 data) -> void { } if((address & 0xe000) == 0x4000) { //$4000-5fff + if(cartridge.rumble) platform->inputRumble(ID::Port::Hardware, ID::Device::Controls, 10, data.bit(3)); io.ram.bank = data.bits(0,3); return; } diff --git a/higan/gb/cartridge/mbc6/mbc6.cpp b/higan/gb/cartridge/mbc6/mbc6.cpp new file mode 100644 index 00000000..4529e74c --- /dev/null +++ b/higan/gb/cartridge/mbc6/mbc6.cpp @@ -0,0 +1,25 @@ +auto Cartridge::MBC6::read(uint16 address) -> uint8 { + if((address & 0xc000) == 0x0000) { //$0000-3fff + 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)); + } + + return 0xff; +} + +auto Cartridge::MBC6::write(uint16 address, uint8 data) -> void { + if((address & 0xf000) == 0x2000) { //$2000-2fff + io.rom.bank = data; + return; + } +} + +auto Cartridge::MBC6::power() -> void { + io = {}; +} + +auto Cartridge::MBC6::serialize(serializer& s) -> void { +} diff --git a/higan/gb/cartridge/mbc6/mbc6.hpp b/higan/gb/cartridge/mbc6/mbc6.hpp new file mode 100644 index 00000000..e2212b86 --- /dev/null +++ b/higan/gb/cartridge/mbc6/mbc6.hpp @@ -0,0 +1,12 @@ +struct MBC6 : Mapper { + auto read(uint16 address) -> uint8; + auto write(uint16 address, uint8 data) -> void; + auto power() -> void; + auto serialize(serializer&) -> void; + + struct IO { + struct ROM { + uint8 bank = 0x01; + } rom; + } io; +} mbc6; diff --git a/higan/gb/cartridge/mbc7/mbc7.cpp b/higan/gb/cartridge/mbc7/mbc7.cpp new file mode 100644 index 00000000..fdd29505 --- /dev/null +++ b/higan/gb/cartridge/mbc7/mbc7.cpp @@ -0,0 +1,81 @@ +auto Cartridge::MBC7::read(uint16 address) -> uint8 { + if((address & 0xc000) == 0x0000) { //$0000-3fff + return cartridge.rom.read(address.bits(0,13)); + } + + if((address & 0xc000) == 0x0000) { //$4000-7fff + return cartridge.rom.read(io.rom.bank << 14 | address.bits(0,13)); + } + + if((address & 0xf000) == 0xa000) { //$a000-afff + if(!io.ram.enable[0] || !io.ram.enable[1]) return 0xff; + + switch(address.bits(4,7)) { + case 2: return io.accelerometer.x.bits(0, 7); + 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 8: return 0xff; + } + + return 0xff; + } + + return 0xff; +} + +auto Cartridge::MBC7::write(uint16 address, uint8 data) -> void { + if((address & 0xe000) == 0x0000) { //$0000-1fff + io.ram.enable[0] = data.bits(0,3) == 0xa; + if(!io.ram.enable[0]) io.ram.enable[1] = false; + return; + } + + if((address & 0xe000) == 0x2000) { //$2000-3fff + io.rom.bank = data; + if(!io.rom.bank) io.rom.bank = 1; + return; + } + + if((address & 0xe000) == 0x4000) { //$4000-5fff + if(!io.ram.enable[0]) return; + io.ram.enable[1] = data == 0x40; + } + + if((address & 0xf000) == 0xa000) { //$a000-afff + if(!io.ram.enable[0] || !io.ram.enable[1]) return; + + switch(address.bits(4,7)) { + + case 0: { + if(data != 0x55) break; + io.accelerometer.x = 0x8000; + io.accelerometer.y = 0x8000; + break; + } + + case 1: { + if(data != 0xaa) break; + io.accelerometer.x = 0x8000 + platform->inputPoll(ID::Port::Hardware, ID::Device::Controls, 8); + io.accelerometer.y = 0x8000 + platform->inputPoll(ID::Port::Hardware, ID::Device::Controls, 9); + break; + } + + case 8: { + break; + } + + } + + return; + } +} + +auto Cartridge::MBC7::power() -> void { + io = {}; +} + +auto Cartridge::MBC7::serialize(serializer& s) -> void { +} diff --git a/higan/gb/cartridge/mbc7/mbc7.hpp b/higan/gb/cartridge/mbc7/mbc7.hpp new file mode 100644 index 00000000..851ee67f --- /dev/null +++ b/higan/gb/cartridge/mbc7/mbc7.hpp @@ -0,0 +1,20 @@ +struct MBC7 : Mapper { + auto read(uint16 address) -> uint8; + auto write(uint16 address, uint8 data) -> void; + auto power() -> void; + auto serialize(serializer&) -> void; + + struct IO { + struct ROM { + uint8 bank = 0x01; + } rom; + struct RAM { + uint1 enable[2]; + } ram; + struct Accelerometer { + uint16 x = 0x8000; + uint16 y = 0x8000; + uint16 z = 0xff00; //unused + } accelerometer; + } io; +} mbc7; diff --git a/higan/gb/cartridge/tama/tama.cpp b/higan/gb/cartridge/tama/tama.cpp index c6ddf7ba..d83ef792 100644 --- a/higan/gb/cartridge/tama/tama.cpp +++ b/higan/gb/cartridge/tama/tama.cpp @@ -183,6 +183,10 @@ auto Cartridge::TAMA::write(uint16 address, uint8 data) -> void { rtc.second = 0; //hack: unclear where this is really being set (if it is at all) } + if(io.mode == 4 && io.index == 0x02 && io.input.bits(0,3) == 0xb) { + rtc.leapYear = data.bits(4,5); + } + if(io.mode == 4 && io.index == 0x02 && io.input.bits(0,3) == 0xe) { rtc.test = io.input.bits(4,7); } diff --git a/higan/gb/interface/interface.cpp b/higan/gb/interface/interface.cpp index 8a85971b..61492f08 100644 --- a/higan/gb/interface/interface.cpp +++ b/higan/gb/interface/interface.cpp @@ -19,6 +19,9 @@ Interface::Interface() { device.inputs.append({0, "A" }); device.inputs.append({0, "Select"}); device.inputs.append({0, "Start" }); + device.inputs.append({1, "X-axis"}); + device.inputs.append({1, "Y-axis"}); + device.inputs.append({2, "Rumble"}); hardwarePort.devices.append(device); } diff --git a/higan/target-tomoko/presentation/presentation.cpp b/higan/target-tomoko/presentation/presentation.cpp index 2451f089..ef45e03f 100644 --- a/higan/target-tomoko/presentation/presentation.cpp +++ b/higan/target-tomoko/presentation/presentation.cpp @@ -169,12 +169,10 @@ Presentation::Presentation() { #endif #if defined(PLATFORM_MACOSX) - showConfigurationSeparator.setVisible(false); - showConfiguration.setVisible(false); about.setVisible(false); Application::Cocoa::onAbout([&] { about.doActivate(); }); Application::Cocoa::onActivate([&] { setFocused(); }); - Application::Cocoa::onPreferences([&] { showConfiguration.doActivate(); }); + Application::Cocoa::onPreferences([&] { showInputSettings.doActivate(); }); Application::Cocoa::onQuit([&] { doClose(); }); #endif } diff --git a/hiro/cocoa/widget/table-view-cell.cpp b/hiro/cocoa/widget/table-view-cell.cpp index 2da1596a..6edcb73f 100644 --- a/hiro/cocoa/widget/table-view-cell.cpp +++ b/hiro/cocoa/widget/table-view-cell.cpp @@ -9,29 +9,31 @@ auto pTableViewCell::destruct() -> void { } auto pTableViewCell::setAlignment(Alignment alignment) -> void { + _redraw(); } auto pTableViewCell::setBackgroundColor(Color color) -> void { + _redraw(); } auto pTableViewCell::setCheckable(bool checkable) -> void { + _redraw(); } auto pTableViewCell::setChecked(bool checked) -> void { + _redraw(); } auto pTableViewCell::setForegroundColor(Color color) -> void { + _redraw(); } auto pTableViewCell::setIcon(const image& icon) -> void { + _redraw(); } auto pTableViewCell::setText(const string& text) -> void { - @autoreleasepool { - if(auto pTableView = _grandparent()) { - [[pTableView->cocoaView content] reloadData]; - } - } + _redraw(); } auto pTableViewCell::_grandparent() -> maybe { @@ -45,6 +47,19 @@ auto pTableViewCell::_parent() -> maybe { return nothing; } +auto pTableViewCell::_redraw() -> void { + @autoreleasepool { + if(auto pTableViewItem = _parent()) { + if(auto pTableView = _grandparent()) { + auto column = self().offset(); + auto row = pTableViewItem->self().offset(); + NSRect rect = [[pTableView->cocoaTableView content] frameOfCellAtColumn:column row:row]; + [[pTableView->cocoaTableView content] setNeedsDisplayInRect:rect]; + } + } + } +} + } #endif diff --git a/hiro/cocoa/widget/table-view-cell.hpp b/hiro/cocoa/widget/table-view-cell.hpp index 0843729a..b57f9268 100644 --- a/hiro/cocoa/widget/table-view-cell.hpp +++ b/hiro/cocoa/widget/table-view-cell.hpp @@ -15,6 +15,7 @@ struct pTableViewCell : pObject { auto _grandparent() -> maybe; auto _parent() -> maybe; + auto _redraw() -> void; }; } diff --git a/hiro/cocoa/widget/table-view.cpp b/hiro/cocoa/widget/table-view.cpp index cba42034..8b476a92 100644 --- a/hiro/cocoa/widget/table-view.cpp +++ b/hiro/cocoa/widget/table-view.cpp @@ -52,6 +52,7 @@ [content setFont:font]; [content setRowHeight:fontHeight]; [self reloadColumns]; + tableView->resizeColumns(); } -(void) reloadColumns { @@ -214,7 +215,7 @@ //needed to trigger trackMouse events -(NSUInteger) hitTestForEvent:(NSEvent*)event inRect:(NSRect)frame ofView:(NSView*)view { NSUInteger hitTest = [super hitTestForEvent:event inRect:frame ofView:view]; - NSPoint point = [view convertPointFromBase:[event locationInWindow]]; + NSPoint point = [view convertPoint:[event locationInWindow] fromView:nil]; NSRect rect = NSMakeRect(frame.origin.x, frame.origin.y, frame.size.height, frame.size.height); if(NSMouseInRect(point, rect, [view isFlipped])) { hitTest |= NSCellHitTrackableArea; @@ -230,7 +231,7 @@ NSEvent* nextEvent; while((nextEvent = [window nextEventMatchingMask:(NSLeftMouseDragged | NSLeftMouseUp)])) { if([nextEvent type] == NSLeftMouseUp) { - NSPoint point = [view convertPointFromBase:[nextEvent locationInWindow]]; + NSPoint point = [view convertPoint:[nextEvent locationInWindow] fromView:nil]; NSRect rect = NSMakeRect(frame.origin.x, frame.origin.y, frame.size.height, frame.size.height); if(NSMouseInRect(point, rect, [view isFlipped])) { if(auto tableViewItem = tableView->item([view rowAtPoint:point])) { @@ -279,6 +280,7 @@ auto pTableView::destruct() -> void { auto pTableView::append(sTableViewHeader header) -> void { @autoreleasepool { [cocoaView reloadColumns]; + resizeColumns(); header->setVisible(header->visible()); } @@ -293,6 +295,7 @@ auto pTableView::append(sTableViewItem item) -> void { auto pTableView::remove(sTableViewHeader header) -> void { @autoreleasepool { [cocoaView reloadColumns]; + resizeColumns(); } } diff --git a/icarus/GNUmakefile b/icarus/GNUmakefile index f46c5a04..e8a5edc8 100644 --- a/icarus/GNUmakefile +++ b/icarus/GNUmakefile @@ -36,8 +36,8 @@ clean: ifeq ($(platform),macosx) @if [ -d out/$(name).app ]; then rm out/$(name).app; fi endif - $(call delete,obj/*) - $(call delete,out/*) + -@$(call delete,obj/*) + -@$(call delete,out/*) install: ifeq ($(platform),macosx) diff --git a/icarus/heuristics/game-boy.cpp b/icarus/heuristics/game-boy.cpp index f2047041..7e579a56 100644 --- a/icarus/heuristics/game-boy.cpp +++ b/icarus/heuristics/game-boy.cpp @@ -7,12 +7,14 @@ struct GameBoyCartridge { bool clear = false; //cartridge works in CGB mode only string mapper = "MBC0"; + bool flash = false; bool battery = false; bool ram = false; bool rtc = false; - bool rumble = false; bool accelerometer = false; + bool rumble = false; + uint flashSize = 0; uint romSize = 0; uint ramSize = 0; uint rtcSize = 0; @@ -157,14 +159,17 @@ GameBoyCartridge::GameBoyCartridge(uint8_t* data, uint size) { case 0x20: mapper = "MBC6"; + flash = true; + battery = true; + ram = true; break; case 0x22: mapper = "MBC7"; battery = true; ram = true; - rumble = true; accelerometer = true; + rumble = true; break; case 0xfc: @@ -204,6 +209,8 @@ GameBoyCartridge::GameBoyCartridge(uint8_t* data, uint size) { case 0x54: romSize = 96 * 16 * 1024; break; } + if(mapper == "MBC6" && flash) flashSize = 1024 * 1024; + switch(data[index + 0x0149]) { default: case 0x00: ramSize = 0 * 1024; break; case 0x01: ramSize = 2 * 1024; break; @@ -212,13 +219,16 @@ GameBoyCartridge::GameBoyCartridge(uint8_t* data, uint size) { } if(mapper == "MBC2" && ram) ramSize = 256; + if(mapper == "MBC6" && ram) ramSize = 32 * 1024; + if(mapper == "MBC7" && ram) ramSize = 256; if(mapper == "TAMA" && ram) ramSize = 32; if(mapper == "MBC3" && rtc) rtcSize = 13; if(mapper == "TAMA" && rtc) rtcSize = 21; - markup.append("board mapper=", mapper, "\n"); + markup.append("board mapper=", mapper, accelerometer ? " accelerometer" : "", rumble ? " rumble" : "", "\n"); markup.append(" rom name=program.rom size=0x", hex(romSize), "\n"); + if(flash && flashSize) markup.append(" flash name=download.rom size=0x", hex(flashSize), "\n"); if(ram && ramSize) markup.append(" ram ", battery ? "name=save.ram " : "", "size=0x", hex(ramSize), "\n"); if(rtc && rtcSize) markup.append(" rtc ", battery ? "name=rtc.ram " : "", "size=0x", hex(rtcSize), "\n"); } diff --git a/nall/image/load.hpp b/nall/image/load.hpp index 6edefe1e..cf40f5ec 100644 --- a/nall/image/load.hpp +++ b/nall/image/load.hpp @@ -27,6 +27,8 @@ auto image::loadBMP(const uint8_t* bmpData, unsigned bmpSize) -> bool { dp += stride(); } } + + return true; } auto image::loadPNG(const string& filename) -> bool { diff --git a/nall/queue.hpp b/nall/queue.hpp index 244aec3a..6890766f 100644 --- a/nall/queue.hpp +++ b/nall/queue.hpp @@ -35,6 +35,7 @@ struct queue { _write = source._write; source._data = nullptr; source.reset(); + return *this; } ~queue() { diff --git a/nall/string/core.hpp b/nall/string/core.hpp index 41d0fe45..41b7869d 100644 --- a/nall/string/core.hpp +++ b/nall/string/core.hpp @@ -48,6 +48,7 @@ template auto string::_prepend(const stringify& source) -> string resize(source.size() + size()); memory::move(get() + source.size(), get(), size() - source.size()); memory::copy(get(), source.data(), source.size()); + return *this; } template auto string::append(const T& value, P&&... p) -> string& { diff --git a/ruby/audio/alsa.cpp b/ruby/audio/alsa.cpp index dfbb581c..d3185635 100644 --- a/ruby/audio/alsa.cpp +++ b/ruby/audio/alsa.cpp @@ -64,11 +64,11 @@ struct AudioALSA : Audio { } if(i < 0) { - if(buffer == output) { + if(_buffer == output) { _offset--; output++; } - memory::move(buffer, output, _offset * sizeof(uint32_t)); + memory::move(_buffer, output, _offset * sizeof(uint32_t)); } } diff --git a/ruby/audio/ao.cpp b/ruby/audio/ao.cpp index 31e0306f..e34da4c2 100644 --- a/ruby/audio/ao.cpp +++ b/ruby/audio/ao.cpp @@ -27,8 +27,8 @@ 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) << 0; - ao_play(_interface, (char*)&sample, 4); //this may need to be byte swapped for big endian + uint32_t sample = uint16_t(samples[0] * 32768.0) << 0 | uint16_t(samples[1] * 32768.0) << 16; + ao_play(_interface, (char*)&sample, 4); } auto initialize() -> bool { @@ -48,8 +48,9 @@ struct AudioAO : Audio { ao_info* information = ao_driver_info(driverID); if(!information) return false; _device = information->short_name; + + ao_option* options = nullptr; if(_device == "alsa") { - ao_option* options = nullptr; ao_append_option(&options, "buffer_time", "100000"); //100ms latency (default was 500ms) } @@ -70,7 +71,7 @@ struct AudioAO : Audio { bool _ready = false; string _device = "Default"; + double _frequency = 48000.0; - int _driverID; ao_device* _interface = nullptr; }; diff --git a/ruby/audio/directsound.cpp b/ruby/audio/directsound.cpp index 32501aa6..ec234f9b 100644 --- a/ruby/audio/directsound.cpp +++ b/ruby/audio/directsound.cpp @@ -109,7 +109,7 @@ private: _buffer = new uint32_t[_period * _rings]; _offset = 0; - if(DirectSoundCreate(0, &_interface, 0) != DS_OK) return term(), false; + if(DirectSoundCreate(0, &_interface, 0) != DS_OK) return terminate(), false; _interface->SetCooperativeLevel(GetDesktopWindow(), DSSCL_PRIORITY); DSBUFFERDESC primaryDescription = {}; diff --git a/ruby/audio/pulseaudio.cpp b/ruby/audio/pulseaudio.cpp index a74e1f2c..0700f738 100644 --- a/ruby/audio/pulseaudio.cpp +++ b/ruby/audio/pulseaudio.cpp @@ -51,7 +51,7 @@ struct AudioPulseAudio : Audio { pa_mainloop_iterate(_mainLoop, 1, nullptr); } uint length = pa_stream_writable_size(_stream); - if(length >= buffer.offset * pa_frame_size(&_specification)) break; + if(length >= _offset * pa_frame_size(&_specification)) break; if(!_blocking) { _offset = 0; return; @@ -110,7 +110,7 @@ private: _ready = false; if(_buffer) { - pa_stream_cancel_write(_buffer); + pa_stream_cancel_write(_stream); _buffer = nullptr; } diff --git a/ruby/audio/pulseaudiosimple.cpp b/ruby/audio/pulseaudiosimple.cpp index 6e228ae5..95f2b1ac 100644 --- a/ruby/audio/pulseaudiosimple.cpp +++ b/ruby/audio/pulseaudiosimple.cpp @@ -2,7 +2,7 @@ #include struct AudioPulseAudioSimple : Audio { - AudioPulseAudio() { initialize(); } + AudioPulseAudioSimple() { initialize(); } ~AudioPulseAudioSimple() { terminate(); } auto ready() -> bool { return _ready; } diff --git a/ruby/input/carbon.cpp b/ruby/input/carbon.cpp index a992316b..c645a9b2 100644 --- a/ruby/input/carbon.cpp +++ b/ruby/input/carbon.cpp @@ -27,7 +27,7 @@ private: return _ready = true; } - auto term() -> void { + auto terminate() -> void { _ready = false; _keyboard.terminate(); } diff --git a/ruby/input/quartz.cpp b/ruby/input/quartz.cpp index 26c5eb3f..e189b2cd 100644 --- a/ruby/input/quartz.cpp +++ b/ruby/input/quartz.cpp @@ -22,13 +22,13 @@ struct InputQuartz : Input { auto initialize() -> bool { terminate(); - if(!_keyboard.init()) return false; + if(!_keyboard.initialize()) return false; return _ready = true; } auto terminate() -> void { _ready = false; - _keyboard.term(); + _keyboard.terminate(); } bool _ready = false; diff --git a/ruby/input/udev.cpp b/ruby/input/udev.cpp index 94dfb787..b1842301 100644 --- a/ruby/input/udev.cpp +++ b/ruby/input/udev.cpp @@ -51,7 +51,7 @@ struct InputUdev : Input { } private: - auto init() -> bool { + auto initialize() -> bool { terminate(); if(!_context) return false; if(!_keyboard.initialize()) return false; diff --git a/ruby/video/cgl.cpp b/ruby/video/cgl.cpp index 79fcd880..d97fddd2 100644 --- a/ruby/video/cgl.cpp +++ b/ruby/video/cgl.cpp @@ -47,7 +47,7 @@ struct VideoCGL : Video, OpenGL { return true; } - auto setShader(string shader) -> string { + auto setShader(string shader) -> bool { if(_shader == shader) return true; OpenGL::shader(_shader = shader); if(!_shader) OpenGL::filter = _smooth ? GL_LINEAR : GL_NEAREST; @@ -141,6 +141,7 @@ private: RubyVideoCGL* view = nullptr; + bool _ready = false; NSView* _context = nullptr; bool _blocking = false; bool _smooth = true;