mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-02-23 22:52:34 +01:00
byuu says: This WIP substantially restructures the ruby API for the first time since that project started. It is my hope that with this restructuring, destruction of the ruby objects should now be deterministic, which should fix the crashing on closing the emulator on Linux. We'll see I guess ... either way, it removed two layers of wrappers from ruby, so it's a pretty nice code cleanup. It won't compile on Windows due to a few issues I didn't see until uploading the WIP, too lazy to upload another. But I fixed all the compilation issues locally, so it'll work on Windows again with the next WIP (unless I break something else.) (Kind of annoying that Linux defines glActiveTexture but Windows doesn't.)
138 lines
4.0 KiB
C++
138 lines
4.0 KiB
C++
//request from emulation core to load non-volatile media folder
|
|
auto Program::loadRequest(unsigned id, string name, string type) -> void {
|
|
string location = BrowserDialog()
|
|
.setTitle({"Load ", name})
|
|
.setPath({config->library.location, name})
|
|
.setFilters({string{name, "|*.", type}})
|
|
.openFolder();
|
|
if(!directory::exists(location)) return;
|
|
|
|
mediaPaths(id) = location;
|
|
folderPaths.append(location);
|
|
emulator->load(id);
|
|
}
|
|
|
|
//request from emulation core to load non-volatile media file
|
|
auto Program::loadRequest(unsigned id, string path) -> void {
|
|
string location = {mediaPaths(emulator->group(id)), path};
|
|
if(!file::exists(location)) return;
|
|
mmapstream stream{location};
|
|
return emulator->load(id, stream);
|
|
}
|
|
|
|
//request from emulation core to save non-volatile media file
|
|
auto Program::saveRequest(unsigned id, string path) -> void {
|
|
string location = {mediaPaths(emulator->group(id)), path};
|
|
filestream stream{location, file::mode::write};
|
|
return emulator->save(id, stream);
|
|
}
|
|
|
|
auto Program::videoColor(unsigned source, uint16 a, uint16 r, uint16 g, uint16 b) -> uint32 {
|
|
if(config->video.saturation != 100) {
|
|
uint16 grayscale = uclamp<16>((r + g + b) / 3);
|
|
double saturation = config->video.saturation * 0.01;
|
|
double inverse = max(0.0, 1.0 - saturation);
|
|
r = uclamp<16>(r * saturation + grayscale * inverse);
|
|
g = uclamp<16>(g * saturation + grayscale * inverse);
|
|
b = uclamp<16>(b * saturation + grayscale * inverse);
|
|
}
|
|
|
|
if(config->video.gamma != 100) {
|
|
double exponent = config->video.gamma * 0.01;
|
|
double reciprocal = 1.0 / 32767.0;
|
|
r = r > 32767 ? r : 32767 * pow(r * reciprocal, exponent);
|
|
g = g > 32767 ? g : 32767 * pow(g * reciprocal, exponent);
|
|
b = b > 32767 ? b : 32767 * pow(b * reciprocal, exponent);
|
|
}
|
|
|
|
if(config->video.luminance != 100) {
|
|
double luminance = config->video.luminance * 0.01;
|
|
r = r * luminance;
|
|
g = g * luminance;
|
|
b = b * luminance;
|
|
}
|
|
|
|
a >>= 8;
|
|
r >>= 8;
|
|
g >>= 8;
|
|
b >>= 8;
|
|
return a << 24 | r << 16 | g << 8 | b << 0;
|
|
}
|
|
|
|
auto Program::videoRefresh(const uint32* palette, const uint32* data, unsigned pitch, unsigned width, unsigned height) -> void {
|
|
uint32* output;
|
|
unsigned length;
|
|
|
|
if(video->lock(output, length, width, height)) {
|
|
pitch >>= 2, length >>= 2;
|
|
|
|
for(auto y : range(height)) {
|
|
const uint32* sp = data + y * pitch;
|
|
uint32* dp = output + y * length;
|
|
for(auto x : range(width)) {
|
|
*dp++ = palette[*sp++];
|
|
}
|
|
}
|
|
|
|
if(emulator->information.overscan && config->video.overscan.mask) {
|
|
unsigned h = config->video.overscan.horizontal;
|
|
unsigned v = config->video.overscan.vertical;
|
|
|
|
if(h) for(auto y : range(height)) {
|
|
memory::fill(output + y * length, 4 * h);
|
|
memory::fill(output + y * length + (width - h), 4 * h);
|
|
}
|
|
|
|
if(v) for(auto y : range(v)) {
|
|
memory::fill(output + y * length, 4 * width);
|
|
memory::fill(output + (height - 1 - y) * length, 4 * width);
|
|
}
|
|
}
|
|
|
|
video->unlock();
|
|
video->refresh();
|
|
}
|
|
|
|
static unsigned frameCounter = 0;
|
|
static time_t previous, current;
|
|
frameCounter++;
|
|
|
|
time(¤t);
|
|
if(current != previous) {
|
|
previous = current;
|
|
statusText = {"FPS: ", frameCounter};
|
|
frameCounter = 0;
|
|
}
|
|
}
|
|
|
|
auto Program::audioSample(int16 lsample, int16 rsample) -> void {
|
|
signed samples[] = {lsample, rsample};
|
|
dsp.sample(samples);
|
|
while(dsp.pending()) {
|
|
dsp.read(samples);
|
|
audio->sample(samples[0], samples[1]);
|
|
}
|
|
}
|
|
|
|
auto Program::inputPoll(unsigned port, unsigned device, unsigned input) -> int16 {
|
|
if(presentation->focused()) {
|
|
auto guid = emulator->port[port].device[device].input[input].guid;
|
|
auto mapping = (InputMapping*)guid;
|
|
if(mapping) return mapping->poll();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
auto Program::inputRumble(unsigned port, unsigned device, unsigned input, bool enable) -> void {
|
|
}
|
|
|
|
auto Program::dipSettings(const Markup::Node& node) -> unsigned {
|
|
}
|
|
|
|
auto Program::path(unsigned group) -> string {
|
|
return mediaPaths(group);
|
|
}
|
|
|
|
auto Program::notify(string text) -> void {
|
|
}
|