mirror of https://github.com/bsnes-emu/bsnes.git
Update to v097r02 release.
byuu says: Note: balanced/performance profiles still broken, sorry. Changelog: - added nall/GNUmakefile unique() function; used on linking phase of higan - added nall/unique_pointer - target-tomoko and {System}::Video updated to use unique_pointer<ClassName> instead of ClassName* [1] - locate() updated to search multiple paths [2] - GB: pass gekkio's if_ie_registers and boot_hwio-G test ROMs - FC, GB, GBA: merge video/ into the PPU cores - ruby: fixed ~AudioXAudio2() typo [1] I expected this to cause new crashes on exit due to changing the order of destruction of objects (and deleting things that weren't deleted before), but ... so far, so good. I guess we'll see what crops up, especially on OS X (which is already crashing for unknown reasons on exit.) [2] right now, the search paths are: programpath(), {configpath(), "higan/"}, {localpath(), "higan/"}; but we can add as many more as we want, and we can also add platform-specific versions.
This commit is contained in:
parent
f1ebef2ea8
commit
344e63d928
|
@ -6,7 +6,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "097.01";
|
||||
static const string Version = "097.02";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
fc_objects := fc-interface fc-system fc-scheduler fc-input
|
||||
fc_objects += fc-memory fc-cartridge fc-cpu fc-apu fc-ppu
|
||||
fc_objects += fc-cheat fc-video
|
||||
fc_objects += fc-cheat
|
||||
objects += $(fc_objects)
|
||||
|
||||
obj/fc-interface.o: $(fc)/interface/interface.cpp $(call rwildcard,$(fc)/interface/)
|
||||
|
@ -13,4 +13,3 @@ obj/fc-cpu.o: $(fc)/cpu/cpu.cpp $(call rwildcard,$(fc)/cpu/)
|
|||
obj/fc-apu.o: $(fc)/apu/apu.cpp $(call rwildcard,$(fc)/apu/)
|
||||
obj/fc-ppu.o: $(fc)/ppu/ppu.cpp $(call rwildcard,$(fc)/ppu/)
|
||||
obj/fc-cheat.o: $(fc)/cheat/cheat.cpp $(call rwildcard,$(fc)/cheat/)
|
||||
obj/fc-video.o: $(fc)/video/video.cpp $(call rwildcard,$(fc)/video/)
|
||||
|
|
|
@ -51,7 +51,6 @@ namespace Famicom {
|
|||
#include <fc/apu/apu.hpp>
|
||||
#include <fc/ppu/ppu.hpp>
|
||||
#include <fc/cheat/cheat.hpp>
|
||||
#include <fc/video/video.hpp>
|
||||
}
|
||||
|
||||
#include <fc/interface/interface.hpp>
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
namespace Famicom {
|
||||
|
||||
#include "serialization.cpp"
|
||||
PPU ppu;
|
||||
#include "video.cpp"
|
||||
|
||||
#include "serialization.cpp"
|
||||
|
||||
auto PPU::Main() -> void {
|
||||
ppu.main();
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "video.hpp"
|
||||
|
||||
struct PPU : Thread {
|
||||
static auto Main() -> void;
|
||||
auto main() -> void;
|
||||
|
|
|
@ -1,34 +1,27 @@
|
|||
#include <fc/fc.hpp>
|
||||
#include <cmath>
|
||||
|
||||
#define VIDEO_CPP
|
||||
namespace Famicom {
|
||||
|
||||
Video video;
|
||||
|
||||
Video::Video() {
|
||||
output = new uint32[256 * 480];
|
||||
paletteLiteral = new uint32[1 << 9];
|
||||
paletteStandard = new uint32[1 << 9];
|
||||
paletteEmulation = new uint32[1 << 9];
|
||||
}
|
||||
|
||||
Video::~Video() {
|
||||
delete[] output;
|
||||
delete[] paletteStandard;
|
||||
delete[] paletteEmulation;
|
||||
}
|
||||
|
||||
auto Video::reset() -> void {
|
||||
memory::fill(output, 256 * 480);
|
||||
memory::fill(output(), 256 * 480);
|
||||
|
||||
for(auto color : range(1 << 9)) {
|
||||
paletteLiteral[color] = color;
|
||||
paletteStandard[color] = generateColor(color, 2.0, 0.0, 1.0, 1.0, 2.2);
|
||||
paletteEmulation[color] = generateColor(color, 2.0, 0.0, 1.0, 1.0, 1.8);
|
||||
}
|
||||
}
|
||||
|
||||
auto Video::refresh() -> void {
|
||||
auto palette = settings.colorEmulation ? paletteEmulation : paletteStandard;
|
||||
auto output = this->output();
|
||||
auto& palette = settings.colorEmulation ? paletteEmulation : paletteStandard;
|
||||
|
||||
if(settings.scanlineEmulation) {
|
||||
for(uint y = 0; y < 240; y++) {
|
||||
|
@ -99,7 +92,5 @@ auto Video::generateColor(
|
|||
uint g = uclamp<16>(65535.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q));
|
||||
uint b = uclamp<16>(65535.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q));
|
||||
|
||||
return (255 << 24) | ((r >> 8) << 16) | ((g >> 8) << 8) | ((b >> 8) << 0);
|
||||
}
|
||||
|
||||
return interface->videoColor(r, g, b);
|
||||
}
|
|
@ -1,16 +1,16 @@
|
|||
struct Video {
|
||||
Video();
|
||||
~Video();
|
||||
|
||||
auto reset() -> void;
|
||||
auto refresh() -> void;
|
||||
|
||||
uint32* output = nullptr;
|
||||
uint32* paletteStandard = nullptr;
|
||||
uint32* paletteEmulation = nullptr;
|
||||
|
||||
private:
|
||||
auto generateColor(uint, double, double, double, double, double) -> uint32;
|
||||
|
||||
unique_pointer<uint32[]> output;
|
||||
unique_pointer<uint32[]> paletteLiteral;
|
||||
unique_pointer<uint32[]> paletteStandard;
|
||||
unique_pointer<uint32[]> paletteEmulation;
|
||||
};
|
||||
|
||||
extern Video video;
|
|
@ -1,7 +1,7 @@
|
|||
gb_objects := gb-interface gb-system gb-scheduler
|
||||
gb_objects += gb-memory gb-cartridge
|
||||
gb_objects += gb-cpu gb-ppu gb-apu
|
||||
gb_objects += gb-cheat gb-video
|
||||
gb_objects += gb-cheat
|
||||
objects += $(gb_objects)
|
||||
|
||||
obj/gb-interface.o: $(gb)/interface/interface.cpp $(call rwildcard,$(gb)/interface/)
|
||||
|
@ -13,4 +13,3 @@ obj/gb-cpu.o: $(gb)/cpu/cpu.cpp $(call rwildcard,$(gb)/cpu/)
|
|||
obj/gb-ppu.o: $(gb)/ppu/ppu.cpp $(call rwildcard,$(gb)/ppu/)
|
||||
obj/gb-apu.o: $(gb)/apu/apu.cpp $(call rwildcard,$(gb)/apu/)
|
||||
obj/gb-cheat.o: $(gb)/cheat/cheat.cpp $(call rwildcard,$(gb)/cheat/)
|
||||
obj/gb-video.o: $(gb)/video/video.cpp $(call rwildcard,$(gb)/video/)
|
||||
|
|
|
@ -38,17 +38,19 @@ auto CPU::mmio_read(uint16 addr) -> uint8 {
|
|||
|
||||
if(addr == 0xff00) { //JOYP
|
||||
mmio_joyp_poll();
|
||||
return (status.p15 << 5)
|
||||
return 0xc0
|
||||
| (status.p15 << 5)
|
||||
| (status.p14 << 4)
|
||||
| (status.joyp << 0);
|
||||
}
|
||||
|
||||
if(addr == 0xff01) { //SB
|
||||
return 0xff;
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
if(addr == 0xff02) { //SC
|
||||
return (status.serial_transfer << 7)
|
||||
| 0x7e
|
||||
| (status.serial_clock << 0);
|
||||
}
|
||||
|
||||
|
@ -65,12 +67,14 @@ auto CPU::mmio_read(uint16 addr) -> uint8 {
|
|||
}
|
||||
|
||||
if(addr == 0xff07) { //TAC
|
||||
return (status.timer_enable << 2)
|
||||
return 0xf8
|
||||
| (status.timer_enable << 2)
|
||||
| (status.timer_clock << 0);
|
||||
}
|
||||
|
||||
if(addr == 0xff0f) { //IF
|
||||
return (status.interrupt_request_joypad << 4)
|
||||
return 0xe0
|
||||
| (status.interrupt_request_joypad << 4)
|
||||
| (status.interrupt_request_serial << 3)
|
||||
| (status.interrupt_request_timer << 2)
|
||||
| (status.interrupt_request_stat << 1)
|
||||
|
@ -123,7 +127,8 @@ auto CPU::mmio_read(uint16 addr) -> uint8 {
|
|||
}
|
||||
|
||||
if(addr == 0xffff) { //IE
|
||||
return (status.interrupt_enable_joypad << 4)
|
||||
return 0xe0
|
||||
| (status.interrupt_enable_joypad << 4)
|
||||
| (status.interrupt_enable_serial << 3)
|
||||
| (status.interrupt_enable_timer << 2)
|
||||
| (status.interrupt_enable_stat << 1)
|
||||
|
|
|
@ -50,7 +50,6 @@ namespace GameBoy {
|
|||
#include <gb/ppu/ppu.hpp>
|
||||
#include <gb/apu/apu.hpp>
|
||||
#include <gb/cheat/cheat.hpp>
|
||||
#include <gb/video/video.hpp>
|
||||
}
|
||||
|
||||
#include <gb/interface/interface.hpp>
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
|
||||
namespace GameBoy {
|
||||
|
||||
PPU ppu;
|
||||
#include "video.cpp"
|
||||
|
||||
#include "mmio.cpp"
|
||||
#include "dmg.cpp"
|
||||
#include "cgb.cpp"
|
||||
#include "serialization.cpp"
|
||||
PPU ppu;
|
||||
|
||||
auto PPU::Main() -> void {
|
||||
ppu.main();
|
||||
|
@ -141,8 +143,8 @@ auto PPU::power() -> void {
|
|||
for(auto& n : vram) n = 0x00;
|
||||
for(auto& n : oam) n = 0x00;
|
||||
for(auto& n : bgp) n = 0x00;
|
||||
for(auto& n : obp[0]) n = 0x00;
|
||||
for(auto& n : obp[1]) n = 0x00;
|
||||
for(auto& n : obp[0]) n = 3;
|
||||
for(auto& n : obp[1]) n = 3;
|
||||
for(auto& n : bgpd) n = 0x0000;
|
||||
for(auto& n : obpd) n = 0x0000;
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "video.hpp"
|
||||
|
||||
struct PPU : Thread, MMIO {
|
||||
static auto Main() -> void;
|
||||
auto main() -> void;
|
||||
|
|
|
@ -1,37 +1,32 @@
|
|||
#include <gb/gb.hpp>
|
||||
|
||||
namespace GameBoy {
|
||||
|
||||
Video video;
|
||||
|
||||
Video::Video() {
|
||||
output = new uint32[160 * 144];
|
||||
paletteLiteral = new uint32[1 << 15];
|
||||
paletteStandard = new uint32[1 << 15];
|
||||
paletteEmulation = new uint32[1 << 15];
|
||||
}
|
||||
|
||||
Video::~Video() {
|
||||
delete[] output;
|
||||
delete[] paletteStandard;
|
||||
delete[] paletteEmulation;
|
||||
}
|
||||
|
||||
auto Video::power() -> void {
|
||||
memory::fill(output, 160 * 144 * sizeof(uint32));
|
||||
memory::fill(output(), 160 * 144 * sizeof(uint32));
|
||||
|
||||
if(system.dmg()) {
|
||||
for(auto color : range(1 << 2)) {
|
||||
uint L = image::normalize(3 - color, 2, 8);
|
||||
uint R = monochrome[color][0] >> 8;
|
||||
uint G = monochrome[color][1] >> 8;
|
||||
uint B = monochrome[color][2] >> 8;
|
||||
paletteStandard[color] = (255 << 24) | (L << 16) | (L << 8) | (L << 0);
|
||||
paletteEmulation[color] = (255 << 24) | (R << 16) | (G << 8) | (B << 0);
|
||||
paletteLiteral[color] = color;
|
||||
|
||||
uint L = image::normalize(3 - color, 2, 16);
|
||||
paletteStandard[color] = interface->videoColor(L, L, L);
|
||||
|
||||
uint R = monochrome[color][0];
|
||||
uint G = monochrome[color][1];
|
||||
uint B = monochrome[color][2];
|
||||
paletteEmulation[color] = interface->videoColor(R, G, B);
|
||||
}
|
||||
}
|
||||
|
||||
if(system.sgb()) {
|
||||
for(auto color : range(1 << 2)) {
|
||||
paletteLiteral[color] = color;
|
||||
paletteStandard[color] = color;
|
||||
paletteEmulation[color] = color;
|
||||
}
|
||||
|
@ -39,30 +34,31 @@ auto Video::power() -> void {
|
|||
|
||||
if(system.cgb()) {
|
||||
for(auto color : range(1 << 15)) {
|
||||
paletteLiteral[color] = color;
|
||||
|
||||
uint r = (uint5)(color >> 0);
|
||||
uint g = (uint5)(color >> 5);
|
||||
uint b = (uint5)(color >> 10);
|
||||
|
||||
{ uint R = image::normalize(r, 5, 8);
|
||||
uint G = image::normalize(g, 5, 8);
|
||||
uint B = image::normalize(b, 5, 8);
|
||||
paletteStandard[color] = (255 << 24) | (R << 16) | (G << 8) | (B << 0);
|
||||
}
|
||||
uint R = image::normalize(r, 5, 16);
|
||||
uint G = image::normalize(g, 5, 16);
|
||||
uint B = image::normalize(b, 5, 16);
|
||||
paletteStandard[color] = interface->videoColor(R, G, B);
|
||||
|
||||
{ uint R = (r * 26 + g * 4 + b * 2);
|
||||
uint G = ( g * 24 + b * 8);
|
||||
uint B = (r * 6 + g * 4 + b * 22);
|
||||
R = min(960, R) >> 2;
|
||||
G = min(960, G) >> 2;
|
||||
B = min(960, B) >> 2;
|
||||
paletteEmulation[color] = (255 << 24) | (R << 16) | (G << 8) | (B << 0);
|
||||
}
|
||||
R = (r * 26 + g * 4 + b * 2);
|
||||
G = ( g * 24 + b * 8);
|
||||
B = (r * 6 + g * 4 + b * 22);
|
||||
R = image::normalize(min(960, R), 10, 16);
|
||||
G = image::normalize(min(960, G), 10, 16);
|
||||
B = image::normalize(min(960, B), 10, 16);
|
||||
paletteEmulation[color] = interface->videoColor(R, G, B);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto Video::refresh() -> void {
|
||||
auto palette = settings.colorEmulation ? paletteEmulation : paletteStandard;
|
||||
auto output = this->output();
|
||||
auto& palette = settings.colorEmulation ? paletteEmulation : paletteStandard;
|
||||
|
||||
for(uint y = 0; y < 144; y++) {
|
||||
auto source = ppu.screen + y * 160;
|
||||
|
@ -107,5 +103,3 @@ const uint16 Video::monochrome[4][3] = {
|
|||
{0x0000, 0x0000, 0x0000},
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
struct Video {
|
||||
Video();
|
||||
|
||||
auto power() -> void;
|
||||
auto refresh() -> void;
|
||||
|
||||
private:
|
||||
unique_pointer<uint32[]> output;
|
||||
unique_pointer<uint32[]> paletteLiteral;
|
||||
unique_pointer<uint32[]> paletteStandard;
|
||||
unique_pointer<uint32[]> paletteEmulation;
|
||||
|
||||
static const uint16 monochrome[4][3];
|
||||
};
|
||||
|
||||
extern Video video;
|
|
@ -1,16 +0,0 @@
|
|||
struct Video {
|
||||
Video();
|
||||
~Video();
|
||||
|
||||
auto power() -> void;
|
||||
auto refresh() -> void;
|
||||
|
||||
uint32* output = nullptr;
|
||||
uint32* paletteStandard = nullptr;
|
||||
uint32* paletteEmulation = nullptr;
|
||||
|
||||
private:
|
||||
static const uint16 monochrome[4][3];
|
||||
};
|
||||
|
||||
extern Video video;
|
|
@ -1,5 +1,5 @@
|
|||
gba_objects := gba-memory gba-interface gba-scheduler gba-system
|
||||
gba_objects += gba-video gba-cartridge gba-player
|
||||
gba_objects += gba-cartridge gba-player
|
||||
gba_objects += gba-cpu gba-ppu gba-apu
|
||||
objects += $(gba_objects)
|
||||
|
||||
|
@ -7,7 +7,6 @@ obj/gba-memory.o: $(gba)/memory/memory.cpp $(call rwildcard,$(gba)/memory)
|
|||
obj/gba-interface.o: $(gba)/interface/interface.cpp $(call rwildcard,$(gba)/interface)
|
||||
obj/gba-scheduler.o: $(gba)/scheduler/scheduler.cpp $(call rwildcard,$(gba)/scheduler)
|
||||
obj/gba-system.o: $(gba)/system/system.cpp $(call rwildcard,$(gba)/system)
|
||||
obj/gba-video.o: $(gba)/video/video.cpp $(call rwildcard,$(gba)/video)
|
||||
obj/gba-cartridge.o: $(gba)/cartridge/cartridge.cpp $(call rwildcard,$(gba)/cartridge)
|
||||
obj/gba-player.o: $(gba)/player/player.cpp $(call rwildcard,$(gba)/player)
|
||||
obj/gba-cpu.o: $(gba)/cpu/cpu.cpp $(call rwildcard,$(gba)/cpu)
|
||||
|
|
|
@ -62,7 +62,6 @@ namespace GameBoyAdvance {
|
|||
#include <gba/cpu/cpu.hpp>
|
||||
#include <gba/ppu/ppu.hpp>
|
||||
#include <gba/apu/apu.hpp>
|
||||
#include <gba/video/video.hpp>
|
||||
}
|
||||
|
||||
#include <gba/interface/interface.hpp>
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
|
||||
namespace GameBoyAdvance {
|
||||
|
||||
PPU ppu;
|
||||
#include "video.cpp"
|
||||
|
||||
#include "registers.cpp"
|
||||
#include "background.cpp"
|
||||
#include "object.cpp"
|
||||
|
@ -20,7 +23,6 @@ namespace GameBoyAdvance {
|
|||
#include "mmio.cpp"
|
||||
#include "memory.cpp"
|
||||
#include "serialization.cpp"
|
||||
PPU ppu;
|
||||
|
||||
PPU::PPU() {
|
||||
output = new uint32[240 * 160];
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "video.hpp"
|
||||
|
||||
struct PPU : Thread, MMIO {
|
||||
#include "registers.hpp"
|
||||
#include "state.hpp"
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
Video video;
|
||||
|
||||
Video::Video() {
|
||||
output = new uint32[240 * 160];
|
||||
paletteLiteral = new uint32[1 << 15];
|
||||
paletteStandard = new uint32[1 << 15];
|
||||
paletteEmulation = new uint32[1 << 15];
|
||||
}
|
||||
|
||||
auto Video::power() -> void {
|
||||
memory::fill(output(), 240 * 160 * sizeof(uint32));
|
||||
|
||||
for(auto color : range(1 << 15)) {
|
||||
paletteLiteral[color] = color;
|
||||
|
||||
uint B = (uint5)(color >> 10);
|
||||
uint G = (uint5)(color >> 5);
|
||||
uint R = (uint5)(color >> 0);
|
||||
|
||||
uint b = image::normalize(B, 5, 16);
|
||||
uint g = image::normalize(G, 5, 16);
|
||||
uint r = image::normalize(R, 5, 16);
|
||||
paletteStandard[color] = interface->videoColor(r, g, b);
|
||||
|
||||
double lcdGamma = 4.0, outGamma = 2.2;
|
||||
double lb = pow(B / 31.0, lcdGamma);
|
||||
double lg = pow(G / 31.0, lcdGamma);
|
||||
double lr = pow(R / 31.0, lcdGamma);
|
||||
b = pow((220 * lb + 10 * lg + 50 * lr) / 255, 1 / outGamma) * (0xffff * 255 / 280);
|
||||
g = pow(( 30 * lb + 230 * lg + 10 * lr) / 255, 1 / outGamma) * (0xffff * 255 / 280);
|
||||
r = pow(( 0 * lb + 50 * lg + 255 * lr) / 255, 1 / outGamma) * (0xffff * 255 / 280);
|
||||
paletteEmulation[color] = interface->videoColor(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
auto Video::refresh() -> void {
|
||||
auto output = this->output();
|
||||
auto& palette = settings.colorEmulation ? paletteEmulation : paletteStandard;
|
||||
|
||||
for(uint y = 0; y < 160; y++) {
|
||||
auto source = ppu.output + y * 240;
|
||||
auto target = output + y * 240;
|
||||
|
||||
if(settings.blurEmulation) {
|
||||
for(uint x = 0; x < 240; x++) {
|
||||
auto a = palette[*source++];
|
||||
auto b = *target;
|
||||
*target++ = (a + b - ((a ^ b) & 0x01010101)) >> 1;
|
||||
}
|
||||
} else {
|
||||
for(uint x = 0; x < 240; x++) {
|
||||
auto color = palette[*source++];
|
||||
*target++ = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface->videoRefresh(output, 240 * sizeof(uint32), 240, 160);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
struct Video {
|
||||
Video();
|
||||
|
||||
auto power() -> void;
|
||||
auto refresh() -> void;
|
||||
|
||||
unique_pointer<uint32[]> output;
|
||||
unique_pointer<uint32[]> paletteLiteral;
|
||||
unique_pointer<uint32[]> paletteStandard;
|
||||
unique_pointer<uint32[]> paletteEmulation;
|
||||
};
|
||||
|
||||
extern Video video;
|
|
@ -1,69 +0,0 @@
|
|||
#include <gba/gba.hpp>
|
||||
|
||||
namespace GameBoyAdvance {
|
||||
|
||||
Video video;
|
||||
|
||||
Video::Video() {
|
||||
output = new uint32[240 * 160];
|
||||
paletteStandard = new uint32[1 << 15];
|
||||
paletteEmulation = new uint32[1 << 15];
|
||||
}
|
||||
|
||||
Video::~Video() {
|
||||
delete[] output;
|
||||
delete[] paletteStandard;
|
||||
delete[] paletteEmulation;
|
||||
}
|
||||
|
||||
auto Video::power() -> void {
|
||||
memory::fill(output, 240 * 160 * sizeof(uint32));
|
||||
|
||||
for(auto color : range(1 << 15)) {
|
||||
uint B = (uint5)(color >> 10);
|
||||
uint G = (uint5)(color >> 5);
|
||||
uint R = (uint5)(color >> 0);
|
||||
|
||||
{ uint b = image::normalize(B, 5, 8);
|
||||
uint g = image::normalize(G, 5, 8);
|
||||
uint r = image::normalize(R, 5, 8);
|
||||
paletteStandard[color] = (255 << 24) | (r << 16) | (g << 8) | (b << 0);
|
||||
}
|
||||
|
||||
{ double lcdGamma = 4.0, outGamma = 2.2;
|
||||
double lb = pow(B / 31.0, lcdGamma);
|
||||
double lg = pow(G / 31.0, lcdGamma);
|
||||
double lr = pow(R / 31.0, lcdGamma);
|
||||
uint b = pow((220 * lb + 10 * lg + 50 * lr) / 255, 1 / outGamma) * (0xffff * 255 / 280);
|
||||
uint g = pow(( 30 * lb + 230 * lg + 10 * lr) / 255, 1 / outGamma) * (0xffff * 255 / 280);
|
||||
uint r = pow(( 0 * lb + 50 * lg + 255 * lr) / 255, 1 / outGamma) * (0xffff * 255 / 280);
|
||||
paletteEmulation[color] = (255 << 24) | ((r >> 8) << 16) | ((g >> 8) << 8) | ((b >> 8) << 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto Video::refresh() -> void {
|
||||
auto palette = settings.colorEmulation ? paletteEmulation : paletteStandard;
|
||||
|
||||
for(uint y = 0; y < 160; y++) {
|
||||
auto source = ppu.output + y * 240;
|
||||
auto target = output + y * 240;
|
||||
|
||||
if(settings.blurEmulation) {
|
||||
for(uint x = 0; x < 240; x++) {
|
||||
auto a = palette[*source++];
|
||||
auto b = *target;
|
||||
*target++ = (a + b - ((a ^ b) & 0x01010101)) >> 1;
|
||||
}
|
||||
} else {
|
||||
for(uint x = 0; x < 240; x++) {
|
||||
auto color = palette[*source++];
|
||||
*target++ = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface->videoRefresh(output, 240 * sizeof(uint32), 240, 160);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
struct Video {
|
||||
Video();
|
||||
~Video();
|
||||
|
||||
auto power() -> void;
|
||||
auto refresh() -> void;
|
||||
|
||||
uint32* output = nullptr;
|
||||
uint32* paletteStandard = nullptr;
|
||||
uint32* paletteEmulation = nullptr;
|
||||
};
|
||||
|
||||
extern Video video;
|
|
@ -21,7 +21,7 @@ auto ICD2::enter() -> void {
|
|||
step(GameBoy::system.clocks_executed);
|
||||
GameBoy::system.clocks_executed = 0;
|
||||
} else { //DMG halted
|
||||
dsp.audio.coprocessorSample(0, 0);
|
||||
audio.coprocessorSample(0, 0);
|
||||
step(1);
|
||||
}
|
||||
synchronizeCPU();
|
||||
|
@ -44,8 +44,8 @@ auto ICD2::unload() -> void {
|
|||
}
|
||||
|
||||
auto ICD2::power() -> void {
|
||||
dsp.audio.coprocessorEnable(true);
|
||||
dsp.audio.coprocessorFrequency(2 * 1024 * 1024);
|
||||
audio.coprocessorEnable(true);
|
||||
audio.coprocessorFrequency(2 * 1024 * 1024);
|
||||
}
|
||||
|
||||
auto ICD2::reset() -> void {
|
||||
|
|
|
@ -93,7 +93,7 @@ auto ICD2::videoRefresh(const uint32* data, uint pitch, uint width, uint height)
|
|||
}
|
||||
|
||||
auto ICD2::audioSample(int16 left, int16 right) -> void {
|
||||
dsp.audio.coprocessorSample(left, right);
|
||||
audio.coprocessorSample(left, right);
|
||||
}
|
||||
|
||||
auto ICD2::inputPoll(uint port, uint device, uint id) -> int16 {
|
||||
|
|
|
@ -41,7 +41,7 @@ auto MSU1::enter() -> void {
|
|||
right = sclamp<16>(rchannel);
|
||||
if(dsp.mute()) left = 0, right = 0;
|
||||
|
||||
dsp.audio.coprocessorSample(left, right);
|
||||
audio.coprocessorSample(left, right);
|
||||
step(1);
|
||||
synchronizeCPU();
|
||||
}
|
||||
|
@ -59,8 +59,8 @@ auto MSU1::unload() -> void {
|
|||
}
|
||||
|
||||
auto MSU1::power() -> void {
|
||||
dsp.audio.coprocessorEnable(true);
|
||||
dsp.audio.coprocessorFrequency(44100.0);
|
||||
audio.coprocessorEnable(true);
|
||||
audio.coprocessorFrequency(44100.0);
|
||||
}
|
||||
|
||||
auto MSU1::reset() -> void {
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
auto DSP::Audio::coprocessorEnable(bool enable) -> void {
|
||||
Audio audio;
|
||||
|
||||
auto Audio::coprocessorEnable(bool enable) -> void {
|
||||
mixer.clear();
|
||||
mixerEnable = enable;
|
||||
dsp.read = dsp.write = 0;
|
||||
mix.read = mix.write = 0;
|
||||
}
|
||||
|
||||
auto DSP::Audio::coprocessorFrequency(double frequency) -> void {
|
||||
auto Audio::coprocessorFrequency(double frequency) -> void {
|
||||
mixer.setFrequency(frequency);
|
||||
mixer.setResampler(nall::DSP::ResampleEngine::Sinc);
|
||||
mixer.setResamplerFrequency(system.apuFrequency() / 768.0);
|
||||
}
|
||||
|
||||
auto DSP::Audio::sample(int16 left, int16 right) -> void {
|
||||
auto Audio::sample(int16 left, int16 right) -> void {
|
||||
if(!mixerEnable) return interface->audioSample(left, right);
|
||||
|
||||
dsp.left[dsp.write] = left;
|
||||
|
@ -20,7 +22,7 @@ auto DSP::Audio::sample(int16 left, int16 right) -> void {
|
|||
flush();
|
||||
}
|
||||
|
||||
auto DSP::Audio::coprocessorSample(int16 left, int16 right) -> void {
|
||||
auto Audio::coprocessorSample(int16 left, int16 right) -> void {
|
||||
int samples[] = {left, right};
|
||||
mixer.sample(samples);
|
||||
while(mixer.pending()) {
|
||||
|
@ -32,7 +34,7 @@ auto DSP::Audio::coprocessorSample(int16 left, int16 right) -> void {
|
|||
}
|
||||
}
|
||||
|
||||
auto DSP::Audio::flush() -> void {
|
||||
auto Audio::flush() -> void {
|
||||
while(dsp.read != dsp.write && mix.read != mix.write) {
|
||||
interface->audioSample(
|
||||
sclamp<16>(dsp.left[dsp.read] + mix.left[mix.read]),
|
||||
|
|
|
@ -16,3 +16,5 @@ private:
|
|||
uint8 write;
|
||||
} dsp, mix;
|
||||
};
|
||||
|
||||
extern Audio audio;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace SuperFamicom {
|
||||
|
||||
DSP dsp;
|
||||
#include "audio.cpp"
|
||||
|
||||
#define REG(n) state.regs[n]
|
||||
#define VREG(n) state.regs[v.vidx + n]
|
||||
|
@ -15,7 +16,6 @@ DSP dsp;
|
|||
#include "voice.cpp"
|
||||
#include "echo.cpp"
|
||||
#include "serialization.cpp"
|
||||
#include "audio.cpp"
|
||||
|
||||
DSP::DSP() {
|
||||
static_assert(sizeof(signed) >= 32 / 8, "signed >= 32-bits");
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
//Sony CXD1222Q-1
|
||||
|
||||
#include "audio.hpp"
|
||||
|
||||
struct DSP : Thread {
|
||||
enum : bool { Threaded = true };
|
||||
|
||||
|
@ -18,9 +20,6 @@ struct DSP : Thread {
|
|||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
#include "audio.hpp"
|
||||
Audio audio;
|
||||
|
||||
privileged:
|
||||
#include "modulo-array.hpp"
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace SuperFamicom {
|
||||
|
||||
PPU ppu;
|
||||
#include "video.cpp"
|
||||
|
||||
#include "background/background.cpp"
|
||||
#include "mmio/mmio.cpp"
|
||||
|
@ -10,7 +11,6 @@ PPU ppu;
|
|||
#include "sprite/sprite.cpp"
|
||||
#include "window/window.cpp"
|
||||
#include "serialization.cpp"
|
||||
#include "video.cpp"
|
||||
|
||||
PPU::PPU() :
|
||||
bg1(*this, Background::ID::BG1),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "video.hpp"
|
||||
|
||||
struct PPU : Thread, public PPUcounter {
|
||||
enum : bool { Threaded = true };
|
||||
|
||||
|
@ -38,7 +40,6 @@ privileged:
|
|||
#include "screen/screen.hpp"
|
||||
#include "sprite/sprite.hpp"
|
||||
#include "window/window.hpp"
|
||||
#include "video.hpp"
|
||||
|
||||
Background bg1;
|
||||
Background bg2;
|
||||
|
@ -47,7 +48,6 @@ privileged:
|
|||
Sprite sprite;
|
||||
Window window;
|
||||
Screen screen;
|
||||
Video video;
|
||||
|
||||
static auto Enter() -> void;
|
||||
alwaysinline auto add_clocks(uint) -> void;
|
||||
|
@ -59,6 +59,7 @@ privileged:
|
|||
friend class PPU::Sprite;
|
||||
friend class PPU::Window;
|
||||
friend class PPU::Screen;
|
||||
friend class Video;
|
||||
|
||||
struct Debugger {
|
||||
hook<void (uint16, uint8)> vram_read;
|
||||
|
|
|
@ -1,23 +1,14 @@
|
|||
PPU::Video::Video() {
|
||||
output = new uint32[512 * 512]();
|
||||
output += 16 * 512; //overscan padding
|
||||
Video video;
|
||||
|
||||
Video::Video() {
|
||||
output = new uint32[512 * 512];
|
||||
paletteLiteral = new uint32[1 << 19];
|
||||
paletteStandard = new uint32[1 << 19];
|
||||
paletteEmulation = new uint32[1 << 19];
|
||||
}
|
||||
|
||||
PPU::Video::~Video() {
|
||||
output -= 16 * 512;
|
||||
delete[] output;
|
||||
|
||||
delete[] paletteLiteral;
|
||||
delete[] paletteStandard;
|
||||
delete[] paletteEmulation;
|
||||
}
|
||||
|
||||
auto PPU::Video::reset() -> void {
|
||||
memory::fill(output, 512 * 480 * sizeof(uint32));
|
||||
auto Video::reset() -> void {
|
||||
memory::fill(output(), 512 * 512 * sizeof(uint32));
|
||||
|
||||
for(auto color : range(1 << 19)) {
|
||||
uint l = (uint4)(color >> 15);
|
||||
|
@ -25,34 +16,31 @@ auto PPU::Video::reset() -> void {
|
|||
uint g = (uint5)(color >> 5);
|
||||
uint r = (uint5)(color >> 0);
|
||||
|
||||
paletteLiteral[color] = color;
|
||||
|
||||
double L = (1.0 + l) / 16.0 * (l ? 1.0 : 0.5);
|
||||
uint R = L * image::normalize(r, 5, 16);
|
||||
uint G = L * image::normalize(g, 5, 16);
|
||||
uint B = L * image::normalize(b, 5, 16);
|
||||
paletteStandard[color] = interface->videoColor(R, G, B);
|
||||
|
||||
{ paletteLiteral[color] = color;
|
||||
}
|
||||
static const uint8 gammaRamp[32] = {
|
||||
0x00, 0x01, 0x03, 0x06, 0x0a, 0x0f, 0x15, 0x1c,
|
||||
0x24, 0x2d, 0x37, 0x42, 0x4e, 0x5b, 0x69, 0x78,
|
||||
0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0,
|
||||
0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8, 0xff,
|
||||
};
|
||||
|
||||
{ uint R = L * image::normalize(r, 5, 16);
|
||||
uint G = L * image::normalize(g, 5, 16);
|
||||
uint B = L * image::normalize(b, 5, 16);
|
||||
paletteStandard[color] = interface->videoColor(R, G, B);
|
||||
}
|
||||
|
||||
{ static const uint8 gammaRamp[32] = {
|
||||
0x00, 0x01, 0x03, 0x06, 0x0a, 0x0f, 0x15, 0x1c,
|
||||
0x24, 0x2d, 0x37, 0x42, 0x4e, 0x5b, 0x69, 0x78,
|
||||
0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0,
|
||||
0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8, 0xff,
|
||||
};
|
||||
|
||||
uint R = L * gammaRamp[r] * 0x0101;
|
||||
uint G = L * gammaRamp[g] * 0x0101;
|
||||
uint B = L * gammaRamp[b] * 0x0101;
|
||||
paletteEmulation[color] = interface->videoColor(R, G, B);
|
||||
}
|
||||
R = L * gammaRamp[r] * 0x0101;
|
||||
G = L * gammaRamp[g] * 0x0101;
|
||||
B = L * gammaRamp[b] * 0x0101;
|
||||
paletteEmulation[color] = interface->videoColor(R, G, B);
|
||||
}
|
||||
}
|
||||
|
||||
auto PPU::Video::refresh() -> void {
|
||||
auto palette = settings.colorEmulation ? paletteEmulation : paletteStandard;
|
||||
auto Video::refresh() -> void {
|
||||
auto output = this->output() + 16 * 512; //add offset for overscan
|
||||
auto& palette = settings.colorEmulation ? paletteEmulation : paletteStandard;
|
||||
|
||||
if(settings.scanlineEmulation) {
|
||||
for(uint y = 0; y < 240; y++) {
|
||||
|
@ -117,7 +105,7 @@ auto PPU::Video::refresh() -> void {
|
|||
scheduler.exit(Scheduler::ExitReason::FrameEvent);
|
||||
}
|
||||
|
||||
auto PPU::Video::drawCursor(uint32 color, int x, int y) -> void {
|
||||
auto Video::drawCursor(uint32 color, int x, int y) -> void {
|
||||
static const uint8 cursor[15 * 15] = {
|
||||
0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
|
||||
0,0,0,0,1,1,2,2,2,1,1,0,0,0,0,
|
||||
|
@ -136,9 +124,7 @@ auto PPU::Video::drawCursor(uint32 color, int x, int y) -> void {
|
|||
0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
|
||||
};
|
||||
|
||||
auto data = (uint32*)output;
|
||||
if(ppu.interlace() && ppu.field()) data += 512;
|
||||
|
||||
auto output = this->output() + 16 * 512;
|
||||
for(int cy = 0; cy < 15; cy++) {
|
||||
int vy = y + cy - 7;
|
||||
if(vy <= 0 || vy >= 240) continue; //do not draw offscreen
|
||||
|
@ -150,15 +136,15 @@ auto PPU::Video::drawCursor(uint32 color, int x, int y) -> void {
|
|||
if(pixel == 0) continue;
|
||||
uint32 pixelcolor = pixel == 1 ? 0xff000000 : color;
|
||||
|
||||
*(data + vy * 1024 + vx * 2 + 0) = pixelcolor;
|
||||
*(data + vy * 1024 + vx * 2 + 1) = pixelcolor;
|
||||
*(data + vy * 1024 + 512 + vx * 2 + 0) = pixelcolor;
|
||||
*(data + vy * 1024 + 512 + vx * 2 + 1) = pixelcolor;
|
||||
*(output + vy * 1024 + vx * 2 + 0) = pixelcolor;
|
||||
*(output + vy * 1024 + vx * 2 + 1) = pixelcolor;
|
||||
*(output + vy * 1024 + 512 + vx * 2 + 0) = pixelcolor;
|
||||
*(output + vy * 1024 + 512 + vx * 2 + 1) = pixelcolor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto PPU::Video::drawCursors() -> void {
|
||||
auto Video::drawCursors() -> void {
|
||||
switch((Device::ID)settings.controllerPort2) {
|
||||
case Device::ID::SuperScope:
|
||||
if(dynamic_cast<SuperScope*>(device.controllerPort2)) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
struct Video {
|
||||
Video();
|
||||
~Video();
|
||||
|
||||
auto reset() -> void;
|
||||
auto refresh() -> void;
|
||||
|
@ -9,8 +8,10 @@ private:
|
|||
auto drawCursor(uint32 color, int x, int y) -> void;
|
||||
auto drawCursors() -> void;
|
||||
|
||||
uint32* output = nullptr;
|
||||
uint32* paletteLiteral = nullptr;
|
||||
uint32* paletteStandard = nullptr;
|
||||
uint32* paletteEmulation = nullptr;
|
||||
unique_pointer<uint32[]> output;
|
||||
unique_pointer<uint32[]> paletteLiteral;
|
||||
unique_pointer<uint32[]> paletteStandard;
|
||||
unique_pointer<uint32[]> paletteEmulation;
|
||||
};
|
||||
|
||||
extern Video video;
|
||||
|
|
|
@ -67,7 +67,7 @@ obj/ui-resource.o:
|
|||
|
||||
# targets
|
||||
build: $(objects)
|
||||
$(strip $(compiler) -o out/$(name) $(objects) $(link))
|
||||
$(call unique,$(compiler) -o out/$(name) $(objects) $(link))
|
||||
ifeq ($(platform),macosx)
|
||||
@if [ -d out/$(name).app ]; then rm -r out/$(name).app; fi
|
||||
mkdir -p out/$(name).app/Contents/MacOS/
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Settings settings;
|
||||
|
||||
Settings::Settings() {
|
||||
Markup::Node::operator=(BML::unserialize(string::read(locate({localpath(), "higan/"}, "settings.bml"))));
|
||||
Markup::Node::operator=(BML::unserialize(string::read(locate("settings.bml"))));
|
||||
|
||||
auto set = [&](const string& name, const string& value) {
|
||||
//create node and set to default value only if it does not already exist
|
||||
|
@ -48,5 +48,5 @@ Settings::Settings() {
|
|||
}
|
||||
|
||||
auto Settings::quit() -> void {
|
||||
file::write(locate({localpath(), "higan/"}, "settings.bml"), BML::serialize(*this));
|
||||
file::write(locate("settings.bml"), BML::serialize(*this));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "../tomoko.hpp"
|
||||
#include "hotkeys.cpp"
|
||||
InputManager* inputManager = nullptr;
|
||||
unique_pointer<InputManager> inputManager;
|
||||
|
||||
auto InputMapping::bind() -> void {
|
||||
auto token = assignment.split("/");
|
||||
|
@ -124,7 +124,10 @@ auto InputMapping::assignmentName() -> string {
|
|||
if(!device) return "None";
|
||||
string path;
|
||||
path.append(device->name());
|
||||
path.append(".", device->group(group).name());
|
||||
if(device->name() != "Keyboard") {
|
||||
//keyboards only have one group; no need to append group name
|
||||
path.append(".", device->group(group).name());
|
||||
}
|
||||
path.append(".", device->group(group).input(input).name());
|
||||
if(qualifier == Qualifier::Lo) path.append(".Lo");
|
||||
if(qualifier == Qualifier::Hi) path.append(".Hi");
|
||||
|
|
|
@ -62,4 +62,4 @@ struct InputManager {
|
|||
vector<InputHotkey*> hotkeys;
|
||||
};
|
||||
|
||||
extern InputManager* inputManager;
|
||||
extern unique_pointer<InputManager> inputManager;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "../tomoko.hpp"
|
||||
Presentation* presentation = nullptr;
|
||||
unique_pointer<Presentation> presentation;
|
||||
|
||||
Presentation::Presentation() {
|
||||
presentation = this;
|
||||
|
@ -275,7 +275,7 @@ auto Presentation::drawSplashScreen() -> void {
|
|||
}
|
||||
|
||||
auto Presentation::loadShaders() -> void {
|
||||
auto pathname = locate({localpath(), "higan/"}, "Video Shaders/");
|
||||
auto pathname = locate("Video Shaders/");
|
||||
|
||||
if(settings["Video/Driver"].text() == "OpenGL") {
|
||||
for(auto shader : directory::folders(pathname, "*.shader")) {
|
||||
|
|
|
@ -70,4 +70,4 @@ struct Presentation : Window {
|
|||
StatusBar statusBar{this};
|
||||
};
|
||||
|
||||
extern Presentation* presentation;
|
||||
extern unique_pointer<Presentation> presentation;
|
||||
|
|
|
@ -16,7 +16,7 @@ auto Program::loadMedia(string location) -> void {
|
|||
auto Program::loadMedia(Emulator::Interface& emulator_, Emulator::Interface::Media& media, const string& location) -> void {
|
||||
unloadMedia();
|
||||
|
||||
mediaPaths(0) = locate({localpath(), "higan/"}, {media.name, ".sys/"});
|
||||
mediaPaths(0) = locate({media.name, ".sys/"});
|
||||
mediaPaths(media.id) = location;
|
||||
folderPaths.append(location);
|
||||
|
||||
|
|
|
@ -7,11 +7,10 @@
|
|||
#include "media.cpp"
|
||||
#include "state.cpp"
|
||||
#include "utility.cpp"
|
||||
Program* program = nullptr;
|
||||
unique_pointer<Program> program;
|
||||
|
||||
Program::Program(lstring args) {
|
||||
program = this;
|
||||
directory::create({localpath(), "higan/"});
|
||||
Application::onMain({&Program::main, this});
|
||||
|
||||
emulators.append(new Famicom::Interface);
|
||||
|
@ -31,10 +30,7 @@ Program::Program(lstring args) {
|
|||
video = Video::create(settings["Video/Driver"].text());
|
||||
video->set(Video::Handle, presentation->viewport.handle());
|
||||
video->set(Video::Synchronize, settings["Video/Synchronize"].boolean());
|
||||
if(!video->init()) {
|
||||
delete video;
|
||||
video = Video::create("None");
|
||||
}
|
||||
if(!video->init()) video = Video::create("None");
|
||||
|
||||
audio = Audio::create(settings["Audio/Driver"].text());
|
||||
audio->set(Audio::Device, settings["Audio/Device"].text());
|
||||
|
@ -42,18 +38,12 @@ Program::Program(lstring args) {
|
|||
audio->set(Audio::Synchronize, settings["Audio/Synchronize"].boolean());
|
||||
audio->set(Audio::Frequency, 96000u);
|
||||
audio->set(Audio::Latency, 80u);
|
||||
if(!audio->init()) {
|
||||
delete audio;
|
||||
audio = Audio::create("None");
|
||||
}
|
||||
if(!audio->init()) audio = Audio::create("None");
|
||||
|
||||
input = Input::create(settings["Input/Driver"].text());
|
||||
input->set(Input::Handle, presentation->viewport.handle());
|
||||
input->onChange({&InputManager::onChange, inputManager});
|
||||
if(!input->init()) {
|
||||
delete input;
|
||||
input = Input::create("None");
|
||||
}
|
||||
input->onChange({&InputManager::onChange, &inputManager()});
|
||||
if(!input->init()) input = Input::create("None");
|
||||
|
||||
dsp.setPrecision(16);
|
||||
dsp.setBalance(0.0);
|
||||
|
@ -82,7 +72,7 @@ auto Program::load(string location) -> void {
|
|||
} else if(file::exists(location)) {
|
||||
//special handling to allow importing the Game Boy Advance BIOS
|
||||
if(file::size(location) == 16384 && file::sha256(location).beginsWith("fd2547724b505f48")) {
|
||||
auto target = locate({localpath(), "higan/"}, "Game Boy Advance.sys/");
|
||||
auto target = locate("Game Boy Advance.sys/");
|
||||
if(file::copy(location, {target, "bios.rom"})) {
|
||||
MessageDialog().setTitle(Emulator::Name).setText("Game Boy Advance BIOS imported successfully!").information();
|
||||
}
|
||||
|
@ -113,8 +103,5 @@ auto Program::quit() -> void {
|
|||
unloadMedia();
|
||||
settings.quit();
|
||||
inputManager->quit();
|
||||
delete video;
|
||||
delete audio;
|
||||
delete input;
|
||||
Application::quit();
|
||||
}
|
||||
|
|
|
@ -50,4 +50,4 @@ struct Program : Emulator::Interface::Bind {
|
|||
time_t statusTime = 0;
|
||||
};
|
||||
|
||||
extern Program* program;
|
||||
extern unique_pointer<Program> program;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "hotkeys.cpp"
|
||||
#include "timing.cpp"
|
||||
#include "advanced.cpp"
|
||||
SettingsManager* settingsManager = nullptr;
|
||||
unique_pointer<SettingsManager> settingsManager;
|
||||
|
||||
SettingsManager::SettingsManager() {
|
||||
settingsManager = this;
|
||||
|
@ -14,7 +14,7 @@ SettingsManager::SettingsManager() {
|
|||
statusBar.setFont(Font().setBold());
|
||||
|
||||
setTitle("Configuration Settings");
|
||||
setSize({600, 400});
|
||||
setSize({600, 405});
|
||||
setAlignment({0.0, 1.0});
|
||||
|
||||
onSize([&] {
|
||||
|
|
|
@ -142,4 +142,4 @@ struct SettingsManager : Window {
|
|||
StatusBar statusBar{this};
|
||||
};
|
||||
|
||||
extern SettingsManager* settingsManager;
|
||||
extern unique_pointer<SettingsManager> settingsManager;
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
#include "tomoko.hpp"
|
||||
Video* video = nullptr;
|
||||
Audio* audio = nullptr;
|
||||
Input* input = nullptr;
|
||||
Emulator::Interface* emulator = nullptr;
|
||||
unique_pointer<Video> video;
|
||||
unique_pointer<Audio> audio;
|
||||
unique_pointer<Input> input;
|
||||
unique_pointer<Emulator::Interface> emulator;
|
||||
|
||||
//if file already exists in the same path as the binary; use it (portable mode)
|
||||
//if not, use default requested path (*nix/user mode)
|
||||
auto locate(string pathname, string filename) -> string {
|
||||
string location{programpath(), filename};
|
||||
auto locate(string name) -> string {
|
||||
string location = {programpath(), name};
|
||||
if(file_system_object::exists(location)) return location;
|
||||
return {pathname, filename};
|
||||
|
||||
location = {configpath(), "higan/", name};
|
||||
if(file_system_object::exists(location)) return location;
|
||||
|
||||
directory::create({localpath(), "higan/"});
|
||||
return {localpath(), "higan/", name};
|
||||
}
|
||||
|
||||
#include <nall/main.hpp>
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
using namespace nall;
|
||||
using namespace ruby;
|
||||
using namespace hiro;
|
||||
extern Video* video;
|
||||
extern Audio* audio;
|
||||
extern Input* input;
|
||||
extern unique_pointer<Video> video;
|
||||
extern unique_pointer<Audio> audio;
|
||||
extern unique_pointer<Input> input;
|
||||
|
||||
#include <emulator/emulator.hpp>
|
||||
extern Emulator::Interface* emulator;
|
||||
extern unique_pointer<Emulator::Interface> emulator;
|
||||
|
||||
#include "program/program.hpp"
|
||||
#include "configuration/configuration.hpp"
|
||||
|
@ -18,4 +18,4 @@ extern Emulator::Interface* emulator;
|
|||
#include "tools/tools.hpp"
|
||||
#include "presentation/presentation.hpp"
|
||||
|
||||
auto locate(string pathname, string filename) -> string;
|
||||
auto locate(string name) -> string;
|
||||
|
|
|
@ -20,7 +20,7 @@ auto CheatDatabase::findCodes() -> void {
|
|||
if(!emulator) return;
|
||||
auto sha256 = emulator->sha256();
|
||||
|
||||
auto contents = string::read(locate({localpath(), "higan/"}, "cheats.bml"));
|
||||
auto contents = string::read(locate("cheats.bml"));
|
||||
auto document = BML::unserialize(contents);
|
||||
|
||||
for(auto cartridge : document.find("cartridge")) {
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
#include "cheat-editor.cpp"
|
||||
#include "state-manager.cpp"
|
||||
#include "manifest-viewer.cpp"
|
||||
CheatDatabase* cheatDatabase = nullptr;
|
||||
ToolsManager* toolsManager = nullptr;
|
||||
ManifestViewer* manifestViewer = nullptr;
|
||||
unique_pointer<CheatDatabase> cheatDatabase;
|
||||
unique_pointer<ToolsManager> toolsManager;
|
||||
|
||||
ToolsManager::ToolsManager() {
|
||||
toolsManager = this;
|
||||
|
@ -13,7 +12,7 @@ ToolsManager::ToolsManager() {
|
|||
layout.setMargin(5);
|
||||
|
||||
setTitle("Tools");
|
||||
setSize({600, 400});
|
||||
setSize({600, 405});
|
||||
setAlignment({1.0, 1.0});
|
||||
|
||||
onSize([&] {
|
||||
|
|
|
@ -95,5 +95,5 @@ struct ToolsManager : Window {
|
|||
ManifestViewer manifestViewer{&panel};
|
||||
};
|
||||
|
||||
extern CheatDatabase* cheatDatabase;
|
||||
extern ToolsManager* toolsManager;
|
||||
extern unique_pointer<CheatDatabase> cheatDatabase;
|
||||
extern unique_pointer<ToolsManager> toolsManager;
|
||||
|
|
|
@ -113,6 +113,14 @@ rwildcard = \
|
|||
) \
|
||||
)
|
||||
|
||||
# function unique(source)
|
||||
unique = \
|
||||
$(eval __temp :=) \
|
||||
$(strip \
|
||||
$(foreach s,$1,$(if $(filter $s,$(__temp)),,$(eval __temp += $s))) \
|
||||
$(__temp) \
|
||||
)
|
||||
|
||||
# function strtr(source, from, to)
|
||||
strtr = \
|
||||
$(eval __temp := $1) \
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <nall/string.hpp>
|
||||
#include <nall/thread.hpp>
|
||||
#include <nall/traits.hpp>
|
||||
#include <nall/unique-pointer.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
#include <nall/varint.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
|
|
|
@ -11,9 +11,9 @@ template<typename T> struct shared_pointer;
|
|||
|
||||
struct shared_pointer_manager {
|
||||
void* pointer = nullptr;
|
||||
function<void (void*)> deleter;
|
||||
unsigned strong = 0;
|
||||
unsigned weak = 0;
|
||||
function<auto (void*) -> void> deleter;
|
||||
uint strong = 0;
|
||||
uint weak = 0;
|
||||
|
||||
shared_pointer_manager(void* pointer) : pointer(pointer) {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
#pragma once
|
||||
|
||||
namespace nall {
|
||||
|
||||
template<typename T>
|
||||
struct unique_pointer {
|
||||
using type = T;
|
||||
T* pointer = nullptr;
|
||||
function<auto (T*) -> void> deleter;
|
||||
|
||||
unique_pointer(const unique_pointer&) = delete;
|
||||
auto operator=(const unique_pointer&) -> unique_pointer& = delete;
|
||||
|
||||
unique_pointer(T* pointer = nullptr, const function<void (T*)>& deleter = {}) : pointer(pointer), deleter(deleter) {}
|
||||
~unique_pointer() { reset(); }
|
||||
|
||||
auto operator=(T* source) -> unique_pointer& {
|
||||
reset();
|
||||
pointer = source;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return pointer; }
|
||||
|
||||
auto operator->() -> T* { return pointer; }
|
||||
auto operator->() const -> const T* { return pointer; }
|
||||
|
||||
auto operator*() -> T& { return *pointer; }
|
||||
auto operator*() const -> const T& { return *pointer; }
|
||||
|
||||
auto operator()() -> T& { return *pointer; }
|
||||
auto operator()() const -> const T& { return *pointer; }
|
||||
|
||||
auto data() -> T* { return pointer; }
|
||||
auto data() const -> const T* { return pointer; }
|
||||
|
||||
auto release() -> T* {
|
||||
auto result = pointer;
|
||||
pointer = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto reset() -> void {
|
||||
if(pointer) {
|
||||
if(deleter) {
|
||||
deleter(pointer);
|
||||
} else {
|
||||
delete pointer;
|
||||
}
|
||||
pointer = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct unique_pointer<T[]> {
|
||||
using type = T;
|
||||
T* pointer = nullptr;
|
||||
function<auto (T*) -> void> deleter;
|
||||
|
||||
unique_pointer(const unique_pointer&) = delete;
|
||||
auto operator=(const unique_pointer&) -> unique_pointer& = delete;
|
||||
|
||||
unique_pointer(T* pointer = nullptr, const function<void (T*)>& deleter = {}) : pointer(pointer), deleter(deleter) {}
|
||||
~unique_pointer() { reset(); }
|
||||
|
||||
auto operator=(T* source) -> unique_pointer& {
|
||||
reset();
|
||||
pointer = source;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return pointer; }
|
||||
|
||||
auto operator()() -> T* { return pointer; }
|
||||
auto operator()() const -> T* { return pointer; }
|
||||
|
||||
alwaysinline auto operator[](uint offset) -> T& { return pointer[offset]; }
|
||||
alwaysinline auto operator[](uint offset) const -> const T& { return pointer[offset]; }
|
||||
|
||||
auto data() -> T* { return pointer; }
|
||||
auto data() const -> const T* { return pointer; }
|
||||
|
||||
auto release() -> T* {
|
||||
auto result = pointer;
|
||||
pointer = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto reset() -> void {
|
||||
if(pointer) {
|
||||
if(deleter) {
|
||||
deleter(pointer);
|
||||
} else {
|
||||
delete[] pointer;
|
||||
}
|
||||
pointer = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
#include <windows.h>
|
||||
|
||||
struct AudioXAudio2 : Audio, public IXAudio2VoiceCallback {
|
||||
AudioXAudio2() { term(); }
|
||||
~AudioXAudio2() { term(); }
|
||||
|
||||
IXAudio2* pXAudio2 = nullptr;
|
||||
IXAudio2MasteringVoice* pMasterVoice = nullptr;
|
||||
|
|
Loading…
Reference in New Issue