Update to v075 release.

byuu says:

This release brings improved Super Game Boy emulation, the final SHA256
hashes for the DSP-(1,1B,2,3,4) and ST-(0010,0011) coprocessors, user
interface improvements, and major internal code restructuring.

Changelog (since v074):
- completely rewrote memory sub-system to support 1-byte granularity in
  XML mapping
- removed Memory inheritance and MMIO class completely, any address can
  be mapped to any function now
- SuperFX: removed SuperFXBus : Bus, now implemented manually
- SA-1: removed SA1Bus : Bus, now implemented manually
- entire bus mapping is now static, happens once on cartridge load
- as a result, read/write handlers now handle MMC mapping; slower
  average case, far faster worst case
- namespace memory is no more, RAM arrays are stored inside the chips
  they are owned by now
- GameBoy: improved CPU HALT emulation, fixes Zelda: Link's Awakening
  scrolling
- GameBoy: added serial emulation (cannot connect to another GB yet),
  fixes Shin Megami Tensei - Devichil
- GameBoy: improved LCD STAT emulation, fixes Sagaia
- ui: added fullscreen support (F11 key), video settings allows for
  three scale settings
- ui: fixed brightness, contrast, gamma, audio volume, input frequency
  values on program startup
- ui: since Qt is dead, config file becomes bsnes.cfg once again
- Super Game Boy: you can now load the BIOS without a game inserted to
  see a pretty white box
- ui-gameboy: can be built without SNES components now
- libsnes: now a UI target, compile with 'make ui=ui-libsnes'
- libsnes: added WRAM, APURAM, VRAM, OAM, CGRAM access (cheat search,
  etc)
- source: removed launcher/, as the Qt port is now gone
- source: Makefile restructuring to better support new ui targets
- source: lots of other internal code cleanup work
This commit is contained in:
Tim Allen 2011-01-27 19:52:34 +11:00
parent 53fe43afd8
commit 6b4104867f
59 changed files with 7121 additions and 6238 deletions

View File

