Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6ec765f2c4 | ||
|
54c7b4692d | ||
|
66067f0015 | ||
|
4c66de6f27 |
36
src/Makefile
@@ -79,8 +79,9 @@ link += $(call ifhas,input.rawinput,$(ruby),-ldinput8 -ldxguid)
|
||||
objects := libco ruby
|
||||
objects += system cartridge cheat
|
||||
objects += memory smemory cpu cpucore scpu smp smpcore ssmp sdsp ppu bppu
|
||||
objects += sgb superfx sa1
|
||||
objects += supergameboy superfx sa1
|
||||
objects += bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010 st011 st018
|
||||
objects += 21fx
|
||||
|
||||
######################
|
||||
### implicit rules ###
|
||||
@@ -166,22 +167,23 @@ obj/system.o: system/system.cpp $(call rwildcard,system/)
|
||||
### special chips ###
|
||||
#####################
|
||||
|
||||
obj/sgb.o : chip/sgb/sgb.cpp $(call rwildcard,chip/sgb/)
|
||||
obj/superfx.o: chip/superfx/superfx.cpp $(call rwildcard,chip/superfx/)
|
||||
obj/sa1.o : chip/sa1/sa1.cpp $(call rwildcard,chip/sa1/)
|
||||
obj/bsx.o : chip/bsx/bsx.cpp chip/bsx/*
|
||||
obj/srtc.o : chip/srtc/srtc.cpp chip/srtc/*
|
||||
obj/sdd1.o : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
obj/spc7110.o: chip/spc7110/spc7110.cpp chip/spc7110/*
|
||||
obj/cx4.o : chip/cx4/cx4.cpp chip/cx4/*
|
||||
obj/dsp1.o : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
obj/dsp2.o : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
obj/dsp3.o : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||
obj/dsp4.o : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obj/obc1.o : chip/obc1/obc1.cpp chip/obc1/*
|
||||
obj/st010.o : chip/st010/st010.cpp chip/st010/*
|
||||
obj/st011.o : chip/st011/st011.cpp chip/st011/*
|
||||
obj/st018.o : chip/st018/st018.cpp chip/st018/*
|
||||
obj/supergameboy.o: chip/supergameboy/supergameboy.cpp $(call rwildcard,chip/supergameboy/)
|
||||
obj/superfx.o : chip/superfx/superfx.cpp $(call rwildcard,chip/superfx/)
|
||||
obj/sa1.o : chip/sa1/sa1.cpp $(call rwildcard,chip/sa1/)
|
||||
obj/bsx.o : chip/bsx/bsx.cpp chip/bsx/*
|
||||
obj/srtc.o : chip/srtc/srtc.cpp chip/srtc/*
|
||||
obj/sdd1.o : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
obj/spc7110.o : chip/spc7110/spc7110.cpp chip/spc7110/*
|
||||
obj/cx4.o : chip/cx4/cx4.cpp chip/cx4/*
|
||||
obj/dsp1.o : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
obj/dsp2.o : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
obj/dsp3.o : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||
obj/dsp4.o : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obj/obc1.o : chip/obc1/obc1.cpp chip/obc1/*
|
||||
obj/st010.o : chip/st010/st010.cpp chip/st010/*
|
||||
obj/st011.o : chip/st011/st011.cpp chip/st011/*
|
||||
obj/st018.o : chip/st018/st018.cpp chip/st018/*
|
||||
obj/21fx.o : chip/21fx/21fx.cpp chip/21fx/*
|
||||
|
||||
###############
|
||||
### targets ###
|
||||
|
@@ -1,6 +1,6 @@
|
||||
static const char bsnesVersion[] = "0.054";
|
||||
static const char bsnesVersion[] = "0.058";
|
||||
static const char bsnesTitle[] = "bsnes";
|
||||
static const unsigned bsnesSaveStateVersion = 3;
|
||||
static const unsigned bsnesSerializerVersion = 4;
|
||||
|
||||
//S-DSP can be encapsulated into a state machine using #define magic
|
||||
//this avoids ~2.048m co_switch() calls per second (~5% speedup)
|
||||
|
@@ -6,13 +6,14 @@
|
||||
namespace SNES {
|
||||
|
||||
#include "header.cpp"
|
||||
#include "gameboyheader.cpp"
|
||||
|
||||
namespace memory {
|
||||
MappedRAM cartrom, cartram, cartrtc;
|
||||
MappedRAM bsxflash, bsxram, bsxpram;
|
||||
MappedRAM stArom, stAram;
|
||||
MappedRAM stBrom, stBram;
|
||||
MappedRAM gbrom, gbram;
|
||||
MappedRAM gbrom, gbram, gbrtc;
|
||||
};
|
||||
|
||||
Cartridge cartridge;
|
||||
@@ -43,7 +44,13 @@ void Cartridge::load(Mode cartridge_mode) {
|
||||
}
|
||||
|
||||
if(mode() == ModeSuperGameBoy) {
|
||||
if(memory::gbrom.data()) memory::gbram.map(allocate<uint8_t>(64 * 1024, 0xff), 64 * 1024);
|
||||
if(memory::gbrom.data()) {
|
||||
unsigned ram_size = gameboy_ram_size();
|
||||
unsigned rtc_size = gameboy_rtc_size();
|
||||
|
||||
if(ram_size) memory::gbram.map(allocate<uint8_t>(ram_size, 0xff), ram_size);
|
||||
if(rtc_size) memory::gbrtc.map(allocate<uint8_t>(rtc_size, 0x00), rtc_size);
|
||||
}
|
||||
}
|
||||
|
||||
memory::cartrom.write_protect(true);
|
||||
@@ -58,6 +65,7 @@ void Cartridge::load(Mode cartridge_mode) {
|
||||
memory::stBram.write_protect(false);
|
||||
memory::gbrom.write_protect(true);
|
||||
memory::gbram.write_protect(false);
|
||||
memory::gbrtc.write_protect(false);
|
||||
|
||||
unsigned checksum = ~0;
|
||||
for(unsigned n = 0; n < memory::cartrom.size(); n++) checksum = crc32_adjust(checksum, memory::cartrom[n]);
|
||||
@@ -104,6 +112,7 @@ void Cartridge::unload() {
|
||||
memory::stBram.reset();
|
||||
memory::gbrom.reset();
|
||||
memory::gbram.reset();
|
||||
memory::gbrtc.reset();
|
||||
|
||||
if(loaded() == false) return;
|
||||
bus.unload_cart();
|
||||
@@ -116,6 +125,8 @@ Cartridge::Type Cartridge::detect_image_type(uint8_t *data, unsigned size) const
|
||||
return info.type;
|
||||
}
|
||||
|
||||
bool Cartridge::has_21fx() const { return s21fx.exists(); }
|
||||
|
||||
void Cartridge::serialize(serializer &s) {
|
||||
if(memory::cartram.size() != 0 && memory::cartram.size() != ~0) {
|
||||
s.array(memory::cartram.data(), memory::cartram.size());
|
||||
@@ -144,6 +155,10 @@ void Cartridge::serialize(serializer &s) {
|
||||
if(memory::gbram.size() != 0 && memory::gbram.size() != ~0) {
|
||||
s.array(memory::gbram.data(), memory::gbram.size());
|
||||
}
|
||||
|
||||
if(memory::gbrtc.size() != 0 && memory::gbrtc.size() != ~0) {
|
||||
s.array(memory::gbrtc.data(), memory::gbrtc.size());
|
||||
}
|
||||
}
|
||||
|
||||
Cartridge::Cartridge() {
|
||||
@@ -213,5 +228,4 @@ Cartridge::cartinfo_t::cartinfo_t() {
|
||||
reset();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -67,6 +67,7 @@ public:
|
||||
property_t<bool> has_dsp1, has_dsp2, has_dsp3, has_dsp4;
|
||||
property_t<bool> has_obc1;
|
||||
property_t<bool> has_st010, has_st011, has_st018;
|
||||
bool has_21fx() const;
|
||||
|
||||
//main interface
|
||||
void load(Mode);
|
||||
@@ -118,6 +119,9 @@ private:
|
||||
unsigned find_header(const uint8_t *data, unsigned size) const;
|
||||
unsigned score_header(const uint8_t *data, unsigned size, unsigned addr) const;
|
||||
void set_cartinfo(const cartinfo_t&);
|
||||
|
||||
unsigned gameboy_ram_size() const;
|
||||
unsigned gameboy_rtc_size() const;
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
@@ -125,7 +129,7 @@ namespace memory {
|
||||
extern MappedRAM bsxflash, bsxram, bsxpram;
|
||||
extern MappedRAM stArom, stAram;
|
||||
extern MappedRAM stBrom, stBram;
|
||||
extern MappedRAM gbrom, gbram;
|
||||
extern MappedRAM gbrom, gbram, gbrtc;
|
||||
};
|
||||
|
||||
extern Cartridge cartridge;
|
||||
|
22
src/cartridge/gameboyheader.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
unsigned Cartridge::gameboy_ram_size() const {
|
||||
if(memory::gbrom.size() < 512) return 0;
|
||||
switch(memory::gbrom[0x0149]) {
|
||||
case 0x00: return 0 * 1024;
|
||||
case 0x01: return 8 * 1024;
|
||||
case 0x02: return 8 * 1024;
|
||||
case 0x03: return 32 * 1024;
|
||||
case 0x04: return 128 * 1024;
|
||||
case 0x05: return 128 * 1024;
|
||||
default: return 128 * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Cartridge::gameboy_rtc_size() const {
|
||||
if(memory::gbrom.size() < 512) return 0;
|
||||
if(memory::gbrom[0x0147] == 0x0f || memory::gbrom[0x0147] == 0x10) return 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
165
src/chip/21fx/21fx.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
//$21f0 command port (r/w)
|
||||
//-------------------
|
||||
//$00 set data port address (sr[3-0] = address)
|
||||
//$01 set audio track number (sr[1-0] = track number)
|
||||
//$02 set volume (sr[1] = left, sr[0] = right)
|
||||
//$03 set audio state (sr[0].d1 = pause, sr[0].d0 = repeat)
|
||||
//
|
||||
//d7 = data port busy
|
||||
//d6 = audio port busy
|
||||
//d5 = audio playing
|
||||
//d4 = reserved (0)
|
||||
//d3-d0 = version (1)
|
||||
//
|
||||
//
|
||||
//$21f1 parameter port (w)
|
||||
//---------------------
|
||||
//(shift register)
|
||||
//
|
||||
//
|
||||
//$21f2 data port (r)
|
||||
//----------------
|
||||
//(auto-increment read port)
|
||||
|
||||
#define S21FX_CPP
|
||||
namespace SNES {
|
||||
|
||||
S21fx s21fx;
|
||||
|
||||
#include "serialization.cpp"
|
||||
|
||||
void S21fx::enter() {
|
||||
scheduler.clock.cop_freq = 44100;
|
||||
|
||||
while(true) {
|
||||
int16 left = 0, right = 0;
|
||||
|
||||
if((mmio.status & AudioPlaying) && !mmio.audio_pause) {
|
||||
if(audiofile.open()) {
|
||||
if(audiofile.end()) {
|
||||
if(!mmio.audio_repeat) mmio.status &= ~AudioPlaying;
|
||||
audiofile.seek(mmio.audio_offset = 58);
|
||||
} else {
|
||||
mmio.audio_offset += 4;
|
||||
left = audiofile.readl(2);
|
||||
right = audiofile.readl(2);
|
||||
}
|
||||
} else {
|
||||
mmio.status &= ~AudioPlaying;
|
||||
}
|
||||
}
|
||||
|
||||
left = sclamp<16>((double)left * (double)mmio.audio_volume_left / 255.0);
|
||||
right = sclamp<16>((double)right * (double)mmio.audio_volume_right / 255.0);
|
||||
|
||||
audio.coprocessor_sample(left, right);
|
||||
scheduler.addclocks_cop(1);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
}
|
||||
|
||||
void S21fx::init() {
|
||||
}
|
||||
|
||||
void S21fx::enable() {
|
||||
audio.coprocessor_enable(true);
|
||||
audio.coprocessor_frequency(44100.0);
|
||||
|
||||
for(unsigned i = 0x21f0; i <= 0x21f7; i++) {
|
||||
memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
if(datafile.open()) datafile.close();
|
||||
datafile.open(string() << basepath << "21fx.bin", file::mode_read);
|
||||
}
|
||||
|
||||
void S21fx::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void S21fx::reset() {
|
||||
mmio.status = DataPortBusy | AudioBusy;
|
||||
mmio.shift_register = 0;
|
||||
|
||||
mmio.data_offset = 0;
|
||||
mmio.audio_offset = 0;
|
||||
mmio.audio_track = 0;
|
||||
mmio.audio_volume_left = 255;
|
||||
mmio.audio_volume_right = 255;
|
||||
mmio.audio_repeat = false;
|
||||
mmio.audio_pause = false;
|
||||
}
|
||||
|
||||
uint8 S21fx::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x21f0) {
|
||||
return mmio.status | 0x01;
|
||||
}
|
||||
|
||||
if(addr == 0x21f2) {
|
||||
if(mmio.status & DataPortBusy) return 0x00;
|
||||
mmio.data_offset++;
|
||||
if(datafile.open()) return datafile.read();
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void S21fx::mmio_write(unsigned addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x21f0) {
|
||||
if(data == 0x00) {
|
||||
mmio.data_offset = mmio.shift_register & 0xffffffff;
|
||||
if(datafile.open()) {
|
||||
datafile.seek(mmio.data_offset);
|
||||
}
|
||||
mmio.status &= ~DataPortBusy;
|
||||
}
|
||||
|
||||
if(data == 0x01) {
|
||||
mmio.audio_track = mmio.shift_register & 0xffff;
|
||||
if(audiofile.open()) audiofile.close();
|
||||
char track[16];
|
||||
sprintf(track, "%.5u", mmio.audio_track);
|
||||
if(audiofile.open(string() << basepath << "audio" << track << ".wav", file::mode_read)) {
|
||||
audiofile.seek(mmio.audio_offset = 58); //skip WAV header
|
||||
}
|
||||
mmio.status &= ~(AudioBusy | AudioPlaying);
|
||||
}
|
||||
|
||||
if(data == 0x02) {
|
||||
mmio.audio_volume_left = mmio.shift_register >> 8;
|
||||
mmio.audio_volume_right = mmio.shift_register >> 0;
|
||||
}
|
||||
|
||||
if(data == 0x03) {
|
||||
mmio.status |= AudioPlaying;
|
||||
mmio.audio_repeat = mmio.shift_register & 1;
|
||||
mmio.audio_pause = mmio.shift_register & 2;
|
||||
}
|
||||
|
||||
mmio.shift_register = 0;
|
||||
}
|
||||
|
||||
if(addr == 0x21f1) {
|
||||
mmio.shift_register = (mmio.shift_register << 8) | data;
|
||||
}
|
||||
}
|
||||
|
||||
void S21fx::base(const string& path) {
|
||||
basepath = path;
|
||||
}
|
||||
|
||||
bool S21fx::exists() {
|
||||
return file::exists(string() << basepath << "21fx.bin");
|
||||
}
|
||||
|
||||
S21fx::S21fx() {
|
||||
}
|
||||
|
||||
}
|
44
src/chip/21fx/21fx.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
class S21fx : public MMIO {
|
||||
public:
|
||||
void enter();
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
void base(const string &path);
|
||||
bool exists();
|
||||
|
||||
void serialize(serializer&);
|
||||
S21fx();
|
||||
|
||||
private:
|
||||
string basepath;
|
||||
file datafile;
|
||||
file audiofile;
|
||||
|
||||
enum Flag {
|
||||
DataPortBusy = 0x80,
|
||||
AudioBusy = 0x40,
|
||||
AudioPlaying = 0x20,
|
||||
};
|
||||
|
||||
struct MMIO {
|
||||
uint8 status;
|
||||
uint64 shift_register;
|
||||
|
||||
uint32 data_offset;
|
||||
uint32 audio_offset;
|
||||
uint16 audio_track;
|
||||
uint8 audio_volume_left;
|
||||
uint8 audio_volume_right;
|
||||
bool audio_repeat;
|
||||
bool audio_pause;
|
||||
} mmio;
|
||||
};
|
||||
|
||||
extern S21fx s21fx;
|
31
src/chip/21fx/serialization.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifdef S21FX_CPP
|
||||
|
||||
void S21fx::serialize(serializer &s) {
|
||||
s.integer(mmio.status);
|
||||
s.integer(mmio.shift_register);
|
||||
|
||||
s.integer(mmio.data_offset);
|
||||
s.integer(mmio.audio_offset);
|
||||
s.integer(mmio.audio_track);
|
||||
s.integer(mmio.audio_volume_left);
|
||||
s.integer(mmio.audio_volume_right);
|
||||
s.integer(mmio.audio_repeat);
|
||||
s.integer(mmio.audio_pause);
|
||||
|
||||
//flush file handles and indices, as a different track may be playing,
|
||||
//or the file offsets may be at the wrong location ...
|
||||
|
||||
if(datafile.open()) datafile.close();
|
||||
if(datafile.open(string() << basepath << "21fx.bin", file::mode_read)) {
|
||||
datafile.seek(mmio.data_offset);
|
||||
}
|
||||
|
||||
if(audiofile.open()) audiofile.close();
|
||||
char track[16];
|
||||
sprintf(track, "%.5u", mmio.audio_track);
|
||||
if(audiofile.open(string() << basepath << "audio" << track << ".wav", file::mode_read)) {
|
||||
audiofile.seek(mmio.audio_offset);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,4 +1,4 @@
|
||||
#include "sgb/sgb.hpp"
|
||||
#include "supergameboy/supergameboy.hpp"
|
||||
#include "superfx/superfx.hpp"
|
||||
#include "sa1/sa1.hpp"
|
||||
#include "bsx/bsx.hpp"
|
||||
@@ -14,3 +14,4 @@
|
||||
#include "st010/st010.hpp"
|
||||
#include "st011/st011.hpp"
|
||||
#include "st018/st018.hpp"
|
||||
#include "21fx/21fx.hpp"
|
||||
|
@@ -55,10 +55,10 @@ uint8 SDD1::mmio_read(unsigned addr) {
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x4804: return (mmc[0] >> 20) & 7;
|
||||
case 0x4805: return (mmc[1] >> 20) & 7;
|
||||
case 0x4806: return (mmc[2] >> 20) & 7;
|
||||
case 0x4807: return (mmc[3] >> 20) & 7;
|
||||
case 0x4804: return mmc[0] >> 20;
|
||||
case 0x4805: return mmc[1] >> 20;
|
||||
case 0x4806: return mmc[2] >> 20;
|
||||
case 0x4807: return mmc[3] >> 20;
|
||||
}
|
||||
|
||||
return cpu.regs.mdr;
|
||||
@@ -84,10 +84,10 @@ void SDD1::mmio_write(unsigned addr, uint8 data) {
|
||||
case 0x4800: sdd1_enable = data; break;
|
||||
case 0x4801: xfer_enable = data; break;
|
||||
|
||||
case 0x4804: mmc[0] = (data & 7) << 20; break;
|
||||
case 0x4805: mmc[1] = (data & 7) << 20; break;
|
||||
case 0x4806: mmc[2] = (data & 7) << 20; break;
|
||||
case 0x4807: mmc[3] = (data & 7) << 20; break;
|
||||
case 0x4804: mmc[0] = data << 20; break;
|
||||
case 0x4805: mmc[1] = data << 20; break;
|
||||
case 0x4806: mmc[2] = data << 20; break;
|
||||
case 0x4807: mmc[3] = data << 20; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,65 +0,0 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
#define SGB_CPP
|
||||
namespace SNES {
|
||||
|
||||
SuperGameBoy sgb;
|
||||
|
||||
void SuperGameBoy::enter() {
|
||||
while(true) {
|
||||
if(sgb_run) {
|
||||
unsigned samples = sgb_run(samplebuffer, 16);
|
||||
scheduler.addclocks_cop(samples * 10);
|
||||
scheduler.sync_copcpu();
|
||||
} else {
|
||||
scheduler.addclocks_cop(64 * 1024 * 1024);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SuperGameBoy::read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
if(sgb_read) return sgb_read(addr);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void SuperGameBoy::write(unsigned addr, uint8_t data) {
|
||||
addr &= 0xffff;
|
||||
if(sgb_write) return sgb_write(addr, data);
|
||||
}
|
||||
|
||||
void SuperGameBoy::init() {
|
||||
if(libsgb.open("SuperGameBoy")) {
|
||||
sgb_init = libsgb.sym("sgb_init");
|
||||
sgb_term = libsgb.sym("sgb_term");
|
||||
sgb_power = libsgb.sym("sgb_power");
|
||||
sgb_reset = libsgb.sym("sgb_reset");
|
||||
sgb_read = libsgb.sym("sgb_read");
|
||||
sgb_write = libsgb.sym("sgb_write");
|
||||
sgb_run = libsgb.sym("sgb_run");
|
||||
}
|
||||
}
|
||||
|
||||
void SuperGameBoy::enable() {
|
||||
}
|
||||
|
||||
void SuperGameBoy::power() {
|
||||
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
|
||||
|
||||
if(sgb_init) {
|
||||
sgb_init(SGB2,
|
||||
memory::gbrom.data(), memory::gbrom.size(),
|
||||
memory::gbram.data(), memory::gbram.size()
|
||||
);
|
||||
}
|
||||
|
||||
if(sgb_power) sgb_power();
|
||||
}
|
||||
|
||||
void SuperGameBoy::reset() {
|
||||
if(sgb_reset) sgb_reset();
|
||||
}
|
||||
|
||||
};
|
@@ -1,27 +0,0 @@
|
||||
class SuperGameBoy : public Memory {
|
||||
public:
|
||||
void enter();
|
||||
|
||||
uint8_t read(unsigned addr);
|
||||
void write(unsigned addr, uint8_t data);
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
library libsgb;
|
||||
uint32_t samplebuffer[4096];
|
||||
|
||||
enum { SGB1 = 0, SGB2 = 1 };
|
||||
function<bool (bool, uint8_t*, unsigned, uint8_t*, unsigned)> sgb_init;
|
||||
function<void ()> sgb_term;
|
||||
function<void ()> sgb_power;
|
||||
function<void ()> sgb_reset;
|
||||
function<uint8_t (unsigned)> sgb_read;
|
||||
function<void (unsigned, uint8_t)> sgb_write;
|
||||
function<unsigned (uint32_t*, unsigned)> sgb_run;
|
||||
};
|
||||
|
||||
extern SuperGameBoy sgb;
|
@@ -535,17 +535,17 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
|
||||
|
||||
case 0x4831: {
|
||||
r4831 = data;
|
||||
dx_offset = datarom_addr((data & 7) * 0x100000);
|
||||
dx_offset = datarom_addr(data * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4832: {
|
||||
r4832 = data;
|
||||
ex_offset = datarom_addr((data & 7) * 0x100000);
|
||||
ex_offset = datarom_addr(data * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4833: {
|
||||
r4833 = data;
|
||||
fx_offset = datarom_addr((data & 7) * 0x100000);
|
||||
fx_offset = datarom_addr(data * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4834: r4834 = data; break;
|
||||
|
133
src/chip/supergameboy/supergameboy.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
#define SUPERGAMEBOY_CPP
|
||||
namespace SNES {
|
||||
|
||||
SuperGameBoy supergameboy;
|
||||
|
||||
void SuperGameBoy::enter() {
|
||||
scheduler.clock.cop_freq = (version == SuperGameBoy1 ? 2147727 : 2097152);
|
||||
|
||||
if(!sgb_run) while(true) {
|
||||
audio.coprocessor_sample(0, 0);
|
||||
scheduler.addclocks_cop(1);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
|
||||
while(true) {
|
||||
unsigned samples = sgb_run(samplebuffer, 16);
|
||||
for(unsigned i = 0; i < samples; i++) {
|
||||
int16 left = samplebuffer[i] >> 0;
|
||||
int16 right = samplebuffer[i] >> 16;
|
||||
|
||||
//SNES audio is notoriously quiet; lower Game Boy samples to match SGB sound effects
|
||||
audio.coprocessor_sample(left / 3, right / 3);
|
||||
}
|
||||
scheduler.addclocks_cop(samples);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
}
|
||||
|
||||
uint8 SuperGameBoy::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x2181) return mmio[0]->mmio_read(addr);
|
||||
if(addr == 0x2182) return mmio[1]->mmio_read(addr);
|
||||
if(addr == 0x420b) return mmio[2]->mmio_read(addr);
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void SuperGameBoy::mmio_write(unsigned addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x2181) {
|
||||
row = (row & 0xff00) | (data << 0);
|
||||
mmio[0]->mmio_write(addr, data);
|
||||
}
|
||||
|
||||
if(addr == 0x2182) {
|
||||
row = (row & 0x00ff) | (data << 8);
|
||||
mmio[1]->mmio_write(addr, data);
|
||||
}
|
||||
|
||||
if(addr == 0x420b) {
|
||||
if(data == 0x10 && sgb_row) {
|
||||
if(row >= 0x5000 && row <= 0x6540) sgb_row((row - 0x5000) / 320);
|
||||
if(row >= 0x6800 && row <= 0x7d40) sgb_row((row - 0x6800) / 320);
|
||||
}
|
||||
mmio[2]->mmio_write(addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 SuperGameBoy::read(unsigned addr) {
|
||||
if(sgb_read) return sgb_read(addr);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void SuperGameBoy::write(unsigned addr, uint8 data) {
|
||||
if(sgb_write) sgb_write(addr, data);
|
||||
}
|
||||
|
||||
void SuperGameBoy::init() {
|
||||
if(open("supergameboy")) {
|
||||
sgb_rom = sym("sgb_rom");
|
||||
sgb_ram = sym("sgb_ram");
|
||||
sgb_rtc = sym("sgb_rtc");
|
||||
sgb_init = sym("sgb_init");
|
||||
sgb_term = sym("sgb_term");
|
||||
sgb_power = sym("sgb_power");
|
||||
sgb_reset = sym("sgb_reset");
|
||||
sgb_row = sym("sgb_row");
|
||||
sgb_read = sym("sgb_read");
|
||||
sgb_write = sym("sgb_write");
|
||||
sgb_run = sym("sgb_run");
|
||||
sgb_save = sym("sgb_save");
|
||||
sgb_serialize = sym("sgb_serialize");
|
||||
}
|
||||
}
|
||||
|
||||
void SuperGameBoy::enable() {
|
||||
mmio[0] = memory::mmio.mmio[0x2181 - 0x2000];
|
||||
mmio[1] = memory::mmio.mmio[0x2182 - 0x2000];
|
||||
mmio[2] = memory::mmio.mmio[0x420b - 0x2000];
|
||||
|
||||
memory::mmio.map(0x2181, *this);
|
||||
memory::mmio.map(0x2182, *this);
|
||||
memory::mmio.map(0x420b, *this);
|
||||
}
|
||||
|
||||
void SuperGameBoy::power() {
|
||||
//determine whether to use SGB1 or SGB2 mode based on the cartridge title (look for the '2')
|
||||
version = memory::cartrom[0x7fcd] != 0x32 ? SuperGameBoy1 : SuperGameBoy2;
|
||||
|
||||
audio.coprocessor_enable(true);
|
||||
audio.coprocessor_frequency(version == SuperGameBoy1 ? 2147727.0 : 2097152.0);
|
||||
|
||||
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
|
||||
|
||||
sgb_rom(memory::gbrom.data(), memory::gbrom.size() == -1U ? 0 : memory::gbrom.size());
|
||||
sgb_ram(memory::gbram.data(), memory::gbram.size() == -1U ? 0 : memory::gbram.size());
|
||||
sgb_rtc(memory::gbrtc.data(), memory::gbrtc.size() == -1U ? 0 : memory::gbrtc.size());
|
||||
|
||||
//determine whether to use SGB1 or SGB2 mode based on the cartridge title (look for the '2')
|
||||
if(sgb_init) sgb_init(version);
|
||||
if(sgb_power) sgb_power();
|
||||
}
|
||||
|
||||
void SuperGameBoy::reset() {
|
||||
if(sgb_reset) sgb_reset();
|
||||
}
|
||||
|
||||
void SuperGameBoy::unload() {
|
||||
if(sgb_term) sgb_term();
|
||||
}
|
||||
|
||||
void SuperGameBoy::serialize(serializer &s) {
|
||||
s.integer(row);
|
||||
s.integer(version);
|
||||
if(sgb_serialize) sgb_serialize(s);
|
||||
}
|
||||
|
||||
}
|
41
src/chip/supergameboy/supergameboy.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
class SuperGameBoy : public MMIO, public Memory, public library {
|
||||
public:
|
||||
void enter();
|
||||
|
||||
MMIO *mmio[3];
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
void unload();
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
private:
|
||||
uint32_t samplebuffer[4096];
|
||||
unsigned row;
|
||||
bool version;
|
||||
|
||||
enum { SuperGameBoy1 = 0, SuperGameBoy2 = 1 };
|
||||
function<void (uint8_t*, unsigned)> sgb_rom;
|
||||
function<void (uint8_t*, unsigned)> sgb_ram;
|
||||
function<void (uint8_t*, unsigned)> sgb_rtc;
|
||||
function<bool (bool)> sgb_init;
|
||||
function<void ()> sgb_term;
|
||||
function<void ()> sgb_power;
|
||||
function<void ()> sgb_reset;
|
||||
function<void (unsigned)> sgb_row;
|
||||
function<uint8 (uint16)> sgb_read;
|
||||
function<void (uint16, uint8)> sgb_write;
|
||||
function<unsigned (uint32_t*, unsigned)> sgb_run;
|
||||
function<void ()> sgb_save;
|
||||
function<void (serializer&)> sgb_serialize;
|
||||
};
|
||||
|
||||
extern SuperGameBoy supergameboy;
|
@@ -102,7 +102,7 @@ uint32 CPUcore::decode(uint8 offset_type, uint32 addr) {
|
||||
return(r & 0xffffff);
|
||||
}
|
||||
|
||||
void CPUcore::disassemble_opcode(char *output) {
|
||||
void CPUcore::disassemble_opcode(char *output, uint32 addr) {
|
||||
static reg24_t pc;
|
||||
char t[256];
|
||||
char *s = output;
|
||||
@@ -112,7 +112,7 @@ void CPUcore::disassemble_opcode(char *output) {
|
||||
return;
|
||||
}
|
||||
|
||||
pc.d = regs.pc.d;
|
||||
pc.d = addr;
|
||||
sprintf(s, "%.6x ", (uint32)pc.d);
|
||||
|
||||
uint8 op = dreadb(pc.d); pc.w++;
|
||||
|
@@ -22,7 +22,7 @@
|
||||
OPTYPE_RELW, //relw
|
||||
};
|
||||
|
||||
void disassemble_opcode(char *output);
|
||||
void disassemble_opcode(char *output, uint32 addr);
|
||||
uint8 dreadb(uint32 addr);
|
||||
uint16 dreadw(uint32 addr);
|
||||
uint32 dreadl(uint32 addr);
|
||||
|
@@ -10,25 +10,36 @@ void sCPUDebug::op_step() {
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::CPUBus, Debugger::Breakpoint::Exec, regs.pc, 0x00);
|
||||
}
|
||||
|
||||
if(debugger.trace_cpu) {
|
||||
char t[256];
|
||||
disassemble_opcode(t);
|
||||
debugger.tracefile.print(string() << t << "\n");
|
||||
}
|
||||
usage[regs.pc] &= ~(UsageFlagM | UsageFlagX);
|
||||
usage[regs.pc] |= UsageExec | (regs.p.m << 1) | (regs.p.x << 0);
|
||||
opcode_pc = regs.pc;
|
||||
|
||||
if(step_event) step_event();
|
||||
sCPU::op_step();
|
||||
scheduler.sync_cpusmp();
|
||||
}
|
||||
|
||||
uint8 sCPUDebug::op_read(uint32 addr) {
|
||||
uint8 data = sCPU::op_read(addr);
|
||||
usage[addr] |= UsageRead;
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::CPUBus, Debugger::Breakpoint::Read, addr, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void sCPUDebug::op_write(uint32 addr, uint8 data) {
|
||||
sCPU::op_write(addr, data);
|
||||
usage[addr] |= UsageWrite;
|
||||
usage[addr] &= ~UsageExec;
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::CPUBus, Debugger::Breakpoint::Write, addr, data);
|
||||
}
|
||||
|
||||
sCPUDebug::sCPUDebug() {
|
||||
usage = new uint8[1 << 24]();
|
||||
opcode_pc = 0x8000;
|
||||
}
|
||||
|
||||
sCPUDebug::~sCPUDebug() {
|
||||
delete[] usage;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,6 +1,21 @@
|
||||
class sCPUDebug : public sCPU {
|
||||
public:
|
||||
function<void ()> step_event;
|
||||
|
||||
enum Usage {
|
||||
UsageRead = 0x80,
|
||||
UsageWrite = 0x40,
|
||||
UsageExec = 0x20,
|
||||
UsageFlagM = 0x02,
|
||||
UsageFlagX = 0x01,
|
||||
};
|
||||
uint8 *usage;
|
||||
uint32 opcode_pc; //points to the current opcode, used to backtrace on read/write breakpoints
|
||||
|
||||
void op_step();
|
||||
uint8 op_read(uint32 addr);
|
||||
void op_write(uint32 addr, uint8 data);
|
||||
|
||||
sCPUDebug();
|
||||
~sCPUDebug();
|
||||
};
|
||||
|
@@ -32,7 +32,7 @@ configuration data.
|
||||
|
||||
<h3>Supported Filetypes</h3><br>
|
||||
|
||||
<b>SFC, SMC:</b> SNES cartridge — ROM image.<br>
|
||||
<b>SFC:</b> SNES cartridge — ROM image.<br>
|
||||
<b>BS:</b> Satellaview BS-X flash cartridge — EEPROM image.<br>
|
||||
<b>ST:</b> Sufami Turbo cartridge — ROM image.<br>
|
||||
<b>SRM, PSR:</b> non-volatile memory, often used to save game data — (P)SRAM image.<br>
|
||||
|
Before Width: | Height: | Size: 574 B |
BIN
src/data/icons-16x16/applications-multimedia.png
Normal file
After Width: | Height: | Size: 592 B |
Before Width: | Height: | Size: 477 B |
BIN
src/data/icons-16x16/media-playback-start.png
Normal file
After Width: | Height: | Size: 660 B |
BIN
src/data/icons-16x16/media-playback-stop.png
Normal file
After Width: | Height: | Size: 429 B |
BIN
src/data/icons-16x16/media-record.png
Normal file
After Width: | Height: | Size: 653 B |
Before Width: | Height: | Size: 378 B |
Before Width: | Height: | Size: 935 B |
BIN
src/data/icons-22x22/image-x-generic.png
Normal file
After Width: | Height: | Size: 900 B |
@@ -8,7 +8,7 @@
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
#if defined(PLATFORM_X)
|
||||
#if defined(PLATFORM_X) || defined(PLATFORM_OSX)
|
||||
#include <dlfcn.h>
|
||||
#elif defined(PLATFORM_WIN)
|
||||
#include <windows.h>
|
||||
@@ -52,6 +52,34 @@ namespace nall {
|
||||
return dlsym((void*)handle, name);
|
||||
}
|
||||
|
||||
inline void library::close() {
|
||||
if(!handle) return;
|
||||
dlclose((void*)handle);
|
||||
handle = 0;
|
||||
}
|
||||
#elif defined(PLATFORM_OSX)
|
||||
inline bool library::open(const char *name) {
|
||||
if(handle) close();
|
||||
char *t = new char[strlen(name) + 256];
|
||||
strcpy(t, "lib");
|
||||
strcat(t, name);
|
||||
strcat(t, ".dylib");
|
||||
handle = (uintptr_t)dlopen(t, RTLD_LAZY);
|
||||
if(!handle) {
|
||||
strcpy(t, "/usr/local/lib/lib");
|
||||
strcat(t, name);
|
||||
strcat(t, ".dylib");
|
||||
handle = (uintptr_t)dlopen(t, RTLD_LAZY);
|
||||
}
|
||||
delete[] t;
|
||||
return handle;
|
||||
}
|
||||
|
||||
inline void* library::sym(const char *name) {
|
||||
if(!handle) return 0;
|
||||
return dlsym((void*)handle, name);
|
||||
}
|
||||
|
||||
inline void library::close() {
|
||||
if(!handle) return;
|
||||
dlclose((void*)handle);
|
||||
|
@@ -136,7 +136,7 @@ namespace nall {
|
||||
function() { data.fn_call = 0; }
|
||||
|
||||
function(void *fn) {
|
||||
data.fn_call = &fn_call_global;
|
||||
data.fn_call = fn ? &fn_call_global : 0;
|
||||
data.fn_global = (R (*)(PL))fn;
|
||||
}
|
||||
|
||||
|
@@ -6,258 +6,381 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
|
||||
namespace nall {
|
||||
enum { input_none = 0 };
|
||||
|
||||
template<int number = -1> struct keyboard {
|
||||
enum {
|
||||
none = keyboard<number - 1>::limit,
|
||||
escape, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12,
|
||||
print_screen, scroll_lock, pause, tilde,
|
||||
num_1, num_2, num_3, num_4, num_5, num_6, num_7, num_8, num_9, num_0,
|
||||
dash, equal, backspace,
|
||||
insert, delete_, home, end, page_up, page_down,
|
||||
a, b, c, d, e, f, g, h, i, j, k, l, m,
|
||||
n, o, p, q, r, s, t, u, v, w, x, y, z,
|
||||
lbracket, rbracket, backslash, semicolon, apostrophe, comma, period, slash,
|
||||
pad_1, pad_2, pad_3, pad_4, pad_5, pad_6, pad_7, pad_8, pad_9, pad_0,
|
||||
point, enter, add, subtract, multiply, divide,
|
||||
num_lock, caps_lock,
|
||||
up, down, left, right,
|
||||
tab, return_, spacebar,
|
||||
lctrl, rctrl, lalt, ralt, lshift, rshift, lsuper, rsuper, menu,
|
||||
limit,
|
||||
};
|
||||
struct Keyboard;
|
||||
Keyboard& keyboard(unsigned = 0);
|
||||
|
||||
static const char KeyboardScancodeName[][64] = {
|
||||
"Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
|
||||
"PrintScreen", "ScrollLock", "Pause", "Tilde",
|
||||
"Num1", "Num2", "Num3", "Num4", "Num5", "Num6", "Num7", "Num8", "Num9", "Num0",
|
||||
"Dash", "Equal", "Backspace",
|
||||
"Insert", "Delete", "Home", "End", "PageUp", "PageDown",
|
||||
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
|
||||
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
||||
"LeftBracket", "RightBracket", "Backslash", "Semicolon", "Apostrophe", "Comma", "Period", "Slash",
|
||||
"Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "Keypad0",
|
||||
"Point", "Enter", "Add", "Subtract", "Multiply", "Divide",
|
||||
"NumLock", "CapsLock",
|
||||
"Up", "Down", "Left", "Right",
|
||||
"Tab", "Return", "Spacebar", "Menu",
|
||||
"Shift", "Control", "Alt", "Super",
|
||||
};
|
||||
|
||||
struct Keyboard {
|
||||
const unsigned ID;
|
||||
enum { Base = 1 };
|
||||
enum { Count = 8, Size = 128 };
|
||||
|
||||
enum Scancode {
|
||||
Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||
PrintScreen, ScrollLock, Pause, Tilde,
|
||||
Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0,
|
||||
Dash, Equal, Backspace,
|
||||
Insert, Delete, Home, End, PageUp, PageDown,
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M,
|
||||
N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||
LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash,
|
||||
Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0,
|
||||
Point, Enter, Add, Subtract, Multiply, Divide,
|
||||
NumLock, CapsLock,
|
||||
Up, Down, Left, Right,
|
||||
Tab, Return, Spacebar, Menu,
|
||||
Shift, Control, Alt, Super,
|
||||
Limit,
|
||||
};
|
||||
|
||||
template<> struct keyboard<-1> {
|
||||
enum { count = 16 };
|
||||
enum {
|
||||
none,
|
||||
escape, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12,
|
||||
print_screen, scroll_lock, pause, tilde,
|
||||
num_1, num_2, num_3, num_4, num_5, num_6, num_7, num_8, num_9, num_0,
|
||||
dash, equal, backspace,
|
||||
insert, delete_, home, end, page_up, page_down,
|
||||
a, b, c, d, e, f, g, h, i, j, k, l, m,
|
||||
n, o, p, q, r, s, t, u, v, w, x, y, z,
|
||||
lbracket, rbracket, backslash, semicolon, apostrophe, comma, period, slash,
|
||||
pad_1, pad_2, pad_3, pad_4, pad_5, pad_6, pad_7, pad_8, pad_9, pad_0,
|
||||
point, enter, add, subtract, multiply, divide,
|
||||
num_lock, caps_lock,
|
||||
up, down, left, right,
|
||||
tab, return_, spacebar,
|
||||
lctrl, rctrl, lalt, ralt, lshift, rshift, lsuper, rsuper, menu,
|
||||
length, //number of syms per keyboard
|
||||
limit = 0,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned keyboard_number, unsigned keyboard_enum) {
|
||||
if(keyboard_number >= count) return input_none;
|
||||
return limit + keyboard_number * length + keyboard_enum;
|
||||
static signed numberDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(keyboard(i).belongsTo(scancode)) return i;
|
||||
}
|
||||
};
|
||||
|
||||
template<int number = -1> struct mouse {
|
||||
enum { buttons = 8 };
|
||||
enum {
|
||||
none = mouse<number - 1>::limit,
|
||||
x, y, z,
|
||||
button,
|
||||
limit = button + buttons,
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct mouse<-1> {
|
||||
enum { count = 16, buttons = 8 };
|
||||
enum {
|
||||
none,
|
||||
x, y, z,
|
||||
button,
|
||||
length = button + buttons - none, //number of syms per mouse
|
||||
limit = keyboard<keyboard<>::count - 1>::limit,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned mouse_number, unsigned mouse_enum) {
|
||||
if(mouse_number >= count) return input_none;
|
||||
return limit + mouse_number * length + mouse_enum;
|
||||
}
|
||||
};
|
||||
|
||||
template<int number = -1> struct joypad {
|
||||
enum { hats = 8, axes = 32, buttons = 96 };
|
||||
enum {
|
||||
none = joypad<number - 1>::limit,
|
||||
hat,
|
||||
axis = hat + hats,
|
||||
button = axis + axes,
|
||||
limit = button + buttons,
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct joypad<-1> {
|
||||
enum { count = 16, hats = 8, axes = 32, buttons = 96 };
|
||||
enum { hat_center = 0, hat_up = 1, hat_right = 2, hat_down = 4, hat_left = 8 };
|
||||
enum {
|
||||
none,
|
||||
hat,
|
||||
axis = hat + hats,
|
||||
button = axis + axes,
|
||||
length = button + buttons - none, //number of syms per joypad
|
||||
limit = mouse<mouse<>::count - 1>::limit,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned joypad_number, unsigned joypad_enum) {
|
||||
if(joypad_number >= count) return input_none;
|
||||
return limit + joypad_number * length + joypad_enum;
|
||||
}
|
||||
};
|
||||
|
||||
enum { input_limit = joypad<joypad<>::count - 1>::limit };
|
||||
|
||||
static const char keysym[][64] = {
|
||||
"none",
|
||||
"escape", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12",
|
||||
"print_screen", "scroll_lock", "pause", "tilde",
|
||||
"num_1", "num_2", "num_3", "num_4", "num_5", "num_6", "num_7", "num_8", "num_9", "num_0",
|
||||
"dash", "equal", "backspace",
|
||||
"insert", "delete", "home", "end", "page_up", "page_down",
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
|
||||
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||
"lbracket", "rbracket", "backslash", "semicolon", "apostrophe", "comma", "period", "slash",
|
||||
"pad_1", "pad_2", "pad_3", "pad_4", "pad_5", "pad_6", "pad_7", "pad_8", "pad_9", "pad_0",
|
||||
"point", "enter", "add", "subtract", "multiply", "divide",
|
||||
"num_lock", "caps_lock",
|
||||
"up", "down", "left", "right",
|
||||
"tab", "return", "spacebar",
|
||||
"lctrl", "rctrl", "lalt", "ralt", "lshift", "rshift", "lsuper", "rsuper", "menu",
|
||||
"limit",
|
||||
};
|
||||
|
||||
static const char* input_find(uint16_t key) {
|
||||
static char buffer[64];
|
||||
|
||||
for(unsigned k = 0; k < keyboard<>::count; k++) {
|
||||
if(key >= keyboard<>::index(k, keyboard<>::none) && key < keyboard<>::index(k, keyboard<>::length)) {
|
||||
sprintf(buffer, "keyboard%.2d.%s", k, keysym[key - keyboard<>::index(k, keyboard<>::none)]);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned m = 0; m < mouse<>::count; m++) {
|
||||
if(key == mouse<>::index(m, mouse<>::x)) { sprintf(buffer, "mouse%.2d.x", m); return buffer; }
|
||||
if(key == mouse<>::index(m, mouse<>::y)) { sprintf(buffer, "mouse%.2d.y", m); return buffer; }
|
||||
if(key == mouse<>::index(m, mouse<>::z)) { sprintf(buffer, "mouse%.2d.z", m); return buffer; }
|
||||
|
||||
if(key >= mouse<>::index(m, mouse<>::button + 0)
|
||||
&& key < mouse<>::index(m, mouse<>::button + mouse<>::buttons)) {
|
||||
sprintf(buffer, "mouse%.2d.button%.2d", m, key - mouse<>::index(m, mouse<>::button));
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned j = 0; j < joypad<>::count; j++) {
|
||||
if(key >= joypad<>::index(j, joypad<>::hat + 0)
|
||||
&& key < joypad<>::index(j, joypad<>::hat + joypad<>::hats)) {
|
||||
sprintf(buffer, "joypad%.2d.hat%.2d", j, key - joypad<>::index(j, joypad<>::hat));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
if(key >= joypad<>::index(j, joypad<>::axis + 0)
|
||||
&& key < joypad<>::index(j, joypad<>::axis + joypad<>::axes)) {
|
||||
sprintf(buffer, "joypad%.2d.axis%.2d", j, key - joypad<>::index(j, joypad<>::axis));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
if(key >= joypad<>::index(j, joypad<>::button + 0)
|
||||
&& key < joypad<>::index(j, joypad<>::button + joypad<>::buttons)) {
|
||||
sprintf(buffer, "joypad%.2d.button%.2d", j, key - joypad<>::index(j, joypad<>::button));
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return "none";
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char* input_find(char *out, uint16_t key) {
|
||||
strcpy(out, input_find(key));
|
||||
return out;
|
||||
static signed keyDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(keyboard(i).isKey(scancode)) return scancode - keyboard(i).key(Escape);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint16_t input_find(const char *key) {
|
||||
if(!memcmp(key, "keyboard", 8)) {
|
||||
key += 8;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t k = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(k >= keyboard<>::count) return input_none;
|
||||
key += 2;
|
||||
static signed modifierDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(keyboard(i).isModifier(scancode)) return scancode - keyboard(i).key(Shift);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(*key++ != '.') return input_none;
|
||||
static bool isAnyKey(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(keyboard(i).isKey(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < keyboard<>::length; i++) {
|
||||
if(!strcmp(key, keysym[i])) return keyboard<>::index(k, i);
|
||||
static bool isAnyModifier(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(keyboard(i).isModifier(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint16_t decode(const char *name) {
|
||||
string s(name);
|
||||
if(!strbegin(name, "KB")) return 0;
|
||||
ltrim(s, "KB");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == KeyboardScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
string encode(uint16_t code) const {
|
||||
unsigned index = 0;
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(code >= Base + Size * i && code < Base + Size * (i + 1)) {
|
||||
index = code - (Base + Size * i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return string() << "KB" << ID << "::" << KeyboardScancodeName[index];
|
||||
}
|
||||
|
||||
if(!memcmp(key, "mouse", 5)) {
|
||||
key += 5;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t m = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(m >= mouse<>::count) return input_none;
|
||||
key += 2;
|
||||
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
||||
uint16_t key(unsigned id) const { return Base + Size * ID + id; }
|
||||
bool isKey(unsigned id) const { return id >= key(Escape) && id <= key(Menu); }
|
||||
bool isModifier(unsigned id) const { return id >= key(Shift) && id <= key(Super); }
|
||||
bool belongsTo(uint16_t scancode) const { return isKey(scancode) || isModifier(scancode); }
|
||||
|
||||
if(!strcmp(key, ".x")) return mouse<>::index(m, mouse<>::x);
|
||||
if(!strcmp(key, ".y")) return mouse<>::index(m, mouse<>::y);
|
||||
if(!strcmp(key, ".z")) return mouse<>::index(m, mouse<>::z);
|
||||
Keyboard(unsigned ID_) : ID(ID_) {}
|
||||
};
|
||||
|
||||
if(!memcmp(key, ".button", 7)) {
|
||||
key += 7;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t button = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(button >= mouse<>::buttons) return input_none;
|
||||
return mouse<>::index(m, mouse<>::button + button);
|
||||
}
|
||||
|
||||
return input_none;
|
||||
}
|
||||
|
||||
if(!memcmp(key, "joypad", 6)) {
|
||||
key += 6;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t j = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(j >= joypad<>::count) return input_none;
|
||||
key += 2;
|
||||
|
||||
if(!memcmp(key, ".hat", 4)) {
|
||||
key += 4;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t hat = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(hat >= joypad<>::hats) return input_none;
|
||||
return joypad<>::index(j, joypad<>::hat + hat);
|
||||
}
|
||||
|
||||
if(!memcmp(key, ".axis", 5)) {
|
||||
key += 5;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t axis = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(axis >= joypad<>::axes) return input_none;
|
||||
return joypad<>::index(j, joypad<>::axis + axis);
|
||||
}
|
||||
|
||||
if(!memcmp(key, ".button", 7)) {
|
||||
key += 7;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t button = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(button >= joypad<>::buttons) return input_none;
|
||||
return joypad<>::index(j, joypad<>::button + button);
|
||||
}
|
||||
|
||||
return input_none;
|
||||
}
|
||||
|
||||
return input_none;
|
||||
inline Keyboard& keyboard(unsigned id) {
|
||||
static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7);
|
||||
switch(id) { default:
|
||||
case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3;
|
||||
case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7;
|
||||
}
|
||||
}
|
||||
|
||||
static const char MouseScancodeName[][64] = {
|
||||
"Xaxis", "Yaxis", "Zaxis",
|
||||
"Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7",
|
||||
};
|
||||
|
||||
struct Mouse;
|
||||
Mouse& mouse(unsigned = 0);
|
||||
|
||||
struct Mouse {
|
||||
const unsigned ID;
|
||||
enum { Base = Keyboard::Base + Keyboard::Size * Keyboard::Count };
|
||||
enum { Count = 8, Size = 16 };
|
||||
enum { Axes = 3, Buttons = 8 };
|
||||
|
||||
enum Scancode {
|
||||
Xaxis, Yaxis, Zaxis,
|
||||
Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7,
|
||||
Limit,
|
||||
};
|
||||
|
||||
static signed numberDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(mouse(i).belongsTo(scancode)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static signed axisDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(mouse(i).isAxis(scancode)) return scancode - mouse(i).axis(0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static signed buttonDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(mouse(i).isButton(scancode)) return scancode - mouse(i).button(0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool isAnyAxis(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(mouse(i).isAxis(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isAnyButton(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(mouse(i).isButton(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint16_t decode(const char *name) {
|
||||
string s(name);
|
||||
if(!strbegin(name, "MS")) return 0;
|
||||
ltrim(s, "MS");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == MouseScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
string encode(uint16_t code) const {
|
||||
unsigned index = 0;
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(code >= Base + Size * i && code < Base + Size * (i + 1)) {
|
||||
index = code - (Base + Size * i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return string() << "MS" << ID << "::" << MouseScancodeName[index];
|
||||
}
|
||||
|
||||
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
||||
uint16_t axis(unsigned id) const { return Base + Size * ID + Xaxis + id; }
|
||||
uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; }
|
||||
bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(2); }
|
||||
bool isButton(unsigned id) const { return id >= button(0) && id <= button(7); }
|
||||
bool belongsTo(uint16_t scancode) const { return isAxis(scancode) || isButton(scancode); }
|
||||
|
||||
Mouse(unsigned ID_) : ID(ID_) {}
|
||||
};
|
||||
|
||||
inline Mouse& mouse(unsigned id) {
|
||||
static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7);
|
||||
switch(id) { default:
|
||||
case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3;
|
||||
case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7;
|
||||
}
|
||||
}
|
||||
|
||||
static const char JoypadScancodeName[][64] = {
|
||||
"Hat0", "Hat1", "Hat2", "Hat3", "Hat4", "Hat5", "Hat6", "Hat7",
|
||||
"Axis0", "Axis1", "Axis2", "Axis3", "Axis4", "Axis5", "Axis6", "Axis7",
|
||||
"Axis8", "Axis9", "Axis10", "Axis11", "Axis12", "Axis13", "Axis14", "Axis15",
|
||||
"Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7",
|
||||
"Button8", "Button9", "Button10", "Button11", "Button12", "Button13", "Button14", "Button15",
|
||||
"Button16", "Button17", "Button18", "Button19", "Button20", "Button21", "Button22", "Button23",
|
||||
"Button24", "Button25", "Button26", "Button27", "Button28", "Button29", "Button30", "Button31",
|
||||
};
|
||||
|
||||
struct Joypad;
|
||||
Joypad& joypad(unsigned = 0);
|
||||
|
||||
struct Joypad {
|
||||
const unsigned ID;
|
||||
enum { Base = Mouse::Base + Mouse::Size * Mouse::Count };
|
||||
enum { Count = 8, Size = 64 };
|
||||
enum { Hats = 8, Axes = 16, Buttons = 32 };
|
||||
|
||||
enum Scancode {
|
||||
Hat0, Hat1, Hat2, Hat3, Hat4, Hat5, Hat6, Hat7,
|
||||
Axis0, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7,
|
||||
Axis8, Axis9, Axis10, Axis11, Axis12, Axis13, Axis14, Axis15,
|
||||
Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7,
|
||||
Button8, Button9, Button10, Button11, Button12, Button13, Button14, Button15,
|
||||
Button16, Button17, Button18, Button19, Button20, Button21, Button22, Button23,
|
||||
Button24, Button25, Button26, Button27, Button28, Button29, Button30, Button31,
|
||||
Limit,
|
||||
};
|
||||
|
||||
enum Hat { HatCenter = 0, HatUp = 1, HatRight = 2, HatDown = 4, HatLeft = 8 };
|
||||
|
||||
static signed numberDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).belongsTo(scancode)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static signed hatDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isHat(scancode)) return scancode - joypad(i).hat(0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static signed axisDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isAxis(scancode)) return scancode - joypad(i).axis(0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static signed buttonDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isButton(scancode)) return scancode - joypad(i).button(0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool isAnyHat(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isHat(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isAnyAxis(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isAxis(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isAnyButton(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isButton(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint16_t decode(const char *name) {
|
||||
string s(name);
|
||||
if(!strbegin(name, "JP")) return 0;
|
||||
ltrim(s, "JP");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == JoypadScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
string encode(uint16_t code) const {
|
||||
unsigned index = 0;
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(code >= Base + Size * i && code < Base + Size * (i + 1)) {
|
||||
index = code - (Base + Size * i);
|
||||
}
|
||||
}
|
||||
return string() << "JP" << ID << "::" << JoypadScancodeName[index];
|
||||
}
|
||||
|
||||
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
||||
uint16_t hat(unsigned id) const { return Base + Size * ID + Hat0 + id; }
|
||||
uint16_t axis(unsigned id) const { return Base + Size * ID + Axis0 + id; }
|
||||
uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; }
|
||||
bool isHat(unsigned id) const { return id >= hat(0) && id <= hat(7); }
|
||||
bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(15); }
|
||||
bool isButton(unsigned id) const { return id >= button(0) && id <= button(31); }
|
||||
bool belongsTo(uint16_t scancode) const { return isHat(scancode) || isAxis(scancode) || isButton(scancode); }
|
||||
|
||||
Joypad(unsigned ID_) : ID(ID_) {}
|
||||
};
|
||||
|
||||
inline Joypad& joypad(unsigned id) {
|
||||
static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7);
|
||||
switch(id) { default:
|
||||
case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3;
|
||||
case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7;
|
||||
}
|
||||
}
|
||||
|
||||
struct Scancode {
|
||||
enum { None = 0, Limit = Joypad::Base + Joypad::Size * Joypad::Count };
|
||||
|
||||
static uint16_t decode(const char *name) {
|
||||
uint16_t code;
|
||||
code = Keyboard::decode(name);
|
||||
if(code) return code;
|
||||
code = Mouse::decode(name);
|
||||
if(code) return code;
|
||||
code = Joypad::decode(name);
|
||||
if(code) return code;
|
||||
return None;
|
||||
}
|
||||
|
||||
static string encode(uint16_t code) {
|
||||
for(unsigned i = 0; i < Keyboard::Count; i++) {
|
||||
if(keyboard(i).belongsTo(code)) return keyboard(i).encode(code);
|
||||
}
|
||||
for(unsigned i = 0; i < Mouse::Count; i++) {
|
||||
if(mouse(i).belongsTo(code)) return mouse(i).encode(code);
|
||||
}
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
if(joypad(i).belongsTo(code)) return joypad(i).encode(code);
|
||||
}
|
||||
return "None";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -20,6 +20,12 @@ namespace nall {
|
||||
|
||||
class serializer {
|
||||
public:
|
||||
enum mode_t { Load, Save, Size };
|
||||
|
||||
mode_t mode() const {
|
||||
return imode;
|
||||
}
|
||||
|
||||
const uint8_t* data() const {
|
||||
return idata;
|
||||
}
|
||||
@@ -37,9 +43,9 @@ namespace nall {
|
||||
//this is rather dangerous, and not cross-platform safe;
|
||||
//but there is no standardized way to export FP-values
|
||||
uint8_t *p = (uint8_t*)&value;
|
||||
if(mode == Save) {
|
||||
if(imode == Save) {
|
||||
for(unsigned n = 0; n < size; n++) idata[isize++] = p[n];
|
||||
} else if(mode == Load) {
|
||||
} else if(imode == Load) {
|
||||
for(unsigned n = 0; n < size; n++) p[n] = idata[isize++];
|
||||
} else {
|
||||
isize += size;
|
||||
@@ -48,12 +54,12 @@ namespace nall {
|
||||
|
||||
template<typename T> void integer(T &value) {
|
||||
enum { size = is_bool<T>::value ? 1 : sizeof(T) };
|
||||
if(mode == Save) {
|
||||
if(imode == Save) {
|
||||
for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3);
|
||||
} else if(mode == Load) {
|
||||
} else if(imode == Load) {
|
||||
value = 0;
|
||||
for(unsigned n = 0; n < size; n++) value |= idata[isize++] << (n << 3);
|
||||
} else if(mode == Size) {
|
||||
} else if(imode == Size) {
|
||||
isize += size;
|
||||
}
|
||||
}
|
||||
@@ -70,7 +76,7 @@ namespace nall {
|
||||
serializer& operator=(const serializer &s) {
|
||||
if(idata) delete[] idata;
|
||||
|
||||
mode = s.mode;
|
||||
imode = s.imode;
|
||||
idata = new uint8_t[s.icapacity];
|
||||
isize = s.isize;
|
||||
icapacity = s.icapacity;
|
||||
@@ -84,20 +90,20 @@ namespace nall {
|
||||
}
|
||||
|
||||
serializer() {
|
||||
mode = Size;
|
||||
imode = Size;
|
||||
idata = 0;
|
||||
isize = 0;
|
||||
}
|
||||
|
||||
serializer(unsigned capacity) {
|
||||
mode = Save;
|
||||
imode = Save;
|
||||
idata = new uint8_t[capacity]();
|
||||
isize = 0;
|
||||
icapacity = capacity;
|
||||
}
|
||||
|
||||
serializer(const uint8_t *data, unsigned capacity) {
|
||||
mode = Load;
|
||||
imode = Load;
|
||||
idata = new uint8_t[capacity];
|
||||
isize = 0;
|
||||
icapacity = capacity;
|
||||
@@ -109,7 +115,7 @@ namespace nall {
|
||||
}
|
||||
|
||||
private:
|
||||
enum mode_t { Load, Save, Size } mode;
|
||||
mode_t imode;
|
||||
uint8_t *idata;
|
||||
unsigned isize;
|
||||
unsigned icapacity;
|
||||
|
@@ -80,6 +80,11 @@ namespace nall {
|
||||
protected:
|
||||
char *data;
|
||||
size_t size;
|
||||
|
||||
#if defined(QT_CORE_LIB)
|
||||
public:
|
||||
inline operator QString() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class lstring : public vector<string> {
|
||||
|
@@ -20,6 +20,11 @@ namespace nall {
|
||||
operator[](size()).assign(to_string<T>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if defined(QT_CORE_LIB)
|
||||
template<> inline string to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }
|
||||
string::operator QString() const { return QString::fromUtf8(*this); }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -31,6 +31,11 @@ namespace nall {
|
||||
inline string basename(char const *name) {
|
||||
string result = name;
|
||||
for(signed i = strlen(result); i >= 0; i--) {
|
||||
if(result[i] == '/' || result[i] == '\\') {
|
||||
//file has no extension
|
||||
break;
|
||||
}
|
||||
|
||||
if(result[i] == '.') {
|
||||
result[i] = 0;
|
||||
break;
|
||||
|
@@ -1,7 +1,5 @@
|
||||
/*
|
||||
audio.alsa (2008-08-12)
|
||||
authors: Nach, RedDwarf
|
||||
*/
|
||||
//audio.alsa (2009-11-30)
|
||||
//authors: BearOso, byuu, Nach, RedDwarf
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
@@ -77,6 +75,22 @@ public:
|
||||
buffer.data[buffer.length++] = left + (right << 16);
|
||||
if(buffer.length < device.period_size) return;
|
||||
|
||||
snd_pcm_sframes_t avail;
|
||||
do {
|
||||
avail = snd_pcm_avail_update(device.handle);
|
||||
if(avail < 0) snd_pcm_recover(device.handle, avail, 1);
|
||||
if(avail < buffer.length) {
|
||||
if(settings.synchronize == false) {
|
||||
buffer.length = 0;
|
||||
return;
|
||||
}
|
||||
int error = snd_pcm_wait(device.handle, -1);
|
||||
if(error < 0) snd_pcm_recover(device.handle, error, 1);
|
||||
}
|
||||
} while(avail < buffer.length);
|
||||
|
||||
//below code has issues with PulseAudio sound server
|
||||
#if 0
|
||||
if(settings.synchronize == false) {
|
||||
snd_pcm_sframes_t avail = snd_pcm_avail_update(device.handle);
|
||||
if(avail < device.period_size) {
|
||||
@@ -84,6 +98,7 @@ public:
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t *buffer_ptr = buffer.data;
|
||||
int i = 4;
|
||||
@@ -114,12 +129,13 @@ public:
|
||||
bool init() {
|
||||
term();
|
||||
|
||||
if(snd_pcm_open(&device.handle, device.name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
|
||||
if(snd_pcm_open(&device.handle, device.name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) {
|
||||
term();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* //below code will not work with 24khz frequency rate (ALSA library bug)
|
||||
//below code will not work with 24khz frequency rate (ALSA library bug)
|
||||
#if 0
|
||||
if(snd_pcm_set_params(device.handle, device.format, SND_PCM_ACCESS_RW_INTERLEAVED,
|
||||
device.channels, settings.frequency, 1, settings.latency * 1000) < 0) {
|
||||
//failed to set device parameters
|
||||
@@ -129,7 +145,8 @@ public:
|
||||
|
||||
if(snd_pcm_get_params(device.handle, &device.buffer_size, &device.period_size) < 0) {
|
||||
device.period_size = settings.latency * 1000 * 1e-6 * settings.frequency / 4;
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_sw_params_t *swparams;
|
||||
|
@@ -19,129 +19,126 @@ public:
|
||||
bool acquired() { return false; }
|
||||
|
||||
bool poll(int16_t *table) {
|
||||
memset(table, 0, nall::input_limit * sizeof(int16_t));
|
||||
memset(table, 0, Scancode::Limit * sizeof(int16_t));
|
||||
|
||||
KeyMap keys;
|
||||
GetKeys(keys);
|
||||
uint8_t *keymap = (uint8_t*)keys;
|
||||
|
||||
#define map(id, name) table[keyboard<0>::name] = (bool)(keymap[id >> 3] & (1 << (id & 7)))
|
||||
map(0x35, escape);
|
||||
#define map(id, name) table[keyboard(0)[name]] = (bool)(keymap[id >> 3] & (1 << (id & 7)))
|
||||
map(0x35, Keyboard::Escape);
|
||||
|
||||
map(0x7a, f1);
|
||||
map(0x78, f2);
|
||||
map(0x63, f3);
|
||||
map(0x76, f4);
|
||||
map(0x60, f5);
|
||||
map(0x61, f6);
|
||||
map(0x62, f7);
|
||||
map(0x64, f8);
|
||||
map(0x65, f9);
|
||||
map(0x6d, f10);
|
||||
map(0x67, f11);
|
||||
//map(0x??, f12);
|
||||
map(0x7a, Keyboard::F1);
|
||||
map(0x78, Keyboard::F2);
|
||||
map(0x63, Keyboard::F3);
|
||||
map(0x76, Keyboard::F4);
|
||||
map(0x60, Keyboard::F5);
|
||||
map(0x61, Keyboard::F6);
|
||||
map(0x62, Keyboard::F7);
|
||||
map(0x64, Keyboard::F8);
|
||||
map(0x65, Keyboard::F9);
|
||||
map(0x6d, Keyboard::F10);
|
||||
map(0x67, Keyboard::F11);
|
||||
//map(0x??, Keyboard::F12);
|
||||
|
||||
map(0x69, print_screen);
|
||||
//map(0x??, scroll_lock);
|
||||
map(0x71, pause);
|
||||
map(0x69, Keyboard::PrintScreen);
|
||||
//map(0x??, Keyboard::ScrollLock);
|
||||
map(0x71, Keyboard::Pause);
|
||||
|
||||
map(0x32, tilde);
|
||||
map(0x12, num_1);
|
||||
map(0x13, num_2);
|
||||
map(0x14, num_3);
|
||||
map(0x15, num_4);
|
||||
map(0x17, num_5);
|
||||
map(0x16, num_6);
|
||||
map(0x1a, num_7);
|
||||
map(0x1c, num_8);
|
||||
map(0x19, num_9);
|
||||
map(0x1d, num_0);
|
||||
map(0x32, Keyboard::Tilde);
|
||||
map(0x12, Keyboard::Num1);
|
||||
map(0x13, Keyboard::Num2);
|
||||
map(0x14, Keyboard::Num3);
|
||||
map(0x15, Keyboard::Num4);
|
||||
map(0x17, Keyboard::Num5);
|
||||
map(0x16, Keyboard::Num6);
|
||||
map(0x1a, Keyboard::Num7);
|
||||
map(0x1c, Keyboard::Num8);
|
||||
map(0x19, Keyboard::Num9);
|
||||
map(0x1d, Keyboard::Num0);
|
||||
|
||||
map(0x1b, dash);
|
||||
map(0x18, equal);
|
||||
map(0x33, backspace);
|
||||
map(0x1b, Keyboard::Dash);
|
||||
map(0x18, Keyboard::Equal);
|
||||
map(0x33, Keyboard::Backspace);
|
||||
|
||||
map(0x72, insert);
|
||||
map(0x75, delete_);
|
||||
map(0x73, home);
|
||||
map(0x77, end);
|
||||
map(0x74, page_up);
|
||||
map(0x79, page_down);
|
||||
map(0x72, Keyboard::Insert);
|
||||
map(0x75, Keyboard::Delete);
|
||||
map(0x73, Keyboard::Home);
|
||||
map(0x77, Keyboard::End);
|
||||
map(0x74, Keyboard::PageUp);
|
||||
map(0x79, Keyboard::PageDown);
|
||||
|
||||
map(0x00, a);
|
||||
map(0x0b, b);
|
||||
map(0x08, c);
|
||||
map(0x02, d);
|
||||
map(0x0e, e);
|
||||
map(0x03, f);
|
||||
map(0x05, g);
|
||||
map(0x04, h);
|
||||
map(0x22, i);
|
||||
map(0x26, j);
|
||||
map(0x28, k);
|
||||
map(0x25, l);
|
||||
map(0x2e, m);
|
||||
map(0x2d, n);
|
||||
map(0x1f, o);
|
||||
map(0x23, p);
|
||||
map(0x0c, q);
|
||||
map(0x0f, r);
|
||||
map(0x01, s);
|
||||
map(0x11, t);
|
||||
map(0x20, u);
|
||||
map(0x09, v);
|
||||
map(0x0d, w);
|
||||
map(0x07, x);
|
||||
map(0x10, y);
|
||||
map(0x06, z);
|
||||
map(0x00, Keyboard::A);
|
||||
map(0x0b, Keyboard::B);
|
||||
map(0x08, Keyboard::C);
|
||||
map(0x02, Keyboard::D);
|
||||
map(0x0e, Keyboard::E);
|
||||
map(0x03, Keyboard::F);
|
||||
map(0x05, Keyboard::G);
|
||||
map(0x04, Keyboard::H);
|
||||
map(0x22, Keyboard::I);
|
||||
map(0x26, Keyboard::J);
|
||||
map(0x28, Keyboard::K);
|
||||
map(0x25, Keyboard::L);
|
||||
map(0x2e, Keyboard::M);
|
||||
map(0x2d, Keyboard::N);
|
||||
map(0x1f, Keyboard::O);
|
||||
map(0x23, Keyboard::P);
|
||||
map(0x0c, Keyboard::Q);
|
||||
map(0x0f, Keyboard::R);
|
||||
map(0x01, Keyboard::S);
|
||||
map(0x11, Keyboard::T);
|
||||
map(0x20, Keyboard::U);
|
||||
map(0x09, Keyboard::V);
|
||||
map(0x0d, Keyboard::W);
|
||||
map(0x07, Keyboard::X);
|
||||
map(0x10, Keyboard::Y);
|
||||
map(0x06, Keyboard::Z);
|
||||
|
||||
map(0x21, lbracket);
|
||||
map(0x1e, rbracket);
|
||||
map(0x2a, backslash);
|
||||
map(0x29, semicolon);
|
||||
map(0x27, apostrophe);
|
||||
map(0x2b, comma);
|
||||
map(0x2f, period);
|
||||
map(0x2c, slash);
|
||||
map(0x21, Keyboard::LeftBracket);
|
||||
map(0x1e, Keyboard::RightBracket);
|
||||
map(0x2a, Keyboard::Backslash);
|
||||
map(0x29, Keyboard::Semicolon);
|
||||
map(0x27, Keyboard::Apostrophe);
|
||||
map(0x2b, Keyboard::Comma);
|
||||
map(0x2f, Keyboard::Period);
|
||||
map(0x2c, Keyboard::Slash);
|
||||
|
||||
map(0x52, pad_0);
|
||||
map(0x53, pad_1);
|
||||
map(0x54, pad_2);
|
||||
map(0x55, pad_3);
|
||||
map(0x56, pad_4);
|
||||
map(0x57, pad_5);
|
||||
map(0x58, pad_6);
|
||||
map(0x59, pad_7);
|
||||
map(0x5b, pad_8);
|
||||
map(0x5c, pad_9);
|
||||
map(0x53, Keyboard::Keypad1);
|
||||
map(0x54, Keyboard::Keypad2);
|
||||
map(0x55, Keyboard::Keypad3);
|
||||
map(0x56, Keyboard::Keypad4);
|
||||
map(0x57, Keyboard::Keypad5);
|
||||
map(0x58, Keyboard::Keypad6);
|
||||
map(0x59, Keyboard::Keypad7);
|
||||
map(0x5b, Keyboard::Keypad8);
|
||||
map(0x5c, Keyboard::Keypad9);
|
||||
map(0x52, Keyboard::Keypad0);
|
||||
|
||||
map(0x45, add);
|
||||
map(0x4e, subtract);
|
||||
map(0x43, multiply);
|
||||
map(0x4b, divide);
|
||||
map(0x4c, enter);
|
||||
//map(0x??, Keyboard::Point);
|
||||
map(0x4c, Keyboard::Enter);
|
||||
map(0x45, Keyboard::Add);
|
||||
map(0x4e, Keyboard::Subtract);
|
||||
map(0x43, Keyboard::Multiply);
|
||||
map(0x4b, Keyboard::Divide);
|
||||
|
||||
map(0x47, num_lock);
|
||||
//map(0x39, caps_lock);
|
||||
map(0x47, Keyboard::NumLock);
|
||||
//map(0x39, Keyboard::CapsLock);
|
||||
|
||||
map(0x7e, up);
|
||||
map(0x7d, down);
|
||||
map(0x7b, left);
|
||||
map(0x7c, right);
|
||||
map(0x7e, Keyboard::Up);
|
||||
map(0x7d, Keyboard::Down);
|
||||
map(0x7b, Keyboard::Left);
|
||||
map(0x7c, Keyboard::Right);
|
||||
|
||||
map(0x30, tab);
|
||||
map(0x24, return_);
|
||||
map(0x31, spacebar);
|
||||
map(0x30, Keyboard::Tab);
|
||||
map(0x24, Keyboard::Return);
|
||||
map(0x31, Keyboard::Spacebar);
|
||||
//map(0x??, Keyboard::Menu);
|
||||
|
||||
map(0x3b, lctrl);
|
||||
//map(0x3b, rctrl);
|
||||
map(0x3a, lalt);
|
||||
//map(0x3a, ralt);
|
||||
map(0x38, lshift);
|
||||
//map(0x38, rshift);
|
||||
map(0x37, lsuper);
|
||||
//map(0x37, rsuper);
|
||||
//map(0x??, menu);
|
||||
map(0x38, Keyboard::Shift);
|
||||
map(0x3b, Keyboard::Control);
|
||||
map(0x3a, Keyboard::Alt);
|
||||
map(0x37, Keyboard::Super);
|
||||
#undef map
|
||||
|
||||
return true;
|
||||
|
@@ -14,7 +14,7 @@ public:
|
||||
LPDIRECTINPUT8 context;
|
||||
LPDIRECTINPUTDEVICE8 keyboard;
|
||||
LPDIRECTINPUTDEVICE8 mouse;
|
||||
LPDIRECTINPUTDEVICE8 gamepad[joypad<>::count];
|
||||
LPDIRECTINPUTDEVICE8 gamepad[Joypad::Count];
|
||||
bool mouseacquired;
|
||||
} device;
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
}
|
||||
|
||||
bool poll(int16_t *table) {
|
||||
memset(table, 0, nall::input_limit * sizeof(int16_t));
|
||||
memset(table, 0, Scancode::Limit * sizeof(int16_t));
|
||||
|
||||
//========
|
||||
//Keyboard
|
||||
@@ -60,122 +60,122 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
table[keyboard<0>::escape] = (bool)(state[0x01] & 0x80);
|
||||
table[keyboard<0>::f1 ] = (bool)(state[0x3b] & 0x80);
|
||||
table[keyboard<0>::f2 ] = (bool)(state[0x3c] & 0x80);
|
||||
table[keyboard<0>::f3 ] = (bool)(state[0x3d] & 0x80);
|
||||
table[keyboard<0>::f4 ] = (bool)(state[0x3e] & 0x80);
|
||||
table[keyboard<0>::f5 ] = (bool)(state[0x3f] & 0x80);
|
||||
table[keyboard<0>::f6 ] = (bool)(state[0x40] & 0x80);
|
||||
table[keyboard<0>::f7 ] = (bool)(state[0x41] & 0x80);
|
||||
table[keyboard<0>::f8 ] = (bool)(state[0x42] & 0x80);
|
||||
table[keyboard<0>::f9 ] = (bool)(state[0x43] & 0x80);
|
||||
table[keyboard<0>::f10 ] = (bool)(state[0x44] & 0x80);
|
||||
table[keyboard<0>::f11 ] = (bool)(state[0x57] & 0x80);
|
||||
table[keyboard<0>::f12 ] = (bool)(state[0x58] & 0x80);
|
||||
#define key(id) table[keyboard(0)[id]]
|
||||
|
||||
table[keyboard<0>::print_screen] = (bool)(state[0xb7] & 0x80);
|
||||
table[keyboard<0>::scroll_lock ] = (bool)(state[0x46] & 0x80);
|
||||
table[keyboard<0>::pause ] = (bool)(state[0xc5] & 0x80);
|
||||
table[keyboard<0>::tilde ] = (bool)(state[0x29] & 0x80);
|
||||
key(Keyboard::Escape) = (bool)(state[0x01] & 0x80);
|
||||
key(Keyboard::F1 ) = (bool)(state[0x3b] & 0x80);
|
||||
key(Keyboard::F2 ) = (bool)(state[0x3c] & 0x80);
|
||||
key(Keyboard::F3 ) = (bool)(state[0x3d] & 0x80);
|
||||
key(Keyboard::F4 ) = (bool)(state[0x3e] & 0x80);
|
||||
key(Keyboard::F5 ) = (bool)(state[0x3f] & 0x80);
|
||||
key(Keyboard::F6 ) = (bool)(state[0x40] & 0x80);
|
||||
key(Keyboard::F7 ) = (bool)(state[0x41] & 0x80);
|
||||
key(Keyboard::F8 ) = (bool)(state[0x42] & 0x80);
|
||||
key(Keyboard::F9 ) = (bool)(state[0x43] & 0x80);
|
||||
key(Keyboard::F10 ) = (bool)(state[0x44] & 0x80);
|
||||
key(Keyboard::F11 ) = (bool)(state[0x57] & 0x80);
|
||||
key(Keyboard::F12 ) = (bool)(state[0x58] & 0x80);
|
||||
|
||||
table[keyboard<0>::num_1] = (bool)(state[0x02] & 0x80);
|
||||
table[keyboard<0>::num_2] = (bool)(state[0x03] & 0x80);
|
||||
table[keyboard<0>::num_3] = (bool)(state[0x04] & 0x80);
|
||||
table[keyboard<0>::num_4] = (bool)(state[0x05] & 0x80);
|
||||
table[keyboard<0>::num_5] = (bool)(state[0x06] & 0x80);
|
||||
table[keyboard<0>::num_6] = (bool)(state[0x07] & 0x80);
|
||||
table[keyboard<0>::num_7] = (bool)(state[0x08] & 0x80);
|
||||
table[keyboard<0>::num_8] = (bool)(state[0x09] & 0x80);
|
||||
table[keyboard<0>::num_9] = (bool)(state[0x0a] & 0x80);
|
||||
table[keyboard<0>::num_0] = (bool)(state[0x0b] & 0x80);
|
||||
key(Keyboard::PrintScreen) = (bool)(state[0xb7] & 0x80);
|
||||
key(Keyboard::ScrollLock ) = (bool)(state[0x46] & 0x80);
|
||||
key(Keyboard::Pause ) = (bool)(state[0xc5] & 0x80);
|
||||
key(Keyboard::Tilde ) = (bool)(state[0x29] & 0x80);
|
||||
|
||||
table[keyboard<0>::dash ] = (bool)(state[0x0c] & 0x80);
|
||||
table[keyboard<0>::equal ] = (bool)(state[0x0d] & 0x80);
|
||||
table[keyboard<0>::backspace] = (bool)(state[0x0e] & 0x80);
|
||||
key(Keyboard::Num1) = (bool)(state[0x02] & 0x80);
|
||||
key(Keyboard::Num2) = (bool)(state[0x03] & 0x80);
|
||||
key(Keyboard::Num3) = (bool)(state[0x04] & 0x80);
|
||||
key(Keyboard::Num4) = (bool)(state[0x05] & 0x80);
|
||||
key(Keyboard::Num5) = (bool)(state[0x06] & 0x80);
|
||||
key(Keyboard::Num6) = (bool)(state[0x07] & 0x80);
|
||||
key(Keyboard::Num7) = (bool)(state[0x08] & 0x80);
|
||||
key(Keyboard::Num8) = (bool)(state[0x09] & 0x80);
|
||||
key(Keyboard::Num9) = (bool)(state[0x0a] & 0x80);
|
||||
key(Keyboard::Num0) = (bool)(state[0x0b] & 0x80);
|
||||
|
||||
table[keyboard<0>::insert ] = (bool)(state[0xd2] & 0x80);
|
||||
table[keyboard<0>::delete_ ] = (bool)(state[0xd3] & 0x80);
|
||||
table[keyboard<0>::home ] = (bool)(state[0xc7] & 0x80);
|
||||
table[keyboard<0>::end ] = (bool)(state[0xcf] & 0x80);
|
||||
table[keyboard<0>::page_up ] = (bool)(state[0xc9] & 0x80);
|
||||
table[keyboard<0>::page_down] = (bool)(state[0xd1] & 0x80);
|
||||
key(Keyboard::Dash ) = (bool)(state[0x0c] & 0x80);
|
||||
key(Keyboard::Equal ) = (bool)(state[0x0d] & 0x80);
|
||||
key(Keyboard::Backspace) = (bool)(state[0x0e] & 0x80);
|
||||
|
||||
table[keyboard<0>::a] = (bool)(state[0x1e] & 0x80);
|
||||
table[keyboard<0>::b] = (bool)(state[0x30] & 0x80);
|
||||
table[keyboard<0>::c] = (bool)(state[0x2e] & 0x80);
|
||||
table[keyboard<0>::d] = (bool)(state[0x20] & 0x80);
|
||||
table[keyboard<0>::e] = (bool)(state[0x12] & 0x80);
|
||||
table[keyboard<0>::f] = (bool)(state[0x21] & 0x80);
|
||||
table[keyboard<0>::g] = (bool)(state[0x22] & 0x80);
|
||||
table[keyboard<0>::h] = (bool)(state[0x23] & 0x80);
|
||||
table[keyboard<0>::i] = (bool)(state[0x17] & 0x80);
|
||||
table[keyboard<0>::j] = (bool)(state[0x24] & 0x80);
|
||||
table[keyboard<0>::k] = (bool)(state[0x25] & 0x80);
|
||||
table[keyboard<0>::l] = (bool)(state[0x26] & 0x80);
|
||||
table[keyboard<0>::m] = (bool)(state[0x32] & 0x80);
|
||||
table[keyboard<0>::n] = (bool)(state[0x31] & 0x80);
|
||||
table[keyboard<0>::o] = (bool)(state[0x18] & 0x80);
|
||||
table[keyboard<0>::p] = (bool)(state[0x19] & 0x80);
|
||||
table[keyboard<0>::q] = (bool)(state[0x10] & 0x80);
|
||||
table[keyboard<0>::r] = (bool)(state[0x13] & 0x80);
|
||||
table[keyboard<0>::s] = (bool)(state[0x1f] & 0x80);
|
||||
table[keyboard<0>::t] = (bool)(state[0x14] & 0x80);
|
||||
table[keyboard<0>::u] = (bool)(state[0x16] & 0x80);
|
||||
table[keyboard<0>::v] = (bool)(state[0x2f] & 0x80);
|
||||
table[keyboard<0>::w] = (bool)(state[0x11] & 0x80);
|
||||
table[keyboard<0>::x] = (bool)(state[0x2d] & 0x80);
|
||||
table[keyboard<0>::y] = (bool)(state[0x15] & 0x80);
|
||||
table[keyboard<0>::z] = (bool)(state[0x2c] & 0x80);
|
||||
key(Keyboard::Insert ) = (bool)(state[0xd2] & 0x80);
|
||||
key(Keyboard::Delete ) = (bool)(state[0xd3] & 0x80);
|
||||
key(Keyboard::Home ) = (bool)(state[0xc7] & 0x80);
|
||||
key(Keyboard::End ) = (bool)(state[0xcf] & 0x80);
|
||||
key(Keyboard::PageUp ) = (bool)(state[0xc9] & 0x80);
|
||||
key(Keyboard::PageDown) = (bool)(state[0xd1] & 0x80);
|
||||
|
||||
table[keyboard<0>::lbracket ] = (bool)(state[0x1a] & 0x80);
|
||||
table[keyboard<0>::rbracket ] = (bool)(state[0x1b] & 0x80);
|
||||
table[keyboard<0>::backslash ] = (bool)(state[0x2b] & 0x80);
|
||||
table[keyboard<0>::semicolon ] = (bool)(state[0x27] & 0x80);
|
||||
table[keyboard<0>::apostrophe] = (bool)(state[0x28] & 0x80);
|
||||
table[keyboard<0>::comma ] = (bool)(state[0x33] & 0x80);
|
||||
table[keyboard<0>::period ] = (bool)(state[0x34] & 0x80);
|
||||
table[keyboard<0>::slash ] = (bool)(state[0x35] & 0x80);
|
||||
key(Keyboard::A) = (bool)(state[0x1e] & 0x80);
|
||||
key(Keyboard::B) = (bool)(state[0x30] & 0x80);
|
||||
key(Keyboard::C) = (bool)(state[0x2e] & 0x80);
|
||||
key(Keyboard::D) = (bool)(state[0x20] & 0x80);
|
||||
key(Keyboard::E) = (bool)(state[0x12] & 0x80);
|
||||
key(Keyboard::F) = (bool)(state[0x21] & 0x80);
|
||||
key(Keyboard::G) = (bool)(state[0x22] & 0x80);
|
||||
key(Keyboard::H) = (bool)(state[0x23] & 0x80);
|
||||
key(Keyboard::I) = (bool)(state[0x17] & 0x80);
|
||||
key(Keyboard::J) = (bool)(state[0x24] & 0x80);
|
||||
key(Keyboard::K) = (bool)(state[0x25] & 0x80);
|
||||
key(Keyboard::L) = (bool)(state[0x26] & 0x80);
|
||||
key(Keyboard::M) = (bool)(state[0x32] & 0x80);
|
||||
key(Keyboard::N) = (bool)(state[0x31] & 0x80);
|
||||
key(Keyboard::O) = (bool)(state[0x18] & 0x80);
|
||||
key(Keyboard::P) = (bool)(state[0x19] & 0x80);
|
||||
key(Keyboard::Q) = (bool)(state[0x10] & 0x80);
|
||||
key(Keyboard::R) = (bool)(state[0x13] & 0x80);
|
||||
key(Keyboard::S) = (bool)(state[0x1f] & 0x80);
|
||||
key(Keyboard::T) = (bool)(state[0x14] & 0x80);
|
||||
key(Keyboard::U) = (bool)(state[0x16] & 0x80);
|
||||
key(Keyboard::V) = (bool)(state[0x2f] & 0x80);
|
||||
key(Keyboard::W) = (bool)(state[0x11] & 0x80);
|
||||
key(Keyboard::X) = (bool)(state[0x2d] & 0x80);
|
||||
key(Keyboard::Y) = (bool)(state[0x15] & 0x80);
|
||||
key(Keyboard::Z) = (bool)(state[0x2c] & 0x80);
|
||||
|
||||
table[keyboard<0>::pad_0] = (bool)(state[0x4f] & 0x80);
|
||||
table[keyboard<0>::pad_1] = (bool)(state[0x50] & 0x80);
|
||||
table[keyboard<0>::pad_2] = (bool)(state[0x51] & 0x80);
|
||||
table[keyboard<0>::pad_3] = (bool)(state[0x4b] & 0x80);
|
||||
table[keyboard<0>::pad_4] = (bool)(state[0x4c] & 0x80);
|
||||
table[keyboard<0>::pad_5] = (bool)(state[0x4d] & 0x80);
|
||||
table[keyboard<0>::pad_6] = (bool)(state[0x47] & 0x80);
|
||||
table[keyboard<0>::pad_7] = (bool)(state[0x48] & 0x80);
|
||||
table[keyboard<0>::pad_8] = (bool)(state[0x49] & 0x80);
|
||||
table[keyboard<0>::pad_9] = (bool)(state[0x52] & 0x80);
|
||||
table[keyboard<0>::point] = (bool)(state[0x53] & 0x80);
|
||||
key(Keyboard::LeftBracket ) = (bool)(state[0x1a] & 0x80);
|
||||
key(Keyboard::RightBracket) = (bool)(state[0x1b] & 0x80);
|
||||
key(Keyboard::Backslash ) = (bool)(state[0x2b] & 0x80);
|
||||
key(Keyboard::Semicolon ) = (bool)(state[0x27] & 0x80);
|
||||
key(Keyboard::Apostrophe ) = (bool)(state[0x28] & 0x80);
|
||||
key(Keyboard::Comma ) = (bool)(state[0x33] & 0x80);
|
||||
key(Keyboard::Period ) = (bool)(state[0x34] & 0x80);
|
||||
key(Keyboard::Slash ) = (bool)(state[0x35] & 0x80);
|
||||
|
||||
table[keyboard<0>::add] = (bool)(state[0x4e] & 0x80);
|
||||
table[keyboard<0>::subtract] = (bool)(state[0x4a] & 0x80);
|
||||
table[keyboard<0>::multiply] = (bool)(state[0x37] & 0x80);
|
||||
table[keyboard<0>::divide] = (bool)(state[0xb5] & 0x80);
|
||||
table[keyboard<0>::enter] = (bool)(state[0x9c] & 0x80);
|
||||
key(Keyboard::Keypad0) = (bool)(state[0x4f] & 0x80);
|
||||
key(Keyboard::Keypad1) = (bool)(state[0x50] & 0x80);
|
||||
key(Keyboard::Keypad2) = (bool)(state[0x51] & 0x80);
|
||||
key(Keyboard::Keypad3) = (bool)(state[0x4b] & 0x80);
|
||||
key(Keyboard::Keypad4) = (bool)(state[0x4c] & 0x80);
|
||||
key(Keyboard::Keypad5) = (bool)(state[0x4d] & 0x80);
|
||||
key(Keyboard::Keypad6) = (bool)(state[0x47] & 0x80);
|
||||
key(Keyboard::Keypad7) = (bool)(state[0x48] & 0x80);
|
||||
key(Keyboard::Keypad8) = (bool)(state[0x49] & 0x80);
|
||||
key(Keyboard::Keypad9) = (bool)(state[0x52] & 0x80);
|
||||
key(Keyboard::Point ) = (bool)(state[0x53] & 0x80);
|
||||
|
||||
table[keyboard<0>::num_lock ] = (bool)(state[0x45] & 0x80);
|
||||
table[keyboard<0>::caps_lock] = (bool)(state[0x3a] & 0x80);
|
||||
key(Keyboard::Add ) = (bool)(state[0x4e] & 0x80);
|
||||
key(Keyboard::Subtract) = (bool)(state[0x4a] & 0x80);
|
||||
key(Keyboard::Multiply) = (bool)(state[0x37] & 0x80);
|
||||
key(Keyboard::Divide ) = (bool)(state[0xb5] & 0x80);
|
||||
key(Keyboard::Enter ) = (bool)(state[0x9c] & 0x80);
|
||||
|
||||
table[keyboard<0>::up ] = (bool)(state[0xc8] & 0x80);
|
||||
table[keyboard<0>::down ] = (bool)(state[0xd0] & 0x80);
|
||||
table[keyboard<0>::left ] = (bool)(state[0xcb] & 0x80);
|
||||
table[keyboard<0>::right] = (bool)(state[0xcd] & 0x80);
|
||||
key(Keyboard::NumLock ) = (bool)(state[0x45] & 0x80);
|
||||
key(Keyboard::CapsLock) = (bool)(state[0x3a] & 0x80);
|
||||
|
||||
table[keyboard<0>::tab ] = (bool)(state[0x0f] & 0x80);
|
||||
table[keyboard<0>::return_ ] = (bool)(state[0x1c] & 0x80);
|
||||
table[keyboard<0>::spacebar] = (bool)(state[0x39] & 0x80);
|
||||
key(Keyboard::Up ) = (bool)(state[0xc8] & 0x80);
|
||||
key(Keyboard::Down ) = (bool)(state[0xd0] & 0x80);
|
||||
key(Keyboard::Left ) = (bool)(state[0xcb] & 0x80);
|
||||
key(Keyboard::Right) = (bool)(state[0xcd] & 0x80);
|
||||
|
||||
table[keyboard<0>::lctrl ] = (bool)(state[0x1d] & 0x80);
|
||||
table[keyboard<0>::rctrl ] = (bool)(state[0x9d] & 0x80);
|
||||
table[keyboard<0>::lalt ] = (bool)(state[0x38] & 0x80);
|
||||
table[keyboard<0>::ralt ] = (bool)(state[0xb8] & 0x80);
|
||||
table[keyboard<0>::lshift] = (bool)(state[0x2a] & 0x80);
|
||||
table[keyboard<0>::rshift] = (bool)(state[0x36] & 0x80);
|
||||
table[keyboard<0>::lsuper] = (bool)(state[0xdb] & 0x80);
|
||||
table[keyboard<0>::rsuper] = (bool)(state[0xdc] & 0x80);
|
||||
table[keyboard<0>::menu ] = (bool)(state[0xdd] & 0x80);
|
||||
key(Keyboard::Tab ) = (bool)(state[0x0f] & 0x80);
|
||||
key(Keyboard::Return ) = (bool)(state[0x1c] & 0x80);
|
||||
key(Keyboard::Spacebar) = (bool)(state[0x39] & 0x80);
|
||||
key(Keyboard::Menu ) = (bool)(state[0xdd] & 0x80);
|
||||
|
||||
key(Keyboard::Shift ) = (bool)(state[0x2a] & 0x80) || (bool)(state[0x36] & 0x80);
|
||||
key(Keyboard::Control) = (bool)(state[0x1d] & 0x80) || (bool)(state[0x9d] & 0x80);
|
||||
key(Keyboard::Alt ) = (bool)(state[0x38] & 0x80) || (bool)(state[0xb8] & 0x80);
|
||||
key(Keyboard::Super ) = (bool)(state[0xdb] & 0x80) || (bool)(state[0xdc] & 0x80);
|
||||
|
||||
#undef key
|
||||
}
|
||||
|
||||
//=====
|
||||
@@ -191,27 +191,26 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
table[mouse<0>::x] = state.lX;
|
||||
table[mouse<0>::y] = state.lY;
|
||||
table[mouse<0>::z] = state.lZ / WHEEL_DELTA;
|
||||
for(unsigned n = 0; n < mouse<>::buttons; n++) {
|
||||
table[mouse<0>::button + n] = (bool)state.rgbButtons[n];
|
||||
table[mouse(0).axis(0)] = state.lX;
|
||||
table[mouse(0).axis(1)] = state.lY;
|
||||
table[mouse(0).axis(2)] = state.lZ / WHEEL_DELTA;
|
||||
for(unsigned n = 0; n < Mouse::Buttons; n++) {
|
||||
table[mouse(0).button(n)] = (bool)state.rgbButtons[n];
|
||||
}
|
||||
|
||||
//on Windows, 0 = left, 1 = right, 2 = middle
|
||||
//swap middle and right buttons for consistency with Linux
|
||||
int16_t temp = table[mouse<0>::button + 1];
|
||||
table[mouse<0>::button + 1] = table[mouse<0>::button + 2];
|
||||
table[mouse<0>::button + 2] = temp;
|
||||
int16_t temp = table[mouse(0).button(1)];
|
||||
table[mouse(0).button(1)] = table[mouse(0).button(2)];
|
||||
table[mouse(0).button(2)] = temp;
|
||||
}
|
||||
|
||||
//=========
|
||||
//Joypad(s)
|
||||
//=========
|
||||
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
if(!device.gamepad[i]) continue;
|
||||
unsigned index = joypad<>::index(i, joypad<>::none);
|
||||
|
||||
if(FAILED(device.gamepad[i]->Poll())) {
|
||||
device.gamepad[i]->Acquire();
|
||||
@@ -222,30 +221,30 @@ public:
|
||||
device.gamepad[i]->GetDeviceState(sizeof(DIJOYSTATE2), &state);
|
||||
|
||||
//POV hats
|
||||
for(unsigned n = 0; n < min((unsigned)joypad<>::hats, 4); n++) {
|
||||
for(unsigned n = 0; n < min((unsigned)Joypad::Hats, 4); n++) {
|
||||
//POV value is in clockwise-hundredth degree units.
|
||||
unsigned pov = state.rgdwPOV[n];
|
||||
//some drivers report a centered POV hat as -1U, others as 65535U.
|
||||
//>= 36000 will match both, as well as invalid ranges.
|
||||
if(pov < 36000) {
|
||||
if(pov >= 31500 || pov <= 4500) table[index + joypad<>::hat + n] |= joypad<>::hat_up;
|
||||
if(pov >= 4500 && pov <= 13500) table[index + joypad<>::hat + n] |= joypad<>::hat_right;
|
||||
if(pov >= 13500 && pov <= 22500) table[index + joypad<>::hat + n] |= joypad<>::hat_down;
|
||||
if(pov >= 22500 && pov <= 31500) table[index + joypad<>::hat + n] |= joypad<>::hat_left;
|
||||
if(pov >= 31500 || pov <= 4500) table[joypad(i).hat(n)] |= Joypad::HatUp;
|
||||
if(pov >= 4500 && pov <= 13500) table[joypad(i).hat(n)] |= Joypad::HatRight;
|
||||
if(pov >= 13500 && pov <= 22500) table[joypad(i).hat(n)] |= Joypad::HatDown;
|
||||
if(pov >= 22500 && pov <= 31500) table[joypad(i).hat(n)] |= Joypad::HatLeft;
|
||||
}
|
||||
}
|
||||
|
||||
//axes
|
||||
table[index + joypad<>::axis + 0] = state.lX;
|
||||
table[index + joypad<>::axis + 1] = state.lY;
|
||||
table[index + joypad<>::axis + 2] = state.lZ;
|
||||
table[index + joypad<>::axis + 3] = state.lRx;
|
||||
table[index + joypad<>::axis + 4] = state.lRy;
|
||||
table[index + joypad<>::axis + 5] = state.lRz;
|
||||
table[joypad(i).axis(0)] = state.lX;
|
||||
table[joypad(i).axis(1)] = state.lY;
|
||||
table[joypad(i).axis(2)] = state.lZ;
|
||||
table[joypad(i).axis(3)] = state.lRx;
|
||||
table[joypad(i).axis(4)] = state.lRy;
|
||||
table[joypad(i).axis(5)] = state.lRz;
|
||||
|
||||
//buttons
|
||||
for(unsigned n = 0; n < min((unsigned)joypad<>::buttons, 128); n++) {
|
||||
table[index + joypad<>::button + n] = (bool)state.rgbButtons[n];
|
||||
for(unsigned n = 0; n < min((unsigned)Joypad::Buttons, 128); n++) {
|
||||
table[joypad(i).button(n)] = (bool)state.rgbButtons[n];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,8 +253,8 @@ public:
|
||||
|
||||
bool init_joypad(const DIDEVICEINSTANCE *instance) {
|
||||
unsigned n;
|
||||
for(n = 0; n < joypad<>::count; n++) { if(!device.gamepad[n]) break; }
|
||||
if(n >= joypad<>::count) return DIENUM_STOP;
|
||||
for(n = 0; n < Joypad::Count; n++) { if(!device.gamepad[n]) break; }
|
||||
if(n >= Joypad::Count) return DIENUM_STOP;
|
||||
|
||||
if(FAILED(device.context->CreateDevice(instance->guidInstance, &device.gamepad[n], 0))) {
|
||||
return DIENUM_CONTINUE; //continue and try next gamepad
|
||||
@@ -270,7 +269,7 @@ public:
|
||||
|
||||
bool init_axis(const DIDEVICEOBJECTINSTANCE *instance) {
|
||||
signed n;
|
||||
for(n = joypad<>::count - 1; n >= 0; n--) { if(device.gamepad[n]) break; }
|
||||
for(n = Joypad::Count - 1; n >= 0; n--) { if(device.gamepad[n]) break; }
|
||||
if(n < 0) return DIENUM_STOP;
|
||||
|
||||
DIPROPRANGE range;
|
||||
@@ -289,7 +288,7 @@ public:
|
||||
device.context = 0;
|
||||
device.keyboard = 0;
|
||||
device.mouse = 0;
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) device.gamepad[i] = 0;
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) device.gamepad[i] = 0;
|
||||
device.mouseacquired = false;
|
||||
|
||||
DirectInput8Create(GetModuleHandle(0), 0x0800, IID_IDirectInput8, (void**)&device.context, 0);
|
||||
@@ -322,7 +321,7 @@ public:
|
||||
device.mouse = 0;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
if(device.gamepad[i]) {
|
||||
device.gamepad[i]->Unacquire();
|
||||
device.gamepad[i]->Release();
|
||||
@@ -366,7 +365,7 @@ public:
|
||||
device.context = 0;
|
||||
device.keyboard = 0;
|
||||
device.mouse = 0;
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) device.gamepad[i] = 0;
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) device.gamepad[i] = 0;
|
||||
device.mouseacquired = false;
|
||||
|
||||
settings.handle = 0;
|
||||
|
@@ -39,139 +39,151 @@ public:
|
||||
};
|
||||
|
||||
struct Keyboard : Device {
|
||||
bool state[keyboard<>::length];
|
||||
bool state[nall::Keyboard::Size];
|
||||
|
||||
void update(RAWINPUT *input) {
|
||||
unsigned code = input->data.keyboard.MakeCode;
|
||||
unsigned flags = input->data.keyboard.Flags;
|
||||
|
||||
#define map(id, flag, name) if(code == id) state[name] = (bool)(flags == flag);
|
||||
map(0x0001, 0, keyboard<>::escape)
|
||||
map(0x003b, 0, keyboard<>::f1)
|
||||
map(0x003c, 0, keyboard<>::f2)
|
||||
map(0x003d, 0, keyboard<>::f3)
|
||||
map(0x003e, 0, keyboard<>::f4)
|
||||
map(0x003f, 0, keyboard<>::f5)
|
||||
map(0x0040, 0, keyboard<>::f6)
|
||||
map(0x0041, 0, keyboard<>::f7)
|
||||
map(0x0042, 0, keyboard<>::f8)
|
||||
map(0x0043, 0, keyboard<>::f9)
|
||||
map(0x0044, 0, keyboard<>::f10)
|
||||
map(0x0057, 0, keyboard<>::f11)
|
||||
map(0x0058, 0, keyboard<>::f12)
|
||||
map(0x0001, 0, nall::Keyboard::Escape)
|
||||
map(0x003b, 0, nall::Keyboard::F1)
|
||||
map(0x003c, 0, nall::Keyboard::F2)
|
||||
map(0x003d, 0, nall::Keyboard::F3)
|
||||
map(0x003e, 0, nall::Keyboard::F4)
|
||||
map(0x003f, 0, nall::Keyboard::F5)
|
||||
map(0x0040, 0, nall::Keyboard::F6)
|
||||
map(0x0041, 0, nall::Keyboard::F7)
|
||||
map(0x0042, 0, nall::Keyboard::F8)
|
||||
map(0x0043, 0, nall::Keyboard::F9)
|
||||
map(0x0044, 0, nall::Keyboard::F10)
|
||||
map(0x0057, 0, nall::Keyboard::F11)
|
||||
map(0x0058, 0, nall::Keyboard::F12)
|
||||
|
||||
map(0x0037, 2, keyboard<>::print_screen)
|
||||
map(0x0046, 0, keyboard<>::scroll_lock)
|
||||
map(0x001d, 4, keyboard<>::pause)
|
||||
map(0x0029, 0, keyboard<>::tilde)
|
||||
map(0x0037, 2, nall::Keyboard::PrintScreen)
|
||||
map(0x0046, 0, nall::Keyboard::ScrollLock)
|
||||
map(0x001d, 4, nall::Keyboard::Pause)
|
||||
map(0x0029, 0, nall::Keyboard::Tilde)
|
||||
|
||||
map(0x0002, 0, keyboard<>::num_1)
|
||||
map(0x0003, 0, keyboard<>::num_2)
|
||||
map(0x0004, 0, keyboard<>::num_3)
|
||||
map(0x0005, 0, keyboard<>::num_4)
|
||||
map(0x0006, 0, keyboard<>::num_5)
|
||||
map(0x0007, 0, keyboard<>::num_6)
|
||||
map(0x0008, 0, keyboard<>::num_7)
|
||||
map(0x0009, 0, keyboard<>::num_8)
|
||||
map(0x000a, 0, keyboard<>::num_9)
|
||||
map(0x000b, 0, keyboard<>::num_0)
|
||||
map(0x0002, 0, nall::Keyboard::Num1)
|
||||
map(0x0003, 0, nall::Keyboard::Num2)
|
||||
map(0x0004, 0, nall::Keyboard::Num3)
|
||||
map(0x0005, 0, nall::Keyboard::Num4)
|
||||
map(0x0006, 0, nall::Keyboard::Num5)
|
||||
map(0x0007, 0, nall::Keyboard::Num6)
|
||||
map(0x0008, 0, nall::Keyboard::Num7)
|
||||
map(0x0009, 0, nall::Keyboard::Num8)
|
||||
map(0x000a, 0, nall::Keyboard::Num9)
|
||||
map(0x000b, 0, nall::Keyboard::Num0)
|
||||
|
||||
map(0x000c, 0, keyboard<>::dash)
|
||||
map(0x000d, 0, keyboard<>::equal)
|
||||
map(0x000e, 0, keyboard<>::backspace)
|
||||
map(0x000c, 0, nall::Keyboard::Dash)
|
||||
map(0x000d, 0, nall::Keyboard::Equal)
|
||||
map(0x000e, 0, nall::Keyboard::Backspace)
|
||||
|
||||
map(0x0052, 2, keyboard<>::insert)
|
||||
map(0x0053, 2, keyboard<>::delete_)
|
||||
map(0x0047, 2, keyboard<>::home)
|
||||
map(0x004f, 2, keyboard<>::end)
|
||||
map(0x0049, 2, keyboard<>::page_up)
|
||||
map(0x0051, 2, keyboard<>::page_down)
|
||||
map(0x0052, 2, nall::Keyboard::Insert)
|
||||
map(0x0053, 2, nall::Keyboard::Delete)
|
||||
map(0x0047, 2, nall::Keyboard::Home)
|
||||
map(0x004f, 2, nall::Keyboard::End)
|
||||
map(0x0049, 2, nall::Keyboard::PageUp)
|
||||
map(0x0051, 2, nall::Keyboard::PageDown)
|
||||
|
||||
map(0x001e, 0, keyboard<>::a)
|
||||
map(0x0030, 0, keyboard<>::b)
|
||||
map(0x002e, 0, keyboard<>::c)
|
||||
map(0x0020, 0, keyboard<>::d)
|
||||
map(0x0012, 0, keyboard<>::e)
|
||||
map(0x0021, 0, keyboard<>::f)
|
||||
map(0x0022, 0, keyboard<>::g)
|
||||
map(0x0023, 0, keyboard<>::h)
|
||||
map(0x0017, 0, keyboard<>::i)
|
||||
map(0x0024, 0, keyboard<>::j)
|
||||
map(0x0025, 0, keyboard<>::k)
|
||||
map(0x0026, 0, keyboard<>::l)
|
||||
map(0x0032, 0, keyboard<>::m)
|
||||
map(0x0031, 0, keyboard<>::n)
|
||||
map(0x0018, 0, keyboard<>::o)
|
||||
map(0x0019, 0, keyboard<>::p)
|
||||
map(0x0010, 0, keyboard<>::q)
|
||||
map(0x0013, 0, keyboard<>::r)
|
||||
map(0x001f, 0, keyboard<>::s)
|
||||
map(0x0014, 0, keyboard<>::t)
|
||||
map(0x0016, 0, keyboard<>::u)
|
||||
map(0x002f, 0, keyboard<>::v)
|
||||
map(0x0011, 0, keyboard<>::w)
|
||||
map(0x002d, 0, keyboard<>::x)
|
||||
map(0x0015, 0, keyboard<>::y)
|
||||
map(0x002c, 0, keyboard<>::z)
|
||||
map(0x001e, 0, nall::Keyboard::A)
|
||||
map(0x0030, 0, nall::Keyboard::B)
|
||||
map(0x002e, 0, nall::Keyboard::C)
|
||||
map(0x0020, 0, nall::Keyboard::D)
|
||||
map(0x0012, 0, nall::Keyboard::E)
|
||||
map(0x0021, 0, nall::Keyboard::F)
|
||||
map(0x0022, 0, nall::Keyboard::G)
|
||||
map(0x0023, 0, nall::Keyboard::H)
|
||||
map(0x0017, 0, nall::Keyboard::I)
|
||||
map(0x0024, 0, nall::Keyboard::J)
|
||||
map(0x0025, 0, nall::Keyboard::K)
|
||||
map(0x0026, 0, nall::Keyboard::L)
|
||||
map(0x0032, 0, nall::Keyboard::M)
|
||||
map(0x0031, 0, nall::Keyboard::N)
|
||||
map(0x0018, 0, nall::Keyboard::O)
|
||||
map(0x0019, 0, nall::Keyboard::P)
|
||||
map(0x0010, 0, nall::Keyboard::Q)
|
||||
map(0x0013, 0, nall::Keyboard::R)
|
||||
map(0x001f, 0, nall::Keyboard::S)
|
||||
map(0x0014, 0, nall::Keyboard::T)
|
||||
map(0x0016, 0, nall::Keyboard::U)
|
||||
map(0x002f, 0, nall::Keyboard::V)
|
||||
map(0x0011, 0, nall::Keyboard::W)
|
||||
map(0x002d, 0, nall::Keyboard::X)
|
||||
map(0x0015, 0, nall::Keyboard::Y)
|
||||
map(0x002c, 0, nall::Keyboard::Z)
|
||||
|
||||
map(0x001a, 0, keyboard<>::lbracket)
|
||||
map(0x001b, 0, keyboard<>::rbracket)
|
||||
map(0x002b, 0, keyboard<>::backslash)
|
||||
map(0x0027, 0, keyboard<>::semicolon)
|
||||
map(0x0028, 0, keyboard<>::apostrophe)
|
||||
map(0x0033, 0, keyboard<>::comma)
|
||||
map(0x0034, 0, keyboard<>::period)
|
||||
map(0x0035, 0, keyboard<>::slash)
|
||||
map(0x001a, 0, nall::Keyboard::LeftBracket)
|
||||
map(0x001b, 0, nall::Keyboard::RightBracket)
|
||||
map(0x002b, 0, nall::Keyboard::Backslash)
|
||||
map(0x0027, 0, nall::Keyboard::Semicolon)
|
||||
map(0x0028, 0, nall::Keyboard::Apostrophe)
|
||||
map(0x0033, 0, nall::Keyboard::Comma)
|
||||
map(0x0034, 0, nall::Keyboard::Period)
|
||||
map(0x0035, 0, nall::Keyboard::Slash)
|
||||
|
||||
map(0x004f, 0, keyboard<>::pad_1)
|
||||
map(0x0050, 0, keyboard<>::pad_2)
|
||||
map(0x0051, 0, keyboard<>::pad_3)
|
||||
map(0x004b, 0, keyboard<>::pad_4)
|
||||
map(0x004c, 0, keyboard<>::pad_5)
|
||||
map(0x004d, 0, keyboard<>::pad_6)
|
||||
map(0x0047, 0, keyboard<>::pad_7)
|
||||
map(0x0048, 0, keyboard<>::pad_8)
|
||||
map(0x0049, 0, keyboard<>::pad_9)
|
||||
map(0x0052, 0, keyboard<>::pad_0)
|
||||
map(0x004f, 0, nall::Keyboard::Keypad1)
|
||||
map(0x0050, 0, nall::Keyboard::Keypad2)
|
||||
map(0x0051, 0, nall::Keyboard::Keypad3)
|
||||
map(0x004b, 0, nall::Keyboard::Keypad4)
|
||||
map(0x004c, 0, nall::Keyboard::Keypad5)
|
||||
map(0x004d, 0, nall::Keyboard::Keypad6)
|
||||
map(0x0047, 0, nall::Keyboard::Keypad7)
|
||||
map(0x0048, 0, nall::Keyboard::Keypad8)
|
||||
map(0x0049, 0, nall::Keyboard::Keypad9)
|
||||
map(0x0052, 0, nall::Keyboard::Keypad0)
|
||||
|
||||
map(0x0053, 0, keyboard<>::point)
|
||||
map(0x001c, 2, keyboard<>::enter)
|
||||
map(0x004e, 0, keyboard<>::add)
|
||||
map(0x004a, 0, keyboard<>::subtract)
|
||||
map(0x0037, 0, keyboard<>::multiply)
|
||||
map(0x0035, 2, keyboard<>::divide)
|
||||
map(0x0053, 0, nall::Keyboard::Point)
|
||||
map(0x001c, 2, nall::Keyboard::Enter)
|
||||
map(0x004e, 0, nall::Keyboard::Add)
|
||||
map(0x004a, 0, nall::Keyboard::Subtract)
|
||||
map(0x0037, 0, nall::Keyboard::Multiply)
|
||||
map(0x0035, 2, nall::Keyboard::Divide)
|
||||
|
||||
map(0x0045, 0, keyboard<>::num_lock)
|
||||
map(0x003a, 0, keyboard<>::caps_lock)
|
||||
map(0x0045, 0, nall::Keyboard::NumLock)
|
||||
map(0x003a, 0, nall::Keyboard::CapsLock)
|
||||
|
||||
//pause signals 0x1d:4 + 0x45:0, whereas num_lock signals only 0x45:0.
|
||||
//this makes it impractical to detect both pause+num_lock independently.
|
||||
//workaround: always detect pause; detect num_lock only when pause is released.
|
||||
if(state[keyboard<>::pause]) state[keyboard<>::num_lock] = false;
|
||||
//Pause signals 0x1d:4 + 0x45:0, whereas NumLock signals only 0x45:0.
|
||||
//this makes it impractical to detect both Pause+NumLock independently.
|
||||
//workaround: always detect Pause; detect NumLock only when Pause is released.
|
||||
if(state[nall::Keyboard::Pause]) state[nall::Keyboard::NumLock] = false;
|
||||
|
||||
map(0x0048, 2, keyboard<>::up)
|
||||
map(0x0050, 2, keyboard<>::down)
|
||||
map(0x004b, 2, keyboard<>::left)
|
||||
map(0x004d, 2, keyboard<>::right)
|
||||
map(0x0048, 2, nall::Keyboard::Up)
|
||||
map(0x0050, 2, nall::Keyboard::Down)
|
||||
map(0x004b, 2, nall::Keyboard::Left)
|
||||
map(0x004d, 2, nall::Keyboard::Right)
|
||||
|
||||
map(0x000f, 0, keyboard<>::tab)
|
||||
map(0x001c, 0, keyboard<>::return_)
|
||||
map(0x0039, 0, keyboard<>::spacebar)
|
||||
map(0x000f, 0, nall::Keyboard::Tab)
|
||||
map(0x001c, 0, nall::Keyboard::Return)
|
||||
map(0x0039, 0, nall::Keyboard::Spacebar)
|
||||
map(0x005d, 2, nall::Keyboard::Menu)
|
||||
|
||||
map(0x001d, 0, keyboard<>::lctrl)
|
||||
map(0x001d, 2, keyboard<>::rctrl)
|
||||
map(0x0038, 0, keyboard<>::lalt)
|
||||
map(0x0038, 2, keyboard<>::ralt)
|
||||
map(0x002a, 0, keyboard<>::lshift)
|
||||
map(0x0036, 0, keyboard<>::rshift)
|
||||
map(0x005b, 2, keyboard<>::lsuper)
|
||||
map(0x005c, 2, keyboard<>::rsuper)
|
||||
map(0x005d, 2, keyboard<>::menu)
|
||||
//merge left and right modifiers to one ID
|
||||
if(code == 0x002a && flags == 0) state[nall::Keyboard::Shift] = 1; //left shift
|
||||
if(code == 0x002a && flags == 1) state[nall::Keyboard::Shift] = 0;
|
||||
if(code == 0x0036 && flags == 0) state[nall::Keyboard::Shift] = 1; //right shift
|
||||
if(code == 0x0036 && flags == 1) state[nall::Keyboard::Shift] = 0;
|
||||
|
||||
if(code == 0x001d && flags == 0) state[nall::Keyboard::Control] = 1; //left control
|
||||
if(code == 0x001d && flags == 1) state[nall::Keyboard::Control] = 0;
|
||||
if(code == 0x001d && flags == 2) state[nall::Keyboard::Control] = 1; //right control
|
||||
if(code == 0x001d && flags == 3) state[nall::Keyboard::Control] = 0;
|
||||
|
||||
if(code == 0x0038 && flags == 0) state[nall::Keyboard::Alt] = 1; //left alt
|
||||
if(code == 0x0038 && flags == 1) state[nall::Keyboard::Alt] = 0;
|
||||
if(code == 0x0038 && flags == 2) state[nall::Keyboard::Alt] = 1; //right alt
|
||||
if(code == 0x0038 && flags == 3) state[nall::Keyboard::Alt] = 0;
|
||||
|
||||
if(code == 0x005b && flags == 2) state[nall::Keyboard::Super] = 1; //left super
|
||||
if(code == 0x005b && flags == 3) state[nall::Keyboard::Super] = 0;
|
||||
if(code == 0x005c && flags == 2) state[nall::Keyboard::Super] = 1; //right super
|
||||
if(code == 0x005c && flags == 3) state[nall::Keyboard::Super] = 0;
|
||||
#undef map
|
||||
}
|
||||
|
||||
Keyboard() {
|
||||
for(unsigned i = 0; i < keyboard<>::length; i++) state[i] = false;
|
||||
for(unsigned i = 0; i < nall::Keyboard::Size; i++) state[i] = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -390,11 +402,11 @@ public:
|
||||
bool button[10];
|
||||
|
||||
void poll(XINPUT_STATE &state) {
|
||||
hat = joypad<>::hat_center;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ) hat |= joypad<>::hat_up;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) hat |= joypad<>::hat_right;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) hat |= joypad<>::hat_down;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) hat |= joypad<>::hat_left;
|
||||
hat = Joypad::HatCenter;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ) hat |= Joypad::HatUp;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) hat |= Joypad::HatRight;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) hat |= Joypad::HatDown;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) hat |= Joypad::HatLeft;
|
||||
|
||||
axis[0] = (int16_t)state.Gamepad.sThumbLX;
|
||||
axis[1] = (int16_t)state.Gamepad.sThumbLY;
|
||||
@@ -426,7 +438,7 @@ public:
|
||||
}
|
||||
|
||||
Gamepad() {
|
||||
hat = joypad<>::hat_center;
|
||||
hat = Joypad::HatCenter;
|
||||
for(unsigned n = 0; n < 6; n++) axis[n] = 0;
|
||||
for(unsigned n = 0; n < 10; n++) button[n] = false;
|
||||
}
|
||||
@@ -490,7 +502,7 @@ public:
|
||||
void poll(DIJOYSTATE2 &state) {
|
||||
//POV hats
|
||||
for(unsigned n = 0; n < 4; n++) {
|
||||
hat[n] = joypad<>::hat_center;
|
||||
hat[n] = Joypad::HatCenter;
|
||||
|
||||
//POV value is in clockwise-hundredth degree units
|
||||
unsigned pov = state.rgdwPOV[n];
|
||||
@@ -499,10 +511,10 @@ public:
|
||||
//>= 36000 will match both, as well as invalid ranges.
|
||||
if(pov >= 36000) continue;
|
||||
|
||||
if(pov >= 31500 || pov <= 4500) hat[n] |= joypad<>::hat_up;
|
||||
if(pov >= 4500 && pov <= 13500) hat[n] |= joypad<>::hat_right;
|
||||
if(pov >= 13500 && pov <= 22500) hat[n] |= joypad<>::hat_down;
|
||||
if(pov >= 22500 && pov <= 31500) hat[n] |= joypad<>::hat_left;
|
||||
if(pov >= 31500 || pov <= 4500) hat[n] |= Joypad::HatUp;
|
||||
if(pov >= 4500 && pov <= 13500) hat[n] |= Joypad::HatRight;
|
||||
if(pov >= 13500 && pov <= 22500) hat[n] |= Joypad::HatDown;
|
||||
if(pov >= 22500 && pov <= 31500) hat[n] |= Joypad::HatLeft;
|
||||
}
|
||||
|
||||
//axes
|
||||
@@ -521,7 +533,7 @@ public:
|
||||
|
||||
Gamepad() {
|
||||
handle = 0;
|
||||
for(unsigned n = 0; n < 4; n++) hat[n] = joypad<>::hat_center;
|
||||
for(unsigned n = 0; n < 4; n++) hat[n] = Joypad::HatCenter;
|
||||
for(unsigned n = 0; n < 6; n++) axis[n] = 0;
|
||||
for(unsigned n = 0; n < 128; n++) button[n] = false;
|
||||
}
|
||||
@@ -672,33 +684,29 @@ public:
|
||||
}
|
||||
|
||||
bool poll(int16_t *table) {
|
||||
memset(table, 0, nall::input_limit * sizeof(int16_t));
|
||||
memset(table, 0, Scancode::Limit * sizeof(int16_t));
|
||||
|
||||
WaitForSingleObject(rawinput.mutex, INFINITE);
|
||||
|
||||
//=========
|
||||
//Keyboards
|
||||
//=========
|
||||
for(unsigned i = 0; i < min(rawinput.lkeyboard.size(), (unsigned)keyboard<>::count); i++) {
|
||||
unsigned index = keyboard<>::index(i, keyboard<>::none);
|
||||
|
||||
for(unsigned n = 0; n < keyboard<>::length; n++) {
|
||||
table[index + n] = rawinput.lkeyboard[i].state[n];
|
||||
for(unsigned i = 0; i < min(rawinput.lkeyboard.size(), (unsigned)Keyboard::Count); i++) {
|
||||
for(unsigned n = 0; n < nall::Keyboard::Size; n++) {
|
||||
table[keyboard(i).key(n)] = rawinput.lkeyboard[i].state[n];
|
||||
}
|
||||
}
|
||||
|
||||
//====
|
||||
//Mice
|
||||
//====
|
||||
for(unsigned i = 0; i < min(rawinput.lmouse.size(), (unsigned)mouse<>::count); i++) {
|
||||
unsigned index = mouse<>::index(i, mouse<>::none);
|
||||
for(unsigned i = 0; i < min(rawinput.lmouse.size(), (unsigned)Mouse::Count); i++) {
|
||||
table[mouse(i).axis(0)] = rawinput.lmouse[i].xDistance;
|
||||
table[mouse(i).axis(1)] = rawinput.lmouse[i].yDistance;
|
||||
table[mouse(i).axis(2)] = rawinput.lmouse[i].zDistance;
|
||||
|
||||
table[index + mouse<>::x] = rawinput.lmouse[i].xDistance;
|
||||
table[index + mouse<>::y] = rawinput.lmouse[i].yDistance;
|
||||
table[index + mouse<>::z] = rawinput.lmouse[i].zDistance;
|
||||
|
||||
for(unsigned n = 0; n < min(5U, (unsigned)mouse<>::buttons); n++) {
|
||||
table[index + mouse<>::button + n] = (bool)(rawinput.lmouse[i].buttonState & (1 << n));
|
||||
for(unsigned n = 0; n < min(5U, (unsigned)Mouse::Buttons); n++) {
|
||||
table[mouse(i).button(n)] = (bool)(rawinput.lmouse[i].buttonState & (1 << n));
|
||||
}
|
||||
|
||||
rawinput.lmouse[i].sync();
|
||||
@@ -713,17 +721,16 @@ public:
|
||||
//==================
|
||||
xinput.poll();
|
||||
for(unsigned i = 0; i < xinput.lgamepad.size(); i++) {
|
||||
if(joy >= joypad<>::count) break;
|
||||
unsigned index = joypad<>::index(joy++, joypad<>::none);
|
||||
if(joy >= Joypad::Count) break;
|
||||
|
||||
table[index + joypad<>::hat + 0] = xinput.lgamepad[i].hat;
|
||||
table[joypad(i).hat(0)] = xinput.lgamepad[i].hat;
|
||||
|
||||
for(unsigned axis = 0; axis < min(6U, (unsigned)joypad<>::axes); axis++) {
|
||||
table[index + joypad<>::axis + axis] = xinput.lgamepad[i].axis[axis];
|
||||
for(unsigned axis = 0; axis < min(6U, (unsigned)Joypad::Axes); axis++) {
|
||||
table[joypad(i).axis(axis)] = xinput.lgamepad[i].axis[axis];
|
||||
}
|
||||
|
||||
for(unsigned button = 0; button < min(10U, (unsigned)joypad<>::buttons); button++) {
|
||||
table[index + joypad<>::button + button] = xinput.lgamepad[i].button[button];
|
||||
for(unsigned button = 0; button < min(10U, (unsigned)Joypad::Buttons); button++) {
|
||||
table[joypad(i).button(button)] = xinput.lgamepad[i].button[button];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -732,19 +739,18 @@ public:
|
||||
//=======================
|
||||
dinput.poll();
|
||||
for(unsigned i = 0; i < dinput.lgamepad.size(); i++) {
|
||||
if(joy >= joypad<>::count) break;
|
||||
unsigned index = joypad<>::index(joy++, joypad<>::none);
|
||||
if(joy >= Joypad::Count) break;
|
||||
|
||||
for(unsigned hat = 0; hat < min(4U, (unsigned)joypad<>::hats); hat++) {
|
||||
table[index + joypad<>::hat + hat] = dinput.lgamepad[i].hat[hat];
|
||||
for(unsigned hat = 0; hat < min(4U, (unsigned)Joypad::Hats); hat++) {
|
||||
table[joypad(i).hat(hat)] = dinput.lgamepad[i].hat[hat];
|
||||
}
|
||||
|
||||
for(unsigned axis = 0; axis < min(6U, (unsigned)joypad<>::axes); axis++) {
|
||||
table[index + joypad<>::axis + axis] = dinput.lgamepad[i].axis[axis];
|
||||
for(unsigned axis = 0; axis < min(6U, (unsigned)Joypad::Axes); axis++) {
|
||||
table[joypad(i).axis(axis)] = dinput.lgamepad[i].axis[axis];
|
||||
}
|
||||
|
||||
for(unsigned button = 0; button < min(128U, (unsigned)joypad<>::buttons); button++) {
|
||||
table[index + joypad<>::button + button] = dinput.lgamepad[i].button[button];
|
||||
for(unsigned button = 0; button < min(128U, (unsigned)Joypad::Buttons); button++) {
|
||||
table[joypad(i).button(button)] = dinput.lgamepad[i].button[button];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -18,7 +18,7 @@ struct pInputSDL {
|
||||
Display *display;
|
||||
Window rootwindow;
|
||||
Cursor InvisibleCursor;
|
||||
SDL_Joystick *gamepad[joypad<>::count];
|
||||
SDL_Joystick *gamepad[Joypad::Count];
|
||||
|
||||
unsigned screenwidth, screenheight;
|
||||
unsigned relativex, relativey;
|
||||
@@ -91,20 +91,13 @@ struct pInputSDL {
|
||||
}
|
||||
|
||||
bool poll(int16_t *table) {
|
||||
memset(table, 0, nall::input_limit * sizeof(int16_t));
|
||||
memset(table, 0, Scancode::Limit * sizeof(int16_t));
|
||||
|
||||
//========
|
||||
//Keyboard
|
||||
//========
|
||||
|
||||
char state[32];
|
||||
XQueryKeymap(device.display, state);
|
||||
|
||||
for(unsigned i = 0; i < keyboard<>::length; i++) {
|
||||
uint8_t code = keycode[i];
|
||||
if(code == 0) continue; //unmapped
|
||||
table[i] = (bool)(state[code >> 3] & (1 << (code & 7)));
|
||||
}
|
||||
x_poll(table);
|
||||
|
||||
//=====
|
||||
//Mouse
|
||||
@@ -123,56 +116,55 @@ struct pInputSDL {
|
||||
XGetWindowAttributes(device.display, settings.handle, &attributes);
|
||||
|
||||
//absolute -> relative conversion
|
||||
table[mouse<0>::x] = (int16_t)(root_x_return - device.screenwidth / 2);
|
||||
table[mouse<0>::y] = (int16_t)(root_y_return - device.screenheight / 2);
|
||||
table[mouse(0).axis(0)] = (int16_t)(root_x_return - device.screenwidth / 2);
|
||||
table[mouse(0).axis(1)] = (int16_t)(root_y_return - device.screenheight / 2);
|
||||
|
||||
if(table[mouse<0>::x] != 0 || table[mouse<0>::y] != 0) {
|
||||
if(table[mouse(0).axis(0)] != 0 || table[mouse(0).axis(1)] != 0) {
|
||||
//if mouse movement occurred, re-center mouse for next poll
|
||||
XWarpPointer(device.display, None, device.rootwindow, 0, 0, 0, 0, device.screenwidth / 2, device.screenheight / 2);
|
||||
}
|
||||
} else {
|
||||
table[mouse<0>::x] = (int16_t)(root_x_return - device.relativex);
|
||||
table[mouse<0>::y] = (int16_t)(root_y_return - device.relativey);
|
||||
table[mouse(0).axis(0)] = (int16_t)(root_x_return - device.relativex);
|
||||
table[mouse(0).axis(1)] = (int16_t)(root_y_return - device.relativey);
|
||||
|
||||
device.relativex = root_x_return;
|
||||
device.relativey = root_y_return;
|
||||
}
|
||||
|
||||
//manual device polling is limited to only five buttons ...
|
||||
table[mouse<0>::button + 0] = (bool)(mask_return & Button1Mask);
|
||||
table[mouse<0>::button + 1] = (bool)(mask_return & Button2Mask);
|
||||
table[mouse<0>::button + 2] = (bool)(mask_return & Button3Mask);
|
||||
table[mouse<0>::button + 3] = (bool)(mask_return & Button4Mask);
|
||||
table[mouse<0>::button + 4] = (bool)(mask_return & Button5Mask);
|
||||
table[mouse(0).button(0)] = (bool)(mask_return & Button1Mask);
|
||||
table[mouse(0).button(1)] = (bool)(mask_return & Button2Mask);
|
||||
table[mouse(0).button(2)] = (bool)(mask_return & Button3Mask);
|
||||
table[mouse(0).button(3)] = (bool)(mask_return & Button4Mask);
|
||||
table[mouse(0).button(4)] = (bool)(mask_return & Button5Mask);
|
||||
|
||||
//=========
|
||||
//Joypad(s)
|
||||
//=========
|
||||
|
||||
SDL_JoystickUpdate();
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
if(!device.gamepad[i]) continue;
|
||||
unsigned index = joypad<>::index(i, joypad<>::none);
|
||||
|
||||
//POV hats
|
||||
unsigned hats = min((unsigned)joypad<>::hats, SDL_JoystickNumHats(device.gamepad[i]));
|
||||
unsigned hats = min((unsigned)Joypad::Hats, SDL_JoystickNumHats(device.gamepad[i]));
|
||||
for(unsigned hat = 0; hat < hats; hat++) {
|
||||
uint8_t state = SDL_JoystickGetHat(device.gamepad[i], hat);
|
||||
if(state & SDL_HAT_UP ) table[index + joypad<>::hat + hat] |= joypad<>::hat_up;
|
||||
if(state & SDL_HAT_RIGHT) table[index + joypad<>::hat + hat] |= joypad<>::hat_right;
|
||||
if(state & SDL_HAT_DOWN ) table[index + joypad<>::hat + hat] |= joypad<>::hat_down;
|
||||
if(state & SDL_HAT_LEFT ) table[index + joypad<>::hat + hat] |= joypad<>::hat_left;
|
||||
if(state & SDL_HAT_UP ) table[joypad(i).hat(hat)] |= Joypad::HatUp;
|
||||
if(state & SDL_HAT_RIGHT) table[joypad(i).hat(hat)] |= Joypad::HatRight;
|
||||
if(state & SDL_HAT_DOWN ) table[joypad(i).hat(hat)] |= Joypad::HatDown;
|
||||
if(state & SDL_HAT_LEFT ) table[joypad(i).hat(hat)] |= Joypad::HatLeft;
|
||||
}
|
||||
|
||||
//axes
|
||||
unsigned axes = min((unsigned)joypad<>::axes, SDL_JoystickNumAxes(device.gamepad[i]));
|
||||
unsigned axes = min((unsigned)Joypad::Axes, SDL_JoystickNumAxes(device.gamepad[i]));
|
||||
for(unsigned axis = 0; axis < axes; axis++) {
|
||||
table[index + joypad<>::axis + axis] = (int16_t)SDL_JoystickGetAxis(device.gamepad[i], axis);
|
||||
table[joypad(i).axis(axis)] = (int16_t)SDL_JoystickGetAxis(device.gamepad[i], axis);
|
||||
}
|
||||
|
||||
//buttons
|
||||
for(unsigned button = 0; button < joypad<>::buttons; button++) {
|
||||
table[index + joypad<>::button + button] = (bool)SDL_JoystickGetButton(device.gamepad[i], button);
|
||||
for(unsigned button = 0; button < Joypad::Buttons; button++) {
|
||||
table[joypad(i).button(button)] = (bool)SDL_JoystickGetButton(device.gamepad[i], button);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +172,7 @@ struct pInputSDL {
|
||||
}
|
||||
|
||||
bool init() {
|
||||
init_keycodes();
|
||||
x_init();
|
||||
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
||||
SDL_JoystickEventState(SDL_IGNORE);
|
||||
|
||||
@@ -208,7 +200,7 @@ struct pInputSDL {
|
||||
device.relativex = 0;
|
||||
device.relativey = 0;
|
||||
|
||||
unsigned joypads = min((unsigned)joypad<>::count, SDL_NumJoysticks());
|
||||
unsigned joypads = min((unsigned)Joypad::Count, SDL_NumJoysticks());
|
||||
for(unsigned i = 0; i < joypads; i++) device.gamepad[i] = SDL_JoystickOpen(i);
|
||||
|
||||
return true;
|
||||
@@ -218,7 +210,7 @@ struct pInputSDL {
|
||||
unacquire();
|
||||
XFreeCursor(device.display, device.InvisibleCursor);
|
||||
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
if(device.gamepad[i]) SDL_JoystickClose(device.gamepad[i]);
|
||||
device.gamepad[i] = 0;
|
||||
}
|
||||
@@ -228,7 +220,7 @@ struct pInputSDL {
|
||||
}
|
||||
|
||||
pInputSDL() {
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) device.gamepad[i] = 0;
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) device.gamepad[i] = 0;
|
||||
settings.handle = 0;
|
||||
}
|
||||
};
|
||||
|
@@ -29,22 +29,13 @@ public:
|
||||
bool acquired() { return false; }
|
||||
|
||||
bool poll(int16_t *table) {
|
||||
memset(table, 0, input_limit * sizeof(int16_t));
|
||||
|
||||
char state[32];
|
||||
XQueryKeymap(display, state);
|
||||
|
||||
for(unsigned i = 0; i < keyboard<>::length; i++) {
|
||||
uint8_t code = keycode[i];
|
||||
if(code == 0) continue; //unmapped
|
||||
table[i] = (bool)(state[code >> 3] & (1 << (code & 7)));
|
||||
}
|
||||
|
||||
memset(table, 0, Scancode::Limit * sizeof(int16_t));
|
||||
x_poll(table);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool init() {
|
||||
init_keycodes();
|
||||
x_init();
|
||||
display = XOpenDisplay(0);
|
||||
return true;
|
||||
}
|
||||
|
@@ -1,137 +1,263 @@
|
||||
//shared keycode lookup table + initialization routine:
|
||||
//#include inside a class interface to use
|
||||
uint8_t scancode[256];
|
||||
|
||||
//Xlib keycodes for each key can vary between platforms, so this header file
|
||||
//will lookup keycodes from static keysyms, and map them to nall/input.hpp's
|
||||
//keyboard identifiers.
|
||||
//
|
||||
//this allows input capture routine to iterate quickly over all keycodes and
|
||||
//map their states to ruby's input state table.
|
||||
enum XScancode {
|
||||
Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||
ScrollLock, Pause, Tilde,
|
||||
Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0,
|
||||
Dash, Equal, Backspace,
|
||||
Insert, Delete, Home, End, PageUp, PageDown,
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M,
|
||||
N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||
LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash,
|
||||
Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0,
|
||||
Point, Enter, Add, Subtract, Multiply, Divide,
|
||||
Up, Down, Left, Right,
|
||||
Tab, Return, Spacebar, Menu,
|
||||
LeftShift, RightShift, LeftControl, RightControl, LeftAlt, RightAlt, LeftSuper, RightSuper,
|
||||
};
|
||||
|
||||
uint8_t keycode[256];
|
||||
|
||||
void init_keycodes() {
|
||||
void x_poll(int16_t *table) {
|
||||
char state[32];
|
||||
Display *display = XOpenDisplay(0);
|
||||
memset(&keycode, 0, sizeof keycode);
|
||||
XQueryKeymap(display, state);
|
||||
XCloseDisplay(display);
|
||||
|
||||
#define assign(x, y) keycode[x] = XKeysymToKeycode(display, y)
|
||||
assign(keyboard<0>::escape, XK_Escape);
|
||||
#define key(id) table[keyboard(0)[id]]
|
||||
#define pressed(id) (bool)(state[scancode[id] >> 3] & (1 << (scancode[id] & 7)))
|
||||
|
||||
assign(keyboard<0>::f1, XK_F1);
|
||||
assign(keyboard<0>::f2, XK_F2);
|
||||
assign(keyboard<0>::f3, XK_F3);
|
||||
assign(keyboard<0>::f4, XK_F4);
|
||||
assign(keyboard<0>::f5, XK_F5);
|
||||
assign(keyboard<0>::f6, XK_F6);
|
||||
assign(keyboard<0>::f7, XK_F7);
|
||||
assign(keyboard<0>::f8, XK_F8);
|
||||
assign(keyboard<0>::f9, XK_F9);
|
||||
assign(keyboard<0>::f10, XK_F10);
|
||||
assign(keyboard<0>::f11, XK_F11);
|
||||
assign(keyboard<0>::f12, XK_F12);
|
||||
key(Keyboard::Escape) = pressed(Escape);
|
||||
|
||||
//assign(keyboard<0>::print_screen, XK_???);
|
||||
assign(keyboard<0>::scroll_lock, XK_Scroll_Lock);
|
||||
assign(keyboard<0>::pause, XK_Pause);
|
||||
key(Keyboard::F1) = pressed(F1);
|
||||
key(Keyboard::F2) = pressed(F2);
|
||||
key(Keyboard::F3) = pressed(F3);
|
||||
key(Keyboard::F4) = pressed(F4);
|
||||
key(Keyboard::F5) = pressed(F5);
|
||||
key(Keyboard::F6) = pressed(F6);
|
||||
key(Keyboard::F7) = pressed(F7);
|
||||
key(Keyboard::F8) = pressed(F8);
|
||||
key(Keyboard::F9) = pressed(F9);
|
||||
key(Keyboard::F10) = pressed(F10);
|
||||
key(Keyboard::F11) = pressed(F11);
|
||||
key(Keyboard::F12) = pressed(F12);
|
||||
|
||||
assign(keyboard<0>::tilde, XK_asciitilde);
|
||||
key(Keyboard::ScrollLock) = pressed(ScrollLock);
|
||||
key(Keyboard::Pause) = pressed(Pause);
|
||||
key(Keyboard::Tilde) = pressed(Tilde);
|
||||
|
||||
assign(keyboard<0>::num_0, XK_0);
|
||||
assign(keyboard<0>::num_1, XK_1);
|
||||
assign(keyboard<0>::num_2, XK_2);
|
||||
assign(keyboard<0>::num_3, XK_3);
|
||||
assign(keyboard<0>::num_4, XK_4);
|
||||
assign(keyboard<0>::num_5, XK_5);
|
||||
assign(keyboard<0>::num_6, XK_6);
|
||||
assign(keyboard<0>::num_7, XK_7);
|
||||
assign(keyboard<0>::num_8, XK_8);
|
||||
assign(keyboard<0>::num_9, XK_9);
|
||||
key(Keyboard::Num1) = pressed(Num1);
|
||||
key(Keyboard::Num2) = pressed(Num2);
|
||||
key(Keyboard::Num3) = pressed(Num3);
|
||||
key(Keyboard::Num4) = pressed(Num4);
|
||||
key(Keyboard::Num5) = pressed(Num5);
|
||||
key(Keyboard::Num6) = pressed(Num6);
|
||||
key(Keyboard::Num7) = pressed(Num7);
|
||||
key(Keyboard::Num8) = pressed(Num8);
|
||||
key(Keyboard::Num9) = pressed(Num9);
|
||||
key(Keyboard::Num0) = pressed(Num0);
|
||||
|
||||
assign(keyboard<0>::dash, XK_minus);
|
||||
assign(keyboard<0>::equal, XK_equal);
|
||||
assign(keyboard<0>::backspace, XK_BackSpace);
|
||||
key(Keyboard::Dash) = pressed(Dash);
|
||||
key(Keyboard::Equal) = pressed(Equal);
|
||||
key(Keyboard::Backspace) = pressed(Backspace);
|
||||
|
||||
assign(keyboard<0>::insert, XK_Insert);
|
||||
assign(keyboard<0>::delete_, XK_Delete);
|
||||
assign(keyboard<0>::home, XK_Home);
|
||||
assign(keyboard<0>::end, XK_End);
|
||||
assign(keyboard<0>::page_up, XK_Prior);
|
||||
assign(keyboard<0>::page_down, XK_Next);
|
||||
key(Keyboard::Insert) = pressed(Insert);
|
||||
key(Keyboard::Delete) = pressed(Delete);
|
||||
key(Keyboard::Home) = pressed(Home);
|
||||
key(Keyboard::End) = pressed(End);
|
||||
key(Keyboard::PageUp) = pressed(PageUp);
|
||||
key(Keyboard::PageDown) = pressed(PageDown);
|
||||
|
||||
assign(keyboard<0>::a, XK_A);
|
||||
assign(keyboard<0>::b, XK_B);
|
||||
assign(keyboard<0>::c, XK_C);
|
||||
assign(keyboard<0>::d, XK_D);
|
||||
assign(keyboard<0>::e, XK_E);
|
||||
assign(keyboard<0>::f, XK_F);
|
||||
assign(keyboard<0>::g, XK_G);
|
||||
assign(keyboard<0>::h, XK_H);
|
||||
assign(keyboard<0>::i, XK_I);
|
||||
assign(keyboard<0>::j, XK_J);
|
||||
assign(keyboard<0>::k, XK_K);
|
||||
assign(keyboard<0>::l, XK_L);
|
||||
assign(keyboard<0>::m, XK_M);
|
||||
assign(keyboard<0>::n, XK_N);
|
||||
assign(keyboard<0>::o, XK_O);
|
||||
assign(keyboard<0>::p, XK_P);
|
||||
assign(keyboard<0>::q, XK_Q);
|
||||
assign(keyboard<0>::r, XK_R);
|
||||
assign(keyboard<0>::s, XK_S);
|
||||
assign(keyboard<0>::t, XK_T);
|
||||
assign(keyboard<0>::u, XK_U);
|
||||
assign(keyboard<0>::v, XK_V);
|
||||
assign(keyboard<0>::w, XK_W);
|
||||
assign(keyboard<0>::x, XK_X);
|
||||
assign(keyboard<0>::y, XK_Y);
|
||||
assign(keyboard<0>::z, XK_Z);
|
||||
key(Keyboard::A) = pressed(A);
|
||||
key(Keyboard::B) = pressed(B);
|
||||
key(Keyboard::C) = pressed(C);
|
||||
key(Keyboard::D) = pressed(D);
|
||||
key(Keyboard::E) = pressed(E);
|
||||
key(Keyboard::F) = pressed(F);
|
||||
key(Keyboard::G) = pressed(G);
|
||||
key(Keyboard::H) = pressed(H);
|
||||
key(Keyboard::I) = pressed(I);
|
||||
key(Keyboard::J) = pressed(J);
|
||||
key(Keyboard::K) = pressed(K);
|
||||
key(Keyboard::L) = pressed(L);
|
||||
key(Keyboard::M) = pressed(M);
|
||||
key(Keyboard::N) = pressed(N);
|
||||
key(Keyboard::O) = pressed(O);
|
||||
key(Keyboard::P) = pressed(P);
|
||||
key(Keyboard::Q) = pressed(Q);
|
||||
key(Keyboard::R) = pressed(R);
|
||||
key(Keyboard::S) = pressed(S);
|
||||
key(Keyboard::T) = pressed(T);
|
||||
key(Keyboard::U) = pressed(U);
|
||||
key(Keyboard::V) = pressed(V);
|
||||
key(Keyboard::W) = pressed(W);
|
||||
key(Keyboard::X) = pressed(X);
|
||||
key(Keyboard::Y) = pressed(Y);
|
||||
key(Keyboard::Z) = pressed(Z);
|
||||
|
||||
assign(keyboard<0>::lbracket, XK_bracketleft);
|
||||
assign(keyboard<0>::rbracket, XK_bracketright);
|
||||
assign(keyboard<0>::backslash, XK_backslash);
|
||||
assign(keyboard<0>::semicolon, XK_semicolon);
|
||||
assign(keyboard<0>::apostrophe, XK_apostrophe);
|
||||
assign(keyboard<0>::comma, XK_comma);
|
||||
assign(keyboard<0>::period, XK_period);
|
||||
assign(keyboard<0>::slash, XK_slash);
|
||||
key(Keyboard::LeftBracket) = pressed(LeftBracket);
|
||||
key(Keyboard::RightBracket) = pressed(RightBracket);
|
||||
key(Keyboard::Backslash) = pressed(Backslash);
|
||||
key(Keyboard::Semicolon) = pressed(Semicolon);
|
||||
key(Keyboard::Apostrophe) = pressed(Apostrophe);
|
||||
key(Keyboard::Comma) = pressed(Comma);
|
||||
key(Keyboard::Period) = pressed(Period);
|
||||
key(Keyboard::Slash) = pressed(Slash);
|
||||
|
||||
assign(keyboard<0>::pad_0, XK_KP_0);
|
||||
assign(keyboard<0>::pad_1, XK_KP_1);
|
||||
assign(keyboard<0>::pad_2, XK_KP_2);
|
||||
assign(keyboard<0>::pad_3, XK_KP_3);
|
||||
assign(keyboard<0>::pad_4, XK_KP_4);
|
||||
assign(keyboard<0>::pad_5, XK_KP_5);
|
||||
assign(keyboard<0>::pad_6, XK_KP_6);
|
||||
assign(keyboard<0>::pad_7, XK_KP_7);
|
||||
assign(keyboard<0>::pad_8, XK_KP_8);
|
||||
assign(keyboard<0>::pad_9, XK_KP_9);
|
||||
key(Keyboard::Keypad1) = pressed(Keypad1);
|
||||
key(Keyboard::Keypad2) = pressed(Keypad2);
|
||||
key(Keyboard::Keypad3) = pressed(Keypad3);
|
||||
key(Keyboard::Keypad4) = pressed(Keypad4);
|
||||
key(Keyboard::Keypad5) = pressed(Keypad5);
|
||||
key(Keyboard::Keypad6) = pressed(Keypad6);
|
||||
key(Keyboard::Keypad7) = pressed(Keypad7);
|
||||
key(Keyboard::Keypad8) = pressed(Keypad8);
|
||||
key(Keyboard::Keypad9) = pressed(Keypad9);
|
||||
key(Keyboard::Keypad0) = pressed(Keypad0);
|
||||
|
||||
assign(keyboard<0>::add, XK_KP_Add);
|
||||
assign(keyboard<0>::subtract, XK_KP_Subtract);
|
||||
assign(keyboard<0>::multiply, XK_KP_Multiply);
|
||||
assign(keyboard<0>::divide, XK_KP_Divide);
|
||||
assign(keyboard<0>::enter, XK_KP_Enter);
|
||||
key(Keyboard::Point) = pressed(Point);
|
||||
key(Keyboard::Enter) = pressed(Enter);
|
||||
key(Keyboard::Add) = pressed(Add);
|
||||
key(Keyboard::Subtract) = pressed(Subtract);
|
||||
key(Keyboard::Multiply) = pressed(Multiply);
|
||||
key(Keyboard::Divide) = pressed(Divide);
|
||||
|
||||
//assign(keyboard<0>::num_lock, XK_???);
|
||||
//assign(keyboard<0>::caps_lock, XK_???);
|
||||
key(Keyboard::Up) = pressed(Up);
|
||||
key(Keyboard::Down) = pressed(Down);
|
||||
key(Keyboard::Left) = pressed(Left);
|
||||
key(Keyboard::Right) = pressed(Right);
|
||||
|
||||
assign(keyboard<0>::up, XK_Up);
|
||||
assign(keyboard<0>::down, XK_Down);
|
||||
assign(keyboard<0>::left, XK_Left);
|
||||
assign(keyboard<0>::right, XK_Right);
|
||||
key(Keyboard::Tab) = pressed(Tab);
|
||||
key(Keyboard::Return) = pressed(Return);
|
||||
key(Keyboard::Spacebar) = pressed(Spacebar);
|
||||
key(Keyboard::Menu) = pressed(Menu);
|
||||
|
||||
assign(keyboard<0>::tab, XK_Tab);
|
||||
assign(keyboard<0>::return_, XK_Return);
|
||||
assign(keyboard<0>::spacebar, XK_space);
|
||||
key(Keyboard::Shift) = pressed(LeftShift) || pressed(RightShift);
|
||||
key(Keyboard::Control) = pressed(LeftControl) || pressed(RightControl);
|
||||
key(Keyboard::Alt) = pressed(LeftAlt) || pressed(RightAlt);
|
||||
key(Keyboard::Super) = pressed(LeftSuper) || pressed(RightSuper);
|
||||
|
||||
#undef key
|
||||
#undef pressed
|
||||
}
|
||||
|
||||
void x_init() {
|
||||
Display *display = XOpenDisplay(0);
|
||||
memset(&scancode, 0, sizeof scancode);
|
||||
|
||||
#define assign(x, y) scancode[x] = XKeysymToKeycode(display, y)
|
||||
assign(Escape, XK_Escape);
|
||||
|
||||
assign(F1, XK_F1);
|
||||
assign(F2, XK_F2);
|
||||
assign(F3, XK_F3);
|
||||
assign(F4, XK_F4);
|
||||
assign(F5, XK_F5);
|
||||
assign(F6, XK_F6);
|
||||
assign(F7, XK_F7);
|
||||
assign(F8, XK_F8);
|
||||
assign(F9, XK_F9);
|
||||
assign(F10, XK_F10);
|
||||
assign(F11, XK_F11);
|
||||
assign(F12, XK_F12);
|
||||
|
||||
assign(ScrollLock, XK_Scroll_Lock);
|
||||
assign(Pause, XK_Pause);
|
||||
|
||||
assign(Tilde, XK_asciitilde);
|
||||
|
||||
assign(Num0, XK_0);
|
||||
assign(Num1, XK_1);
|
||||
assign(Num2, XK_2);
|
||||
assign(Num3, XK_3);
|
||||
assign(Num4, XK_4);
|
||||
assign(Num5, XK_5);
|
||||
assign(Num6, XK_6);
|
||||
assign(Num7, XK_7);
|
||||
assign(Num8, XK_8);
|
||||
assign(Num9, XK_9);
|
||||
|
||||
assign(Dash, XK_minus);
|
||||
assign(Equal, XK_equal);
|
||||
assign(Backspace, XK_BackSpace);
|
||||
|
||||
assign(Insert, XK_Insert);
|
||||
assign(Delete, XK_Delete);
|
||||
assign(Home, XK_Home);
|
||||
assign(End, XK_End);
|
||||
assign(PageUp, XK_Prior);
|
||||
assign(PageDown, XK_Next);
|
||||
|
||||
assign(A, XK_A);
|
||||
assign(B, XK_B);
|
||||
assign(C, XK_C);
|
||||
assign(D, XK_D);
|
||||
assign(E, XK_E);
|
||||
assign(F, XK_F);
|
||||
assign(G, XK_G);
|
||||
assign(H, XK_H);
|
||||
assign(I, XK_I);
|
||||
assign(J, XK_J);
|
||||
assign(K, XK_K);
|
||||
assign(L, XK_L);
|
||||
assign(M, XK_M);
|
||||
assign(N, XK_N);
|
||||
assign(O, XK_O);
|
||||
assign(P, XK_P);
|
||||
assign(Q, XK_Q);
|
||||
assign(R, XK_R);
|
||||
assign(S, XK_S);
|
||||
assign(T, XK_T);
|
||||
assign(U, XK_U);
|
||||
assign(V, XK_V);
|
||||
assign(W, XK_W);
|
||||
assign(X, XK_X);
|
||||
assign(Y, XK_Y);
|
||||
assign(Z, XK_Z);
|
||||
|
||||
assign(LeftBracket, XK_bracketleft);
|
||||
assign(RightBracket, XK_bracketright);
|
||||
assign(Backslash, XK_backslash);
|
||||
assign(Semicolon, XK_semicolon);
|
||||
assign(Apostrophe, XK_apostrophe);
|
||||
assign(Comma, XK_comma);
|
||||
assign(Period, XK_period);
|
||||
assign(Slash, XK_slash);
|
||||
|
||||
assign(Keypad0, XK_KP_0);
|
||||
assign(Keypad1, XK_KP_1);
|
||||
assign(Keypad2, XK_KP_2);
|
||||
assign(Keypad3, XK_KP_3);
|
||||
assign(Keypad4, XK_KP_4);
|
||||
assign(Keypad5, XK_KP_5);
|
||||
assign(Keypad6, XK_KP_6);
|
||||
assign(Keypad7, XK_KP_7);
|
||||
assign(Keypad8, XK_KP_8);
|
||||
assign(Keypad9, XK_KP_9);
|
||||
|
||||
assign(Add, XK_KP_Add);
|
||||
assign(Subtract, XK_KP_Subtract);
|
||||
assign(Multiply, XK_KP_Multiply);
|
||||
assign(Divide, XK_KP_Divide);
|
||||
assign(Enter, XK_KP_Enter);
|
||||
|
||||
assign(Up, XK_Up);
|
||||
assign(Down, XK_Down);
|
||||
assign(Left, XK_Left);
|
||||
assign(Right, XK_Right);
|
||||
|
||||
assign(Tab, XK_Tab);
|
||||
assign(Return, XK_Return);
|
||||
assign(Spacebar, XK_space);
|
||||
|
||||
assign(LeftControl, XK_Control_L);
|
||||
assign(RightControl, XK_Control_R);
|
||||
assign(LeftAlt, XK_Alt_L);
|
||||
assign(RightAlt, XK_Alt_R);
|
||||
assign(LeftShift, XK_Shift_L);
|
||||
assign(RightShift, XK_Shift_R);
|
||||
assign(LeftSuper, XK_Super_L);
|
||||
assign(RightSuper, XK_Super_R);
|
||||
assign(Menu, XK_Menu);
|
||||
|
||||
assign(keyboard<0>::lctrl, XK_Control_L);
|
||||
assign(keyboard<0>::rctrl, XK_Control_R);
|
||||
assign(keyboard<0>::lalt, XK_Alt_L);
|
||||
assign(keyboard<0>::ralt, XK_Alt_R);
|
||||
assign(keyboard<0>::lshift, XK_Shift_L);
|
||||
assign(keyboard<0>::rshift, XK_Shift_R);
|
||||
assign(keyboard<0>::lsuper, XK_Super_L);
|
||||
assign(keyboard<0>::rsuper, XK_Super_R);
|
||||
assign(keyboard<0>::menu, XK_Menu);
|
||||
#undef assign
|
||||
|
||||
XCloseDisplay(display);
|
||||
|
@@ -14,6 +14,8 @@ InputInterface input;
|
||||
const char *Video::Handle = "Handle";
|
||||
const char *Video::Synchronize = "Synchronize";
|
||||
const char *Video::Filter = "Filter";
|
||||
const char *Video::FragmentShader = "FragmentShader";
|
||||
const char *Video::VertexShader = "VertexShader";
|
||||
|
||||
void VideoInterface::driver(const char *driver) {
|
||||
if(p) term();
|
||||
|
@@ -3,6 +3,8 @@ public:
|
||||
static const char *Handle;
|
||||
static const char *Synchronize;
|
||||
static const char *Filter;
|
||||
static const char *FragmentShader;
|
||||
static const char *VertexShader;
|
||||
|
||||
enum Filter {
|
||||
FilterPoint,
|
||||
|
@@ -2,7 +2,7 @@
|
||||
video.glx
|
||||
author: byuu
|
||||
license: public domain
|
||||
last updated: 2008-08-20
|
||||
last updated: 2009-12-08
|
||||
|
||||
Design notes:
|
||||
SGI's GLX is the X11/Xlib interface to OpenGL.
|
||||
@@ -34,6 +34,8 @@ static Bool glx_wait_for_map_notify(Display *d, XEvent *e, char *arg) {
|
||||
|
||||
class pVideoGLX : public OpenGL {
|
||||
public:
|
||||
int (*glSwapInterval)(int);
|
||||
|
||||
Display *display;
|
||||
int screen;
|
||||
Window xwindow;
|
||||
@@ -60,6 +62,8 @@ public:
|
||||
if(name == Video::Handle) return true;
|
||||
if(name == Video::Synchronize) return true;
|
||||
if(name == Video::Filter) return true;
|
||||
if(name == Video::FragmentShader) return true;
|
||||
if(name == Video::VertexShader) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -79,7 +83,7 @@ public:
|
||||
if(name == Video::Synchronize) {
|
||||
if(settings.synchronize != any_cast<bool>(value)) {
|
||||
settings.synchronize = any_cast<bool>(value);
|
||||
if(glxcontext) init();
|
||||
if(glSwapInterval) glSwapInterval(settings.synchronize);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -89,6 +93,16 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::FragmentShader) {
|
||||
OpenGL::set_fragment_shader(any_cast<const char*>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::VertexShader) {
|
||||
OpenGL::set_vertex_shader(any_cast<const char*>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -138,11 +152,8 @@ public:
|
||||
|
||||
//let GLX determine the best Visual to use for GL output; provide a few hints
|
||||
//note: some video drivers will override double buffering attribute
|
||||
int elements = 0;
|
||||
int attributelist[] = { GLX_RGBA, None };
|
||||
int attributelist_sync[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
|
||||
XVisualInfo *vi = glXChooseVisual(display, screen,
|
||||
settings.synchronize ? attributelist_sync : attributelist);
|
||||
int attributelist[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
|
||||
XVisualInfo *vi = glXChooseVisual(display, screen, attributelist);
|
||||
|
||||
//Window settings.handle has already been realized, most likely with DefaultVisual.
|
||||
//GLX requires that the GL output window has the same Visual as the GLX context.
|
||||
@@ -175,6 +186,13 @@ public:
|
||||
OpenGL::init();
|
||||
settings.width = 256;
|
||||
settings.height = 256;
|
||||
|
||||
//vertical synchronization
|
||||
if(!glSwapInterval) glSwapInterval = (int (*)(int))glGetProcAddress("glXSwapIntervalEXT");
|
||||
if(!glSwapInterval) glSwapInterval = (int (*)(int))glGetProcAddress("glXSwapIntervalSGI");
|
||||
if(!glSwapInterval) glSwapInterval = (int (*)(int))glGetProcAddress("glXSwapIntervalMESA");
|
||||
if( glSwapInterval) glSwapInterval(settings.synchronize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -197,7 +215,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
pVideoGLX() {
|
||||
pVideoGLX() : glSwapInterval(0) {
|
||||
settings.handle = 0;
|
||||
settings.synchronize = false;
|
||||
xwindow = 0;
|
||||
|
@@ -2,15 +2,36 @@
|
||||
|
||||
#if defined(PLATFORM_X)
|
||||
#include <GL/glx.h>
|
||||
#define glGetProcAddress(name) (*glXGetProcAddress)((const GLubyte*)(name))
|
||||
#elif defined(PLATFORM_WIN)
|
||||
#include <GL/glext.h>
|
||||
#define glGetProcAddress(name) wglGetProcAddress(name)
|
||||
#else
|
||||
#error "ruby::OpenGL: unsupported platform"
|
||||
#endif
|
||||
|
||||
PFNGLCREATEPROGRAMPROC glCreateProgram = 0;
|
||||
PFNGLUSEPROGRAMPROC glUseProgram = 0;
|
||||
PFNGLCREATESHADERPROC glCreateShader = 0;
|
||||
PFNGLDELETESHADERPROC glDeleteShader = 0;
|
||||
PFNGLSHADERSOURCEPROC glShaderSource = 0;
|
||||
PFNGLCOMPILESHADERPROC glCompileShader = 0;
|
||||
PFNGLATTACHSHADERPROC glAttachShader = 0;
|
||||
PFNGLDETACHSHADERPROC glDetachShader = 0;
|
||||
PFNGLLINKPROGRAMPROC glLinkProgram = 0;
|
||||
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = 0;
|
||||
PFNGLUNIFORM1IPROC glUniform1i = 0;
|
||||
PFNGLUNIFORM2FVPROC glUniform2fv = 0;
|
||||
PFNGLUNIFORM4FVPROC glUniform4fv = 0;
|
||||
|
||||
class OpenGL {
|
||||
public:
|
||||
GLuint gltexture;
|
||||
GLuint glprogram;
|
||||
GLuint fragmentshader;
|
||||
GLuint vertexshader;
|
||||
bool shader_support;
|
||||
|
||||
uint32_t *buffer;
|
||||
unsigned iwidth, iheight;
|
||||
|
||||
@@ -45,6 +66,23 @@ public:
|
||||
}
|
||||
|
||||
void refresh(bool smooth, unsigned inwidth, unsigned inheight, unsigned outwidth, unsigned outheight) {
|
||||
if(shader_support) {
|
||||
glUseProgram(glprogram);
|
||||
GLint location;
|
||||
|
||||
float inputSize[2] = { inwidth, inheight };
|
||||
location = glGetUniformLocation(glprogram, "rubyInputSize");
|
||||
glUniform2fv(location, 1, inputSize);
|
||||
|
||||
float outputSize[2] = { outwidth, outheight };
|
||||
location = glGetUniformLocation(glprogram, "rubyOutputSize");
|
||||
glUniform2fv(location, 1, outputSize);
|
||||
|
||||
float textureSize[2] = { iwidth, iheight };
|
||||
location = glGetUniformLocation(glprogram, "rubyTextureSize");
|
||||
glUniform2fv(location, 1, textureSize);
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth ? GL_LINEAR : GL_NEAREST);
|
||||
@@ -78,6 +116,48 @@ public:
|
||||
glEnd();
|
||||
|
||||
glFlush();
|
||||
|
||||
if(shader_support) {
|
||||
glUseProgram(0);
|
||||
}
|
||||
}
|
||||
|
||||
void set_fragment_shader(const char *source) {
|
||||
if(!shader_support) return;
|
||||
|
||||
if(fragmentshader) {
|
||||
glDetachShader(glprogram, fragmentshader);
|
||||
glDeleteShader(fragmentshader);
|
||||
fragmentshader = 0;
|
||||
}
|
||||
|
||||
if(source) {
|
||||
fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentshader, 1, &source, 0);
|
||||
glCompileShader(fragmentshader);
|
||||
glAttachShader(glprogram, fragmentshader);
|
||||
}
|
||||
|
||||
glLinkProgram(glprogram);
|
||||
}
|
||||
|
||||
void set_vertex_shader(const char *source) {
|
||||
if(!shader_support) return;
|
||||
|
||||
if(vertexshader) {
|
||||
glDetachShader(glprogram, vertexshader);
|
||||
glDeleteShader(vertexshader);
|
||||
vertexshader = 0;
|
||||
}
|
||||
|
||||
if(source) {
|
||||
vertexshader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexshader, 1, &source, 0);
|
||||
glCompileShader(vertexshader);
|
||||
glAttachShader(glprogram, vertexshader);
|
||||
}
|
||||
|
||||
glLinkProgram(glprogram);
|
||||
}
|
||||
|
||||
void init() {
|
||||
@@ -92,6 +172,28 @@ public:
|
||||
glEnable(GL_DITHER);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
//bind shader functions
|
||||
glCreateProgram = (PFNGLCREATEPROGRAMPROC)glGetProcAddress("glCreateProgram");
|
||||
glUseProgram = (PFNGLUSEPROGRAMPROC)glGetProcAddress("glUseProgram");
|
||||
glCreateShader = (PFNGLCREATESHADERPROC)glGetProcAddress("glCreateShader");
|
||||
glDeleteShader = (PFNGLDELETESHADERPROC)glGetProcAddress("glDeleteShader");
|
||||
glShaderSource = (PFNGLSHADERSOURCEPROC)glGetProcAddress("glShaderSource");
|
||||
glCompileShader = (PFNGLCOMPILESHADERPROC)glGetProcAddress("glCompileShader");
|
||||
glAttachShader = (PFNGLATTACHSHADERPROC)glGetProcAddress("glAttachShader");
|
||||
glDetachShader = (PFNGLDETACHSHADERPROC)glGetProcAddress("glDetachShader");
|
||||
glLinkProgram = (PFNGLLINKPROGRAMPROC)glGetProcAddress("glLinkProgram");
|
||||
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)glGetProcAddress("glGetUniformLocation");
|
||||
glUniform1i = (PFNGLUNIFORM1IPROC)glGetProcAddress("glUniform1i");
|
||||
glUniform2fv = (PFNGLUNIFORM2FVPROC)glGetProcAddress("glUniform2fv");
|
||||
glUniform4fv = (PFNGLUNIFORM4FVPROC)glGetProcAddress("glUniform4fv");
|
||||
|
||||
shader_support = glCreateProgram && glUseProgram && glCreateShader
|
||||
&& glDeleteShader && glShaderSource && glCompileShader && glAttachShader
|
||||
&& glDetachShader && glLinkProgram && glGetUniformLocation
|
||||
&& glUniform1i && glUniform2fv && glUniform4fv;
|
||||
|
||||
if(shader_support) glprogram = glCreateProgram();
|
||||
|
||||
//create surface texture
|
||||
resize(256, 256);
|
||||
}
|
||||
@@ -112,6 +214,10 @@ public:
|
||||
|
||||
OpenGL() {
|
||||
gltexture = 0;
|
||||
glprogram = 0;
|
||||
fragmentshader = 0;
|
||||
vertexshader = 0;
|
||||
|
||||
buffer = 0;
|
||||
iwidth = 0;
|
||||
iheight = 0;
|
||||
|
@@ -9,6 +9,8 @@ namespace ruby {
|
||||
|
||||
class pVideoWGL : public OpenGL {
|
||||
public:
|
||||
BOOL (APIENTRY *glSwapInterval)(int);
|
||||
|
||||
HDC display;
|
||||
HGLRC wglcontext;
|
||||
HWND window;
|
||||
@@ -27,6 +29,8 @@ public:
|
||||
if(name == Video::Handle) return true;
|
||||
if(name == Video::Synchronize) return true;
|
||||
if(name == Video::Filter) return true;
|
||||
if(name == Video::FragmentShader) return true;
|
||||
if(name == Video::VertexShader) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -55,6 +59,16 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::FragmentShader) {
|
||||
OpenGL::set_fragment_shader(any_cast<const char*>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::VertexShader) {
|
||||
OpenGL::set_vertex_shader(any_cast<const char*>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -92,7 +106,7 @@ public:
|
||||
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | (settings.synchronize ? PFD_DOUBLEBUFFER : 0);
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
|
||||
display = GetDC(settings.handle);
|
||||
@@ -105,6 +119,11 @@ public:
|
||||
OpenGL::init();
|
||||
settings.width = 256;
|
||||
settings.height = 256;
|
||||
|
||||
//vertical synchronization
|
||||
if(!glSwapInterval) glSwapInterval = (BOOL (APIENTRY*)(int))glGetProcAddress("wglSwapIntervalEXT");
|
||||
if( glSwapInterval) glSwapInterval(settings.synchronize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -117,7 +136,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
pVideoWGL() {
|
||||
pVideoWGL() : glSwapInterval(0) {
|
||||
settings.handle = 0;
|
||||
settings.synchronize = false;
|
||||
settings.filter = 0;
|
||||
|
@@ -5,5 +5,3 @@ mkdir nall
|
||||
mkdir ruby
|
||||
xcopy /E ..\..\..\nall nall
|
||||
xcopy /E ..\..\..\ruby ruby
|
||||
del ruby\test*
|
||||
del ruby\cc.*
|
||||
|
@@ -8,5 +8,3 @@ cp -r ../../../ruby ./ruby
|
||||
|
||||
rm -r libco/doc
|
||||
rm -r libco/test
|
||||
rm ruby/test*
|
||||
rm ruby/cc.*
|
||||
|
@@ -23,7 +23,15 @@ void bPPU::enter() {
|
||||
scanline();
|
||||
add_clocks(10);
|
||||
|
||||
//H = 10 (OAM address reset)
|
||||
//H = 10 (cache mode7 registers + OAM address reset)
|
||||
cache.m7_hofs = regs.m7_hofs;
|
||||
cache.m7_vofs = regs.m7_vofs;
|
||||
cache.m7a = regs.m7a;
|
||||
cache.m7b = regs.m7b;
|
||||
cache.m7c = regs.m7c;
|
||||
cache.m7d = regs.m7d;
|
||||
cache.m7x = regs.m7x;
|
||||
cache.m7y = regs.m7y;
|
||||
if(vcounter() == (!overscan() ? 225 : 240)) {
|
||||
if(regs.display_disabled == false) {
|
||||
regs.oam_addr = regs.oam_baseaddr << 1;
|
||||
|
@@ -24,6 +24,12 @@ public:
|
||||
uint8 oam_basesize;
|
||||
uint8 oam_nameselect;
|
||||
uint16 oam_tdaddr;
|
||||
|
||||
//$210d-$210e
|
||||
uint16 m7_hofs, m7_vofs;
|
||||
|
||||
//$211b-$2120
|
||||
uint16 m7a, m7b, m7c, m7d, m7x, m7y;
|
||||
} cache;
|
||||
|
||||
alwaysinline bool interlace() const { return display.interlace; }
|
||||
|
@@ -55,6 +55,10 @@ template<unsigned mode, unsigned bg, unsigned color_depth>
|
||||
void bPPU::render_line_bg(uint8 pri0_pos, uint8 pri1_pos) {
|
||||
if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false) return;
|
||||
|
||||
if(render_enabled(bg, 0) == false) pri0_pos = 0;
|
||||
if(render_enabled(bg, 1) == false) pri1_pos = 0;
|
||||
if(pri0_pos == 0 && pri1_pos == 0) return;
|
||||
|
||||
const bool bg_enabled = regs.bg_enabled[bg];
|
||||
const bool bgsub_enabled = regs.bgsub_enabled[bg];
|
||||
|
||||
|
@@ -16,18 +16,22 @@ template<unsigned bg>
|
||||
void bPPU::render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) {
|
||||
if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false) return;
|
||||
|
||||
if(render_enabled(bg, 0) == false) pri0_pos = 0;
|
||||
if(render_enabled(bg, 1) == false) pri1_pos = 1;
|
||||
if(pri0_pos == 0 && pri1_pos == 0) return;
|
||||
|
||||
int32 px, py;
|
||||
int32 tx, ty, tile, palette;
|
||||
|
||||
int32 a = sclip<16>(regs.m7a);
|
||||
int32 b = sclip<16>(regs.m7b);
|
||||
int32 c = sclip<16>(regs.m7c);
|
||||
int32 d = sclip<16>(regs.m7d);
|
||||
int32 a = sclip<16>(cache.m7a);
|
||||
int32 b = sclip<16>(cache.m7b);
|
||||
int32 c = sclip<16>(cache.m7c);
|
||||
int32 d = sclip<16>(cache.m7d);
|
||||
|
||||
int32 cx = sclip<13>(regs.m7x);
|
||||
int32 cy = sclip<13>(regs.m7y);
|
||||
int32 hofs = sclip<13>(regs.m7_hofs);
|
||||
int32 vofs = sclip<13>(regs.m7_vofs);
|
||||
int32 cx = sclip<13>(cache.m7x);
|
||||
int32 cy = sclip<13>(cache.m7y);
|
||||
int32 hofs = sclip<13>(cache.m7_hofs);
|
||||
int32 vofs = sclip<13>(cache.m7_vofs);
|
||||
|
||||
int _pri, _x;
|
||||
bool _bg_enabled = regs.bg_enabled[bg];
|
||||
|
@@ -189,6 +189,12 @@ void bPPU::render_line_oam_rto() {
|
||||
void bPPU::render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos) {
|
||||
if(regs.bg_enabled[OAM] == false && regs.bgsub_enabled[OAM] == false) return;
|
||||
|
||||
if(render_enabled(OAM, 0) == false) pri0_pos = 0;
|
||||
if(render_enabled(OAM, 1) == false) pri1_pos = 0;
|
||||
if(render_enabled(OAM, 2) == false) pri2_pos = 0;
|
||||
if(render_enabled(OAM, 3) == false) pri3_pos = 0;
|
||||
if(pri0_pos == 0 && pri1_pos == 0 && pri2_pos == 0 && pri3_pos == 0) return;
|
||||
|
||||
for(unsigned s = 0; s < 34; s++) {
|
||||
if(oam_tilelist[s].tile == 0xffff) continue;
|
||||
render_oam_tile(s);
|
||||
|
@@ -8,6 +8,17 @@
|
||||
#include "addsub.cpp"
|
||||
#include "line.cpp"
|
||||
|
||||
bool bPPU::render_enabled(unsigned bg, unsigned pri) const {
|
||||
switch(bg) {
|
||||
case BG1: return config.ppu.bg1_enabled[pri];
|
||||
case BG2: return config.ppu.bg2_enabled[pri];
|
||||
case BG3: return config.ppu.bg3_enabled[pri];
|
||||
case BG4: return config.ppu.bg4_enabled[pri];
|
||||
case OAM: return config.ppu.oam_enabled[pri];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//Mode 0: ->
|
||||
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
|
||||
// BG4B, BG3B, OAM0, BG4A, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3
|
||||
|
@@ -1,4 +1,6 @@
|
||||
//render.cpp
|
||||
bool render_enabled(unsigned bg, unsigned pri) const;
|
||||
|
||||
inline void render_line_mode0();
|
||||
inline void render_line_mode1();
|
||||
inline void render_line_mode2();
|
||||
|
@@ -5,18 +5,18 @@ uint16 SMPcore::__relb(int8 offset, int op_len) {
|
||||
return pc + offset;
|
||||
}
|
||||
|
||||
void SMPcore::disassemble_opcode(char *output) {
|
||||
void SMPcore::disassemble_opcode(char *output, uint16 addr) {
|
||||
char *s, t[512];
|
||||
uint8 op, op0, op1;
|
||||
uint16 opw, opdp0, opdp1;
|
||||
s = output;
|
||||
|
||||
sprintf(s, "..%.4x ", regs.pc);
|
||||
sprintf(s, "..%.4x ", addr);
|
||||
|
||||
//TODO: read from IPLROM when applicable
|
||||
op = memory::apuram[(uint16)(regs.pc + 0)];
|
||||
op0 = memory::apuram[(uint16)(regs.pc + 1)];
|
||||
op1 = memory::apuram[(uint16)(regs.pc + 2)];
|
||||
op = memory::apuram[(uint16)(addr + 0)];
|
||||
op0 = memory::apuram[(uint16)(addr + 1)];
|
||||
op1 = memory::apuram[(uint16)(addr + 2)];
|
||||
opw = (op0) | (op1 << 8);
|
||||
opdp0 = ((unsigned)regs.p.p << 8) + op0;
|
||||
opdp1 = ((unsigned)regs.p.p << 8) + op1;
|
||||
|
@@ -1,2 +1,2 @@
|
||||
void disassemble_opcode(char *output);
|
||||
void disassemble_opcode(char *output, uint16 addr);
|
||||
inline uint16 __relb(int8 offset, int op_len);
|
||||
|
@@ -10,14 +10,35 @@ void sSMPDebug::op_step() {
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::APURAM, Debugger::Breakpoint::Exec, regs.pc, 0x00);
|
||||
}
|
||||
|
||||
if(debugger.trace_smp) {
|
||||
char t[256];
|
||||
disassemble_opcode(t);
|
||||
debugger.tracefile.print(string() << t << "\n");
|
||||
}
|
||||
usage[regs.pc] |= UsageExec;
|
||||
opcode_pc = regs.pc;
|
||||
|
||||
if(step_event) step_event();
|
||||
sSMP::op_step();
|
||||
scheduler.sync_smpcpu();
|
||||
}
|
||||
|
||||
uint8 sSMPDebug::op_read(uint16 addr) {
|
||||
uint8 data = sSMP::op_read(addr);
|
||||
usage[addr] |= UsageRead;
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::APURAM, Debugger::Breakpoint::Read, addr, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void sSMPDebug::op_write(uint16 addr, uint8 data) {
|
||||
sSMP::op_write(addr, data);
|
||||
usage[addr] |= UsageWrite;
|
||||
usage[addr] &= ~UsageExec;
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::APURAM, Debugger::Breakpoint::Write, addr, data);
|
||||
}
|
||||
|
||||
sSMPDebug::sSMPDebug() {
|
||||
usage = new uint8[1 << 16]();
|
||||
opcode_pc = 0xffc0;
|
||||
}
|
||||
|
||||
sSMPDebug::~sSMPDebug() {
|
||||
delete[] usage;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,4 +1,19 @@
|
||||
class sSMPDebug : public sSMP {
|
||||
public:
|
||||
function<void ()> step_event;
|
||||
|
||||
enum Usage {
|
||||
UsageRead = 0x80,
|
||||
UsageWrite = 0x40,
|
||||
UsageExec = 0x20,
|
||||
};
|
||||
uint8 *usage;
|
||||
uint16 opcode_pc;
|
||||
|
||||
void op_step();
|
||||
uint8 op_read(uint16 addr);
|
||||
void op_write(uint16 addr, uint8 data);
|
||||
|
||||
sSMPDebug();
|
||||
~sSMPDebug();
|
||||
};
|
||||
|
@@ -1,12 +1,12 @@
|
||||
uint8 ram_read(uint16 addr);
|
||||
void ram_write(uint16 addr, uint8 data);
|
||||
uint8 ram_read(uint16 addr);
|
||||
void ram_write(uint16 addr, uint8 data);
|
||||
|
||||
uint8 port_read(uint8 port);
|
||||
void port_write(uint8 port, uint8 data);
|
||||
uint8 port_read(uint8 port);
|
||||
void port_write(uint8 port, uint8 data);
|
||||
|
||||
uint8 op_busread(uint16 addr);
|
||||
void op_buswrite(uint16 addr, uint8 data);
|
||||
uint8 op_busread(uint16 addr);
|
||||
void op_buswrite(uint16 addr, uint8 data);
|
||||
|
||||
void op_io();
|
||||
uint8 op_read(uint16 addr);
|
||||
void op_write(uint16 addr, uint8 data);
|
||||
void op_io();
|
||||
debugvirtual uint8 op_read(uint16 addr);
|
||||
debugvirtual void op_write(uint16 addr, uint8 data);
|
||||
|
@@ -2,11 +2,89 @@
|
||||
|
||||
Audio audio;
|
||||
|
||||
void Audio::sample(uint16 l_sample, uint16 r_sample) {
|
||||
system.interface->audio_sample(l_sample, r_sample);
|
||||
void Audio::coprocessor_enable(bool state) {
|
||||
coprocessor = state;
|
||||
|
||||
dsp_rdoffset = cop_rdoffset = 0;
|
||||
dsp_wroffset = cop_wroffset = 0;
|
||||
dsp_length = cop_length = 0;
|
||||
|
||||
r_sum_l = r_sum_r = 0;
|
||||
}
|
||||
|
||||
void Audio::coprocessor_frequency(double input_frequency) {
|
||||
double output_frequency;
|
||||
if(system.region() == System::NTSC) {
|
||||
output_frequency = config.smp.ntsc_clock_rate / 768.0;
|
||||
} else /* (system.region() == System::PAL) */ {
|
||||
output_frequency = config.smp.pal_clock_rate / 768.0;
|
||||
}
|
||||
|
||||
r_step = input_frequency / output_frequency;
|
||||
r_frac = 0;
|
||||
}
|
||||
|
||||
void Audio::sample(int16 left, int16 right) {
|
||||
if(coprocessor == false) {
|
||||
system.interface->audio_sample(left, right);
|
||||
} else {
|
||||
dsp_buffer[dsp_wroffset] = ((uint16)left << 0) + ((uint16)right << 16);
|
||||
dsp_wroffset = (dsp_wroffset + 1) & 32767;
|
||||
dsp_length = (dsp_length + 1) & 32767;
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::coprocessor_sample(int16 left, int16 right) {
|
||||
if(r_frac >= 1.0) {
|
||||
r_frac -= 1.0;
|
||||
r_sum_l += left;
|
||||
r_sum_r += right;
|
||||
return;
|
||||
}
|
||||
|
||||
r_sum_l += left * r_frac;
|
||||
r_sum_r += right * r_frac;
|
||||
|
||||
uint16 output_left = sclamp<16>(int(r_sum_l / r_step));
|
||||
uint16 output_right = sclamp<16>(int(r_sum_r / r_step));
|
||||
|
||||
double first = 1.0 - r_frac;
|
||||
r_sum_l = left * first;
|
||||
r_sum_r = right * first;
|
||||
r_frac = r_step - first;
|
||||
|
||||
cop_buffer[cop_wroffset] = (output_left << 0) + (output_right << 16);
|
||||
cop_wroffset = (cop_wroffset + 1) & 32767;
|
||||
cop_length = (cop_length + 1) & 32767;
|
||||
flush();
|
||||
}
|
||||
|
||||
void Audio::init() {
|
||||
}
|
||||
|
||||
void Audio::flush() {
|
||||
while(dsp_length > 0 && cop_length > 0) {
|
||||
uint32 dsp_sample = dsp_buffer[dsp_rdoffset];
|
||||
uint32 cop_sample = cop_buffer[cop_rdoffset];
|
||||
|
||||
dsp_rdoffset = (dsp_rdoffset + 1) & 32767;
|
||||
cop_rdoffset = (cop_rdoffset + 1) & 32767;
|
||||
|
||||
dsp_length--;
|
||||
cop_length--;
|
||||
|
||||
int dsp_left = (int16)(dsp_sample >> 0);
|
||||
int dsp_right = (int16)(dsp_sample >> 16);
|
||||
|
||||
int cop_left = (int16)(cop_sample >> 0);
|
||||
int cop_right = (int16)(cop_sample >> 16);
|
||||
|
||||
system.interface->audio_sample(
|
||||
sclamp<16>((dsp_left + cop_left ) / 2),
|
||||
sclamp<16>((dsp_right + cop_right) / 2)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,7 +1,22 @@
|
||||
class Audio {
|
||||
public:
|
||||
void sample(uint16 l_sample, uint16 r_sample);
|
||||
void coprocessor_enable(bool state);
|
||||
void coprocessor_frequency(double frequency);
|
||||
void sample(int16 left, int16 right);
|
||||
void coprocessor_sample(int16 left, int16 right);
|
||||
void init();
|
||||
|
||||
private:
|
||||
bool coprocessor;
|
||||
uint32 dsp_buffer[32768], cop_buffer[32768];
|
||||
unsigned dsp_rdoffset, cop_rdoffset;
|
||||
unsigned dsp_wroffset, cop_wroffset;
|
||||
unsigned dsp_length, cop_length;
|
||||
|
||||
double r_step, r_frac;
|
||||
int r_sum_l, r_sum_r;
|
||||
|
||||
void flush();
|
||||
};
|
||||
|
||||
extern Audio audio;
|
||||
|
@@ -18,6 +18,12 @@ Configuration::Configuration() {
|
||||
smp.ntsc_clock_rate = 24607104; //32040.5 * 768
|
||||
smp.pal_clock_rate = 24607104;
|
||||
|
||||
ppu.bg1_enabled[0] = ppu.bg1_enabled[1] = true;
|
||||
ppu.bg2_enabled[0] = ppu.bg2_enabled[1] = true;
|
||||
ppu.bg3_enabled[0] = ppu.bg3_enabled[1] = true;
|
||||
ppu.bg4_enabled[0] = ppu.bg4_enabled[1] = true;
|
||||
ppu.oam_enabled[0] = ppu.oam_enabled[1] = ppu.oam_enabled[2] = ppu.oam_enabled[3] = true;
|
||||
|
||||
ppu1.version = 1;
|
||||
ppu2.version = 3;
|
||||
|
||||
|
@@ -18,6 +18,14 @@ struct Configuration {
|
||||
unsigned pal_clock_rate;
|
||||
} smp;
|
||||
|
||||
struct PPU {
|
||||
bool bg1_enabled[2];
|
||||
bool bg2_enabled[2];
|
||||
bool bg3_enabled[2];
|
||||
bool bg4_enabled[2];
|
||||
bool oam_enabled[4];
|
||||
} ppu;
|
||||
|
||||
struct PPU1 {
|
||||
unsigned version;
|
||||
} ppu1;
|
||||
|
@@ -22,10 +22,6 @@ public:
|
||||
bool step_cpu;
|
||||
bool step_smp;
|
||||
|
||||
file tracefile;
|
||||
bool trace_cpu;
|
||||
bool trace_smp;
|
||||
|
||||
enum MemorySource { CPUBus, APURAM, VRAM, OAM, CGRAM };
|
||||
uint8 read(MemorySource, unsigned addr);
|
||||
void write(MemorySource, unsigned addr, uint8 data);
|
||||
|
@@ -8,58 +8,40 @@ uint8 Input::port_read(bool portnumber) {
|
||||
switch(p.device) {
|
||||
case DeviceJoypad: {
|
||||
if(p.counter0 >= 16) return 1;
|
||||
unsigned deviceid = (portnumber == 0 ? DeviceIDJoypad1 : DeviceIDJoypad2);
|
||||
return system.interface->input_poll(deviceid, p.counter0++);
|
||||
return system.interface->input_poll(portnumber, p.device, 0, p.counter0++);
|
||||
} //case DeviceJoypad
|
||||
|
||||
case DeviceMultitap: {
|
||||
if(cpu.joylatch()) return 2; //when latch is high -- data2 = 1, data1 = 0
|
||||
|
||||
unsigned deviceidx, deviceid0, deviceid1;
|
||||
if(portnumber == 0) {
|
||||
if(cpu.pio() & 0x40) {
|
||||
deviceidx = p.counter0;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter0++;
|
||||
unsigned deviceidx, deviceindex0, deviceindex1;
|
||||
uint8 mask = (portnumber == 0 ? 0x40 : 0x80);
|
||||
|
||||
deviceid0 = DeviceIDMultitap1A;
|
||||
deviceid1 = DeviceIDMultitap1B;
|
||||
} else {
|
||||
deviceidx = p.counter1;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter1++;
|
||||
if(cpu.pio() & mask) {
|
||||
deviceidx = p.counter0;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter0++;
|
||||
|
||||
deviceid0 = DeviceIDMultitap1C;
|
||||
deviceid1 = DeviceIDMultitap1D;
|
||||
}
|
||||
deviceindex0 = 0; //controller 1
|
||||
deviceindex1 = 1; //controller 2
|
||||
} else {
|
||||
if(cpu.pio() & 0x80) {
|
||||
deviceidx = p.counter0;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter0++;
|
||||
deviceidx = p.counter1;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter1++;
|
||||
|
||||
deviceid0 = DeviceIDMultitap2A;
|
||||
deviceid1 = DeviceIDMultitap2B;
|
||||
} else {
|
||||
deviceidx = p.counter1;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter1++;
|
||||
|
||||
deviceid0 = DeviceIDMultitap2C;
|
||||
deviceid1 = DeviceIDMultitap2D;
|
||||
}
|
||||
deviceindex0 = 2; //controller 3
|
||||
deviceindex1 = 3; //controller 4
|
||||
}
|
||||
|
||||
return (system.interface->input_poll(deviceid0, deviceidx) << 0)
|
||||
| (system.interface->input_poll(deviceid1, deviceidx) << 1);
|
||||
return (system.interface->input_poll(portnumber, p.device, deviceindex0, deviceidx) << 0)
|
||||
| (system.interface->input_poll(portnumber, p.device, deviceindex1, deviceidx) << 1);
|
||||
} //case DeviceMultitap
|
||||
|
||||
case DeviceMouse: {
|
||||
if(p.counter0 >= 32) return 1;
|
||||
unsigned deviceid = (portnumber == 0 ? DeviceIDMouse1 : DeviceIDMouse2);
|
||||
|
||||
int position_x = system.interface->input_poll(deviceid, MouseX); //-n = left, 0 = center, +n = right
|
||||
int position_y = system.interface->input_poll(deviceid, MouseY); //-n = up, 0 = center, +n = right
|
||||
int position_x = system.interface->input_poll(portnumber, p.device, 0, MouseX); //-n = left, 0 = center, +n = right
|
||||
int position_y = system.interface->input_poll(portnumber, p.device, 0, MouseY); //-n = up, 0 = center, +n = right
|
||||
|
||||
bool direction_x = position_x < 0; //0 = right, 1 = left
|
||||
bool direction_y = position_y < 0; //0 = down, 1 = up
|
||||
@@ -80,8 +62,8 @@ uint8 Input::port_read(bool portnumber) {
|
||||
case 6: return 0;
|
||||
case 7: return 0;
|
||||
|
||||
case 8: return system.interface->input_poll(deviceid, MouseRight);
|
||||
case 9: return system.interface->input_poll(deviceid, MouseLeft);
|
||||
case 8: return system.interface->input_poll(portnumber, p.device, 0, MouseRight);
|
||||
case 9: return system.interface->input_poll(portnumber, p.device, 0, MouseLeft);
|
||||
case 10: return 0; //speed (0 = slow, 1 = normal, 2 = fast, 3 = unused)
|
||||
case 11: return 0; // ||
|
||||
|
||||
@@ -116,7 +98,7 @@ uint8 Input::port_read(bool portnumber) {
|
||||
|
||||
if(p.counter0 == 0) {
|
||||
//turbo is a switch; toggle is edge sensitive
|
||||
bool turbo = system.interface->input_poll(DeviceIDSuperScope, SuperScopeTurbo);
|
||||
bool turbo = system.interface->input_poll(portnumber, p.device, 0, SuperScopeTurbo);
|
||||
if(turbo && !p.superscope.turbolock) {
|
||||
p.superscope.turbo = !p.superscope.turbo; //toggle state
|
||||
p.superscope.turbolock = true;
|
||||
@@ -127,7 +109,7 @@ uint8 Input::port_read(bool portnumber) {
|
||||
//trigger is a button
|
||||
//if turbo is active, trigger is level sensitive; otherwise it is edge sensitive
|
||||
p.superscope.trigger = false;
|
||||
bool trigger = system.interface->input_poll(DeviceIDSuperScope, SuperScopeTrigger);
|
||||
bool trigger = system.interface->input_poll(portnumber, p.device, 0, SuperScopeTrigger);
|
||||
if(trigger && (p.superscope.turbo || !p.superscope.triggerlock)) {
|
||||
p.superscope.trigger = true;
|
||||
p.superscope.triggerlock = true;
|
||||
@@ -136,11 +118,11 @@ uint8 Input::port_read(bool portnumber) {
|
||||
}
|
||||
|
||||
//cursor is a button; it is always level sensitive
|
||||
p.superscope.cursor = system.interface->input_poll(DeviceIDSuperScope, SuperScopeCursor);
|
||||
p.superscope.cursor = system.interface->input_poll(portnumber, p.device, 0, SuperScopeCursor);
|
||||
|
||||
//pause is a button; it is always edge sensitive
|
||||
p.superscope.pause = false;
|
||||
bool pause = system.interface->input_poll(DeviceIDSuperScope, SuperScopePause);
|
||||
bool pause = system.interface->input_poll(portnumber, p.device, 0, SuperScopePause);
|
||||
if(pause && !p.superscope.pauselock) {
|
||||
p.superscope.pause = true;
|
||||
p.superscope.pauselock = true;
|
||||
@@ -171,12 +153,12 @@ uint8 Input::port_read(bool portnumber) {
|
||||
if(p.counter0 >= 32) return 1;
|
||||
|
||||
if(p.counter0 == 0) {
|
||||
p.justifier.trigger1 = system.interface->input_poll(DeviceIDJustifier1, JustifierTrigger);
|
||||
p.justifier.start1 = system.interface->input_poll(DeviceIDJustifier1, JustifierStart);
|
||||
p.justifier.trigger1 = system.interface->input_poll(portnumber, p.device, 0, JustifierTrigger);
|
||||
p.justifier.start1 = system.interface->input_poll(portnumber, p.device, 0, JustifierStart);
|
||||
|
||||
if(p.device == DeviceJustifiers) {
|
||||
p.justifier.trigger2 = system.interface->input_poll(DeviceIDJustifier2, JustifierTrigger);
|
||||
p.justifier.start2 = system.interface->input_poll(DeviceIDJustifier2, JustifierStart);
|
||||
p.justifier.trigger2 = system.interface->input_poll(portnumber, p.device, 1, JustifierTrigger);
|
||||
p.justifier.start2 = system.interface->input_poll(portnumber, p.device, 1, JustifierStart);
|
||||
} else {
|
||||
p.justifier.x2 = -1;
|
||||
p.justifier.y2 = -1;
|
||||
@@ -238,8 +220,8 @@ void Input::update() {
|
||||
|
||||
switch(p.device) {
|
||||
case DeviceSuperScope: {
|
||||
int x = system.interface->input_poll(DeviceIDSuperScope, SuperScopeX);
|
||||
int y = system.interface->input_poll(DeviceIDSuperScope, SuperScopeY);
|
||||
int x = system.interface->input_poll(1, p.device, 0, SuperScopeX);
|
||||
int y = system.interface->input_poll(1, p.device, 0, SuperScopeY);
|
||||
x += p.superscope.x;
|
||||
y += p.superscope.y;
|
||||
p.superscope.x = max(-16, min(256 + 16, x));
|
||||
@@ -251,15 +233,15 @@ void Input::update() {
|
||||
|
||||
case DeviceJustifier:
|
||||
case DeviceJustifiers: {
|
||||
int x1 = system.interface->input_poll(DeviceIDJustifier1, JustifierX);
|
||||
int y1 = system.interface->input_poll(DeviceIDJustifier1, JustifierY);
|
||||
int x1 = system.interface->input_poll(1, p.device, 0, JustifierX);
|
||||
int y1 = system.interface->input_poll(1, p.device, 0, JustifierY);
|
||||
x1 += p.justifier.x1;
|
||||
y1 += p.justifier.y1;
|
||||
p.justifier.x1 = max(-16, min(256 + 16, x1));
|
||||
p.justifier.y1 = max(-16, min(240 + 16, y1));
|
||||
|
||||
int x2 = system.interface->input_poll(DeviceIDJustifier2, JustifierX);
|
||||
int y2 = system.interface->input_poll(DeviceIDJustifier2, JustifierY);
|
||||
int x2 = system.interface->input_poll(1, p.device, 1, JustifierX);
|
||||
int y2 = system.interface->input_poll(1, p.device, 1, JustifierY);
|
||||
x2 += p.justifier.x2;
|
||||
y2 += p.justifier.y2;
|
||||
p.justifier.x2 = max(-16, min(256 + 16, x2));
|
||||
|
@@ -10,32 +10,13 @@ public:
|
||||
DeviceJustifiers,
|
||||
};
|
||||
|
||||
enum DeviceID {
|
||||
DeviceIDNone,
|
||||
DeviceIDJoypad1,
|
||||
DeviceIDJoypad2,
|
||||
DeviceIDMultitap1A,
|
||||
DeviceIDMultitap1B,
|
||||
DeviceIDMultitap1C,
|
||||
DeviceIDMultitap1D,
|
||||
DeviceIDMultitap2A,
|
||||
DeviceIDMultitap2B,
|
||||
DeviceIDMultitap2C,
|
||||
DeviceIDMultitap2D,
|
||||
DeviceIDMouse1,
|
||||
DeviceIDMouse2,
|
||||
DeviceIDSuperScope,
|
||||
DeviceIDJustifier1,
|
||||
DeviceIDJustifier2,
|
||||
};
|
||||
|
||||
enum JoypadID {
|
||||
JoypadB = 0, JoypadY = 1,
|
||||
JoypadSelect = 2, JoypadStart = 3,
|
||||
JoypadUp = 4, JoypadDown = 5,
|
||||
JoypadLeft = 6, JoypadRight = 7,
|
||||
JoypadA = 8, JoypadX = 9,
|
||||
JoypadL = 10, JoypadR = 11,
|
||||
JoypadB = 0, JoypadY = 1,
|
||||
JoypadSelect = 2, JoypadStart = 3,
|
||||
JoypadUp = 4, JoypadDown = 5,
|
||||
JoypadLeft = 6, JoypadRight = 7,
|
||||
JoypadA = 8, JoypadX = 9,
|
||||
JoypadL = 10, JoypadR = 11,
|
||||
};
|
||||
|
||||
enum MouseID {
|
||||
|
@@ -3,5 +3,5 @@ public:
|
||||
virtual void video_refresh(uint16_t *data, unsigned pitch, unsigned *line, unsigned width, unsigned height) {}
|
||||
virtual void audio_sample(uint16_t l_sample, uint16_t r_sample) {}
|
||||
virtual void input_poll() {}
|
||||
virtual int16_t input_poll(unsigned deviceid, unsigned id) { return 0; }
|
||||
virtual int16_t input_poll(bool port, unsigned device, unsigned index, unsigned id) { return 0; }
|
||||
};
|
||||
|
@@ -23,6 +23,7 @@ void Scheduler::init() {
|
||||
clock.smp_freq = system.region() == System::NTSC
|
||||
? config.smp.ntsc_clock_rate
|
||||
: config.smp.pal_clock_rate;
|
||||
clock.cop_freq = clock.cpu_freq;
|
||||
|
||||
clock.cpucop = 0;
|
||||
clock.cpuppu = 0;
|
||||
|
@@ -15,6 +15,7 @@ public:
|
||||
|
||||
struct {
|
||||
uint32 cpu_freq;
|
||||
uint32 cop_freq;
|
||||
uint32 smp_freq;
|
||||
|
||||
int64 cpucop;
|
||||
@@ -102,13 +103,13 @@ public:
|
||||
//==========
|
||||
|
||||
alwaysinline void addclocks_cpu(unsigned clocks) {
|
||||
clock.cpucop -= clocks;
|
||||
clock.cpucop -= clocks * (uint64)clock.cop_freq;
|
||||
clock.cpuppu -= clocks;
|
||||
clock.cpusmp -= clocks * (uint64)clock.smp_freq;
|
||||
}
|
||||
|
||||
alwaysinline void addclocks_cop(unsigned clocks) {
|
||||
clock.cpucop += clocks;
|
||||
clock.cpucop += clocks * (uint64)clock.cpu_freq;
|
||||
}
|
||||
|
||||
alwaysinline void addclocks_ppu(unsigned clocks) {
|
||||
|
@@ -1,12 +1,20 @@
|
||||
#ifdef SYSTEM_CPP
|
||||
|
||||
serializer System::serialize() {
|
||||
serializer s(serialize_size);
|
||||
unsigned System::serialize_size() const {
|
||||
return serializer_size;
|
||||
}
|
||||
|
||||
serializer System::serialize() {
|
||||
serializer s(serializer_size);
|
||||
|
||||
unsigned signature = 0x31545342, version = bsnesSerializerVersion, crc32 = cartridge.crc32();
|
||||
char description[512];
|
||||
memset(&description, 0, sizeof description);
|
||||
|
||||
unsigned signature = 0x31545342, version = bsnesSaveStateVersion, crc32 = cartridge.crc32();
|
||||
s.integer(signature);
|
||||
s.integer(version);
|
||||
s.integer(crc32);
|
||||
s.array(description);
|
||||
|
||||
serialize_all(s);
|
||||
return s;
|
||||
@@ -14,12 +22,15 @@ serializer System::serialize() {
|
||||
|
||||
bool System::unserialize(serializer &s) {
|
||||
unsigned signature, version, crc32;
|
||||
char description[512];
|
||||
|
||||
s.integer(signature);
|
||||
s.integer(version);
|
||||
s.integer(crc32);
|
||||
s.array(description);
|
||||
|
||||
if(signature != 0x31545342) return false;
|
||||
if(version != bsnesSaveStateVersion) return false;
|
||||
if(version != bsnesSerializerVersion) return false;
|
||||
//if(crc32 != cartridge.crc32()) return false;
|
||||
scheduler.init();
|
||||
|
||||
@@ -27,7 +38,9 @@ bool System::unserialize(serializer &s) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//========
|
||||
//internal
|
||||
//========
|
||||
|
||||
void System::serialize(serializer &s) {
|
||||
s.integer(snes_region);
|
||||
@@ -51,6 +64,8 @@ void System::serialize_all(serializer &s) {
|
||||
ppu.serialize(s);
|
||||
dsp.serialize(s);
|
||||
|
||||
if(cartridge.mode() == Cartridge::ModeSuperGameBoy) supergameboy.serialize(s);
|
||||
|
||||
if(cartridge.has_srtc()) srtc.serialize(s);
|
||||
if(cartridge.has_sdd1()) sdd1.serialize(s);
|
||||
if(cartridge.has_spc7110()) spc7110.serialize(s);
|
||||
@@ -59,6 +74,7 @@ void System::serialize_all(serializer &s) {
|
||||
if(cartridge.has_dsp2()) dsp2.serialize(s);
|
||||
if(cartridge.has_obc1()) obc1.serialize(s);
|
||||
if(cartridge.has_st010()) st010.serialize(s);
|
||||
if(cartridge.has_21fx()) s21fx.serialize(s);
|
||||
}
|
||||
|
||||
//called once upon cartridge load event: perform dry-run state save.
|
||||
@@ -68,12 +84,15 @@ void System::serialize_init() {
|
||||
serializer s;
|
||||
|
||||
unsigned signature = 0, version = 0, crc32 = 0;
|
||||
char description[512];
|
||||
|
||||
s.integer(signature);
|
||||
s.integer(version);
|
||||
s.integer(crc32);
|
||||
s.array(description);
|
||||
|
||||
serialize_all(s);
|
||||
serialize_size = s.size();
|
||||
serializer_size = s.size();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,191 +0,0 @@
|
||||
StateManager statemanager;
|
||||
|
||||
void StateManager::list(lstring &l) const {
|
||||
l.reset();
|
||||
|
||||
for(unsigned x = 0; x < info.slotcount; x++) {
|
||||
for(unsigned y = 0; y < info.slotcount; y++) {
|
||||
if(info.slot[y] == x) {
|
||||
unsigned n = l.size();
|
||||
char slot[8];
|
||||
sprintf(slot, "%3u", x + 1);
|
||||
l[n] << slot << "\t";
|
||||
|
||||
char datetime[DateTimeSize + 1];
|
||||
memcpy(datetime, &info.datetime[y * DateTimeSize], DateTimeSize);
|
||||
datetime[DateTimeSize] = 0;
|
||||
l[n] << datetime << "\t";
|
||||
|
||||
char desc[DescriptionSize + 1];
|
||||
memcpy(desc, &info.description[y * DescriptionSize], DescriptionSize);
|
||||
desc[DescriptionSize] = 0;
|
||||
l[n] << desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool StateManager::set_description(const char *filename, uint8 slot, const char *description) {
|
||||
if(load(filename) == false) return false;
|
||||
if(info.slotcount <= slot) return false;
|
||||
file fp;
|
||||
if(fp.open(filename, file::mode_readwrite) == false) return false;
|
||||
|
||||
uint8 index = findslot(slot);
|
||||
if(index == SlotInvalid) { fp.close(); return false; }
|
||||
|
||||
char desc[DescriptionSize];
|
||||
memset(&desc, 0, DescriptionSize);
|
||||
strlcpy(desc, description, DescriptionSize);
|
||||
|
||||
fp.seek(DescIndex + index * DescriptionSize);
|
||||
fp.write((uint8*)&desc[0], DescriptionSize);
|
||||
fp.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
serializer StateManager::load(const char *filename, uint8 slot) {
|
||||
if(load(filename) == false) throw;
|
||||
if(info.slotcount <= slot) throw;
|
||||
uint8 index = findslot(slot);
|
||||
if(index == SlotInvalid) throw;
|
||||
file fp;
|
||||
if(fp.open(filename, file::mode_read) == false) throw;
|
||||
|
||||
fp.seek(HeaderSize + system.serialize_size * index);
|
||||
uint8 *data = new uint8[system.serialize_size];
|
||||
fp.read(data, system.serialize_size);
|
||||
serializer s(data, system.serialize_size);
|
||||
delete[] data;
|
||||
fp.close();
|
||||
return s;
|
||||
}
|
||||
|
||||
bool StateManager::save(const char *filename, uint8 slot, serializer &s, const char *description) {
|
||||
//if no state archive exists ...
|
||||
if(file::exists(filename) == false) {
|
||||
//try and create one
|
||||
if(create(filename) == false) return false;
|
||||
}
|
||||
//if we cannot load the existing state archive ...
|
||||
if(load(filename) == false) {
|
||||
//it's probably an older version, try and create a new one
|
||||
if(create(filename) == false) return false;
|
||||
//it still needs to be loaded before we can write to it
|
||||
if(load(filename) == false) return false;
|
||||
}
|
||||
|
||||
uint8 index = findslot(slot);
|
||||
if(index == SlotInvalid) {
|
||||
//create new slot instead of over-writing existing slot
|
||||
if(info.slotcount >= 255) return false;
|
||||
index = info.slotcount;
|
||||
slot = info.slotcount;
|
||||
}
|
||||
|
||||
file fp;
|
||||
if(fp.open(filename, file::mode_readwrite) == false) return false;
|
||||
|
||||
fp.seek(SlotIndex + index);
|
||||
fp.write(slot);
|
||||
|
||||
time_t current = time(0);
|
||||
tm *ts = localtime(¤t);
|
||||
char timestamp[32];
|
||||
sprintf(timestamp, "%.4u-%.2u-%.2u %.2u:%.2u:%.2u",
|
||||
1900 + ts->tm_year, ts->tm_mon + 1, ts->tm_mday,
|
||||
ts->tm_hour, ts->tm_min, ts->tm_sec,
|
||||
(ts->tm_hour < 12 ? "AM" : "PM")
|
||||
);
|
||||
fp.seek(DateTimeIndex + index * DateTimeSize);
|
||||
fp.write((uint8*)×tamp[0], DateTimeSize);
|
||||
|
||||
char desc[DescriptionSize];
|
||||
memset(&desc, 0, DescriptionSize);
|
||||
strlcpy(desc, description, DescriptionSize);
|
||||
fp.seek(DescIndex + index * DescriptionSize);
|
||||
fp.write((uint8*)&desc[0], DescriptionSize);
|
||||
|
||||
fp.seek(HeaderSize + index * system.serialize_size);
|
||||
fp.write(s.data(), s.size());
|
||||
for(unsigned n = 0; n < system.serialize_size - s.size(); n++) fp.write(0x00);
|
||||
|
||||
fp.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StateManager::erase(const char *filename, uint8 slot) {
|
||||
if(load(filename) == false) return false;
|
||||
uint8 index = findslot(slot);
|
||||
if(index == SlotInvalid) return false;
|
||||
|
||||
file fp;
|
||||
if(fp.open(filename, file::mode_readwrite) == false) return false;
|
||||
if(info.slotcount <= slot) return false;
|
||||
|
||||
//copy the very last state to the slot that is to be erased
|
||||
uint8 lastslot = info.slotcount - 1;
|
||||
info.slot[index] = info.slot[lastslot];
|
||||
info.slot[lastslot] = SlotInvalid;
|
||||
|
||||
fp.seek(DateTimeIndex + index * DateTimeSize);
|
||||
fp.write((uint8*)&info.datetime[lastslot * DateTimeSize], DateTimeSize);
|
||||
|
||||
fp.seek(DescIndex + index * DescriptionSize);
|
||||
fp.write((uint8*)&info.description[lastslot * DescriptionSize], DescriptionSize);
|
||||
|
||||
fp.seek(HeaderSize + system.serialize_size * lastslot);
|
||||
uint8 *data = new uint8[system.serialize_size];
|
||||
fp.read(data, system.serialize_size);
|
||||
|
||||
fp.seek(HeaderSize + system.serialize_size * index);
|
||||
fp.write(data, system.serialize_size);
|
||||
delete[] data;
|
||||
|
||||
//decrement all IDs after the deleted one (removes empty slot ID from deletion)
|
||||
for(unsigned n = 0; n < lastslot; n++) {
|
||||
if(info.slot[n] > slot) info.slot[n]--;
|
||||
}
|
||||
|
||||
fp.seek(SlotIndex);
|
||||
fp.write(info.slot, 256);
|
||||
|
||||
unsigned size = fp.size();
|
||||
fp.truncate(size - system.serialize_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StateManager::load(const char *filename) {
|
||||
file fp;
|
||||
if(fp.open(filename, file::mode_read) == false) return false;
|
||||
unsigned filesize = fp.size();
|
||||
if(filesize < HeaderSize) return false;
|
||||
fp.seek(0);
|
||||
if(fp.readl(4) != 0x31415342) return false;
|
||||
if(fp.readl(4) != bsnesSaveStateVersion) return false;
|
||||
fp.read((uint8*)&info.slot[0], 256);
|
||||
fp.read((uint8*)&info.datetime[0], 256 * DateTimeSize);
|
||||
fp.read((uint8*)&info.description[0], 256 * DescriptionSize);
|
||||
info.slotcount = (filesize - HeaderSize) / system.serialize_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StateManager::create(const char *filename) const {
|
||||
file fp;
|
||||
if(fp.open(filename, file::mode_write) == false) return false;
|
||||
fp.writel(0x31415342, 4); //signature ('BSA1')
|
||||
fp.writel(bsnesSaveStateVersion, 4); //version
|
||||
for(unsigned i = 0; i < 256 * SlotSize; i++) fp.write(SlotInvalid); //slot index
|
||||
for(unsigned i = 0; i < 256 * DateTimeSize; i++) fp.write(0x20); //date / time
|
||||
for(unsigned i = 0; i < 256 * DescriptionSize; i++) fp.write(0x00); //description
|
||||
fp.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8 StateManager::findslot(uint8 slot) const {
|
||||
if(slot == SlotInvalid) return SlotInvalid;
|
||||
for(unsigned n = 0; n < info.slotcount; n++) {
|
||||
if(info.slot[n] == slot) return n;
|
||||
}
|
||||
return SlotInvalid;
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
class StateManager : noncopyable {
|
||||
public:
|
||||
enum {
|
||||
SlotInvalid = 0xff,
|
||||
|
||||
SlotSize = 1,
|
||||
DateTimeSize = 19,
|
||||
DescriptionSize = 512,
|
||||
|
||||
HeaderSize = 8 + (256 * SlotSize) + (256 * DateTimeSize) + (256 * DescriptionSize),
|
||||
SlotIndex = 8,
|
||||
DateTimeIndex = SlotIndex + (256 * SlotSize),
|
||||
DescIndex = DateTimeIndex + (256 * DateTimeSize),
|
||||
};
|
||||
|
||||
void list(lstring&) const;
|
||||
bool load(const char *filename);
|
||||
bool set_description(const char *filename, uint8 slot, const char *description);
|
||||
serializer load(const char *filename, uint8 slot);
|
||||
bool save(const char *filename, uint8 slot, serializer&, const char *description);
|
||||
bool erase(const char *filename, uint8 slot);
|
||||
|
||||
private:
|
||||
struct Info {
|
||||
unsigned slotcount;
|
||||
uint8 slot[256 * SlotSize];
|
||||
char datetime[256 * DateTimeSize];
|
||||
char description[256 * DescriptionSize];
|
||||
} info;
|
||||
|
||||
bool create(const char *filename) const;
|
||||
uint8 findslot(uint8 slot) const;
|
||||
};
|
||||
|
||||
extern StateManager statemanager;
|
@@ -9,16 +9,16 @@ System system;
|
||||
#include "debugger/debugger.cpp"
|
||||
#include "serialization.cpp"
|
||||
#include "scheduler/scheduler.cpp"
|
||||
#include "statemanager/statemanager.cpp"
|
||||
|
||||
#include "video/video.cpp"
|
||||
#include "audio/audio.cpp"
|
||||
#include "input/input.cpp"
|
||||
|
||||
void System::coprocessor_enter() {
|
||||
if(cartridge.mode() == Cartridge::ModeSuperGameBoy) sgb.enter();
|
||||
if(cartridge.mode() == Cartridge::ModeSuperGameBoy) supergameboy.enter();
|
||||
if(cartridge.has_superfx()) superfx.enter();
|
||||
if(cartridge.has_sa1()) sa1.enter();
|
||||
if(cartridge.has_21fx()) s21fx.enter();
|
||||
|
||||
while(true) {
|
||||
scheduler.addclocks_cop(64 * 1024 * 1024);
|
||||
@@ -60,7 +60,7 @@ void System::init(Interface *interface_) {
|
||||
interface = interface_;
|
||||
assert(interface != 0);
|
||||
|
||||
sgb.init();
|
||||
supergameboy.init();
|
||||
sa1.init();
|
||||
superfx.init();
|
||||
bsxbase.init();
|
||||
@@ -78,6 +78,7 @@ void System::init(Interface *interface_) {
|
||||
st010.init();
|
||||
st011.init();
|
||||
st018.init();
|
||||
s21fx.init();
|
||||
|
||||
video.init();
|
||||
audio.init();
|
||||
@@ -95,6 +96,8 @@ void System::power() {
|
||||
snes_region = (cartridge.region() == Cartridge::NTSC ? NTSC : PAL);
|
||||
}
|
||||
|
||||
audio.coprocessor_enable(false);
|
||||
|
||||
scheduler.init();
|
||||
bus.power();
|
||||
|
||||
@@ -108,7 +111,7 @@ void System::power() {
|
||||
if(expansion() == ExpansionBSX) bsxbase.enable();
|
||||
if(memory::bsxflash.data()) bsxflash.enable();
|
||||
if(cartridge.mode() == Cartridge::ModeBsx) bsxcart.enable();
|
||||
if(cartridge.mode() == Cartridge::ModeSuperGameBoy) sgb.enable();
|
||||
if(cartridge.mode() == Cartridge::ModeSuperGameBoy) supergameboy.enable();
|
||||
|
||||
if(cartridge.has_superfx()) superfx.enable();
|
||||
if(cartridge.has_sa1()) sa1.enable();
|
||||
@@ -124,11 +127,12 @@ void System::power() {
|
||||
if(cartridge.has_st010()) st010.enable();
|
||||
if(cartridge.has_st011()) st011.enable();
|
||||
if(cartridge.has_st018()) st018.enable();
|
||||
if(cartridge.has_21fx()) s21fx.enable();
|
||||
|
||||
if(expansion() == ExpansionBSX) bsxbase.power();
|
||||
if(memory::bsxflash.data()) bsxflash.power();
|
||||
if(cartridge.mode() == Cartridge::ModeBsx) bsxcart.power();
|
||||
if(cartridge.mode() == Cartridge::ModeSuperGameBoy) sgb.power();
|
||||
if(cartridge.mode() == Cartridge::ModeSuperGameBoy) supergameboy.power();
|
||||
|
||||
if(cartridge.has_superfx()) superfx.power();
|
||||
if(cartridge.has_sa1()) sa1.power();
|
||||
@@ -144,8 +148,8 @@ void System::power() {
|
||||
if(cartridge.has_st010()) st010.power();
|
||||
if(cartridge.has_st011()) st011.power();
|
||||
if(cartridge.has_st018()) st018.power();
|
||||
if(cartridge.has_21fx()) s21fx.power();
|
||||
|
||||
//ppu.PPUcounter::reset();
|
||||
cpu.power();
|
||||
smp.power();
|
||||
dsp.power();
|
||||
@@ -160,7 +164,6 @@ void System::power() {
|
||||
void System::reset() {
|
||||
scheduler.init();
|
||||
|
||||
//ppu.PPUcounter::reset();
|
||||
cpu.reset();
|
||||
smp.reset();
|
||||
dsp.reset();
|
||||
@@ -170,7 +173,7 @@ void System::reset() {
|
||||
if(expansion() == ExpansionBSX) bsxbase.reset();
|
||||
if(memory::bsxflash.data()) bsxflash.reset();
|
||||
if(cartridge.mode() == Cartridge::ModeBsx) bsxcart.reset();
|
||||
if(cartridge.mode() == Cartridge::ModeSuperGameBoy) sgb.reset();
|
||||
if(cartridge.mode() == Cartridge::ModeSuperGameBoy) supergameboy.reset();
|
||||
|
||||
if(cartridge.has_superfx()) superfx.reset();
|
||||
if(cartridge.has_sa1()) sa1.reset();
|
||||
@@ -186,6 +189,7 @@ void System::reset() {
|
||||
if(cartridge.has_st010()) st010.reset();
|
||||
if(cartridge.has_st011()) st011.reset();
|
||||
if(cartridge.has_st018()) st018.reset();
|
||||
if(cartridge.has_21fx()) s21fx.reset();
|
||||
|
||||
input.port_set_device(0, config.controller_port1);
|
||||
input.port_set_device(1, config.controller_port2);
|
||||
@@ -193,6 +197,10 @@ void System::reset() {
|
||||
video.update();
|
||||
}
|
||||
|
||||
void System::unload() {
|
||||
if(cartridge.mode() == Cartridge::ModeSuperGameBoy) supergameboy.unload();
|
||||
}
|
||||
|
||||
void System::scanline() {
|
||||
video.scanline();
|
||||
if(cpu.vcounter() == 241) scheduler.exit();
|
||||
|
@@ -2,7 +2,6 @@
|
||||
#include "debugger/debugger.hpp"
|
||||
#include "interface/interface.hpp"
|
||||
#include "scheduler/scheduler.hpp"
|
||||
#include "statemanager/statemanager.hpp"
|
||||
|
||||
#include "video/video.hpp"
|
||||
#include "audio/audio.hpp"
|
||||
@@ -17,22 +16,24 @@ public:
|
||||
enum ExpansionPortDevice { ExpansionNone = 0, ExpansionBSX = 1 };
|
||||
|
||||
//system functions
|
||||
virtual void run();
|
||||
virtual void runtosave();
|
||||
void run();
|
||||
void runtosave();
|
||||
|
||||
virtual void init(Interface*);
|
||||
virtual void term();
|
||||
virtual void power();
|
||||
virtual void reset();
|
||||
void init(Interface*);
|
||||
void term();
|
||||
void power();
|
||||
void reset();
|
||||
void unload();
|
||||
|
||||
virtual void frame();
|
||||
virtual void scanline();
|
||||
void frame();
|
||||
void scanline();
|
||||
|
||||
//return *active* region / expansion port device information
|
||||
//settings cached upon power-on
|
||||
Region region() const;
|
||||
ExpansionPortDevice expansion() const;
|
||||
|
||||
unsigned serialize_size() const;
|
||||
serializer serialize();
|
||||
bool unserialize(serializer&);
|
||||
|
||||
@@ -40,7 +41,7 @@ public:
|
||||
virtual ~System() {}
|
||||
|
||||
private:
|
||||
unsigned serialize_size;
|
||||
unsigned serializer_size;
|
||||
void serialize(serializer&);
|
||||
void serialize_all(serializer&);
|
||||
void serialize_init();
|
||||
|
@@ -1,23 +1,38 @@
|
||||
objects := ui-main $(objects)
|
||||
objects := ui-main ui-base ui-debugger ui-input ui-movie ui-settings ui-state ui-tools $(objects)
|
||||
objects += $(if $(call streq,$(platform),win),resource)
|
||||
link += $(qtlib)
|
||||
|
||||
headers := $(call rwildcard,$(ui)/,%.hpp)
|
||||
moc_headers := $(call rwildcard,$(ui)/,%.moc.hpp)
|
||||
moc_objects := $(patsubst %.moc.hpp,%.moc,$(moc_headers))
|
||||
moc_objects := $(foreach f,$(moc_headers),obj/$(notdir $(patsubst %.moc.hpp,%.moc,$f)))
|
||||
qt_compile = $(call compile,-Iobj $(qtinc))
|
||||
|
||||
#############
|
||||
### rules ###
|
||||
#############
|
||||
|
||||
# automatically run moc on all .moc.hpp (MOC header) files
|
||||
%.moc: $<; $(moc) -f $< -o $@
|
||||
$(foreach f,$(moc_objects),$(eval $f: $(patsubst %.moc,%.moc.hpp,$f)))
|
||||
%.moc: $<; $(moc) -i $< -o $@
|
||||
|
||||
obj/ui-main.o: $(ui)/main.cpp $(call rwildcard,$(ui)/)
|
||||
$(call compile,$(qtinc))
|
||||
# automatically generate %.moc build rules
|
||||
__list = $(moc_headers)
|
||||
$(foreach f,$(moc_objects), \
|
||||
$(eval __file = $(word 1,$(__list))) \
|
||||
$(eval __list = $(wordlist 2,$(words $(__list)),$(__list))) \
|
||||
$(eval $f: $(__file)) \
|
||||
)
|
||||
|
||||
$(ui)/resource/resource.rcc: $(ui)/resource/resource.qrc data/*
|
||||
$(rcc) $(ui)/resource/resource.qrc -o $(ui)/resource/resource.rcc
|
||||
obj/ui-main.o: $(ui)/main.cpp $(headers) $(wildcard $(ui)/*.cpp) $(wildcard $(ui)/platform/*.cpp) $(wildcard $(ui)/utility/*.cpp); $(qt_compile)
|
||||
obj/ui-base.o: $(ui)/base/base.cpp $(headers) $(wildcard $(ui)/base/*.cpp); $(qt_compile)
|
||||
obj/ui-debugger.o: $(ui)/debugger/debugger.cpp $(headers) $(wildcard $(ui)/debugger/*.cpp); $(qt_compile)
|
||||
obj/ui-input.o: $(ui)/input/input.cpp $(headers) $(wildcard $(ui)/input/*.cpp); $(qt_compile)
|
||||
obj/ui-movie.o: $(ui)/movie/movie.cpp $(headers) $(wildcard $(ui)/movie/*.cpp); $(qt_compile)
|
||||
obj/ui-settings.o: $(ui)/settings/settings.cpp $(headers) $(wildcard $(ui)/settings/*.cpp); $(qt_compile)
|
||||
obj/ui-state.o: $(ui)/state/state.cpp $(headers) $(wildcard $(ui)/state/*.cpp); $(qt_compile)
|
||||
obj/ui-tools.o: $(ui)/tools/tools.cpp $(headers) $(wildcard $(ui)/tools/*.cpp); $(qt_compile)
|
||||
|
||||
obj/resource.rcc: $(ui)/resource/resource.qrc data/*
|
||||
$(rcc) $(ui)/resource/resource.qrc -o obj/resource.rcc
|
||||
|
||||
obj/resource.o: $(ui)/resource/resource.rc
|
||||
windres $(ui)/resource/resource.rc obj/resource.o
|
||||
@@ -26,7 +41,7 @@ obj/resource.o: $(ui)/resource/resource.rc
|
||||
### targets ###
|
||||
###############
|
||||
|
||||
ui_build: $(ui)/resource/resource.rcc $(moc_objects);
|
||||
ui_build: obj/resource.rcc $(moc_objects);
|
||||
ui_clean:
|
||||
-$(foreach f,$(moc_objects),@$(call delete,$f))
|
||||
-@$(call delete,$(ui)/resource/resource.rcc)
|
||||
-@$(call delete,obj/*.rcc)
|
||||
-@$(call delete,obj/*.moc)
|
||||
|
@@ -1,3 +1,6 @@
|
||||
#include "application.moc"
|
||||
Application application;
|
||||
|
||||
#include "init.cpp"
|
||||
#include "qb.cpp"
|
||||
|
||||
@@ -15,30 +18,30 @@ void Application::initPaths(const char *basename) {
|
||||
}
|
||||
|
||||
if(strend(temp, "/") == false) strcat(temp, "/");
|
||||
config.path.base = temp;
|
||||
config().path.base = temp;
|
||||
} else {
|
||||
config.path.base = "";
|
||||
config().path.base = "";
|
||||
}
|
||||
|
||||
if(userpath(temp)) {
|
||||
strtr(temp, "\\", "/");
|
||||
if(strend(temp, "/") == false) strcat(temp, "/");
|
||||
config.path.user = temp;
|
||||
config().path.user = temp;
|
||||
} else {
|
||||
config.path.user = "";
|
||||
config().path.user = "";
|
||||
}
|
||||
|
||||
char cwd[PATH_MAX];
|
||||
config.path.current = getcwd(cwd);
|
||||
config().path.startup = getcwd(cwd);
|
||||
}
|
||||
|
||||
void Application::locateFile(string &filename, bool createDataDirectory) {
|
||||
//first, check if file exists in executable directory (single-user mode)
|
||||
string temp = string() << config.path.base << filename;
|
||||
string temp = string() << config().path.base << filename;
|
||||
|
||||
if(file::exists(temp) == false) {
|
||||
//if not, use user data path (multi-user mode)
|
||||
temp = config.path.user;
|
||||
temp = config().path.user;
|
||||
temp << ".bsnes";
|
||||
if(createDataDirectory) mkdir(temp); //ensure directory exists
|
||||
temp << "/" << filename;
|
||||
@@ -66,9 +69,11 @@ int Application::main(int &argc, char **argv) {
|
||||
app->setStyleSheet(defaultStylesheet);
|
||||
}
|
||||
|
||||
config.load(configFilename);
|
||||
config().load(configFilename);
|
||||
mapper().bind();
|
||||
init();
|
||||
SNES::system.init(&interface);
|
||||
mainWindow->system_loadSpecial_superGameBoy->setVisible(SNES::supergameboy.opened());
|
||||
|
||||
if(argc == 2) {
|
||||
//if valid file was specified on the command-line, attempt to load it now
|
||||
@@ -81,23 +86,12 @@ int Application::main(int &argc, char **argv) {
|
||||
app->exec();
|
||||
|
||||
//QbWindow::hide() saves window geometry for next run
|
||||
loaderWindow->window->hide();
|
||||
htmlViewerWindow->window->hide();
|
||||
aboutWindow->window->hide();
|
||||
diskBrowser->window->hide();
|
||||
folderCreator->window->hide();
|
||||
settingsWindow->window->hide();
|
||||
inputCaptureWindow->window->hide();
|
||||
inputMouseCaptureWindow->window->hide();
|
||||
inputCalibrationWindow->window->hide();
|
||||
toolsWindow->window->hide();
|
||||
debugger->window->hide();
|
||||
breakpointEditor->window->hide();
|
||||
memoryEditor->window->hide();
|
||||
vramViewer->window->hide();
|
||||
for(unsigned i = 0; i < windowList.size(); i++) {
|
||||
windowList[i]->hide();
|
||||
}
|
||||
|
||||
utility.unloadCartridge();
|
||||
config.save(configFilename);
|
||||
config().save(configFilename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -110,9 +104,9 @@ void Application::run() {
|
||||
|
||||
QApplication::processEvents();
|
||||
utility.updateSystemState();
|
||||
inputManager.refresh();
|
||||
mapper().poll();
|
||||
|
||||
if(config.input.focusPolicy == Configuration::Input::FocusPolicyPauseEmulation) {
|
||||
if(config().input.focusPolicy == Configuration::Input::FocusPolicyPauseEmulation) {
|
||||
bool active = mainWindow->isActive();
|
||||
if(!autopause && !active) {
|
||||
autopause = true;
|
||||
@@ -126,6 +120,7 @@ void Application::run() {
|
||||
|
||||
if(SNES::cartridge.loaded() && !pause && !autopause && (!debug || debugrun)) {
|
||||
SNES::system.run();
|
||||
#if defined(DEBUGGER)
|
||||
if(SNES::debugger.break_event != SNES::Debugger::None) {
|
||||
debug = true;
|
||||
debugrun = false;
|
||||
@@ -133,6 +128,7 @@ void Application::run() {
|
||||
debugger->event();
|
||||
SNES::debugger.break_event = SNES::Debugger::None;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
usleep(20 * 1000);
|
||||
}
|
||||
@@ -145,7 +141,7 @@ void Application::run() {
|
||||
if(autosaveTime >= CLOCKS_PER_SEC * 60) {
|
||||
//auto-save RAM once per minute in case of emulator crash
|
||||
autosaveTime = 0;
|
||||
if(config.system.autoSaveMemory == true) utility.saveMemory();
|
||||
if(config().system.autoSaveMemory == true) utility.saveMemory();
|
||||
}
|
||||
|
||||
if(screensaverTime >= CLOCKS_PER_SEC * 30) {
|
||||
|
@@ -29,6 +29,8 @@ public:
|
||||
string configFilename;
|
||||
string styleSheetFilename;
|
||||
|
||||
array<QbWindow*> windowList;
|
||||
|
||||
int main(int &argc, char **argv);
|
||||
void locateFile(string &filename, bool createDataDirectory = false);
|
||||
void initPaths(const char *basename);
|
||||
@@ -39,4 +41,6 @@ public:
|
||||
|
||||
public slots:
|
||||
void run();
|
||||
} application;
|
||||
};
|
||||
|
||||
extern Application application;
|
||||
|
@@ -1,25 +1,7 @@
|
||||
#include "../base/main.moc"
|
||||
#include "../base/diskbrowser.moc"
|
||||
#include "../base/loader.moc"
|
||||
#include "../base/htmlviewer.moc"
|
||||
#include "../base/about.moc"
|
||||
|
||||
#include "../settings/settings.moc"
|
||||
#include "../tools/tools.moc"
|
||||
|
||||
#include "../base/main.cpp"
|
||||
#include "../base/diskbrowser.cpp"
|
||||
#include "../base/loader.cpp"
|
||||
#include "../base/htmlviewer.cpp"
|
||||
#include "../base/about.cpp"
|
||||
|
||||
#include "../settings/settings.cpp"
|
||||
#include "../tools/tools.cpp"
|
||||
|
||||
void Application::init() {
|
||||
if(config.system.crashedOnLastRun == true) {
|
||||
if(config().system.crashedOnLastRun == true) {
|
||||
//emulator crashed on last run, disable all drivers
|
||||
QMessageBox::warning(0, "bsnes Crash Notification", utf8() <<
|
||||
QMessageBox::warning(0, "bsnes Crash Notification", string() <<
|
||||
"<p><b>Warning:</b><br>bsnes crashed while attempting to initialize device "
|
||||
"drivers the last time it was run.</p>"
|
||||
"<p>To prevent this from occurring again, all drivers have been disabled. Please "
|
||||
@@ -27,19 +9,19 @@ void Application::init() {
|
||||
"restart the emulator for the changes to take effect. <i>Video, audio and input "
|
||||
"will not work until you do this!</i></p>"
|
||||
"<p><b>Settings that caused failure on last run:</b><br>"
|
||||
<< "Video driver: " << config.system.video << "<br>"
|
||||
<< "Audio driver: " << config.system.audio << "<br>"
|
||||
<< "Input driver: " << config.system.input << "<br></p>"
|
||||
<< "Video driver: " << config().system.video << "<br>"
|
||||
<< "Audio driver: " << config().system.audio << "<br>"
|
||||
<< "Input driver: " << config().system.input << "<br></p>"
|
||||
);
|
||||
|
||||
config.system.video = "None";
|
||||
config.system.audio = "None";
|
||||
config.system.input = "None";
|
||||
config().system.video = "None";
|
||||
config().system.audio = "None";
|
||||
config().system.input = "None";
|
||||
}
|
||||
|
||||
if(config.system.video == "") config.system.video = video.default_driver();
|
||||
if(config.system.audio == "") config.system.audio = audio.default_driver();
|
||||
if(config.system.input == "") config.system.input = input.default_driver();
|
||||
if(config().system.video == "") config().system.video = video.default_driver();
|
||||
if(config().system.audio == "") config().system.audio = audio.default_driver();
|
||||
if(config().system.input == "") config().system.input = input.default_driver();
|
||||
|
||||
mainWindow = new MainWindow;
|
||||
loaderWindow = new LoaderWindow;
|
||||
@@ -53,21 +35,23 @@ void Application::init() {
|
||||
utility.updateFullscreenState();
|
||||
QApplication::processEvents();
|
||||
|
||||
#if defined(DEBUGGER)
|
||||
debugger = new Debugger;
|
||||
#endif
|
||||
settingsWindow = new SettingsWindow;
|
||||
toolsWindow = new ToolsWindow;
|
||||
|
||||
//if emulator crashes while initializing drivers, next run will disable them all.
|
||||
//this will allow user to choose different driver settings.
|
||||
config.system.crashedOnLastRun = true;
|
||||
config.save(configFilename);
|
||||
config().system.crashedOnLastRun = true;
|
||||
config().save(configFilename);
|
||||
|
||||
video.driver(config.system.video);
|
||||
video.driver(config().system.video);
|
||||
video.set(Video::Handle, (uintptr_t)mainWindow->canvas->winId());
|
||||
video.set("QWidget", (QWidget*)mainWindow->canvas);
|
||||
if(video.init() == false) {
|
||||
QMessageBox::warning(0, "bsnes", utf8() <<
|
||||
"<p><b>Warning:</b> " << config.system.video << " video driver failed to initialize. "
|
||||
QMessageBox::warning(0, "bsnes", string() <<
|
||||
"<p><b>Warning:</b> " << config().system.video << " video driver failed to initialize. "
|
||||
"Video driver has been disabled.</p>"
|
||||
"<p>Please go to Settings->Configuration->Advanced and choose a different driver, and "
|
||||
"then restart the emulator for the changes to take effect.</p>"
|
||||
@@ -76,14 +60,14 @@ void Application::init() {
|
||||
video.init();
|
||||
}
|
||||
|
||||
audio.driver(config.system.audio);
|
||||
audio.driver(config().system.audio);
|
||||
audio.set(Audio::Handle, (uintptr_t)mainWindow->canvas->winId());
|
||||
audio.set(Audio::Frequency, config.audio.outputFrequency);
|
||||
audio.set(Audio::Latency, config.audio.latency);
|
||||
audio.set(Audio::Volume, config.audio.volume);
|
||||
audio.set(Audio::Frequency, config().audio.outputFrequency);
|
||||
audio.set(Audio::Latency, config().audio.latency);
|
||||
audio.set(Audio::Volume, config().audio.volume);
|
||||
if(audio.init() == false) {
|
||||
QMessageBox::warning(0, "bsnes", utf8() <<
|
||||
"<p><b>Warning:</b> " << config.system.audio << " audio driver failed to initialize. "
|
||||
QMessageBox::warning(0, "bsnes", string() <<
|
||||
"<p><b>Warning:</b> " << config().system.audio << " audio driver failed to initialize. "
|
||||
"Audio driver has been disabled.</p>"
|
||||
"<p>Please go to Settings->Configuration->Advanced and choose a different driver, and "
|
||||
"then restart the emulator for the changes to take effect.</p>"
|
||||
@@ -92,11 +76,11 @@ void Application::init() {
|
||||
audio.init();
|
||||
}
|
||||
|
||||
input.driver(config.system.input);
|
||||
input.driver(config().system.input);
|
||||
input.set("Handle", (uintptr_t)mainWindow->canvas->winId());
|
||||
if(input.init() == false) {
|
||||
QMessageBox::warning(0, "bsnes", utf8() <<
|
||||
"<p><b>Warning:</b> " << config.system.input << " input driver failed to initialize. "
|
||||
QMessageBox::warning(0, "bsnes", string() <<
|
||||
"<p><b>Warning:</b> " << config().system.input << " input driver failed to initialize. "
|
||||
"Input driver has been disabled.</p>"
|
||||
"<p>Please go to Settings->Configuration->Advanced and choose a different driver, and "
|
||||
"then restart the emulator for the changes to take effect.</p>"
|
||||
@@ -106,18 +90,17 @@ void Application::init() {
|
||||
}
|
||||
|
||||
//didn't crash, note this in the config file now in case a different kind of crash occurs later
|
||||
config.system.crashedOnLastRun = false;
|
||||
config.save(configFilename);
|
||||
config().system.crashedOnLastRun = false;
|
||||
config().save(configFilename);
|
||||
|
||||
inputManager.bind();
|
||||
inputManager.refresh();
|
||||
inputManager.refresh();
|
||||
inputManager.onInput = bind(&Utility::inputEvent, &utility);
|
||||
//no sense showing unusable options ...
|
||||
pixelShaderWindow->setVisible(video.cap(Video::FragmentShader) || video.cap(Video::VertexShader));
|
||||
|
||||
utility.resizeMainWindow();
|
||||
utility.updateAvSync();
|
||||
utility.updateVideoMode();
|
||||
utility.updateColorFilter();
|
||||
utility.updatePixelShader();
|
||||
utility.updateHardwareFilter();
|
||||
utility.updateSoftwareFilter();
|
||||
utility.updateEmulationSpeed();
|
||||
|
@@ -1,8 +1,10 @@
|
||||
void QbWindow::shrink() {
|
||||
for(unsigned i = 0; i < 2; i++) {
|
||||
resize(0, 0);
|
||||
usleep(2000);
|
||||
QApplication::processEvents();
|
||||
if(config().video.isFullscreen == false) {
|
||||
for(unsigned i = 0; i < 2; i++) {
|
||||
resize(0, 0);
|
||||
usleep(2000);
|
||||
QApplication::processEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +44,14 @@ void QbWindow::closeEvent(QCloseEvent *event) {
|
||||
QWidget::hide();
|
||||
}
|
||||
|
||||
void QbWindow::keyReleaseEvent(QKeyEvent *event) {
|
||||
if(event->key() == Qt::Key_Escape) close();
|
||||
QWidget::keyReleaseEvent(event);
|
||||
}
|
||||
|
||||
QbWindow::QbWindow(string &geometryString_) : geometryString(geometryString_) {
|
||||
//keep track of all created windows (for geometry save on exit, always-on-top control, etc)
|
||||
application.windowList.add(this);
|
||||
}
|
||||
|
||||
//
|
||||
|
@@ -4,6 +4,7 @@ public:
|
||||
void show();
|
||||
void hide();
|
||||
void closeEvent(QCloseEvent*);
|
||||
void keyReleaseEvent(QKeyEvent*);
|
||||
QbWindow(string&);
|
||||
|
||||
private:
|
||||
|
@@ -1,19 +1,21 @@
|
||||
AboutWindow::AboutWindow() {
|
||||
window = new QbWindow(config.geometry.aboutWindow);
|
||||
window->setObjectName("about-window");
|
||||
window->setWindowTitle("About bsnes ...");
|
||||
#include "about.moc"
|
||||
AboutWindow *aboutWindow;
|
||||
|
||||
AboutWindow::AboutWindow() : QbWindow(config().geometry.aboutWindow) {
|
||||
setObjectName("about-window");
|
||||
setWindowTitle("About bsnes ...");
|
||||
|
||||
layout = new QVBoxLayout;
|
||||
layout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
layout->setMargin(Style::WindowMargin);
|
||||
layout->setSpacing(Style::WidgetSpacing);
|
||||
window->setLayout(layout);
|
||||
setLayout(layout);
|
||||
|
||||
logo = new Logo;
|
||||
logo->setFixedSize(600, 106);
|
||||
layout->addWidget(logo);
|
||||
|
||||
info = new QLabel(utf8() <<
|
||||
info = new QLabel(string() <<
|
||||
"<table>"
|
||||
"<tr><td align='right'><b>Version: </b></td><td>" << bsnesVersion << "</td></tr>"
|
||||
"<tr><td align='right'><b>Author: </b></td><td>byuu</td></tr>"
|
||||
|
@@ -1,15 +1,14 @@
|
||||
class AboutWindow : public QObject {
|
||||
class AboutWindow : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QbWindow *window;
|
||||
QVBoxLayout *layout;
|
||||
struct Logo : public QWidget {
|
||||
void paintEvent(QPaintEvent*);
|
||||
} *logo;
|
||||
QLabel *info;
|
||||
struct Logo : public QWidget {
|
||||
void paintEvent(QPaintEvent*);
|
||||
} *logo;
|
||||
QLabel *info;
|
||||
|
||||
AboutWindow();
|
||||
};
|
||||
|
||||
public slots:
|
||||
} *aboutWindow;
|
||||
extern AboutWindow *aboutWindow;
|
||||
|
7
src/ui_qt/base/base.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "../ui-base.hpp"
|
||||
|
||||
#include "about.cpp"
|
||||
#include "diskbrowser.cpp"
|
||||
#include "htmlviewer.cpp"
|
||||
#include "loader.cpp"
|
||||
#include "main.cpp"
|
@@ -1,17 +1,20 @@
|
||||
#include "diskbrowser.moc"
|
||||
FolderCreator *folderCreator;
|
||||
DiskBrowser *diskBrowser;
|
||||
|
||||
//=============
|
||||
//FolderCreator
|
||||
//=============
|
||||
|
||||
FolderCreator::FolderCreator() {
|
||||
window = new QbWindow(config.geometry.folderCreator);
|
||||
window->setObjectName("folder-creator");
|
||||
window->setWindowTitle("Create New Folder");
|
||||
FolderCreator::FolderCreator() : QbWindow(config().geometry.folderCreator) {
|
||||
setObjectName("folder-creator");
|
||||
setWindowTitle("Create New Folder");
|
||||
|
||||
layout = new QVBoxLayout;
|
||||
layout->setMargin(Style::WindowMargin);
|
||||
layout->setSpacing(Style::WidgetSpacing);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
window->setLayout(layout);
|
||||
setLayout(layout);
|
||||
|
||||
label = new QLabel("Folder name:");
|
||||
layout->addWidget(label);
|
||||
@@ -31,12 +34,12 @@ FolderCreator::FolderCreator() {
|
||||
|
||||
connect(name, SIGNAL(returnPressed()), this, SLOT(createFolder()));
|
||||
connect(ok, SIGNAL(released()), this, SLOT(createFolder()));
|
||||
connect(cancel, SIGNAL(released()), window, SLOT(hide()));
|
||||
connect(cancel, SIGNAL(released()), this, SLOT(close()));
|
||||
}
|
||||
|
||||
void FolderCreator::show() {
|
||||
name->setText("");
|
||||
window->show();
|
||||
QbWindow::show();
|
||||
name->setFocus();
|
||||
}
|
||||
|
||||
@@ -45,12 +48,12 @@ void FolderCreator::createFolder() {
|
||||
QMessageBox::warning(0, "Create New Folder", "<b>Note:</b> you must enter a folder name.");
|
||||
} else {
|
||||
string folderName = string()
|
||||
<< diskBrowser->path->currentText().toUtf8().constData()
|
||||
<< diskBrowser->model->rootPath().toUtf8().constData()
|
||||
<< "/"
|
||||
<< name->text().toUtf8().constData();
|
||||
|
||||
if(mkdir(folderName) == 0) {
|
||||
window->hide();
|
||||
hide();
|
||||
} else {
|
||||
QMessageBox::warning(0, "Create new Folder", "<b>Error:</b> failed to create folder. Please ensure only valid characters were used in the folder name.");
|
||||
}
|
||||
@@ -78,17 +81,6 @@ void DiskBrowserView::keyPressEvent(QKeyEvent *event) {
|
||||
QTreeView::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void DiskBrowserView::keyReleaseEvent(QKeyEvent *event) {
|
||||
//act like a modal dialog; close window on escape keypress
|
||||
if(event->key() == Qt::Key_Escape) {
|
||||
emit escape();
|
||||
return;
|
||||
}
|
||||
|
||||
//fallback: unrecognized keypresses get handled by the widget itself
|
||||
QTreeView::keyReleaseEvent(event);
|
||||
}
|
||||
|
||||
void DiskBrowserView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) {
|
||||
QAbstractItemView::currentChanged(current, previous);
|
||||
emit changed(current);
|
||||
@@ -101,7 +93,7 @@ void DiskBrowserView::currentChanged(const QModelIndex ¤t, const QModelInd
|
||||
void DiskBrowserImage::paintEvent(QPaintEvent*) {
|
||||
QPainter painter(this);
|
||||
if(name != "") {
|
||||
QImage image(name);
|
||||
QImage image(QString::fromUtf8(name));
|
||||
painter.drawImage(0, 0, image);
|
||||
}
|
||||
}
|
||||
@@ -110,82 +102,161 @@ void DiskBrowserImage::paintEvent(QPaintEvent*) {
|
||||
//DiskBrowser
|
||||
//===========
|
||||
|
||||
void DiskBrowser::chooseFolder(PathSettingWidget *widget, const char *title) {
|
||||
void DiskBrowser::inputEvent(uint16_t scancode) {
|
||||
if(!isActiveWindow() || isMinimized()) return;
|
||||
|
||||
//provide very simple support for controlling the window via gamepads
|
||||
if(Joypad::isAnyHat(scancode)) {
|
||||
int16_t state = mapper().state(scancode);
|
||||
|
||||
if(state == Joypad::HatUp) {
|
||||
QKeyEvent event((QEvent::Type)6, Qt::Key_Up, Qt::NoModifier);
|
||||
view->keyPressEvent(&event);
|
||||
}
|
||||
|
||||
if(state == Joypad::HatDown) {
|
||||
QKeyEvent event((QEvent::Type)6, Qt::Key_Down, Qt::NoModifier);
|
||||
view->keyPressEvent(&event);
|
||||
}
|
||||
|
||||
if(state == Joypad::HatLeft) {
|
||||
QKeyEvent event((QEvent::Type)6, Qt::Key_Backspace, Qt::NoModifier);
|
||||
view->keyPressEvent(&event);
|
||||
}
|
||||
|
||||
if(state == Joypad::HatRight) {
|
||||
QKeyEvent event((QEvent::Type)6, Qt::Key_Return, Qt::NoModifier);
|
||||
view->keyPressEvent(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiskBrowser::chooseFolder(const function<void (string)> &callback_, string ¤tPath_, const char *title) {
|
||||
callback = callback_;
|
||||
currentPath = ¤tPath_;
|
||||
browseMode = Folder;
|
||||
activePath = widget;
|
||||
window->hide();
|
||||
|
||||
hide();
|
||||
group->hide();
|
||||
ok->setText("Choose");
|
||||
window->setWindowTitle(utf8() << title);
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setWindowTitle(string() << title);
|
||||
setPath(*currentPath);
|
||||
setNameFilters("Folders ()");
|
||||
window->show();
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::chooseFile(const function<void (string)> &callback_, string ¤tPath_, const char *title) {
|
||||
callback = callback_;
|
||||
currentPath = ¤tPath_;
|
||||
browseMode = File;
|
||||
|
||||
hide();
|
||||
group->hide();
|
||||
ok->setText("Choose");
|
||||
setWindowTitle(string() << title);
|
||||
setPath(*currentPath);
|
||||
setNameFilters("All Files (*)");
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadCartridge() {
|
||||
currentPath = &config().path.current.cartridge;
|
||||
browseMode = Cartridge;
|
||||
window->hide();
|
||||
group->show();
|
||||
|
||||
hide();
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
window->setWindowTitle("Load Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "SNES cartridges (*.sfc *.smc" << reader.filterList << ");;All files (*)");
|
||||
window->show();
|
||||
setWindowTitle("Load Cartridge");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "SNES cartridges (*.sfc" << reader.extensionList << reader.compressionList << ");;"
|
||||
<< "BS-X cartridges (*.bs" << reader.compressionList << ");;"
|
||||
<< "Sufami Turbo cartridges (*.st" << reader.compressionList << ");;"
|
||||
<< "Game Boy cartridges (*.gb *.sgb *.gbc" << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
filter->setCurrentIndex(config().path.current.filter);
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadBaseCartridge() {
|
||||
currentPath = &config().path.current.cartridge;
|
||||
browseMode = BaseCartridge;
|
||||
window->hide();
|
||||
group->show();
|
||||
|
||||
hide();
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
window->setWindowTitle("Load Base Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "SNES cartridges (*.sfc *.smc" << reader.filterList << ");;All files (*)");
|
||||
window->show();
|
||||
setWindowTitle("Load Base Cartridge");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "SNES cartridges (*.sfc" << reader.extensionList << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadBsxCartridge() {
|
||||
currentPath = &config().path.current.bsx;
|
||||
browseMode = BsxCartridge;
|
||||
window->hide();
|
||||
group->show();
|
||||
|
||||
hide();
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
window->setWindowTitle("Load BS-X Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "BS-X cartridges (*.bs" << reader.filterList << ");;All files (*)");
|
||||
window->show();
|
||||
setWindowTitle("Load BS-X Cartridge");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "BS-X cartridges (*.bs" << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadSufamiTurboCartridge1() {
|
||||
currentPath = &config().path.current.st;
|
||||
browseMode = SufamiTurboCartridge1;
|
||||
window->hide();
|
||||
group->show();
|
||||
|
||||
hide();
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
window->setWindowTitle("Load Slot-A Sufami Turbo Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "Sufami Turbo cartridges (*.st" << reader.filterList << ");;All files (*)");
|
||||
window->show();
|
||||
setWindowTitle("Load Slot-A Sufami Turbo Cartridge");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "Sufami Turbo cartridges (*.st" << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadSufamiTurboCartridge2() {
|
||||
currentPath = &config().path.current.st;
|
||||
browseMode = SufamiTurboCartridge2;
|
||||
window->hide();
|
||||
group->show();
|
||||
|
||||
hide();
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
window->setWindowTitle("Load Slot-B Sufami Turbo Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "Sufami Turbo Cartridges (*.st" << reader.filterList << ");;All files (*)");
|
||||
window->show();
|
||||
setWindowTitle("Load Slot-B Sufami Turbo Cartridge");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "Sufami Turbo Cartridges (*.st" << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadSuperGameBoyCartridge() {
|
||||
currentPath = &config().path.current.sgb;
|
||||
browseMode = SuperGameBoyCartridge;
|
||||
window->hide();
|
||||
group->show();
|
||||
|
||||
hide();
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
window->setWindowTitle("Load Super Game Boy Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "Game Boy cartridges (*.gb *.gbc" << reader.filterList << ");;All files (*)");
|
||||
window->show();
|
||||
setWindowTitle("Load Super Game Boy Cartridge");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "Game Boy cartridges (*.gb *.sgb *.gbc" << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
show();
|
||||
}
|
||||
|
||||
string DiskBrowser::queryImageInformation() {
|
||||
@@ -231,7 +302,7 @@ void DiskBrowser::changeItem(const QModelIndex &item) {
|
||||
ok->setEnabled(true);
|
||||
image->name = nall::basename(filename) << ".png";
|
||||
if(file::exists(image->name) == false) image->name = "";
|
||||
info->setText(utf8() << queryImageInformation());
|
||||
info->setText(string() << queryImageInformation());
|
||||
string patch = nall::basename(filename) << ".ups";
|
||||
applyPatch->setVisible(file::exists(patch));
|
||||
}
|
||||
@@ -246,17 +317,48 @@ void DiskBrowser::loadSelected() {
|
||||
|
||||
if(browseMode == Folder || loadable == true) {
|
||||
QModelIndex item = view->currentIndex();
|
||||
config.path.current = dir(model->filePath(item).toUtf8().constData());
|
||||
window->hide();
|
||||
if(currentPath) *currentPath = dir(model->filePath(item).toUtf8().constData());
|
||||
hide();
|
||||
|
||||
switch(browseMode) { default:
|
||||
case Folder: activePath->selectPath(filename); break;
|
||||
case Cartridge: utility.loadCartridgeNormal(filename); break;
|
||||
case BaseCartridge: loaderWindow->selectBaseCartridge(filename); break;
|
||||
case BsxCartridge: loaderWindow->selectSlot1Cartridge(filename); break;
|
||||
case SufamiTurboCartridge1: loaderWindow->selectSlot1Cartridge(filename); break;
|
||||
case SufamiTurboCartridge2: loaderWindow->selectSlot2Cartridge(filename); break;
|
||||
case SuperGameBoyCartridge: loaderWindow->selectSlot1Cartridge(filename); break;
|
||||
if(browseMode == Folder || browseMode == File) {
|
||||
callback(filename);
|
||||
} else if(browseMode == Cartridge) {
|
||||
//quick-loading mode: determine load type via active filter
|
||||
config().path.current.filter = filter->currentIndex();
|
||||
|
||||
if(config().path.current.filter == 1) { //"BS-X cartridges"
|
||||
if(config().path.bsx == "") {
|
||||
loaderWindow->loadBsxCartridge("", filename);
|
||||
} else {
|
||||
utility.loadCartridgeBsx(config().path.bsx, filename);
|
||||
}
|
||||
} else if(config().path.current.filter == 2) { //"Sufami Turbo cartridges"
|
||||
if(config().path.st == "") {
|
||||
loaderWindow->loadSufamiTurboCartridge("", filename, "");
|
||||
} else {
|
||||
utility.loadCartridgeSufamiTurbo(config().path.st, filename, "");
|
||||
}
|
||||
} else if(config().path.current.filter == 3) { //"Game Boy cartridges"
|
||||
if(SNES::supergameboy.opened() == false) {
|
||||
QMessageBox::warning(0, "Warning", "Super Game Boy support missing - cartridge cannot be loaded.");
|
||||
} else if(config().path.sgb == "") {
|
||||
loaderWindow->loadSuperGameBoyCartridge("", filename);
|
||||
} else {
|
||||
utility.loadCartridgeSuperGameBoy(config().path.sgb, filename);
|
||||
}
|
||||
} else { //"SNES cartridges" (0) or "All files" (4)
|
||||
utility.loadCartridgeNormal(filename);
|
||||
}
|
||||
} else if(browseMode == BaseCartridge) {
|
||||
loaderWindow->selectBaseCartridge(filename);
|
||||
} else if(browseMode == BsxCartridge) {
|
||||
loaderWindow->selectSlot1Cartridge(filename);
|
||||
} else if(browseMode == SufamiTurboCartridge1) {
|
||||
loaderWindow->selectSlot1Cartridge(filename);
|
||||
} else if(browseMode == SufamiTurboCartridge2) {
|
||||
loaderWindow->selectSlot2Cartridge(filename);
|
||||
} else if(browseMode == SuperGameBoyCartridge) {
|
||||
loaderWindow->selectSlot1Cartridge(filename);
|
||||
}
|
||||
} else {
|
||||
//this is a standard folder in ROM loading mode; enter into the folder
|
||||
@@ -271,7 +373,10 @@ void DiskBrowser::setPath(const QString &reqPath) {
|
||||
disconnect(path, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePath()));
|
||||
|
||||
QString effectivePath = reqPath;
|
||||
if(effectivePath == "<root>") {
|
||||
if(effectivePath == "") {
|
||||
effectivePath = QString::fromUtf8(config().path.startup);
|
||||
}
|
||||
if(effectivePath == "<root>" || QDir(reqPath).exists() == false) {
|
||||
effectivePath = "";
|
||||
newFolder->setEnabled(false);
|
||||
} else {
|
||||
@@ -306,7 +411,7 @@ void DiskBrowser::setNameFilters(const QString &filters) {
|
||||
filterPart.split(";;", filterData);
|
||||
|
||||
for(unsigned i = 0; i < filterPart.size(); i++) {
|
||||
filter->addItem(utf8() << filterPart[i]);
|
||||
filter->addItem(filterPart[i]);
|
||||
}
|
||||
|
||||
connect(filter, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFilter()));
|
||||
@@ -314,7 +419,7 @@ void DiskBrowser::setNameFilters(const QString &filters) {
|
||||
}
|
||||
|
||||
void DiskBrowser::cdUp() {
|
||||
folderCreator->window->hide();
|
||||
folderCreator->hide();
|
||||
//if we aren't already at the root node, select the second node, which is one path higher than the current
|
||||
if(path->count() > 1) path->setCurrentIndex(1);
|
||||
}
|
||||
@@ -349,8 +454,8 @@ bool DiskBrowser::currentFilename(string &filename) {
|
||||
|
||||
if(browseMode != Folder) {
|
||||
if(model->isDir(item) == true) {
|
||||
QDir directory(utf8() << filename);
|
||||
directory.setNameFilters(QStringList() << "*.sfc" << "*.smc");
|
||||
QDir directory(filename);
|
||||
directory.setNameFilters(QStringList() << "*.sfc");
|
||||
QStringList list = directory.entryList(QDir::Files | QDir::NoDotAndDotDot);
|
||||
if(list.count() == 1) {
|
||||
filename << "/" << list[0].toUtf8().constData();
|
||||
@@ -364,15 +469,20 @@ bool DiskBrowser::currentFilename(string &filename) {
|
||||
return loadable;
|
||||
}
|
||||
|
||||
DiskBrowser::DiskBrowser() {
|
||||
window = new QbWindow(config.geometry.diskBrowser);
|
||||
window->setObjectName("disk-browser");
|
||||
window->resize(720, 480);
|
||||
void DiskBrowser::toggleShowPanel() {
|
||||
showPanel->setChecked(!showPanel->isChecked());
|
||||
config().diskBrowser.showPanel = showPanel->isChecked();
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
}
|
||||
|
||||
DiskBrowser::DiskBrowser() : QbWindow(config().geometry.diskBrowser) {
|
||||
setObjectName("disk-browser");
|
||||
resize(720, 480);
|
||||
|
||||
layout = new QVBoxLayout;
|
||||
layout->setMargin(Style::WindowMargin);
|
||||
layout->setSpacing(Style::WidgetSpacing);
|
||||
window->setLayout(layout);
|
||||
setLayout(layout);
|
||||
|
||||
topLayout = new QHBoxLayout;
|
||||
layout->addLayout(topLayout);
|
||||
@@ -384,6 +494,7 @@ DiskBrowser::DiskBrowser() {
|
||||
browseLayout->addLayout(pathLayout);
|
||||
|
||||
path = new QComboBox;
|
||||
path->setEditable(true);
|
||||
path->setMinimumContentsLength(16);
|
||||
path->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
|
||||
path->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
@@ -434,12 +545,14 @@ DiskBrowser::DiskBrowser() {
|
||||
controlLayout->addWidget(filter);
|
||||
|
||||
options = new QPushButton("Options");
|
||||
options->setEnabled(false);
|
||||
controlLayout->addWidget(options);
|
||||
|
||||
QMenu *menu = new QMenu;
|
||||
menu = new QMenu;
|
||||
options->setMenu(menu);
|
||||
|
||||
menu->addAction(showPanel = new QbCheckAction("Show Side Panel", 0));
|
||||
showPanel->setChecked(config().diskBrowser.showPanel);
|
||||
|
||||
ok = new QPushButton("Ok");
|
||||
ok->setEnabled(false);
|
||||
controlLayout->addWidget(ok);
|
||||
@@ -468,7 +581,8 @@ DiskBrowser::DiskBrowser() {
|
||||
connect(view, SIGNAL(cdUp()), this, SLOT(cdUp()));
|
||||
connect(view, SIGNAL(activated(const QModelIndex&)), this, SLOT(activateItem(const QModelIndex&)));
|
||||
connect(view, SIGNAL(changed(const QModelIndex&)), this, SLOT(changeItem(const QModelIndex&)));
|
||||
connect(view, SIGNAL(escape()), window, SLOT(hide()));
|
||||
connect(ok, SIGNAL(released()), this, SLOT(loadSelected()));
|
||||
connect(cancel, SIGNAL(released()), window, SLOT(hide()));
|
||||
connect(cancel, SIGNAL(released()), this, SLOT(close()));
|
||||
|
||||
connect(showPanel, SIGNAL(triggered()), this, SLOT(toggleShowPanel()));
|
||||
}
|
||||
|
@@ -1,10 +1,7 @@
|
||||
class PathSettingWidget;
|
||||
|
||||
class FolderCreator : public QObject {
|
||||
class FolderCreator : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QbWindow *window;
|
||||
QVBoxLayout *layout;
|
||||
QLabel *label;
|
||||
QLineEdit *name;
|
||||
@@ -17,19 +14,19 @@ public:
|
||||
public slots:
|
||||
void show();
|
||||
void createFolder();
|
||||
} *folderCreator;
|
||||
};
|
||||
|
||||
extern FolderCreator *folderCreator;
|
||||
|
||||
class DiskBrowserView : public QTreeView {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
void keyPressEvent(QKeyEvent*);
|
||||
void keyReleaseEvent(QKeyEvent*);
|
||||
|
||||
signals:
|
||||
void cdUp();
|
||||
void changed(const QModelIndex&);
|
||||
void escape();
|
||||
|
||||
public slots:
|
||||
void currentChanged(const QModelIndex&, const QModelIndex&);
|
||||
@@ -41,11 +38,10 @@ public:
|
||||
void paintEvent(QPaintEvent*);
|
||||
};
|
||||
|
||||
class DiskBrowser : public QObject {
|
||||
class DiskBrowser : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QbWindow *window;
|
||||
QVBoxLayout *layout;
|
||||
QHBoxLayout *topLayout;
|
||||
QVBoxLayout *browseLayout;
|
||||
@@ -66,15 +62,22 @@ public:
|
||||
QPushButton *ok;
|
||||
QPushButton *cancel;
|
||||
QFileSystemModel *model;
|
||||
PathSettingWidget *activePath;
|
||||
|
||||
void chooseFolder(PathSettingWidget*, const char*);
|
||||
QMenu *menu;
|
||||
QbCheckAction *showPanel;
|
||||
|
||||
void inputEvent(uint16_t scancode);
|
||||
|
||||
void chooseFolder(const function<void (string)>&, string&, const char*);
|
||||
void chooseFile(const function<void (string)>&, string&, const char*);
|
||||
|
||||
void loadCartridge();
|
||||
void loadBaseCartridge();
|
||||
void loadBsxCartridge();
|
||||
void loadSufamiTurboCartridge1();
|
||||
void loadSufamiTurboCartridge2();
|
||||
void loadSuperGameBoyCartridge();
|
||||
|
||||
string queryImageInformation();
|
||||
|
||||
void setPath(const QString&);
|
||||
@@ -90,9 +93,15 @@ public slots:
|
||||
void changeItem(const QModelIndex&);
|
||||
void loadSelected();
|
||||
|
||||
void toggleShowPanel();
|
||||
|
||||
private:
|
||||
function<void (string)> callback;
|
||||
string *currentPath;
|
||||
|
||||
enum BrowseMode {
|
||||
Folder,
|
||||
File,
|
||||
Cartridge,
|
||||
BaseCartridge,
|
||||
BsxCartridge,
|
||||
@@ -102,4 +111,6 @@ private:
|
||||
} browseMode;
|
||||
|
||||
bool currentFilename(string&);
|
||||
} *diskBrowser;
|
||||
};
|
||||
|
||||
extern DiskBrowser *diskBrowser;
|
||||
|
@@ -1,19 +1,21 @@
|
||||
HtmlViewerWindow::HtmlViewerWindow() {
|
||||
window = new QbWindow(config.geometry.htmlViewerWindow);
|
||||
window->setObjectName("html-window");
|
||||
window->resize(560, 480);
|
||||
#include "htmlviewer.moc"
|
||||
HtmlViewerWindow *htmlViewerWindow;
|
||||
|
||||
HtmlViewerWindow::HtmlViewerWindow() : QbWindow(config().geometry.htmlViewerWindow) {
|
||||
setObjectName("html-window");
|
||||
resize(560, 480);
|
||||
|
||||
layout = new QVBoxLayout;
|
||||
layout->setMargin(Style::WindowMargin);
|
||||
layout->setSpacing(0);
|
||||
window->setLayout(layout);
|
||||
setLayout(layout);
|
||||
|
||||
document = new QTextBrowser;
|
||||
layout->addWidget(document);
|
||||
}
|
||||
|
||||
void HtmlViewerWindow::show(const char *title, const char *htmlData) {
|
||||
document->setHtml(utf8() << htmlData);
|
||||
window->setWindowTitle(title);
|
||||
window->show();
|
||||
document->setHtml(string() << htmlData);
|
||||
setWindowTitle(title);
|
||||
QbWindow::show();
|
||||
}
|
||||
|
@@ -1,13 +1,14 @@
|
||||
class HtmlViewerWindow : public QObject {
|
||||
class HtmlViewerWindow : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QbWindow *window;
|
||||
QVBoxLayout *layout;
|
||||
QTextBrowser *document;
|
||||
QTextBrowser *document;
|
||||
|
||||
void show(const char *title, const char *htmlData);
|
||||
HtmlViewerWindow();
|
||||
|
||||
public slots:
|
||||
} *htmlViewerWindow;
|
||||
};
|
||||
|
||||
extern HtmlViewerWindow *htmlViewerWindow;
|
||||
|
@@ -1,70 +1,63 @@
|
||||
LoaderWindow::LoaderWindow() {
|
||||
window = new QbWindow(config.geometry.loaderWindow);
|
||||
window->setObjectName("loader-window");
|
||||
window->setMinimumWidth(520);
|
||||
#include "loader.moc"
|
||||
LoaderWindow *loaderWindow;
|
||||
|
||||
LoaderWindow::LoaderWindow() : QbWindow(config().geometry.loaderWindow) {
|
||||
setObjectName("loader-window");
|
||||
setMinimumWidth(520);
|
||||
|
||||
layout = new QVBoxLayout;
|
||||
layout->setMargin(Style::WindowMargin);
|
||||
layout->setSpacing(0);
|
||||
window->setLayout(layout);
|
||||
layout->setSpacing(Style::WidgetSpacing);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
grid = new QGridLayout; {
|
||||
baseLabel = new QLabel("Base cartridge:");
|
||||
grid->addWidget(baseLabel, 0, 0);
|
||||
|
||||
baseFile = new QLineEdit;
|
||||
baseFile->setReadOnly(true);
|
||||
grid->addWidget(baseFile, 0, 1);
|
||||
|
||||
baseBrowse = new QPushButton("Browse ...");
|
||||
grid->addWidget(baseBrowse, 0, 2);
|
||||
|
||||
baseClear = new QPushButton("Clear");
|
||||
grid->addWidget(baseClear, 0, 3);
|
||||
|
||||
slot1Label = new QLabel("Slot A cartridge:");
|
||||
grid->addWidget(slot1Label, 1, 0);
|
||||
|
||||
slot1File = new QLineEdit;
|
||||
slot1File->setReadOnly(true);
|
||||
grid->addWidget(slot1File, 1, 1);
|
||||
|
||||
slot1Browse = new QPushButton("Browse ...");
|
||||
grid->addWidget(slot1Browse, 1, 2);
|
||||
|
||||
slot1Clear = new QPushButton("Clear");
|
||||
grid->addWidget(slot1Clear, 1, 3);
|
||||
|
||||
slot2Label = new QLabel("Slot B cartridge:");
|
||||
grid->addWidget(slot2Label, 2, 0);
|
||||
|
||||
slot2File = new QLineEdit;
|
||||
slot2File->setReadOnly(true);
|
||||
grid->addWidget(slot2File, 2, 1);
|
||||
|
||||
slot2Browse = new QPushButton("Browse ...");
|
||||
grid->addWidget(slot2Browse, 2, 2);
|
||||
|
||||
slot2Clear = new QPushButton("Clear");
|
||||
grid->addWidget(slot2Clear, 2, 3);
|
||||
}
|
||||
grid->setSpacing(Style::WidgetSpacing);
|
||||
grid = new QGridLayout;
|
||||
layout->addLayout(grid);
|
||||
layout->addSpacing(Style::WidgetSpacing);
|
||||
|
||||
controls = new QHBoxLayout; {
|
||||
load = new QPushButton("Load");
|
||||
controls->addWidget(load);
|
||||
baseLabel = new QLabel("Base cartridge:");
|
||||
grid->addWidget(baseLabel, 0, 0);
|
||||
|
||||
cancel = new QPushButton("Cancel");
|
||||
controls->addWidget(cancel);
|
||||
}
|
||||
controls->setSpacing(Style::WidgetSpacing);
|
||||
layout->addLayout(controls);
|
||||
baseFile = new QLineEdit;
|
||||
baseFile->setReadOnly(true);
|
||||
grid->addWidget(baseFile, 0, 1);
|
||||
|
||||
spacer = new QWidget;
|
||||
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
layout->addWidget(spacer);
|
||||
baseBrowse = new QPushButton("Browse ...");
|
||||
grid->addWidget(baseBrowse, 0, 2);
|
||||
|
||||
baseClear = new QPushButton("Clear");
|
||||
grid->addWidget(baseClear, 0, 3);
|
||||
|
||||
slot1Label = new QLabel("Slot A cartridge:");
|
||||
grid->addWidget(slot1Label, 1, 0);
|
||||
|
||||
slot1File = new QLineEdit;
|
||||
slot1File->setReadOnly(true);
|
||||
grid->addWidget(slot1File, 1, 1);
|
||||
|
||||
slot1Browse = new QPushButton("Browse ...");
|
||||
grid->addWidget(slot1Browse, 1, 2);
|
||||
|
||||
slot1Clear = new QPushButton("Clear");
|
||||
grid->addWidget(slot1Clear, 1, 3);
|
||||
|
||||
slot2Label = new QLabel("Slot B cartridge:");
|
||||
grid->addWidget(slot2Label, 2, 0);
|
||||
|
||||
slot2File = new QLineEdit;
|
||||
slot2File->setReadOnly(true);
|
||||
grid->addWidget(slot2File, 2, 1);
|
||||
|
||||
slot2Browse = new QPushButton("Browse ...");
|
||||
grid->addWidget(slot2Browse, 2, 2);
|
||||
|
||||
slot2Clear = new QPushButton("Clear");
|
||||
grid->addWidget(slot2Clear, 2, 3);
|
||||
|
||||
load = new QPushButton("Load");
|
||||
grid->addWidget(load, 3, 2);
|
||||
|
||||
cancel = new QPushButton("Cancel");
|
||||
grid->addWidget(cancel, 3, 3);
|
||||
|
||||
connect(baseBrowse, SIGNAL(released()), this, SLOT(selectBaseCartridge()));
|
||||
connect(baseClear, SIGNAL(released()), this, SLOT(clearBaseCartridge()));
|
||||
@@ -73,7 +66,7 @@ LoaderWindow::LoaderWindow() {
|
||||
connect(slot2Browse, SIGNAL(released()), this, SLOT(selectSlot2Cartridge()));
|
||||
connect(slot2Clear, SIGNAL(released()), this, SLOT(clearSlot2Cartridge()));
|
||||
connect(load, SIGNAL(released()), this, SLOT(onLoad()));
|
||||
connect(cancel, SIGNAL(released()), this, SLOT(onCancel()));
|
||||
connect(cancel, SIGNAL(released()), this, SLOT(close()));
|
||||
}
|
||||
|
||||
void LoaderWindow::syncUi() {
|
||||
@@ -82,7 +75,7 @@ void LoaderWindow::syncUi() {
|
||||
}
|
||||
|
||||
void LoaderWindow::loadBsxSlottedCartridge(const char *filebase, const char *fileSlot1) {
|
||||
window->hide();
|
||||
hide();
|
||||
baseLabel->show(), baseFile->show(), baseBrowse->show(), baseClear->show();
|
||||
slot1Label->show(), slot1File->show(), slot1Browse->show(), slot1Clear->show();
|
||||
slot2Label->hide(), slot2File->hide(), slot2Browse->hide(), slot2Clear->hide();
|
||||
@@ -98,7 +91,7 @@ void LoaderWindow::loadBsxSlottedCartridge(const char *filebase, const char *fil
|
||||
}
|
||||
|
||||
void LoaderWindow::loadBsxCartridge(const char *fileBase, const char *fileSlot1) {
|
||||
window->hide();
|
||||
hide();
|
||||
baseLabel->show(), baseFile->show(), baseBrowse->show(), baseClear->show();
|
||||
slot1Label->show(), slot1File->show(), slot1Browse->show(), slot1Clear->show();
|
||||
slot2Label->hide(), slot2File->hide(), slot2Browse->hide(), slot2Clear->hide();
|
||||
@@ -114,7 +107,7 @@ void LoaderWindow::loadBsxCartridge(const char *fileBase, const char *fileSlot1)
|
||||
}
|
||||
|
||||
void LoaderWindow::loadSufamiTurboCartridge(const char *fileBase, const char *fileSlot1, const char *fileSlot2) {
|
||||
window->hide();
|
||||
hide();
|
||||
baseLabel->show(), baseFile->show(), baseBrowse->show(), baseClear->show();
|
||||
slot1Label->show(), slot1File->show(), slot1Browse->show(), slot1Clear->show();
|
||||
slot2Label->show(), slot2File->show(), slot2Browse->show(), slot2Clear->show();
|
||||
@@ -132,7 +125,7 @@ void LoaderWindow::loadSufamiTurboCartridge(const char *fileBase, const char *fi
|
||||
}
|
||||
|
||||
void LoaderWindow::loadSuperGameBoyCartridge(const char *fileBase, const char *fileSlot1) {
|
||||
window->hide();
|
||||
hide();
|
||||
baseLabel->show(), baseFile->show(), baseBrowse->show(), baseClear->show();
|
||||
slot1Label->show(), slot1File->show(), slot1Browse->show(), slot1Clear->show();
|
||||
slot2Label->hide(), slot2File->hide(), slot2Browse->hide(), slot2Clear->hide();
|
||||
@@ -148,24 +141,24 @@ void LoaderWindow::loadSuperGameBoyCartridge(const char *fileBase, const char *f
|
||||
}
|
||||
|
||||
void LoaderWindow::showWindow(const char *title) {
|
||||
window->setWindowTitle(title);
|
||||
window->show();
|
||||
window->shrink();
|
||||
setWindowTitle(title);
|
||||
show();
|
||||
shrink();
|
||||
load->setFocus();
|
||||
}
|
||||
|
||||
void LoaderWindow::selectBaseCartridge(const char *filename) {
|
||||
baseFile->setText(utf8() << filename);
|
||||
baseFile->setText(string() << filename);
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void LoaderWindow::selectSlot1Cartridge(const char *filename) {
|
||||
slot1File->setText(utf8() << filename);
|
||||
slot1File->setText(string() << filename);
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void LoaderWindow::selectSlot2Cartridge(const char *filename) {
|
||||
slot2File->setText(utf8() << filename);
|
||||
slot2File->setText(string() << filename);
|
||||
syncUi();
|
||||
}
|
||||
|
||||
@@ -208,7 +201,7 @@ void LoaderWindow::clearSlot2Cartridge() {
|
||||
}
|
||||
|
||||
void LoaderWindow::onLoad() {
|
||||
window->hide();
|
||||
hide();
|
||||
string base = baseFile->text().toUtf8().data();
|
||||
string slot1 = slot1File->text().toUtf8().data();
|
||||
string slot2 = slot2File->text().toUtf8().data();
|
||||
@@ -219,22 +212,18 @@ void LoaderWindow::onLoad() {
|
||||
} break;
|
||||
|
||||
case SNES::Cartridge::ModeBsx: {
|
||||
config.path.bsx = base;
|
||||
config().path.bsx = base;
|
||||
utility.loadCartridgeBsx(base, slot1);
|
||||
} break;
|
||||
|
||||
case SNES::Cartridge::ModeSufamiTurbo: {
|
||||
config.path.st = base;
|
||||
config().path.st = base;
|
||||
utility.loadCartridgeSufamiTurbo(base, slot1, slot2);
|
||||
} break;
|
||||
|
||||
case SNES::Cartridge::ModeSuperGameBoy: {
|
||||
config.path.sgb = base;
|
||||
config().path.sgb = base;
|
||||
utility.loadCartridgeSuperGameBoy(base, slot1);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void LoaderWindow::onCancel() {
|
||||
window->hide();
|
||||
}
|
||||
|
@@ -1,26 +1,23 @@
|
||||
class LoaderWindow : public QObject {
|
||||
class LoaderWindow : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QbWindow *window;
|
||||
QVBoxLayout *layout;
|
||||
QGridLayout *grid;
|
||||
QLabel *baseLabel;
|
||||
QLineEdit *baseFile;
|
||||
QPushButton *baseBrowse;
|
||||
QPushButton *baseClear;
|
||||
QLabel *slot1Label;
|
||||
QLineEdit *slot1File;
|
||||
QPushButton *slot1Browse;
|
||||
QPushButton *slot1Clear;
|
||||
QLabel *slot2Label;
|
||||
QLineEdit *slot2File;
|
||||
QPushButton *slot2Browse;
|
||||
QPushButton *slot2Clear;
|
||||
QHBoxLayout *controls;
|
||||
QPushButton *load;
|
||||
QPushButton *cancel;
|
||||
QWidget *spacer;
|
||||
QGridLayout *grid;
|
||||
QLabel *baseLabel;
|
||||
QLineEdit *baseFile;
|
||||
QPushButton *baseBrowse;
|
||||
QPushButton *baseClear;
|
||||
QLabel *slot1Label;
|
||||
QLineEdit *slot1File;
|
||||
QPushButton *slot1Browse;
|
||||
QPushButton *slot1Clear;
|
||||
QLabel *slot2Label;
|
||||
QLineEdit *slot2File;
|
||||
QPushButton *slot2Browse;
|
||||
QPushButton *slot2Clear;
|
||||
QPushButton *load;
|
||||
QPushButton *cancel;
|
||||
|
||||
void syncUi();
|
||||
void loadBsxSlottedCartridge(const char*, const char*);
|
||||
@@ -40,11 +37,11 @@ public slots:
|
||||
void clearSlot1Cartridge();
|
||||
void selectSlot2Cartridge();
|
||||
void clearSlot2Cartridge();
|
||||
|
||||
void onLoad();
|
||||
void onCancel();
|
||||
|
||||
private:
|
||||
SNES::Cartridge::Mode mode;
|
||||
void showWindow(const char *title);
|
||||
} *loaderWindow;
|
||||
};
|
||||
|
||||
extern LoaderWindow *loaderWindow;
|
||||
|
@@ -1,7 +1,9 @@
|
||||
MainWindow::MainWindow() {
|
||||
window = new Window(config.geometry.mainWindow);
|
||||
window->setObjectName("main-window");
|
||||
window->setWindowTitle(utf8() << bsnesTitle << " v" << bsnesVersion);
|
||||
#include "main.moc"
|
||||
MainWindow *mainWindow;
|
||||
|
||||
MainWindow::MainWindow() : QbWindow(config().geometry.mainWindow) {
|
||||
setObjectName("main-window");
|
||||
setWindowTitle(string() << bsnesTitle << " v" << bsnesVersion);
|
||||
|
||||
//menu bar
|
||||
#if defined(PLATFORM_OSX)
|
||||
@@ -10,127 +12,183 @@ MainWindow::MainWindow() {
|
||||
menuBar = new QMenuBar;
|
||||
#endif
|
||||
|
||||
system = menuBar->addMenu("System");
|
||||
system_load = system->addAction("Load Cartridge ...");
|
||||
system_load->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system_loadSpecial = system->addMenu("Load Special");
|
||||
system_loadSpecial->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system_loadSpecial_bsxSlotted = system_loadSpecial->addAction("Load BS-X Slotted Cartridge ...");
|
||||
system_loadSpecial_bsxSlotted->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system_loadSpecial_bsx = system_loadSpecial->addAction("Load BS-X Cartridge ...");
|
||||
system_loadSpecial_bsx->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system_loadSpecial_sufamiTurbo = system_loadSpecial->addAction("Load Sufami Turbo Cartridge ...");
|
||||
system_loadSpecial_sufamiTurbo->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system_loadSpecial_superGameBoy = system_loadSpecial->addAction("Load Super Game Boy Cartridge ...");
|
||||
system_loadSpecial_superGameBoy->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system_loadSpecial_superGameBoy->setVisible(false);
|
||||
system->addSeparator();
|
||||
system->addAction(system_power = new QbCheckAction("Power", 0));
|
||||
system_reset = system->addAction("Reset");
|
||||
system_reset->setIcon(QIcon(":/16x16/view-refresh.png"));
|
||||
system->addSeparator();
|
||||
system_port1 = system->addMenu("Controller Port 1");
|
||||
system_port1->setIcon(QIcon(":/16x16/input-gaming.png"));
|
||||
system_port1->addAction(system_port1_none = new QbRadioAction("None", 0));
|
||||
system_port1->addAction(system_port1_joypad = new QbRadioAction("Joypad", 0));
|
||||
system_port1->addAction(system_port1_multitap = new QbRadioAction("Multitap", 0));
|
||||
system_port1->addAction(system_port1_mouse = new QbRadioAction("Mouse", 0));
|
||||
system_port2 = system->addMenu("Controller Port 2");
|
||||
system_port2->setIcon(QIcon(":/16x16/input-gaming.png"));
|
||||
system_port2->addAction(system_port2_none = new QbRadioAction("None", 0));
|
||||
system_port2->addAction(system_port2_joypad = new QbRadioAction("Joypad", 0));
|
||||
system_port2->addAction(system_port2_multitap = new QbRadioAction("Multitap", 0));
|
||||
system_port2->addAction(system_port2_mouse = new QbRadioAction("Mouse", 0));
|
||||
system_port2->addAction(system_port2_superscope = new QbRadioAction("Super Scope", 0));
|
||||
system_port2->addAction(system_port2_justifier = new QbRadioAction("Justifier", 0));
|
||||
system_port2->addAction(system_port2_justifiers = new QbRadioAction("Two Justifiers", 0));
|
||||
#if !defined(PLATFORM_OSX)
|
||||
system->addSeparator();
|
||||
#endif
|
||||
system_exit = system->addAction("Exit");
|
||||
system_exit->setIcon(QIcon(":/16x16/process-stop.png"));
|
||||
system_exit->setMenuRole(QAction::QuitRole);
|
||||
system = menuBar->addMenu("&System");
|
||||
|
||||
settings = menuBar->addMenu("Settings");
|
||||
settings_videoMode = settings->addMenu("Video Mode");
|
||||
settings_videoMode->setIcon(QIcon(":/16x16/video-display.png"));
|
||||
settings_videoMode->addAction(settings_videoMode_1x = new QbRadioAction("Scale 1x", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_2x = new QbRadioAction("Scale 2x", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_3x = new QbRadioAction("Scale 3x", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_4x = new QbRadioAction("Scale 4x", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_max = new QbRadioAction("Scale Max", 0));
|
||||
settings_videoMode->addSeparator();
|
||||
settings_videoMode->addAction(settings_videoMode_correctAspectRatio = new QbCheckAction("Correct Aspect Ratio", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_fullscreen = new QbCheckAction("Fullscreen", 0));
|
||||
settings_videoMode->addSeparator();
|
||||
settings_videoMode->addAction(settings_videoMode_ntsc = new QbRadioAction("NTSC", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_pal = new QbRadioAction("PAL", 0));
|
||||
system_load = system->addAction("Load &Cartridge ...");
|
||||
system_load->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
if(filter.opened()) {
|
||||
settings_videoFilter = settings->addMenu("Video Filter");
|
||||
settings_videoFilter->setIcon(QIcon(":/16x16/image-x-generic.png"));
|
||||
system_loadSpecial = system->addMenu("Load &Special");
|
||||
system_loadSpecial->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
settings_videoFilter_configure = settings_videoFilter->addAction("Configure Active Filter ...");
|
||||
settings_videoFilter_configure->setIcon(QIcon(":/16x16/preferences-desktop.png"));
|
||||
settings_videoFilter->addSeparator();
|
||||
system_loadSpecial_bsxSlotted = system_loadSpecial->addAction("Load BS-X &Slotted Cartridge ...");
|
||||
system_loadSpecial_bsxSlotted->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
settings_videoFilter->addAction(settings_videoFilter_none = new QbRadioAction("None", 0));
|
||||
settings_videoFilter_list.add(settings_videoFilter_none);
|
||||
system_loadSpecial_bsx = system_loadSpecial->addAction("Load &BS-X Cartridge ...");
|
||||
system_loadSpecial_bsx->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
lstring filterlist;
|
||||
filterlist.split(";", filter.dl_supported());
|
||||
for(unsigned i = 0; i < filterlist.size(); i++) {
|
||||
QbRadioAction *action = new QbRadioAction(utf8() << filterlist[i], 0);
|
||||
settings_videoFilter->addAction(action);
|
||||
settings_videoFilter_list.add(action);
|
||||
}
|
||||
system_loadSpecial_sufamiTurbo = system_loadSpecial->addAction("Load Sufami &Turbo Cartridge ...");
|
||||
system_loadSpecial_sufamiTurbo->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
system_loadSpecial_superGameBoy = system_loadSpecial->addAction("Load Super &Game Boy Cartridge ...");
|
||||
system_loadSpecial_superGameBoy->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
system->addSeparator();
|
||||
|
||||
system->addAction(system_power = new QbCheckAction("&Power", 0));
|
||||
|
||||
system_reset = system->addAction("&Reset");
|
||||
system_reset->setIcon(QIcon(":/16x16/view-refresh.png"));
|
||||
|
||||
system->addSeparator();
|
||||
|
||||
system_port1 = system->addMenu("Controller Port &1");
|
||||
system_port1->setIcon(QIcon(":/16x16/input-gaming.png"));
|
||||
system_port1->addAction(system_port1_none = new QbRadioAction("&None", 0));
|
||||
system_port1->addAction(system_port1_gamepad = new QbRadioAction("&Gamepad", 0));
|
||||
system_port1->addAction(system_port1_asciipad = new QbRadioAction("&asciiPad", 0));
|
||||
system_port1->addAction(system_port1_multitap = new QbRadioAction("&Multitap", 0));
|
||||
system_port1->addAction(system_port1_mouse = new QbRadioAction("&Mouse", 0));
|
||||
|
||||
system_port2 = system->addMenu("Controller Port &2");
|
||||
system_port2->setIcon(QIcon(":/16x16/input-gaming.png"));
|
||||
system_port2->addAction(system_port2_none = new QbRadioAction("&None", 0));
|
||||
system_port2->addAction(system_port2_gamepad = new QbRadioAction("&Gamepad", 0));
|
||||
system_port2->addAction(system_port2_asciipad = new QbRadioAction("&asciiPad", 0));
|
||||
system_port2->addAction(system_port2_multitap = new QbRadioAction("&Multitap", 0));
|
||||
system_port2->addAction(system_port2_mouse = new QbRadioAction("&Mouse", 0));
|
||||
system_port2->addAction(system_port2_superscope = new QbRadioAction("&Super Scope", 0));
|
||||
system_port2->addAction(system_port2_justifier = new QbRadioAction("&Justifier", 0));
|
||||
system_port2->addAction(system_port2_justifiers = new QbRadioAction("Two &Justifiers", 0));
|
||||
|
||||
#if !defined(PLATFORM_OSX)
|
||||
system->addSeparator();
|
||||
#endif
|
||||
|
||||
system_exit = system->addAction("E&xit");
|
||||
system_exit->setIcon(QIcon(":/16x16/process-stop.png"));
|
||||
system_exit->setMenuRole(QAction::QuitRole);
|
||||
|
||||
settings = menuBar->addMenu("S&ettings");
|
||||
|
||||
settings_videoMode = settings->addMenu("Video &Mode");
|
||||
settings_videoMode->setIcon(QIcon(":/16x16/video-display.png"));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_1x = new QbRadioAction("Scale &1x", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_2x = new QbRadioAction("Scale &2x", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_3x = new QbRadioAction("Scale &3x", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_4x = new QbRadioAction("Scale &4x", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_5x = new QbRadioAction("Scale &5x", 0));
|
||||
|
||||
settings_videoMode->addSeparator();
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_correctAspectRatio = new QbCheckAction("Correct &Aspect Ratio", 0));
|
||||
|
||||
settings_videoMode->addSeparator();
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_ntsc = new QbRadioAction("&NTSC", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_pal = new QbRadioAction("&PAL", 0));
|
||||
|
||||
if(filter.opened()) {
|
||||
settings_videoFilter = settings->addMenu("Video &Filter");
|
||||
settings_videoFilter->setIcon(QIcon(":/16x16/image-x-generic.png"));
|
||||
|
||||
settings_videoFilter_configure = settings_videoFilter->addAction("&Configure Active Filter ...");
|
||||
settings_videoFilter_configure->setIcon(QIcon(":/16x16/preferences-desktop.png"));
|
||||
settings_videoFilter->addSeparator();
|
||||
|
||||
settings_videoFilter->addAction(settings_videoFilter_none = new QbRadioAction("&None", 0));
|
||||
settings_videoFilter_list.add(settings_videoFilter_none);
|
||||
|
||||
lstring filterlist;
|
||||
filterlist.split(";", filter.dl_supported());
|
||||
for(unsigned i = 0; i < filterlist.size(); i++) {
|
||||
QbRadioAction *action = new QbRadioAction(filterlist[i], 0);
|
||||
settings_videoFilter->addAction(action);
|
||||
settings_videoFilter_list.add(action);
|
||||
}
|
||||
}
|
||||
|
||||
settings->addAction(settings_smoothVideo = new QbCheckAction("Smooth Video Output", 0));
|
||||
settings->addSeparator();
|
||||
settings->addAction(settings_muteAudio = new QbCheckAction("Mute Audio Output", 0));
|
||||
settings->addSeparator();
|
||||
settings_emulationSpeed = settings->addMenu("Emulation Speed");
|
||||
settings_emulationSpeed->setIcon(QIcon(":/16x16/appointment-new.png"));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_slowest = new QbRadioAction("50%", 0));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_slow = new QbRadioAction("75%", 0));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_normal = new QbRadioAction("100%", 0));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_fast = new QbRadioAction("150%", 0));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_fastest = new QbRadioAction("200%", 0));
|
||||
settings_emulationSpeed->addSeparator();
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_syncVideo = new QbCheckAction("Sync Video", 0));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_syncAudio = new QbCheckAction("Sync Audio", 0));
|
||||
settings_configuration = settings->addAction("Configuration ...");
|
||||
settings_configuration->setIcon(QIcon(":/16x16/preferences-desktop.png"));
|
||||
settings_configuration->setMenuRole(QAction::PreferencesRole);
|
||||
settings->addAction(settings_smoothVideo = new QbCheckAction("&Smooth Video Output", 0));
|
||||
|
||||
tools = menuBar->addMenu("Tools");
|
||||
tools_cheatEditor = tools->addAction("Cheat Editor ...");
|
||||
tools_cheatEditor->setIcon(QIcon(":/16x16/accessories-text-editor.png"));
|
||||
tools_cheatFinder = tools->addAction("Cheat Finder ...");
|
||||
tools_cheatFinder->setIcon(QIcon(":/16x16/system-search.png"));
|
||||
tools_stateManager = tools->addAction("State Manager ...");
|
||||
tools_stateManager->setIcon(QIcon(":/16x16/system-file-manager.png"));
|
||||
#if defined(DEBUGGER)
|
||||
tools->addSeparator();
|
||||
#endif
|
||||
tools_debugger = tools->addAction("Debugger ...");
|
||||
tools_debugger->setIcon(QIcon(":/16x16/utilities-terminal.png"));
|
||||
#if !defined(DEBUGGER)
|
||||
tools_debugger->setVisible(false);
|
||||
#endif
|
||||
settings->addSeparator();
|
||||
|
||||
help = menuBar->addMenu("Help");
|
||||
help_documentation = help->addAction("Documentation ...");
|
||||
help_documentation->setIcon(QIcon(":/16x16/text-x-generic.png"));
|
||||
help_license = help->addAction("License ...");
|
||||
help_license->setIcon(QIcon(":/16x16/text-x-generic.png"));
|
||||
#if !defined(PLATFORM_OSX)
|
||||
help->addSeparator();
|
||||
#endif
|
||||
help_about = help->addAction("About ...");
|
||||
help_about->setIcon(QIcon(":/16x16/help-browser.png"));
|
||||
help_about->setMenuRole(QAction::AboutRole);
|
||||
settings->addAction(settings_muteAudio = new QbCheckAction("&Mute Audio Output", 0));
|
||||
|
||||
settings->addSeparator();
|
||||
|
||||
settings_emulationSpeed = settings->addMenu("Emulation &Speed");
|
||||
settings_emulationSpeed->setIcon(QIcon(":/16x16/appointment-new.png"));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_slowest = new QbRadioAction("Slowest", 0));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_slow = new QbRadioAction("Slow", 0));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_normal = new QbRadioAction("Normal", 0));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_fast = new QbRadioAction("Fast", 0));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_fastest = new QbRadioAction("Fastest", 0));
|
||||
|
||||
settings_emulationSpeed->addSeparator();
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_syncVideo = new QbCheckAction("Sync &Video", 0));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_syncAudio = new QbCheckAction("Sync &Audio", 0));
|
||||
|
||||
settings_configuration = settings->addAction("&Configuration ...");
|
||||
settings_configuration->setIcon(QIcon(":/16x16/preferences-desktop.png"));
|
||||
settings_configuration->setMenuRole(QAction::PreferencesRole);
|
||||
|
||||
tools = menuBar->addMenu("&Tools");
|
||||
|
||||
tools_movies = tools->addMenu("&Movies");
|
||||
tools_movies->setIcon(QIcon(":/16x16/applications-multimedia.png"));
|
||||
|
||||
tools_movies_play = tools_movies->addAction("Play Movie ...");
|
||||
tools_movies_play->setIcon(QIcon(":/16x16/media-playback-start.png"));
|
||||
|
||||
tools_movies_stop = tools_movies->addAction("Stop");
|
||||
tools_movies_stop->setIcon(QIcon(":/16x16/media-playback-stop.png"));
|
||||
|
||||
tools_movies_recordFromPowerOn = tools_movies->addAction("Record Movie (and restart system)");
|
||||
tools_movies_recordFromPowerOn->setIcon(QIcon(":/16x16/media-record.png"));
|
||||
|
||||
tools_movies_recordFromHere = tools_movies->addAction("Record Movie (starting from here)");
|
||||
tools_movies_recordFromHere->setIcon(QIcon(":/16x16/media-record.png"));
|
||||
|
||||
tools_captureScreenshot = tools->addAction("&Capture Screenshot");
|
||||
tools_captureScreenshot->setIcon(QIcon(":/16x16/image-x-generic.png"));
|
||||
|
||||
tools->addSeparator();
|
||||
|
||||
tools_debugger = tools->addAction("&Debugger ...");
|
||||
tools_debugger->setIcon(QIcon(":/16x16/utilities-terminal.png"));
|
||||
#if !defined(DEBUGGER)
|
||||
tools_debugger->setVisible(false);
|
||||
#endif
|
||||
|
||||
tools_dialog = tools->addAction("&Tools Dialog ...");
|
||||
tools_dialog->setIcon(QIcon(":/16x16/preferences-desktop.png"));
|
||||
|
||||
help = menuBar->addMenu("&Help");
|
||||
|
||||
help_documentation = help->addAction("&Documentation ...");
|
||||
help_documentation->setIcon(QIcon(":/16x16/text-x-generic.png"));
|
||||
|
||||
help_license = help->addAction("&License ...");
|
||||
help_license->setIcon(QIcon(":/16x16/text-x-generic.png"));
|
||||
|
||||
#if !defined(PLATFORM_OSX)
|
||||
help->addSeparator();
|
||||
#endif
|
||||
|
||||
help_about = help->addAction("&About ...");
|
||||
help_about->setIcon(QIcon(":/16x16/help-browser.png"));
|
||||
help_about->setMenuRole(QAction::AboutRole);
|
||||
|
||||
//canvas
|
||||
canvasContainer = new CanvasObject;
|
||||
@@ -171,7 +229,7 @@ MainWindow::MainWindow() {
|
||||
#endif
|
||||
layout->addWidget(canvasContainer);
|
||||
layout->addWidget(statusBar);
|
||||
window->setLayout(layout);
|
||||
setLayout(layout);
|
||||
|
||||
//slots
|
||||
connect(system_load, SIGNAL(triggered()), this, SLOT(loadCartridge()));
|
||||
@@ -182,11 +240,13 @@ MainWindow::MainWindow() {
|
||||
connect(system_power, SIGNAL(triggered()), this, SLOT(power()));
|
||||
connect(system_reset, SIGNAL(triggered()), this, SLOT(reset()));
|
||||
connect(system_port1_none, SIGNAL(triggered()), this, SLOT(setPort1None()));
|
||||
connect(system_port1_joypad, SIGNAL(triggered()), this, SLOT(setPort1Joypad()));
|
||||
connect(system_port1_gamepad, SIGNAL(triggered()), this, SLOT(setPort1Gamepad()));
|
||||
connect(system_port1_asciipad, SIGNAL(triggered()), this, SLOT(setPort1Asciipad()));
|
||||
connect(system_port1_multitap, SIGNAL(triggered()), this, SLOT(setPort1Multitap()));
|
||||
connect(system_port1_mouse, SIGNAL(triggered()), this, SLOT(setPort1Mouse()));
|
||||
connect(system_port2_none, SIGNAL(triggered()), this, SLOT(setPort2None()));
|
||||
connect(system_port2_joypad, SIGNAL(triggered()), this, SLOT(setPort2Joypad()));
|
||||
connect(system_port2_gamepad, SIGNAL(triggered()), this, SLOT(setPort2Gamepad()));
|
||||
connect(system_port2_asciipad, SIGNAL(triggered()), this, SLOT(setPort2Asciipad()));
|
||||
connect(system_port2_multitap, SIGNAL(triggered()), this, SLOT(setPort2Multitap()));
|
||||
connect(system_port2_mouse, SIGNAL(triggered()), this, SLOT(setPort2Mouse()));
|
||||
connect(system_port2_superscope, SIGNAL(triggered()), this, SLOT(setPort2SuperScope()));
|
||||
@@ -197,9 +257,8 @@ MainWindow::MainWindow() {
|
||||
connect(settings_videoMode_2x, SIGNAL(triggered()), this, SLOT(setVideoMode2x()));
|
||||
connect(settings_videoMode_3x, SIGNAL(triggered()), this, SLOT(setVideoMode3x()));
|
||||
connect(settings_videoMode_4x, SIGNAL(triggered()), this, SLOT(setVideoMode4x()));
|
||||
connect(settings_videoMode_max, SIGNAL(triggered()), this, SLOT(setVideoModeMax()));
|
||||
connect(settings_videoMode_5x, SIGNAL(triggered()), this, SLOT(setVideoMode5x()));
|
||||
connect(settings_videoMode_correctAspectRatio, SIGNAL(triggered()), this, SLOT(toggleAspectCorrection()));
|
||||
connect(settings_videoMode_fullscreen, SIGNAL(triggered()), this, SLOT(toggleFullscreen()));
|
||||
connect(settings_videoMode_ntsc, SIGNAL(triggered()), this, SLOT(setVideoNtsc()));
|
||||
connect(settings_videoMode_pal, SIGNAL(triggered()), this, SLOT(setVideoPal()));
|
||||
if(filter.opened()) {
|
||||
@@ -218,10 +277,13 @@ MainWindow::MainWindow() {
|
||||
connect(settings_emulationSpeed_syncVideo, SIGNAL(triggered()), this, SLOT(syncVideo()));
|
||||
connect(settings_emulationSpeed_syncAudio, SIGNAL(triggered()), this, SLOT(syncAudio()));
|
||||
connect(settings_configuration, SIGNAL(triggered()), this, SLOT(showConfigWindow()));
|
||||
connect(tools_cheatEditor, SIGNAL(triggered()), this, SLOT(showCheatEditor()));
|
||||
connect(tools_cheatFinder, SIGNAL(triggered()), this, SLOT(showCheatFinder()));
|
||||
connect(tools_stateManager, SIGNAL(triggered()), this, SLOT(showStateManager()));
|
||||
connect(tools_movies_play, SIGNAL(triggered()), this, SLOT(playMovie()));
|
||||
connect(tools_movies_stop, SIGNAL(triggered()), this, SLOT(stopMovie()));
|
||||
connect(tools_movies_recordFromPowerOn, SIGNAL(triggered()), this, SLOT(recordMovieFromPowerOn()));
|
||||
connect(tools_movies_recordFromHere, SIGNAL(triggered()), this, SLOT(recordMovieFromHere()));
|
||||
connect(tools_captureScreenshot, SIGNAL(triggered()), this, SLOT(saveScreenshot()));
|
||||
connect(tools_debugger, SIGNAL(triggered()), this, SLOT(showDebugger()));
|
||||
connect(tools_dialog, SIGNAL(triggered()), this, SLOT(showToolsDialog()));
|
||||
connect(help_documentation, SIGNAL(triggered()), this, SLOT(showDocumentation()));
|
||||
connect(help_license, SIGNAL(triggered()), this, SLOT(showLicense()));
|
||||
connect(help_about, SIGNAL(triggered()), this, SLOT(showAbout()));
|
||||
@@ -235,53 +297,64 @@ void MainWindow::syncUi() {
|
||||
system_power->setEnabled(SNES::cartridge.loaded());
|
||||
system_reset->setEnabled(SNES::cartridge.loaded() && application.power);
|
||||
|
||||
system_port1_none->setChecked (SNES::config.controller_port1 == SNES::Input::DeviceNone);
|
||||
system_port1_joypad->setChecked (SNES::config.controller_port1 == SNES::Input::DeviceJoypad);
|
||||
system_port1_multitap->setChecked (SNES::config.controller_port1 == SNES::Input::DeviceMultitap);
|
||||
system_port1_mouse->setChecked (SNES::config.controller_port1 == SNES::Input::DeviceMouse);
|
||||
system_port2_none->setChecked (SNES::config.controller_port2 == SNES::Input::DeviceNone);
|
||||
system_port2_joypad->setChecked (SNES::config.controller_port2 == SNES::Input::DeviceJoypad);
|
||||
system_port2_multitap->setChecked (SNES::config.controller_port2 == SNES::Input::DeviceMultitap);
|
||||
system_port2_mouse->setChecked (SNES::config.controller_port2 == SNES::Input::DeviceMouse);
|
||||
system_port2_superscope->setChecked(SNES::config.controller_port2 == SNES::Input::DeviceSuperScope);
|
||||
system_port2_justifier->setChecked (SNES::config.controller_port2 == SNES::Input::DeviceJustifier);
|
||||
system_port2_justifiers->setChecked(SNES::config.controller_port2 == SNES::Input::DeviceJustifiers);
|
||||
system_port1_none->setChecked (config().input.port1 == ControllerPort1::None);
|
||||
system_port1_gamepad->setChecked (config().input.port1 == ControllerPort1::Gamepad);
|
||||
system_port1_asciipad->setChecked (config().input.port1 == ControllerPort1::Asciipad);
|
||||
system_port1_multitap->setChecked (config().input.port1 == ControllerPort1::Multitap);
|
||||
system_port1_mouse->setChecked (config().input.port1 == ControllerPort1::Mouse);
|
||||
|
||||
settings_videoMode_1x->setChecked (config.video.context->multiplier == 1);
|
||||
settings_videoMode_2x->setChecked (config.video.context->multiplier == 2);
|
||||
settings_videoMode_3x->setChecked (config.video.context->multiplier == 3);
|
||||
settings_videoMode_4x->setChecked (config.video.context->multiplier == 4);
|
||||
settings_videoMode_max->setChecked(config.video.context->multiplier >= 5);
|
||||
system_port2_none->setChecked (config().input.port2 == ControllerPort2::None);
|
||||
system_port2_gamepad->setChecked (config().input.port2 == ControllerPort2::Gamepad);
|
||||
system_port2_asciipad->setChecked (config().input.port2 == ControllerPort2::Asciipad);
|
||||
system_port2_multitap->setChecked (config().input.port2 == ControllerPort2::Multitap);
|
||||
system_port2_mouse->setChecked (config().input.port2 == ControllerPort2::Mouse);
|
||||
system_port2_superscope->setChecked(config().input.port2 == ControllerPort2::SuperScope);
|
||||
system_port2_justifier->setChecked (config().input.port2 == ControllerPort2::Justifier);
|
||||
system_port2_justifiers->setChecked(config().input.port2 == ControllerPort2::Justifiers);
|
||||
|
||||
settings_videoMode_correctAspectRatio->setChecked(config.video.context->correctAspectRatio);
|
||||
settings_videoMode_fullscreen->setChecked(config.video.isFullscreen);
|
||||
settings_videoMode_ntsc->setChecked(config.video.context->region == 0);
|
||||
settings_videoMode_pal->setChecked (config.video.context->region == 1);
|
||||
settings_videoMode_1x->setChecked(config().video.context->multiplier == 1);
|
||||
settings_videoMode_2x->setChecked(config().video.context->multiplier == 2);
|
||||
settings_videoMode_3x->setChecked(config().video.context->multiplier == 3);
|
||||
settings_videoMode_4x->setChecked(config().video.context->multiplier == 4);
|
||||
settings_videoMode_5x->setChecked(config().video.context->multiplier == 5);
|
||||
|
||||
settings_videoMode_correctAspectRatio->setChecked(config().video.context->correctAspectRatio);
|
||||
settings_videoMode_ntsc->setChecked(config().video.context->region == 0);
|
||||
settings_videoMode_pal->setChecked (config().video.context->region == 1);
|
||||
|
||||
if(filter.opened()) {
|
||||
//only enable configuration option if the active filter supports it ...
|
||||
settings_videoFilter_configure->setEnabled(filter.settings());
|
||||
|
||||
for(unsigned i = 0; i < settings_videoFilter_list.size(); i++) {
|
||||
settings_videoFilter_list[i]->setChecked(config.video.context->swFilter == i);
|
||||
settings_videoFilter_list[i]->setChecked(config().video.context->swFilter == i);
|
||||
}
|
||||
}
|
||||
|
||||
settings_smoothVideo->setChecked(config.video.context->hwFilter == 1);
|
||||
settings_muteAudio->setChecked(config.audio.mute);
|
||||
settings_smoothVideo->setChecked(config().video.context->hwFilter == 1);
|
||||
settings_muteAudio->setChecked(config().audio.mute);
|
||||
|
||||
settings_emulationSpeed_slowest->setChecked(config.system.speed == 0);
|
||||
settings_emulationSpeed_slow->setChecked (config.system.speed == 1);
|
||||
settings_emulationSpeed_normal->setChecked (config.system.speed == 2);
|
||||
settings_emulationSpeed_fast->setChecked (config.system.speed == 3);
|
||||
settings_emulationSpeed_fastest->setChecked(config.system.speed == 4);
|
||||
settings_emulationSpeed_slowest->setChecked(config().system.speed == 0);
|
||||
settings_emulationSpeed_slow->setChecked (config().system.speed == 1);
|
||||
settings_emulationSpeed_normal->setChecked (config().system.speed == 2);
|
||||
settings_emulationSpeed_fast->setChecked (config().system.speed == 3);
|
||||
settings_emulationSpeed_fastest->setChecked(config().system.speed == 4);
|
||||
|
||||
settings_emulationSpeed_syncVideo->setChecked(config.video.synchronize);
|
||||
settings_emulationSpeed_syncAudio->setChecked(config.audio.synchronize);
|
||||
settings_emulationSpeed_syncVideo->setChecked(config().video.synchronize);
|
||||
settings_emulationSpeed_syncAudio->setChecked(config().audio.synchronize);
|
||||
|
||||
//movies contian save states to synchronize playback to recorded input
|
||||
tools_movies->setEnabled(SNES::cartridge.loaded() && utility.saveStatesSupported());
|
||||
if(tools_movies->isEnabled()) {
|
||||
tools_movies_play->setEnabled(movie.state == Movie::Inactive);
|
||||
tools_movies_stop->setEnabled(movie.state != Movie::Inactive);
|
||||
tools_movies_recordFromPowerOn->setEnabled(movie.state == Movie::Inactive);
|
||||
tools_movies_recordFromHere->setEnabled(movie.state == Movie::Inactive);
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::isActive() {
|
||||
return window->isActiveWindow() && !window->isMinimized();
|
||||
return isActiveWindow() && !isMinimized();
|
||||
}
|
||||
|
||||
void MainWindow::loadCartridge() {
|
||||
@@ -293,15 +366,15 @@ void MainWindow::loadBsxSlottedCartridge() {
|
||||
}
|
||||
|
||||
void MainWindow::loadBsxCartridge() {
|
||||
loaderWindow->loadBsxCartridge(config.path.bsx, "");
|
||||
loaderWindow->loadBsxCartridge(config().path.bsx, "");
|
||||
}
|
||||
|
||||
void MainWindow::loadSufamiTurboCartridge() {
|
||||
loaderWindow->loadSufamiTurboCartridge(config.path.st, "", "");
|
||||
loaderWindow->loadSufamiTurboCartridge(config().path.st, "", "");
|
||||
}
|
||||
|
||||
void MainWindow::loadSuperGameBoyCartridge() {
|
||||
loaderWindow->loadSuperGameBoyCartridge(config.path.sgb, "");
|
||||
loaderWindow->loadSuperGameBoyCartridge(config().path.sgb, "");
|
||||
}
|
||||
|
||||
void MainWindow::power() {
|
||||
@@ -317,52 +390,101 @@ void MainWindow::reset() {
|
||||
utility.modifySystemState(Utility::Reset);
|
||||
}
|
||||
|
||||
void MainWindow::setPort1None() { SNES::config.controller_port1 = SNES::Input::DeviceNone; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort1Joypad() { SNES::config.controller_port1 = SNES::Input::DeviceJoypad; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort1Multitap() { SNES::config.controller_port1 = SNES::Input::DeviceMultitap; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort1Mouse() { SNES::config.controller_port1 = SNES::Input::DeviceMouse; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2None() { SNES::config.controller_port2 = SNES::Input::DeviceNone; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2Joypad() { SNES::config.controller_port2 = SNES::Input::DeviceJoypad; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2Multitap() { SNES::config.controller_port2 = SNES::Input::DeviceMultitap; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2Mouse() { SNES::config.controller_port2 = SNES::Input::DeviceMouse; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2SuperScope() { SNES::config.controller_port2 = SNES::Input::DeviceSuperScope; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2Justifier() { SNES::config.controller_port2 = SNES::Input::DeviceJustifier; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2Justifiers() { SNES::config.controller_port2 = SNES::Input::DeviceJustifiers; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort1None() {
|
||||
config().input.port1 = ControllerPort1::None;
|
||||
SNES::config.controller_port1 = SNES::Input::DeviceNone;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort1Gamepad() {
|
||||
config().input.port1 = ControllerPort1::Gamepad;
|
||||
SNES::config.controller_port1 = SNES::Input::DeviceJoypad;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort1Asciipad() {
|
||||
config().input.port1 = ControllerPort1::Asciipad;
|
||||
SNES::config.controller_port1 = SNES::Input::DeviceJoypad;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort1Multitap() {
|
||||
config().input.port1 = ControllerPort1::Multitap;
|
||||
SNES::config.controller_port1 = SNES::Input::DeviceMultitap;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort1Mouse() {
|
||||
config().input.port1 = ControllerPort1::Mouse;
|
||||
SNES::config.controller_port1 = SNES::Input::DeviceMouse;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2None() {
|
||||
config().input.port2 = ControllerPort2::None;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceNone;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Gamepad() {
|
||||
config().input.port2 = ControllerPort2::Gamepad;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceJoypad;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Asciipad() {
|
||||
config().input.port2 = ControllerPort2::Asciipad;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceJoypad;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Multitap() {
|
||||
config().input.port2 = ControllerPort2::Multitap;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceMultitap;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Mouse() {
|
||||
config().input.port2 = ControllerPort2::Mouse;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceMouse;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2SuperScope() {
|
||||
config().input.port2 = ControllerPort2::SuperScope;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceSuperScope;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Justifier() {
|
||||
config().input.port2 = ControllerPort2::Justifier;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceJustifier;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Justifiers() {
|
||||
config().input.port2 = ControllerPort2::Justifiers;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceJustifiers;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::quit() {
|
||||
window->hide();
|
||||
hide();
|
||||
application.terminate = true;
|
||||
}
|
||||
|
||||
void MainWindow::setVideoMode1x() { config.video.context->multiplier = 1; utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoMode2x() { config.video.context->multiplier = 2; utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoMode3x() { config.video.context->multiplier = 3; utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoMode4x() { config.video.context->multiplier = 4; utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoModeMax() { config.video.context->multiplier = 9; utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoMode1x() { utility.setScale(1); }
|
||||
void MainWindow::setVideoMode2x() { utility.setScale(2); }
|
||||
void MainWindow::setVideoMode3x() { utility.setScale(3); }
|
||||
void MainWindow::setVideoMode4x() { utility.setScale(4); }
|
||||
void MainWindow::setVideoMode5x() { utility.setScale(5); }
|
||||
|
||||
void MainWindow::toggleAspectCorrection() {
|
||||
settings_videoMode_correctAspectRatio->toggleChecked();
|
||||
config.video.context->correctAspectRatio = settings_videoMode_correctAspectRatio->isChecked();
|
||||
utility.resizeMainWindow();
|
||||
}
|
||||
void MainWindow::toggleAspectCorrection() { utility.toggleAspectCorrection(); }
|
||||
|
||||
void MainWindow::toggleFullscreen() {
|
||||
settings_videoMode_fullscreen->toggleChecked();
|
||||
config.video.isFullscreen = settings_videoMode_fullscreen->isChecked();
|
||||
utility.updateFullscreenState();
|
||||
utility.resizeMainWindow();
|
||||
syncUi();
|
||||
}
|
||||
void MainWindow::setVideoNtsc() { utility.setNtscMode(); }
|
||||
void MainWindow::setVideoPal() { utility.setPalMode(); }
|
||||
|
||||
void MainWindow::setVideoNtsc() { config.video.context->region = 0; utility.updateVideoMode(); utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoPal() { config.video.context->region = 1; utility.updateVideoMode(); utility.resizeMainWindow(); syncUi(); }
|
||||
|
||||
void MainWindow::toggleSmoothVideo() {
|
||||
settings_smoothVideo->toggleChecked();
|
||||
config.video.context->hwFilter = settings_smoothVideo->isChecked();
|
||||
utility.updateHardwareFilter();
|
||||
syncUi();
|
||||
}
|
||||
void MainWindow::toggleSmoothVideo() { utility.toggleSmoothVideoOutput(); }
|
||||
|
||||
void MainWindow::configureFilter() {
|
||||
QWidget *widget = filter.settings();
|
||||
@@ -376,7 +498,7 @@ void MainWindow::configureFilter() {
|
||||
void MainWindow::setFilter() {
|
||||
for(unsigned i = 0; i < settings_videoFilter_list.size(); i++) {
|
||||
if(sender() == settings_videoFilter_list[i]) {
|
||||
config.video.context->swFilter = i;
|
||||
config().video.context->swFilter = i;
|
||||
utility.updateSoftwareFilter();
|
||||
syncUi();
|
||||
return;
|
||||
@@ -386,33 +508,53 @@ void MainWindow::setFilter() {
|
||||
|
||||
void MainWindow::muteAudio() {
|
||||
settings_muteAudio->toggleChecked();
|
||||
config.audio.mute = settings_muteAudio->isChecked();
|
||||
config().audio.mute = settings_muteAudio->isChecked();
|
||||
}
|
||||
|
||||
void MainWindow::setSpeedSlowest() { config.system.speed = 0; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedSlow() { config.system.speed = 1; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedNormal() { config.system.speed = 2; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedFast() { config.system.speed = 3; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedFastest() { config.system.speed = 4; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedSlowest() { config().system.speed = 0; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedSlow() { config().system.speed = 1; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedNormal() { config().system.speed = 2; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedFast() { config().system.speed = 3; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedFastest() { config().system.speed = 4; utility.updateEmulationSpeed(); syncUi(); }
|
||||
|
||||
void MainWindow::syncVideo() {
|
||||
settings_emulationSpeed_syncVideo->toggleChecked();
|
||||
config.video.synchronize = settings_emulationSpeed_syncVideo->isChecked();
|
||||
utility.updateAvSync();
|
||||
void MainWindow::syncVideo() { utility.toggleSynchronizeVideo(); }
|
||||
void MainWindow::syncAudio() { utility.toggleSynchronizeAudio(); }
|
||||
|
||||
void MainWindow::showConfigWindow() { settingsWindow->show(); }
|
||||
|
||||
void MainWindow::playMovie() {
|
||||
movie.chooseFile();
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void MainWindow::syncAudio() {
|
||||
settings_emulationSpeed_syncAudio->toggleChecked();
|
||||
config.audio.synchronize = settings_emulationSpeed_syncAudio->isChecked();
|
||||
utility.updateAvSync();
|
||||
void MainWindow::stopMovie() {
|
||||
movie.stop();
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void MainWindow::showConfigWindow() { settingsWindow->window->show(); }
|
||||
void MainWindow::recordMovieFromPowerOn() {
|
||||
utility.modifySystemState(Utility::PowerCycle);
|
||||
movie.record();
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void MainWindow::showCheatEditor() { toolsWindow->showCheatEditor(); }
|
||||
void MainWindow::showCheatFinder() { toolsWindow->showCheatFinder(); }
|
||||
void MainWindow::showStateManager() { toolsWindow->showStateManager(); }
|
||||
void MainWindow::showDebugger() { debugger->window->show(); }
|
||||
void MainWindow::recordMovieFromHere() {
|
||||
movie.record();
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void MainWindow::saveScreenshot() {
|
||||
//tell SNES::Interface to save a screenshot at the next video_refresh() event
|
||||
interface.saveScreenshot = true;
|
||||
}
|
||||
|
||||
void MainWindow::showDebugger() {
|
||||
#if defined(DEBUGGER)
|
||||
debugger->show();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::showToolsDialog() { toolsWindow->show(); }
|
||||
|
||||
void MainWindow::showDocumentation() {
|
||||
QFile file(":/documentation.html");
|
||||
@@ -430,14 +572,12 @@ void MainWindow::showLicense() {
|
||||
}
|
||||
}
|
||||
void MainWindow::showAbout() {
|
||||
aboutWindow->window->show();
|
||||
aboutWindow->show();
|
||||
}
|
||||
|
||||
void MainWindow::Window::closeEvent(QCloseEvent*) {
|
||||
mainWindow->quit();
|
||||
}
|
||||
|
||||
MainWindow::Window::Window(string &geometry) : QbWindow(geometry) {
|
||||
void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
QbWindow::closeEvent(event);
|
||||
quit();
|
||||
}
|
||||
|
||||
//============
|
||||
|
@@ -13,14 +13,10 @@ public:
|
||||
void paintEvent(QPaintEvent*);
|
||||
};
|
||||
|
||||
class MainWindow : public QObject {
|
||||
class MainWindow : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct Window : public QbWindow {
|
||||
void closeEvent(QCloseEvent*);
|
||||
Window(string&);
|
||||
} *window;
|
||||
QMenuBar *menuBar;
|
||||
QStatusBar *statusBar;
|
||||
QVBoxLayout *layout;
|
||||
@@ -35,12 +31,14 @@ public:
|
||||
QAction *system_reset;
|
||||
QMenu *system_port1;
|
||||
QbRadioAction *system_port1_none;
|
||||
QbRadioAction *system_port1_joypad;
|
||||
QbRadioAction *system_port1_gamepad;
|
||||
QbRadioAction *system_port1_asciipad;
|
||||
QbRadioAction *system_port1_multitap;
|
||||
QbRadioAction *system_port1_mouse;
|
||||
QMenu *system_port2;
|
||||
QbRadioAction *system_port2_none;
|
||||
QbRadioAction *system_port2_joypad;
|
||||
QbRadioAction *system_port2_gamepad;
|
||||
QbRadioAction *system_port2_asciipad;
|
||||
QbRadioAction *system_port2_multitap;
|
||||
QbRadioAction *system_port2_mouse;
|
||||
QbRadioAction *system_port2_superscope;
|
||||
@@ -53,9 +51,8 @@ public:
|
||||
QbRadioAction *settings_videoMode_2x;
|
||||
QbRadioAction *settings_videoMode_3x;
|
||||
QbRadioAction *settings_videoMode_4x;
|
||||
QbRadioAction *settings_videoMode_max;
|
||||
QbRadioAction *settings_videoMode_5x;
|
||||
QbCheckAction *settings_videoMode_correctAspectRatio;
|
||||
QbCheckAction *settings_videoMode_fullscreen;
|
||||
QbRadioAction *settings_videoMode_ntsc;
|
||||
QbRadioAction *settings_videoMode_pal;
|
||||
QMenu *settings_videoFilter;
|
||||
@@ -74,22 +71,27 @@ public:
|
||||
QbCheckAction *settings_emulationSpeed_syncAudio;
|
||||
QAction *settings_configuration;
|
||||
QMenu *tools;
|
||||
QAction *tools_cheatEditor;
|
||||
QAction *tools_cheatFinder;
|
||||
QAction *tools_stateManager;
|
||||
QMenu *tools_movies;
|
||||
QAction *tools_movies_play;
|
||||
QAction *tools_movies_stop;
|
||||
QAction *tools_movies_recordFromPowerOn;
|
||||
QAction *tools_movies_recordFromHere;
|
||||
QAction *tools_captureScreenshot;
|
||||
QAction *tools_debugger;
|
||||
QAction *tools_dialog;
|
||||
QMenu *help;
|
||||
QAction *help_documentation;
|
||||
QAction *help_license;
|
||||
QAction *help_about;
|
||||
//
|
||||
|
||||
CanvasObject *canvasContainer;
|
||||
QVBoxLayout *canvasLayout;
|
||||
CanvasWidget *canvas;
|
||||
QVBoxLayout *canvasLayout;
|
||||
CanvasWidget *canvas;
|
||||
QLabel *systemState;
|
||||
|
||||
void syncUi();
|
||||
bool isActive();
|
||||
void closeEvent(QCloseEvent*);
|
||||
MainWindow();
|
||||
|
||||
public slots:
|
||||
@@ -101,11 +103,13 @@ public slots:
|
||||
void power();
|
||||
void reset();
|
||||
void setPort1None();
|
||||
void setPort1Joypad();
|
||||
void setPort1Gamepad();
|
||||
void setPort1Asciipad();
|
||||
void setPort1Multitap();
|
||||
void setPort1Mouse();
|
||||
void setPort2None();
|
||||
void setPort2Joypad();
|
||||
void setPort2Gamepad();
|
||||
void setPort2Asciipad();
|
||||
void setPort2Multitap();
|
||||
void setPort2Mouse();
|
||||
void setPort2SuperScope();
|
||||
@@ -116,9 +120,8 @@ public slots:
|
||||
void setVideoMode2x();
|
||||
void setVideoMode3x();
|
||||
void setVideoMode4x();
|
||||
void setVideoModeMax();
|
||||
void setVideoMode5x();
|
||||
void toggleAspectCorrection();
|
||||
void toggleFullscreen();
|
||||
void setVideoNtsc();
|
||||
void setVideoPal();
|
||||
void configureFilter();
|
||||
@@ -133,11 +136,16 @@ public slots:
|
||||
void syncVideo();
|
||||
void syncAudio();
|
||||
void showConfigWindow();
|
||||
void showCheatEditor();
|
||||
void showCheatFinder();
|
||||
void showStateManager();
|
||||
void playMovie();
|
||||
void stopMovie();
|
||||
void recordMovieFromPowerOn();
|
||||
void recordMovieFromHere();
|
||||
void saveScreenshot();
|
||||
void showDebugger();
|
||||
void showToolsDialog();
|
||||
void showDocumentation();
|
||||
void showLicense();
|
||||
void showAbout();
|
||||
} *mainWindow;
|
||||
};
|
||||
|
||||
extern MainWindow *mainWindow;
|
||||
|
@@ -1,3 +1,8 @@
|
||||
Configuration &config() {
|
||||
static Configuration configuration;
|
||||
return configuration;
|
||||
}
|
||||
|
||||
bool Configuration::load(const char *filename) {
|
||||
if(configuration::load(filename) == false) return false;
|
||||
SNES::config.superfx.speed = max(0, min(2, SNES::config.superfx.speed));
|
||||
@@ -5,21 +10,6 @@ bool Configuration::load(const char *filename) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Configuration::attachJoypad(Configuration::Input::Joypad &joypad, const char *name) {
|
||||
attach(joypad.up = "none", string() << name << ".up");
|
||||
attach(joypad.down = "none", string() << name << ".down");
|
||||
attach(joypad.left = "none", string() << name << ".left");
|
||||
attach(joypad.right = "none", string() << name << ".right");
|
||||
attach(joypad.a = "none", string() << name << ".a");
|
||||
attach(joypad.b = "none", string() << name << ".b");
|
||||
attach(joypad.x = "none", string() << name << ".x");
|
||||
attach(joypad.y = "none", string() << name << ".y");
|
||||
attach(joypad.l = "none", string() << name << ".l");
|
||||
attach(joypad.r = "none", string() << name << ".r");
|
||||
attach(joypad.select = "none", string() << name << ".select");
|
||||
attach(joypad.start = "none", string() << name << ".start");
|
||||
}
|
||||
|
||||
Configuration::Configuration() {
|
||||
//========
|
||||
//external
|
||||
@@ -54,22 +44,39 @@ Configuration::Configuration() {
|
||||
attach(system.input = "", "system.input");
|
||||
attach(system.crashedOnLastRun = false, "system.crashedOnLastRun");
|
||||
attach(system.speed = 2, "system.speed");
|
||||
attach(system.speedSlowest = 50, "system.speedSlowest");
|
||||
attach(system.speedSlow = 75, "system.speedSlow");
|
||||
attach(system.speedNormal = 100, "system.speedNormal");
|
||||
attach(system.speedFast = 150, "system.speedFast");
|
||||
attach(system.speedFastest = 200, "system.speedFastest");
|
||||
attach(system.autoSaveMemory = false, "system.autoSaveMemory", "Automatically save cartridge back-up RAM once every minute");
|
||||
attach(system.autoHideMenus = false, "system.autoHideMenus", "Automatically hide the menu and status bars when entering fullscreen mode");
|
||||
attach(system.rewindEnabled = false, "system.rewindEnabled", "Automatically save states periodically to allow auto-rewind support");
|
||||
|
||||
attach(diskBrowser.showPanel = true, "diskBrowser.showPanel");
|
||||
|
||||
attach(file.autodetect_type = false, "file.autodetectType");
|
||||
attach(file.bypass_patch_crc32 = false, "file.bypassPatchCrc32");
|
||||
|
||||
attach(path.current = "", "path.current");
|
||||
attach(path.rom = "", "path.rom");
|
||||
attach(path.save = "", "path.save");
|
||||
attach(path.state = "", "path.state");
|
||||
attach(path.patch = "", "path.patch");
|
||||
attach(path.cheat = "", "path.cheat");
|
||||
attach(path.data = "", "path.data");
|
||||
attach(path.bsx = "", "path.bsx");
|
||||
attach(path.st = "", "path.st");
|
||||
attach(path.sgb = "", "path.sgb");
|
||||
attach(path.rom = "", "path.rom");
|
||||
attach(path.save = "", "path.save");
|
||||
attach(path.state = "", "path.state");
|
||||
attach(path.patch = "", "path.patch");
|
||||
attach(path.cheat = "", "path.cheat");
|
||||
attach(path.data = "", "path.data");
|
||||
attach(path.bsx = "", "path.bsx");
|
||||
attach(path.st = "", "path.st");
|
||||
attach(path.sgb = "", "path.sgb");
|
||||
attach(path.fragmentShader = "", "path.fragmentShader");
|
||||
attach(path.vertexShader = "", "path.vertexShader");
|
||||
|
||||
attach(path.current.folder = "", "path.current.folder");
|
||||
attach(path.current.movie = "", "path.current.movie");
|
||||
attach(path.current.shader = "", "path.current.shader");
|
||||
attach(path.current.cartridge = "", "path.current.cartridge");
|
||||
attach(path.current.bsx = "", "path.current.bsx");
|
||||
attach(path.current.st = "", "path.current.st");
|
||||
attach(path.current.sgb = "", "path.current.sgb");
|
||||
attach(path.current.filter = 0, "path.current.filter");
|
||||
|
||||
video.context = &video.windowed;
|
||||
attach(video.isFullscreen = false, "video.isFullscreen");
|
||||
@@ -78,6 +85,7 @@ Configuration::Configuration() {
|
||||
attach(video.contrastAdjust = 0, "video.contrastAdjust");
|
||||
attach(video.brightnessAdjust = 0, "video.brightnessAdjust");
|
||||
attach(video.gammaAdjust = 0, "video.gammaAdjust");
|
||||
attach(video.scanlineAdjust = 100, "video.scanlineAdjust");
|
||||
attach(video.enableGammaRamp = true, "video.enableGammaRamp");
|
||||
|
||||
attach(video.ntscAspectRatio = 54.0 / 47.0, "video.ntscAspectRatio", "NTSC aspect ratio (x / y)");
|
||||
@@ -105,98 +113,22 @@ Configuration::Configuration() {
|
||||
attach(audio.outputFrequency = 48000, "audio.outputFrequency");
|
||||
attach(audio.inputFrequency = 32000, "audio.inputFrequency");
|
||||
|
||||
attach(input.port1 = ControllerPort1::Gamepad, "input.port1");
|
||||
attach(input.port2 = ControllerPort2::Gamepad, "input.port2");
|
||||
attach(input.focusPolicy = Input::FocusPolicyIgnoreInput, "input.focusPolicy");
|
||||
attach(input.allowInvalidInput = false, "input.allowInvalidInput", "Allow up+down / left+right combinations; may trigger bugs in some games");
|
||||
|
||||
attach(input.joypad1.up = "keyboard00.up", "input.joypad1.up");
|
||||
attach(input.joypad1.down = "keyboard00.down", "input.joypad1.down");
|
||||
attach(input.joypad1.left = "keyboard00.left", "input.joypad1.left");
|
||||
attach(input.joypad1.right = "keyboard00.right", "input.joypad1.right");
|
||||
attach(input.joypad1.a = "keyboard00.x", "input.joypad1.a");
|
||||
attach(input.joypad1.b = "keyboard00.z", "input.joypad1.b");
|
||||
attach(input.joypad1.x = "keyboard00.s", "input.joypad1.x");
|
||||
attach(input.joypad1.y = "keyboard00.a", "input.joypad1.y");
|
||||
attach(input.joypad1.l = "keyboard00.d", "input.joypad1.l");
|
||||
attach(input.joypad1.r = "keyboard00.c", "input.joypad1.r");
|
||||
attach(input.joypad1.select = "keyboard00.rshift", "input.joypad1.select");
|
||||
attach(input.joypad1.start = "keyboard00.return", "input.joypad1.start");
|
||||
|
||||
//these are all mapped to "none" by default
|
||||
attachJoypad(input.joypad2, "input.joypad2");
|
||||
attachJoypad(input.multitap1a, "input.multitap1a");
|
||||
attachJoypad(input.multitap1b, "input.multitap1b");
|
||||
attachJoypad(input.multitap1c, "input.multitap1c");
|
||||
attachJoypad(input.multitap1d, "input.multitap1d");
|
||||
attachJoypad(input.multitap2a, "input.multitap2a");
|
||||
attachJoypad(input.multitap2b, "input.multitap2b");
|
||||
attachJoypad(input.multitap2c, "input.multitap2c");
|
||||
attachJoypad(input.multitap2d, "input.multitap2d");
|
||||
|
||||
attach(input.mouse1.x = "mouse00.x", "input.mouse1.x");
|
||||
attach(input.mouse1.y = "mouse00.y", "input.mouse1.y");
|
||||
attach(input.mouse1.left = "mouse00.button00", "input.mouse1.left");
|
||||
attach(input.mouse1.right = "mouse00.button02", "input.mouse1.right");
|
||||
|
||||
//more likely a user will only use one mouse at a time, than for a system to have two mice
|
||||
attach(input.mouse2.x = "mouse00.x", "input.mouse2.x");
|
||||
attach(input.mouse2.y = "mouse00.y", "input.mouse2.y");
|
||||
attach(input.mouse2.left = "mouse00.button00", "input.mouse2.left");
|
||||
attach(input.mouse2.right = "mouse00.button02", "input.mouse2.right");
|
||||
|
||||
//unlikely a user will have a five-button mouse for turbo / pause mapping
|
||||
attach(input.superscope.x = "mouse00.x", "input.superscope.x");
|
||||
attach(input.superscope.y = "mouse00.y", "input.superscope.y");
|
||||
attach(input.superscope.trigger = "mouse00.button00", "input.superscope.trigger");
|
||||
attach(input.superscope.cursor = "mouse00.button02", "input.superscope.cursor");
|
||||
attach(input.superscope.turbo = "keyboard00.t", "input.superscope.turbo");
|
||||
attach(input.superscope.pause = "keyboard00.p", "input.superscope.pause");
|
||||
|
||||
attach(input.justifier1.x = "mouse00.x", "input.justifier1.x");
|
||||
attach(input.justifier1.y = "mouse00.y", "input.justifier1.y");
|
||||
attach(input.justifier1.trigger = "mouse00.button00", "input.justifier1.trigger");
|
||||
attach(input.justifier1.start = "mouse00.button02", "input.jusitifer1.start");
|
||||
|
||||
attach(input.justifier2.x = "mouse01.x", "input.justifier2.x");
|
||||
attach(input.justifier2.y = "mouse01.y", "input.justifier2.y");
|
||||
attach(input.justifier2.trigger = "mouse01.button00", "input.justifier2.trigger");
|
||||
attach(input.justifier2.start = "mouse01.button02", "input.justifier2.start");
|
||||
|
||||
attach(input.uiGeneral.loadCartridge = "none", "input.uiGeneral.loadCartridge");
|
||||
attach(input.uiGeneral.pauseEmulation = "keyboard00.pause", "input.uiGeneral.pauseEmulation");
|
||||
attach(input.uiGeneral.resetSystem = "none", "input.uiGeneral.resetSystem");
|
||||
attach(input.uiGeneral.powerCycleSystem = "none", "input.uiGeneral.powerCycleSystem");
|
||||
|
||||
attach(input.uiGeneral.saveScreenshot = "none", "input.uiGeneral.saveScreenshot");
|
||||
attach(input.uiGeneral.showStateManager = "keyboard00.f3", "input.uiGeneral.showStateManager");
|
||||
|
||||
attach(input.uiGeneral.quickLoad1 = "keyboard00.f4", "input.uiGeneral.quickLoad1");
|
||||
attach(input.uiGeneral.quickLoad2 = "none", "input.uiGeneral.quickLoad2");
|
||||
attach(input.uiGeneral.quickLoad3 = "none", "input.uiGeneral.quickLoad3");
|
||||
attach(input.uiGeneral.quickSave1 = "keyboard00.f2", "input.uiGeneral.quickSave1");
|
||||
attach(input.uiGeneral.quickSave2 = "none", "input.uiGeneral.quickSave2");
|
||||
attach(input.uiGeneral.quickSave3 = "none", "input.uiGeneral.quickSave3");
|
||||
|
||||
attach(input.uiGeneral.lowerSpeed = "keyboard00.divide", "input.uiGeneral.lowerSpeed");
|
||||
attach(input.uiGeneral.raiseSpeed = "keyboard00.multiply", "input.uiGeneral.raiseSpeed");
|
||||
attach(input.uiGeneral.toggleCheatSystem = "none", "input.uiGeneral.toggleCheatSystem");
|
||||
attach(input.uiGeneral.toggleFullscreen = "keyboard00.f11", "input.uiGeneral.toggleFullscreen");
|
||||
attach(input.uiGeneral.toggleMenu = "keyboard00.escape", "input.uiGeneral.toggleMenu");
|
||||
attach(input.uiGeneral.toggleStatus = "keyboard00.escape", "input.uiGeneral.toggleStatus");
|
||||
attach(input.uiGeneral.exitEmulator = "none", "input.uiGeneral.exitEmulator");
|
||||
|
||||
attach(geometry.mainWindow = "", "geometry.mainWindow");
|
||||
attach(geometry.loaderWindow = "", "geometry.loaderWindow");
|
||||
attach(geometry.htmlViewerWindow = "", "geometry.htmlViewerWindow");
|
||||
attach(geometry.aboutWindow = "", "geometry.aboutWindow");
|
||||
attach(geometry.diskBrowser = "", "geometry.diskBrowser");
|
||||
attach(geometry.folderCreator = "", "geometry.folderCreator");
|
||||
attach(geometry.settingsWindow = "", "geometry.settingsWindow");
|
||||
attach(geometry.inputCaptureWindow = "", "geometry.inputCaptureWindow");
|
||||
attach(geometry.inputMouseCaptureWindow = "", "geometry.inputMouseCaptureWindow");
|
||||
attach(geometry.inputCalibrationWindow = "", "geometry.inputCalibrationWindow");
|
||||
attach(geometry.toolsWindow = "", "geometry.toolsWindow");
|
||||
attach(geometry.debugger = "", "geometry.debugger");
|
||||
attach(geometry.breakpointEditor = "", "geometry.breakpointEditor");
|
||||
attach(geometry.memoryEditor = "", "geometry.memoryEditor");
|
||||
attach(geometry.vramViewer = "", "geometry.vramViewer");
|
||||
attach(geometry.mainWindow = "", "geometry.mainWindow");
|
||||
attach(geometry.loaderWindow = "", "geometry.loaderWindow");
|
||||
attach(geometry.htmlViewerWindow = "", "geometry.htmlViewerWindow");
|
||||
attach(geometry.aboutWindow = "", "geometry.aboutWindow");
|
||||
attach(geometry.diskBrowser = "", "geometry.diskBrowser");
|
||||
attach(geometry.folderCreator = "", "geometry.folderCreator");
|
||||
attach(geometry.settingsWindow = "", "geometry.settingsWindow");
|
||||
attach(geometry.toolsWindow = "", "geometry.toolsWindow");
|
||||
attach(geometry.debugger = "", "geometry.debugger");
|
||||
attach(geometry.disassembler = "", "geometry.disassembler");
|
||||
attach(geometry.breakpointEditor = "", "geometry.breakpointEditor");
|
||||
attach(geometry.memoryEditor = "", "geometry.memoryEditor");
|
||||
attach(geometry.vramViewer = "", "geometry.vramViewer");
|
||||
}
|
||||
|
@@ -4,8 +4,13 @@ public:
|
||||
string video, audio, input;
|
||||
bool crashedOnLastRun;
|
||||
unsigned speed;
|
||||
unsigned speedSlowest;
|
||||
unsigned speedSlow;
|
||||
unsigned speedNormal;
|
||||
unsigned speedFast;
|
||||
unsigned speedFastest;
|
||||
bool autoSaveMemory;
|
||||
bool autoHideMenus;
|
||||
bool rewindEnabled;
|
||||
} system;
|
||||
|
||||
struct File {
|
||||
@@ -13,18 +18,28 @@ public:
|
||||
bool bypass_patch_crc32;
|
||||
} file;
|
||||
|
||||
struct DiskBrowser {
|
||||
bool showPanel;
|
||||
} diskBrowser;
|
||||
|
||||
struct Path {
|
||||
string base; //binary path
|
||||
string user; //user profile path (bsnes.cfg, ...)
|
||||
string current; //current working directory (path to currently loaded cartridge)
|
||||
string startup; //startup path
|
||||
string rom, save, state, patch, cheat, data;
|
||||
string bsx, st, sgb;
|
||||
string fragmentShader, vertexShader;
|
||||
|
||||
struct Current {
|
||||
string folder, movie, shader, cartridge, bsx, st, sgb;
|
||||
unsigned filter; //current active filter for "Load Cartridge"
|
||||
} current;
|
||||
} path;
|
||||
|
||||
struct Video {
|
||||
bool isFullscreen;
|
||||
bool synchronize;
|
||||
signed contrastAdjust, brightnessAdjust, gammaAdjust;
|
||||
signed contrastAdjust, brightnessAdjust, gammaAdjust, scanlineAdjust;
|
||||
bool enableGammaRamp;
|
||||
double ntscAspectRatio, palAspectRatio;
|
||||
|
||||
@@ -42,49 +57,11 @@ public:
|
||||
} audio;
|
||||
|
||||
struct Input {
|
||||
unsigned port1;
|
||||
unsigned port2;
|
||||
enum policy_t { FocusPolicyPauseEmulation, FocusPolicyIgnoreInput, FocusPolicyAllowInput };
|
||||
unsigned focusPolicy;
|
||||
bool allowInvalidInput;
|
||||
|
||||
struct Joypad {
|
||||
string up, down, left, right, a, b, x, y, l, r, select, start;
|
||||
} joypad1, joypad2,
|
||||
multitap1a, multitap1b, multitap1c, multitap1d,
|
||||
multitap2a, multitap2b, multitap2c, multitap2d;
|
||||
|
||||
struct Mouse {
|
||||
string x, y, left, right;
|
||||
} mouse1, mouse2;
|
||||
|
||||
struct SuperScope {
|
||||
string x, y, trigger, turbo, cursor, pause;
|
||||
} superscope;
|
||||
|
||||
struct Justifier {
|
||||
string x, y, trigger, start;
|
||||
} justifier1, justifier2;
|
||||
|
||||
struct UiGeneral {
|
||||
string loadCartridge;
|
||||
string pauseEmulation;
|
||||
string resetSystem;
|
||||
string powerCycleSystem;
|
||||
string saveScreenshot;
|
||||
string showStateManager;
|
||||
string quickLoad1;
|
||||
string quickLoad2;
|
||||
string quickLoad3;
|
||||
string quickSave1;
|
||||
string quickSave2;
|
||||
string quickSave3;
|
||||
string lowerSpeed;
|
||||
string raiseSpeed;
|
||||
string toggleCheatSystem;
|
||||
string toggleFullscreen;
|
||||
string toggleMenu;
|
||||
string toggleStatus;
|
||||
string exitEmulator;
|
||||
} uiGeneral;
|
||||
} input;
|
||||
|
||||
struct Geometry {
|
||||
@@ -94,21 +71,17 @@ public:
|
||||
string aboutWindow;
|
||||
string diskBrowser;
|
||||
string folderCreator;
|
||||
|
||||
string settingsWindow;
|
||||
string inputCaptureWindow;
|
||||
string inputMouseCaptureWindow;
|
||||
string inputCalibrationWindow;
|
||||
|
||||
string toolsWindow;
|
||||
|
||||
string debugger;
|
||||
string disassembler;
|
||||
string breakpointEditor;
|
||||
string memoryEditor;
|
||||
string vramViewer;
|
||||
} geometry;
|
||||
|
||||
bool load(const char *filename);
|
||||
void attachJoypad(Configuration::Input::Joypad &joypad, const char *name);
|
||||
Configuration();
|
||||
} config;
|
||||
};
|
||||
|
||||
Configuration &config();
|
||||
|
@@ -1,3 +1,6 @@
|
||||
#include "breakpoint.moc"
|
||||
BreakpointEditor *breakpointEditor;
|
||||
|
||||
BreakpointItem::BreakpointItem(unsigned id_) : id(id_) {
|
||||
layout = new QHBoxLayout;
|
||||
layout->setMargin(0);
|
||||
@@ -58,16 +61,15 @@ void BreakpointItem::toggle() {
|
||||
}
|
||||
}
|
||||
|
||||
BreakpointEditor::BreakpointEditor() {
|
||||
window = new QbWindow(config.geometry.breakpointEditor);
|
||||
window->setObjectName("breakpoint-editor");
|
||||
window->setWindowTitle("Breakpoint Editor");
|
||||
BreakpointEditor::BreakpointEditor() : QbWindow(config().geometry.breakpointEditor) {
|
||||
setObjectName("breakpoint-editor");
|
||||
setWindowTitle("Breakpoint Editor");
|
||||
|
||||
layout = new QVBoxLayout;
|
||||
layout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
layout->setMargin(Style::WindowMargin);
|
||||
layout->setSpacing(Style::WidgetSpacing);
|
||||
window->setLayout(layout);
|
||||
setLayout(layout);
|
||||
|
||||
for(unsigned n = 0; n < SNES::Debugger::Breakpoints; n++) {
|
||||
breakpoint[n] = new BreakpointItem(n);
|
||||
|
@@ -17,13 +17,14 @@ private:
|
||||
const unsigned id;
|
||||
};
|
||||
|
||||
class BreakpointEditor : public QObject {
|
||||
class BreakpointEditor : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QbWindow *window;
|
||||
QVBoxLayout *layout;
|
||||
BreakpointItem *breakpoint[SNES::Debugger::Breakpoints];
|
||||
|
||||
BreakpointEditor();
|
||||
} *breakpointEditor;
|
||||
};
|
||||
|
||||
extern BreakpointEditor *breakpointEditor;
|
||||
|
@@ -1,32 +1,37 @@
|
||||
#include "../ui-base.hpp"
|
||||
|
||||
#if defined(DEBUGGER)
|
||||
|
||||
#include "debugger.moc"
|
||||
Debugger *debugger;
|
||||
|
||||
#include "hexeditor.cpp"
|
||||
#include "disassembler.cpp"
|
||||
#include "breakpoint.cpp"
|
||||
#include "memory.cpp"
|
||||
#include "vramviewer.cpp"
|
||||
#include "tracer.cpp"
|
||||
|
||||
Debugger::Debugger() {
|
||||
window = new QbWindow(config.geometry.debugger);
|
||||
window->setObjectName("debugger");
|
||||
window->setWindowTitle("Debugger");
|
||||
Debugger::Debugger() : QbWindow(config().geometry.debugger) {
|
||||
setObjectName("debugger");
|
||||
setWindowTitle("Debugger");
|
||||
|
||||
layout = new QHBoxLayout;
|
||||
layout->setMargin(Style::WindowMargin);
|
||||
layout->setSpacing(Style::WidgetSpacing);
|
||||
window->setLayout(layout);
|
||||
setLayout(layout);
|
||||
|
||||
menu = new QMenuBar;
|
||||
layout->setMenuBar(menu);
|
||||
|
||||
tools = menu->addMenu("Tools");
|
||||
tools_disassembler = tools->addAction("Disassembler ...");
|
||||
tools_breakpoint = tools->addAction("Breakpoint Editor ...");
|
||||
tools_breakpoint->setIcon(QIcon(":/16x16/process-stop.png"));
|
||||
tools_memory = tools->addAction("Memory Editor ...");
|
||||
tools_memory->setIcon(QIcon(":/16x16/text-x-generic.png"));
|
||||
tools_vramViewer = tools->addAction("Video RAM Viewer ...");
|
||||
tools_vramViewer->setIcon(QIcon(":/16x16/image-x-generic.png"));
|
||||
|
||||
miscOptions = menu->addMenu("Misc");
|
||||
miscOptions_clear = miscOptions->addAction("Clear Console");
|
||||
miscOptions_clear->setIcon(QIcon(":/16x16/document-new.png"));
|
||||
|
||||
console = new QTextEdit;
|
||||
console->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
@@ -53,22 +58,32 @@ Debugger::Debugger() {
|
||||
|
||||
controlLayout->addSpacing(Style::WidgetSpacing);
|
||||
|
||||
stepCPU = new QCheckBox("Step CPU");
|
||||
stepCPU = new QCheckBox("Step S-CPU");
|
||||
controlLayout->addWidget(stepCPU);
|
||||
|
||||
stepSMP = new QCheckBox("Step SMP");
|
||||
stepSMP = new QCheckBox("Step S-SMP");
|
||||
controlLayout->addWidget(stepSMP);
|
||||
|
||||
traceCPU = new QCheckBox("Trace CPU opcodes");
|
||||
traceCPU = new QCheckBox("Trace S-CPU opcodes");
|
||||
controlLayout->addWidget(traceCPU);
|
||||
|
||||
traceSMP = new QCheckBox("Trace SMP opcodes");
|
||||
traceSMP = new QCheckBox("Trace S-SMP opcodes");
|
||||
controlLayout->addWidget(traceSMP);
|
||||
|
||||
traceMask = new QCheckBox("Enable trace mask");
|
||||
controlLayout->addWidget(traceMask);
|
||||
|
||||
spacer = new QWidget;
|
||||
spacer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
controlLayout->addWidget(spacer);
|
||||
|
||||
disassembler = new Disassembler;
|
||||
breakpointEditor = new BreakpointEditor;
|
||||
memoryEditor = new MemoryEditor;
|
||||
vramViewer = new VramViewer;
|
||||
tracer = new Tracer;
|
||||
|
||||
connect(tools_disassembler, SIGNAL(triggered()), this, SLOT(showDisassembler()));
|
||||
connect(tools_breakpoint, SIGNAL(triggered()), this, SLOT(showBreakpointEditor()));
|
||||
connect(tools_memory, SIGNAL(triggered()), this, SLOT(showMemoryEditor()));
|
||||
connect(tools_vramViewer, SIGNAL(triggered()), this, SLOT(showVramViewer()));
|
||||
@@ -78,16 +93,37 @@ Debugger::Debugger() {
|
||||
connect(stepInstruction, SIGNAL(released()), this, SLOT(stepAction()));
|
||||
connect(stepCPU, SIGNAL(released()), this, SLOT(synchronize()));
|
||||
connect(stepSMP, SIGNAL(released()), this, SLOT(synchronize()));
|
||||
connect(traceCPU, SIGNAL(released()), this, SLOT(toggleTraceCPU()));
|
||||
connect(traceSMP, SIGNAL(released()), this, SLOT(toggleTraceSMP()));
|
||||
|
||||
breakpointEditor = new BreakpointEditor;
|
||||
memoryEditor = new MemoryEditor;
|
||||
vramViewer = new VramViewer;
|
||||
connect(traceCPU, SIGNAL(stateChanged(int)), tracer, SLOT(setCpuTraceState(int)));
|
||||
connect(traceSMP, SIGNAL(stateChanged(int)), tracer, SLOT(setSmpTraceState(int)));
|
||||
connect(traceMask, SIGNAL(stateChanged(int)), tracer, SLOT(setTraceMaskState(int)));
|
||||
|
||||
frameCounter = 0;
|
||||
synchronize();
|
||||
window->resize(855, 425);
|
||||
resize(855, 425);
|
||||
}
|
||||
|
||||
void Debugger::modifySystemState(unsigned state) {
|
||||
string usagefile = string() << dir(utility.cartridge.baseName) << "usage.bin";
|
||||
file fp;
|
||||
|
||||
if(state == Utility::LoadCartridge) {
|
||||
if(fp.open(usagefile, file::mode_read)) {
|
||||
fp.read(SNES::cpu.usage, 1 << 24);
|
||||
fp.read(SNES::smp.usage, 1 << 16);
|
||||
fp.close();
|
||||
} else {
|
||||
memset(SNES::cpu.usage, 0x00, 1 << 24);
|
||||
memset(SNES::smp.usage, 0x00, 1 << 16);
|
||||
}
|
||||
}
|
||||
|
||||
if(state == Utility::UnloadCartridge) {
|
||||
if(fp.open(usagefile, file::mode_write)) {
|
||||
fp.write(SNES::cpu.usage, 1 << 24);
|
||||
fp.write(SNES::smp.usage, 1 << 16);
|
||||
fp.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::synchronize() {
|
||||
@@ -108,16 +144,20 @@ void Debugger::clear() {
|
||||
console->setHtml("");
|
||||
}
|
||||
|
||||
void Debugger::showDisassembler() {
|
||||
disassembler->show();
|
||||
}
|
||||
|
||||
void Debugger::showBreakpointEditor() {
|
||||
breakpointEditor->window->show();
|
||||
breakpointEditor->show();
|
||||
}
|
||||
|
||||
void Debugger::showMemoryEditor() {
|
||||
memoryEditor->window->show();
|
||||
memoryEditor->show();
|
||||
}
|
||||
|
||||
void Debugger::showVramViewer() {
|
||||
vramViewer->window->show();
|
||||
vramViewer->show();
|
||||
vramViewer->refresh();
|
||||
}
|
||||
|
||||
@@ -131,63 +171,47 @@ void Debugger::stepAction() {
|
||||
application.debugrun = true;
|
||||
}
|
||||
|
||||
void Debugger::tracerUpdate() {
|
||||
if(SNES::debugger.trace_cpu || SNES::debugger.trace_smp) {
|
||||
if(SNES::debugger.tracefile.open() == false) {
|
||||
SNES::debugger.tracefile.open(utf8() << config.path.data << "trace.log", file::mode_write);
|
||||
}
|
||||
} else if(!SNES::debugger.trace_cpu && !SNES::debugger.trace_smp) {
|
||||
if(SNES::debugger.tracefile.open() == true) {
|
||||
SNES::debugger.tracefile.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::toggleTraceCPU() {
|
||||
SNES::debugger.trace_cpu = traceCPU->isChecked();
|
||||
tracerUpdate();
|
||||
}
|
||||
|
||||
void Debugger::toggleTraceSMP() {
|
||||
SNES::debugger.trace_smp = traceSMP->isChecked();
|
||||
tracerUpdate();
|
||||
}
|
||||
|
||||
void Debugger::event() {
|
||||
char t[256];
|
||||
|
||||
switch(SNES::debugger.break_event) {
|
||||
case SNES::Debugger::BreakpointHit: {
|
||||
unsigned n = SNES::debugger.breakpoint_hit;
|
||||
echo(utf8() << "Breakpoint " << n << " hit (" << SNES::debugger.breakpoint[n].counter << ").<br>");
|
||||
echo(string() << "Breakpoint " << n << " hit (" << SNES::debugger.breakpoint[n].counter << ").<br>");
|
||||
|
||||
if(SNES::debugger.breakpoint[n].mode == SNES::Debugger::Breakpoint::Exec) {
|
||||
if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::CPUBus) {
|
||||
SNES::debugger.step_cpu = true;
|
||||
SNES::cpu.disassemble_opcode(t);
|
||||
echo(utf8() << t << "<br>");
|
||||
}
|
||||
if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::CPUBus) {
|
||||
SNES::debugger.step_cpu = true;
|
||||
SNES::cpu.disassemble_opcode(t, SNES::cpu.opcode_pc);
|
||||
string s = t;
|
||||
s.replace(" ", " ");
|
||||
echo(string() << "<font color='#a00000'>" << s << "</font><br>");
|
||||
disassembler->refresh(Disassembler::CPU, SNES::cpu.opcode_pc);
|
||||
}
|
||||
|
||||
if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::APURAM) {
|
||||
SNES::debugger.step_smp = true;
|
||||
SNES::smp.disassemble_opcode(t);
|
||||
echo(utf8() << t << "<br>");
|
||||
}
|
||||
if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::APURAM) {
|
||||
SNES::debugger.step_smp = true;
|
||||
SNES::smp.disassemble_opcode(t, SNES::smp.opcode_pc);
|
||||
string s = t;
|
||||
s.replace(" ", " ");
|
||||
echo(string() << "<font color='#a00000'>" << t << "</font><br>");
|
||||
disassembler->refresh(Disassembler::SMP, SNES::smp.opcode_pc);
|
||||
}
|
||||
} break;
|
||||
|
||||
case SNES::Debugger::CPUStep: {
|
||||
SNES::cpu.disassemble_opcode(t);
|
||||
SNES::cpu.disassemble_opcode(t, SNES::cpu.regs.pc);
|
||||
string s = t;
|
||||
s.replace(" ", " ");
|
||||
echo(utf8() << "<font color='#0000a0'>" << s << "</font><br>");
|
||||
echo(string() << "<font color='#0000a0'>" << s << "</font><br>");
|
||||
disassembler->refresh(Disassembler::CPU, SNES::cpu.regs.pc);
|
||||
} break;
|
||||
|
||||
case SNES::Debugger::SMPStep: {
|
||||
SNES::smp.disassemble_opcode(t);
|
||||
SNES::smp.disassemble_opcode(t, SNES::smp.regs.pc);
|
||||
string s = t;
|
||||
s.replace(" ", " ");
|
||||
echo(utf8() << "<font color='#a00000'>" << s << "</font><br>");
|
||||
echo(string() << "<font color='#a00000'>" << s << "</font><br>");
|
||||
disassembler->refresh(Disassembler::SMP, SNES::smp.regs.pc);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
@@ -200,3 +224,5 @@ void Debugger::frameTick() {
|
||||
vramViewer->autoUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,39 +1,37 @@
|
||||
#include "hexeditor.moc"
|
||||
#include "breakpoint.moc"
|
||||
#include "memory.moc"
|
||||
#include "vramviewer.moc"
|
||||
|
||||
class Debugger : public QObject {
|
||||
class Debugger : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QbWindow *window;
|
||||
QMenuBar *menu;
|
||||
QMenu *tools;
|
||||
QAction *tools_breakpoint;
|
||||
QAction *tools_memory;
|
||||
QAction *tools_vramViewer;
|
||||
QMenu *miscOptions;
|
||||
QAction *miscOptions_clear;
|
||||
QHBoxLayout *layout;
|
||||
QTextEdit *console;
|
||||
QVBoxLayout *controlLayout;
|
||||
QHBoxLayout *commandLayout;
|
||||
QPushButton *runBreak;
|
||||
QPushButton *stepInstruction;
|
||||
QCheckBox *stepCPU;
|
||||
QCheckBox *stepSMP;
|
||||
QCheckBox *traceCPU;
|
||||
QCheckBox *traceSMP;
|
||||
QWidget *spacer;
|
||||
QMenu *tools;
|
||||
QAction *tools_disassembler;
|
||||
QAction *tools_breakpoint;
|
||||
QAction *tools_memory;
|
||||
QAction *tools_vramViewer;
|
||||
QMenu *miscOptions;
|
||||
QAction *miscOptions_clear;
|
||||
|
||||
QHBoxLayout *layout;
|
||||
QTextEdit *console;
|
||||
QVBoxLayout *controlLayout;
|
||||
QHBoxLayout *commandLayout;
|
||||
QPushButton *runBreak;
|
||||
QPushButton *stepInstruction;
|
||||
QCheckBox *stepCPU;
|
||||
QCheckBox *stepSMP;
|
||||
QCheckBox *traceCPU;
|
||||
QCheckBox *traceSMP;
|
||||
QCheckBox *traceMask;
|
||||
QWidget *spacer;
|
||||
|
||||
void modifySystemState(unsigned);
|
||||
void echo(const char *message);
|
||||
void tracerUpdate();
|
||||
void event();
|
||||
void frameTick();
|
||||
Debugger();
|
||||
|
||||
public slots:
|
||||
void showDisassembler();
|
||||
void showBreakpointEditor();
|
||||
void showMemoryEditor();
|
||||
void showVramViewer();
|
||||
@@ -42,9 +40,9 @@ public slots:
|
||||
|
||||
void toggleRunStatus();
|
||||
void stepAction();
|
||||
void toggleTraceCPU();
|
||||
void toggleTraceSMP();
|
||||
|
||||
private:
|
||||
unsigned frameCounter;
|
||||
} *debugger;
|
||||
};
|
||||
|
||||
extern Debugger *debugger;
|
||||
|