@ -1,7 +1,7 @@
include nall/Makefile
snes := snes
gameboy := gameboy
profile := compatibility
profile := accuracy
ui := ui
# compiler
@ -50,39 +50,8 @@ obj/libco.o: libco/libco.c libco/*
include $(ui)/Makefile
objects := $(patsubst %,obj/%.o,$(objects))
# targets
build: ui_build $(objects)
ifeq ($(platform),osx)
test -d ../$(output).app || mkdir -p ../$(output).app/Contents/MacOS
$(strip $(cpp) -o ../$(output).app/Contents/MacOS/$(output) $(objects) $(link))
else
$(strip $(cpp) -o out/$(output) $(objects) $(link))
endif
install:
ifeq ($(platform),x)
install -D -m 755 out/$(output) $(DESTDIR)$(prefix)/bin/$(output)
endif
ifeq ($(output),bsnes)
install -D -m 644 data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
test -d ~/.bsnes || mkdir ~/.bsnes
cp data/cheats.xml ~/.bsnes/cheats.xml
chmod 777 ~/.bsnes ~/.bsnes/cheats.xml
endif
uninstall:
ifeq ($(platform),x)
rm $(DESTDIR)$(prefix)/bin/$(output)
endif
ifeq ($(output),bsnes)
rm $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
rm $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
endif
clean: ui_clean
clean:
-@$(call delete,obj/*.o)
-@$(call delete,obj/*.a)
-@$(call delete,obj/*.so)

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@ Cartridge cartridge;
void Cartridge::load(const string &xml, const uint8_t *data, unsigned size) {
if(size == 0) size = 32768;
romdata = new uint8[romsize = size]();
romdata = allocate<uint8>(romsize = size, 0xff);
if(data) memcpy(romdata, data, size);
//uint32_t crc = crc32_calculate(data, size);

View File

@ -28,8 +28,6 @@ else ifeq ($(profile),performance)
snesppu := $(snes)/alt/ppu-performance
endif
obj/libsnes.o: $(snes)/libsnes/libsnes.cpp $(snes)/libsnes/*
obj/snes-system.o : $(snes)/system/system.cpp $(call rwildcard,$(snes)/system/) $(call rwildcard,$(snes)/video/)
obj/snes-memory.o : $(snes)/memory/memory.cpp $(call rwildcard,$(snes)/memory/)
obj/snes-cpucore.o : $(snes)/cpu/core/core.cpp $(call rwildcard,$(snes)/cpu/core/)
@ -55,37 +53,3 @@ obj/snes-st0018.o : $(snes)/chip/st0018/st0018.cpp $(snes)/chip/st0018/*
obj/snes-sufamiturbo.o: $(snes)/chip/sufamiturbo/sufamiturbo.cpp $(snes)/chip/sufamiturbo/*
obj/snes-msu1.o : $(snes)/chip/msu1/msu1.cpp $(snes)/chip/msu1/*
obj/snes-serial.o : $(snes)/chip/serial/serial.cpp $(snes)/chip/serial/*
###########
# library #
###########
snes_objects := $(patsubst %,obj/%.o,$(snes_objects))
library: $(snes_objects) obj/libsnes.o
ifeq ($(platform),x)
ar rcs out/libsnes.a $(snes_objects) obj/libsnes.o
$(cpp) -o out/libsnes.so -shared -Wl,-soname,libsnes.so.1 $(snes_objects) obj/libsnes.o
else ifeq ($(platform),osx)
ar rcs out/libsnes.a $(snes_objects) obj/libsnes.o
$(cpp) -o out/libsnes.dylib -install_name @executable_path/../Libraries/libsnes.dylib -shared -dynamiclib $(snes_objects) obj/libsnes.o
else ifeq ($(platform),win)
$(cpp) -o out/snes.dll -shared -Wl,--out-implib,libsnes.a $(snes_objects) obj/libsnes.o
endif
library-install:
ifeq ($(platform),x)
install -D -m 755 out/libsnes.a $(DESTDIR)$(prefix)/lib/libsnes.a
install -D -m 755 out/libsnes.so $(DESTDIR)$(prefix)/lib/libsnes.so
ldconfig -n $(DESTDIR)$(prefix)/lib
else ifeq ($(platform),osx)
cp out/libsnes.dylib /usr/local/lib/libsnes.dylib
endif
library-uninstall:
ifeq ($(platform),x)
rm $(DESTDIR)$(prefix)/lib/libsnes.a
rm $(DESTDIR)$(prefix)/lib/libsnes.so
else ifeq ($(platform),osx)
rm /usr/local/lib/libsnes.dylib
endif

View File

@ -61,10 +61,12 @@ void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) {
}
void Cartridge::unload() {
if(loaded == false) return;
system.unload();
rom.reset();
ram.reset();
if(loaded == false) return;
loaded = false;
}

View File

@ -52,6 +52,7 @@ void Cartridge::parse_xml_cartridge(const char *data) {
}
void Cartridge::parse_xml_bsx(const char *data) {
has_bsx_slot = true;
}
void Cartridge::parse_xml_sufami_turbo(const char *data, bool slot) {
@ -70,7 +71,7 @@ void Cartridge::xml_parse_rom(xml_element &root) {
if(attr.name == "offset") m.offset = hex(attr.content);
if(attr.name == "size") m.size = hex(attr.content);
}
if(m.size == 0) m.size = rom.size() - m.offset;
if(m.size == 0) m.size = rom.size();
mapping.append(m);
}
}
@ -90,7 +91,7 @@ void Cartridge::xml_parse_ram(xml_element &root) {
if(attr.name == "offset") m.offset = hex(attr.content);
if(attr.name == "size") m.size = hex(attr.content);
}
if(m.size == 0) m.size = ram_size - m.offset;
if(m.size == 0) m.size = ram_size;
mapping.append(m);
}
}

View File

@ -5,7 +5,7 @@ BSXCartridge bsxcartridge;
void BSXCartridge::init() {
}
void BSXCartridge::enable() {
void BSXCartridge::load() {
sram.map(allocate<uint8>(32 * 1024, 0xff), 32 * 1024);
sram.write_protect(false);
cartridge.nvram.append({ "bss", sram.data(), sram.size() });
@ -15,6 +15,9 @@ void BSXCartridge::enable() {
cartridge.nvram.append({ "bsp", psram.data(), psram.size() });
}
void BSXCartridge::unload() {
}
void BSXCartridge::power() {
reset();
}

View File

@ -4,7 +4,8 @@ public:
MappedRAM psram;
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -5,7 +5,14 @@ BSXFlash bsxflash;
void BSXFlash::init() {
}
void BSXFlash::enable() {
void BSXFlash::load() {
if(memory.size() == 0) {
memory.map(allocate<uint8>(1024 * 1024, 0xff), 1024 * 1024);
}
}
void BSXFlash::unload() {
memory.reset();
}
void BSXFlash::power() {

View File

@ -3,7 +3,8 @@ public:
MappedRAM memory;
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -5,11 +5,14 @@ BSXSatellaview bsxsatellaview;
void BSXSatellaview::init() {
}
void BSXSatellaview::enable() {
void BSXSatellaview::load() {
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2188, 0x219f, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview });
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2188, 0x219f, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview });
}
void BSXSatellaview::unload() {
}
void BSXSatellaview::power() {
reset();
}

View File

@ -1,7 +1,8 @@
class BSXSatellaview {
public:
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -20,7 +20,10 @@ Cx4 cx4;
void Cx4::init() {
}
void Cx4::enable() {
void Cx4::load() {
}
void Cx4::unload() {
}
uint32 Cx4::ldr(uint8 r) {

View File

@ -1,7 +1,8 @@
class Cx4 {
public:
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -31,13 +31,16 @@ void ICD2::enter() {
void ICD2::init() {
}
void ICD2::enable() {
void ICD2::load() {
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2181, 0x2182, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x420b, 0x420b, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2181, 0x2182, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x420b, 0x420b, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
}
void ICD2::unload() {
}
void ICD2::power() {
reset();
}

View File

@ -6,7 +6,8 @@ public:
void enter();
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -48,11 +48,15 @@ void MSU1::enter() {
void MSU1::init() {
}
void MSU1::enable() {
void MSU1::load() {
if(datafile.open()) datafile.close();
datafile.open(string(cartridge.basename(), ".msu"), file::mode::read);
}
void MSU1::unload() {
if(datafile.open()) datafile.close();
}
void MSU1::power() {
audio.coprocessor_enable(true);
audio.coprocessor_frequency(44100.0);

View File

@ -3,7 +3,8 @@ public:
static void Enter();
void enter();
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -245,12 +245,15 @@ void NECDSP::exec_ld(uint24 opcode) {
void NECDSP::init() {
}
void NECDSP::enable() {
void NECDSP::load() {
if(revision == Revision::uPD96050) {
cartridge.nvram.append({ "nec", (uint8_t*)dataRAM, 4096 });
}
}
void NECDSP::unload() {
}
void NECDSP::power() {
if(revision == Revision::uPD7725) {
regs.pc.bits(11);

View File

@ -33,7 +33,8 @@ public:
void dp_write(unsigned addr, uint8 data);
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -10,7 +10,10 @@ OBC1 obc1;
void OBC1::init() {
}
void OBC1::enable() {
void OBC1::load() {
}
void OBC1::unload() {
}
void OBC1::power() {

View File

@ -1,7 +1,8 @@
class OBC1 {
public:
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -118,7 +118,10 @@ void SA1::trigger_irq() {
void SA1::init() {
}
void SA1::enable() {
void SA1::load() {
}
void SA1::unload() {
}
void SA1::power() {

View File

@ -26,7 +26,8 @@ public:
alwaysinline bool interrupt_pending();
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -11,13 +11,16 @@ SDD1 sdd1;
void SDD1::init() {
}
void SDD1::enable() {
void SDD1::load() {
//hook S-CPU DMA MMIO registers to gather information for struct dma[];
//buffer address and transfer size information for use in SDD1::mcu_read()
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
}
void SDD1::unload() {
}
void SDD1::power() {
reset();
}

View File

@ -3,7 +3,8 @@
class SDD1 {
public:
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -77,7 +77,7 @@ void Serial::mmio_write(unsigned addr, uint8 data) {
void Serial::init() {
}
void Serial::enable() {
void Serial::load() {
if(opened()) close();
string name = notdir(cartridge.basename());
string path = dir(cartridge.basename());
@ -91,6 +91,10 @@ void Serial::enable() {
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, { &Serial::mmio_read, &serial }, { &Serial::mmio_write, &serial });
}
void Serial::unload() {
if(opened()) close();
}
void Serial::power() {
reset();
}

View File

@ -3,7 +3,8 @@ public:
static void Enter();
void enter();
void init();
void enable();
void load();
void unload();
void power();
void reset();
void serialize(serializer&);

View File

@ -13,11 +13,14 @@ const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 3
void SPC7110::init() {
}
void SPC7110::enable() {
void SPC7110::load() {
for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff;
if(cartridge.has_spc7110rtc()) cartridge.nvram.append({ "rtc", rtc, 20 });
}
void SPC7110::unload() {
}
void SPC7110::power() {
reset();
}

View File

@ -23,7 +23,8 @@ public:
unsigned data_rom_offset;
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -12,11 +12,14 @@ const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,
void SRTC::init() {
}
void SRTC::enable() {
void SRTC::load() {
for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff;
cartridge.nvram.append({ "rtc", rtc, 20 });
}
void SRTC::unload() {
}
void SRTC::power() {
reset();
}

View File

@ -3,7 +3,8 @@ public:
uint8 rtc[20];
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -48,7 +48,10 @@ void ST0018::mmio_write(unsigned addr, uint8 data) {
void ST0018::init() {
}
void ST0018::enable() {
void ST0018::load() {
}
void ST0018::unload() {
}
void ST0018::power() {

View File

@ -1,7 +1,8 @@
class ST0018 {
public:
void init();
void enable();
void load();
void unload();
void power();
void reset();

View File

@ -6,16 +6,28 @@ namespace SNES {
#include "serialization.cpp"
SufamiTurbo sufamiturbo;
void SufamiTurbo::enable() {
void SufamiTurbo::load() {
slotA.ram.map(allocate<uint8>(128 * 1024, 0xff), 128 * 1024);
slotB.ram.map(allocate<uint8>(128 * 1024, 0xff), 128 * 1024);
if(slotA.rom.data()) {
slotA.ram.map(allocate<uint8>(128 * 1024, 0xff), 128 * 1024);
cartridge.nvram.append({ "srm", slotA.ram.data(), slotA.ram.size(), 1 });
} else {
slotA.rom.map(allocate<uint8>(128 * 1024, 0xff), 128 * 1024);
}
if(slotB.rom.data()) {
slotB.ram.map(allocate<uint8>(128 * 1024, 0xff), 128 * 1024);
cartridge.nvram.append({ "srm", slotB.ram.data(), slotB.ram.size(), 2 });
} else {
slotB.rom.map(allocate<uint8>(128 * 1024, 0xff), 128 * 1024);
}
}
void SufamiTurbo::unload() {
slotA.rom.reset();
slotA.ram.reset();
slotB.rom.reset();
slotB.ram.reset();
}
}

View File

@ -5,7 +5,8 @@ public:
MappedRAM ram;
} slotA, slotB;
void enable();
void load();
void unload();
void serialize(serializer&);
};

View File

@ -43,7 +43,10 @@ void SuperFX::init() {
regs.r[15].on_modify = { &SuperFX::r15_modify, this };
}
void SuperFX::enable() {
void SuperFX::load() {
}
void SuperFX::unload() {
}
void SuperFX::power() {

View File

@ -10,7 +10,8 @@ public:
static void Enter();
void enter();
void init();
void enable();
void load();
void unload();
void power();
void reset();
void serialize(serializer&);

View File

@ -45,10 +45,10 @@ void Bus::map(
for(unsigned addr = addr_lo; addr <= addr_hi; addr++) {
unsigned destaddr = (bank << 16) | addr;
if(mode == MapMode::Linear) {
destaddr = base + mirror(offset, length);
destaddr = mirror(base + offset, length);
offset = (offset + 1) % length;
} else if(mode == MapMode::Shadow) {
destaddr = base + mirror(destaddr, length);
destaddr = mirror(base + destaddr, length);
}
lookup[(bank << 16) | addr] = id;
target[(bank << 16) | addr] = destaddr;

View File

@ -1,7 +1,7 @@
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
static const char Version[] = "074.11";
static const char Version[] = "075";
static const unsigned SerializerVersion = 17;
}
}

View File

@ -104,23 +104,43 @@ void System::load() {
cpu.enable();
ppu.enable();
if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.enable();
if(cartridge.mode() == Cartridge::Mode::Bsx) bsxcartridge.enable();
if(cartridge.mode() == Cartridge::Mode::SufamiTurbo) sufamiturbo.enable();
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.enable();
if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.load();
if(cartridge.mode() == Cartridge::Mode::Bsx) bsxcartridge.load();
if(cartridge.mode() == Cartridge::Mode::SufamiTurbo) sufamiturbo.load();
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.load();
if(cartridge.has_bsx_slot()) bsxflash.enable();
if(cartridge.has_superfx()) superfx.enable();
if(cartridge.has_sa1()) sa1.enable();
if(cartridge.has_necdsp()) necdsp.enable();
if(cartridge.has_srtc()) srtc.enable();
if(cartridge.has_sdd1()) sdd1.enable();
if(cartridge.has_spc7110()) spc7110.enable();
if(cartridge.has_cx4()) cx4.enable();
if(cartridge.has_obc1()) obc1.enable();
if(cartridge.has_st0018()) st0018.enable();
if(cartridge.has_msu1()) msu1.enable();
if(cartridge.has_serial()) serial.enable();
if(cartridge.has_bsx_slot()) bsxflash.load();
if(cartridge.has_superfx()) superfx.load();
if(cartridge.has_sa1()) sa1.load();
if(cartridge.has_necdsp()) necdsp.load();
if(cartridge.has_srtc()) srtc.load();
if(cartridge.has_sdd1()) sdd1.load();
if(cartridge.has_spc7110()) spc7110.load();
if(cartridge.has_cx4()) cx4.load();
if(cartridge.has_obc1()) obc1.load();
if(cartridge.has_st0018()) st0018.load();
if(cartridge.has_msu1()) msu1.load();
if(cartridge.has_serial()) serial.load();
}
void System::unload() {
if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.unload();
if(cartridge.mode() == Cartridge::Mode::Bsx) bsxcartridge.unload();
if(cartridge.mode() == Cartridge::Mode::SufamiTurbo) sufamiturbo.unload();
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.unload();
if(cartridge.has_bsx_slot()) bsxflash.unload();
if(cartridge.has_superfx()) superfx.unload();
if(cartridge.has_sa1()) sa1.unload();
if(cartridge.has_necdsp()) necdsp.unload();
if(cartridge.has_srtc()) srtc.unload();
if(cartridge.has_sdd1()) sdd1.unload();
if(cartridge.has_spc7110()) spc7110.unload();
if(cartridge.has_cx4()) cx4.unload();
if(cartridge.has_obc1()) obc1.unload();
if(cartridge.has_st0018()) st0018.unload();
if(cartridge.has_msu1()) msu1.unload();
if(cartridge.has_serial()) serial.unload();
}
void System::power() {
@ -209,9 +229,6 @@ void System::reset() {
input.update();
}
void System::unload() {
}
void System::scanline() {
video.scanline();
if(cpu.vcounter() == 241) scheduler.exit(Scheduler::ExitReason::FrameEvent);

View File

@ -11,9 +11,9 @@ public:
void init(Interface*);
void term();
void load();
void unload();
void power();
void reset();
void unload();
void frame();
void scanline();

View File

@ -1,4 +1,3 @@
output := bgameboy
include $(gameboy)/Makefile
ui_objects := ui-main ui-utility
@ -58,6 +57,7 @@ rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
# rules
objects := $(ui_objects) $(objects)
objects := $(patsubst %,obj/%.o,$(objects))
obj/ui-main.o: $(ui)/main.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/*); $(phoenix_compile)
obj/ui-utility.o: $(ui)/utility/utility.cpp $(call rwildcard,$(ui)/utility/*); $(phoenix_compile)
@ -69,6 +69,20 @@ obj/phoenix.o: phoenix/phoenix.cpp $(call rwildcard,phoenix/*)
$(phoenix_compile)
# targets
ui_build:;
build: $(objects)
ifeq ($(platform),osx)
test -d ../bgameboy.app || mkdir -p ../bgameboy.app/Contents/MacOS
$(strip $(cpp) -o ../bgameboy.app/Contents/MacOS/bgameboy $(objects) $(link))
else
$(strip $(cpp) -o out/bgameboy $(objects) $(link))
endif
ui_clean:;
install:
ifeq ($(platform),x)
install -D -m 755 out/bgameboy $(DESTDIR)$(prefix)/bin/bgameboy
endif
uninstall:
ifeq ($(platform),x)
rm $(DESTDIR)$(prefix)/bin/bgameboy
endif

45
bsnes/ui-libsnes/Makefile Executable file
View File

@ -0,0 +1,45 @@
include $(snes)/Makefile
include $(gameboy)/Makefile
output := libsnes
ifeq ($(platform),x)
flags += -fPIC
else ifeq ($(platform),osx)
flags += -fPIC
else ifeq ($(platform),win)
endif
#rules
objects := $(objects) libsnes
objects := $(patsubst %,obj/%.o,$(objects))
obj/libsnes.o: $(ui)/libsnes.cpp $(ui)/*
#targets
build: $(objects)
ifeq ($(platform),x)
ar rcs out/libsnes.a $(objects)
$(cpp) -o out/libsnes.so -shared -Wl,-soname,libsnes.so.1 $(objects)
else ifeq ($(platform),osx)
ar rcs out/libsnes.a $(objects)
$(cpp) -o out/libsnes.dylib -install_name @executable_path/../Libraries/libsnes.dylib -shared -dynamiclib $(objects)
else ifeq ($(platform),win)
$(cpp) -o out/snes.dll -shared -Wl,--out-implib,libsnes.a $(objects)
endif
install:
ifeq ($(platform),x)
install -D -m 755 out/libsnes.a $(DESTDIR)$(prefix)/lib/libsnes.a
install -D -m 755 out/libsnes.so $(DESTDIR)$(prefix)/lib/libsnes.so
ldconfig -n $(DESTDIR)$(prefix)/lib
else ifeq ($(platform),osx)
cp out/libsnes.dylib /usr/local/lib/libsnes.dylib
endif
uninstall:
ifeq ($(platform),x)
rm $(DESTDIR)$(prefix)/lib/libsnes.a
rm $(DESTDIR)$(prefix)/lib/libsnes.so
else ifeq ($(platform),osx)
rm /usr/local/lib/libsnes.dylib
endif

View File

@ -1,4 +1,3 @@
output := bsnes
include $(snes)/Makefile
include $(gameboy)/Makefile
@ -60,6 +59,7 @@ rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
# rules
objects := $(ui_objects) $(objects)
objects := $(patsubst %,obj/%.o,$(objects))
obj/ui-main.o: $(ui)/main.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/*); $(phoenix_compile)
obj/ui-general.o: $(ui)/general/general.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/general/*); $(phoenix_compile)
@ -80,6 +80,27 @@ obj/resource.o: $(ui)/resource.rc
windres $(ui)/resource.rc obj/resource.o
# targets
ui_build:;
build: $(objects)
ifeq ($(platform),osx)
test -d ../bsnes.app || mkdir -p ../bsnes.app/Contents/MacOS
$(strip $(cpp) -o ../bsnes.app/Contents/MacOS/bsnes $(objects) $(link))
else
$(strip $(cpp) -o out/bsnes $(objects) $(link))
endif
ui_clean:;
install:
ifeq ($(platform),x)
install -D -m 755 out/bsnes $(DESTDIR)$(prefix)/bin/bsnes
endif
install -D -m 644 data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
test -d ~/.bsnes || mkdir ~/.bsnes
cp data/cheats.xml ~/.bsnes/cheats.xml
chmod 777 ~/.bsnes ~/.bsnes/cheats.xml
uninstall:
ifeq ($(platform),x)
rm $(DESTDIR)$(prefix)/bin/bsnes
endif
rm $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
rm $(DESTDIR)$(prefix)/share/applications/bsnes.desktop

View File

@ -22,6 +22,7 @@ void Configuration::create() {
attach(video.shader = "", "video.shader");
attach(video.region = 0, "video.region");
attach(video.scale = 2, "video.scale");
attach(video.fullscreenScale = 0, "video.fullscreenScale");
attach(video.aspectRatioCorrection = true, "video.aspectRatioCorrection");
attach(video.brightness = 100, "video.brightness");
attach(video.contrast = 100, "video.contrast");

View File

@ -16,6 +16,7 @@ struct Configuration : public configuration {
string shader;
bool region;
unsigned scale;
unsigned fullscreenScale;
bool aspectRatioCorrection;
unsigned brightness;
unsigned contrast;

View File

@ -7,14 +7,12 @@ void AudioSettings::create() {
unsigned x = 5, y = 5;
volumeLabel.create(*this, x, y, 70, Style::SliderHeight, "Volume:");
volumeValue.create(*this, x + 70, y, 60, Style::SliderHeight, "100%");
volumeValue.create(*this, x + 70, y, 60, Style::SliderHeight);
volumeSlider.create(*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight + 5;
volumeSlider.setPosition(config.audio.volume);
frequencyLabel.create(*this, x, y, 70, Style::SliderHeight, "Frequency:");
frequencyValue.create(*this, x + 70, y, 60, Style::SliderHeight, "32000hz");
frequencyValue.create(*this, x + 70, y, 60, Style::SliderHeight);
frequencySlider.create(*this, x + 130, y, 300, Style::SliderHeight, 2001); y += Style::SliderHeight + 5;
frequencySlider.setPosition(config.audio.inputFrequency - 31000);
volumeSlider.onChange = []() {
config.audio.volume = audioSettings.volumeSlider.position();
@ -29,4 +27,10 @@ void AudioSettings::create() {
};
setGeometry(0, 0, 440, y);
volumeSlider.setPosition(config.audio.volume);
volumeValue.setText({ config.audio.volume, "%" });
frequencySlider.setPosition(config.audio.inputFrequency - 31000);
frequencyValue.setText({ config.audio.inputFrequency, "hz" });
}

View File

@ -10,19 +10,26 @@ void VideoSettings::create() {
colorAdjustmentLabel.setFont(application.proportionalFontBold);
brightnessLabel.create (*this, x, y, 80, Style::SliderHeight, "Brightness:");
brightnessValue.create (*this, x + 80, y, 40, Style::SliderHeight, "100%");
brightnessValue.create (*this, x + 80, y, 40, Style::SliderHeight);
brightnessSlider.create(*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight;
contrastLabel.create (*this, x, y, 80, Style::SliderHeight, "Contrast:");
contrastValue.create (*this, x + 80, y, 50, Style::SliderHeight, "100%");
contrastValue.create (*this, x + 80, y, 50, Style::SliderHeight);
contrastSlider.create (*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight;
gammaLabel.create (*this, x, y, 80, Style::SliderHeight, "Gamma:");
gammaValue.create (*this, x + 80, y, 50, Style::SliderHeight, "100%");
gammaValue.create (*this, x + 80, y, 50, Style::SliderHeight);
gammaSlider.create (*this, x + 130, y, 300, Style::SliderHeight, 201); y += Style::SliderHeight + 5;
gammaRampCheck.create (*this, x, y, 430, Style::CheckBoxHeight, "Enable NTSC gamma ramp simulation"); y += Style::CheckBoxHeight + 5;
fullscreenLabel.create(*this, x, y, 340, Style::LabelHeight, "Fullscreen :."); y += Style::LabelHeight + 5;
fullscreenLabel.setFont(application.proportionalFontBold);
fullscreenCenter.create (*this, x, y, 135, Style::CheckBoxHeight, "Center");
fullscreenScale.create (fullscreenCenter, x + 140, y, 135, Style::CheckBoxHeight, "Scale");
fullscreenStretch.create(fullscreenCenter, x + 280, y, 135, Style::CheckBoxHeight, "Stretch"); y += Style::CheckBoxHeight + 5;
filterLabel.create(*this, x, y, 340, Style::LabelHeight, "Video Filter :."); y += Style::LabelHeight + 5;
filterLabel.setFont(application.proportionalFontBold);
@ -44,13 +51,29 @@ void VideoSettings::create() {
setGeometry(0, 0, 440, y);
brightnessSlider.setPosition(config.video.brightness);
brightnessValue.setText({ config.video.brightness, "%" });
contrastSlider.setPosition(config.video.contrast);
contrastValue.setText({ config.video.contrast, "%" });
gammaSlider.setPosition(config.video.gamma);
gammaValue.setText({ config.video.gamma, "%" });
gammaRampCheck.setChecked(config.video.useGammaRamp);
switch(config.video.fullscreenScale) { default:
case 0: fullscreenCenter.setChecked(); break;
case 1: fullscreenScale.setChecked(); break;
case 2: fullscreenStretch.setChecked(); break;
}
contrastSlider.onChange = brightnessSlider.onChange = gammaSlider.onChange = gammaRampCheck.onTick =
{ &VideoSettings::adjust, this };
fullscreenCenter.onTick = []() { config.video.fullscreenScale = 0; };
fullscreenScale.onTick = []() { config.video.fullscreenScale = 1; };
fullscreenStretch.onTick = []() { config.video.fullscreenScale = 2; };
filterClear.onTick = []() {
config.video.filter = "";
videoSettings.filterPath.setText(config.video.filter);

View File

@ -11,6 +11,11 @@ struct VideoSettings : TopLevelWindow {
HorizontalSlider gammaSlider;
CheckBox gammaRampCheck;
Label fullscreenLabel;
RadioBox fullscreenCenter;
RadioBox fullscreenScale;
RadioBox fullscreenStretch;
Label filterLabel;
TextBox filterPath;
Button filterClear;

View File

@ -82,10 +82,36 @@ void Utility::setFullscreen(bool fullscreen) {
if(fullscreen == false) {
setScale();
} else {
unsigned baseHeight = config.video.region == 0 ? 224 : 239;
unsigned heightScale = OS::desktopHeight() / baseHeight;
unsigned height = baseHeight * heightScale;
unsigned width = min(OS::desktopWidth(), (unsigned)(256.0 / baseHeight * height));
unsigned width, height;
switch(config.video.fullscreenScale) { default:
case 0: { //center (even multiple of base height)
unsigned baseHeight = config.video.region == 0 ? 224 : 239;
unsigned heightScale = OS::desktopHeight() / baseHeight;
height = baseHeight * heightScale;
width = 256 * heightScale;
if(config.video.region == 0 && config.video.aspectRatioCorrection) width *= 54.0 / 47.0;
if(config.video.region == 1 && config.video.aspectRatioCorrection) width *= 32.0 / 23.0;
width = min(width, OS::desktopWidth());
break;
}
case 1: { //scale (100% screen height, aspect-corrected width)
unsigned baseHeight = config.video.region == 0 ? 224 : 239;
height = OS::desktopHeight();
width = 256.0 / baseHeight * height;
if(config.video.region == 0 && config.video.aspectRatioCorrection) width *= 54.0 / 47.0;
if(config.video.region == 1 && config.video.aspectRatioCorrection) width *= 32.0 / 23.0;
width = min(width, OS::desktopWidth());
break;
}
case 2: { //stretch (100% screen width and 100% screen height)
width = OS::desktopWidth();
height = OS::desktopHeight();
break;
}
}
mainWindow.viewport.setGeometry(
(OS::desktopWidth() - width) / 2,
(OS::desktopHeight() - height) / 2,