mirror of https://github.com/bsnes-emu/bsnes.git
Update to v079r06 release.
byuu says: It does add some more code to the CPU::step() function, so performance probably went down actually, by about 1%. Removing the input.tick() call didn't compensate as much as I'd hoped. Hooked up Super Scope and Justifier support. The good news is that the Justifier alignment doesn't get fucked up anymore when you go off-screen. Never could fix that in the old version. The bad news is that it takes a major speed hit for the time being. I need to figure out how to run the CPU and input threads out of order. Every time I try, the input gets thrown off by most of a scanline. Right now, I'm forced to sync constantly to get the latching position really accurate. But worst case, I can cut the syncs down by skipping large chunks around the cursor position, +/-40 clock cycles. So it's only temporarily slow. Lastly, killed the old Input class, merged Controllers class into it. I actually like Controllers as a name better, but it doesn't jive with video/audio/input, so oh well.
This commit is contained in:
parent
cf09d41669
commit
927c97eb06
|
@ -9,7 +9,7 @@ void Link::Enter() { link.enter(); }
|
|||
|
||||
void Link::enter() {
|
||||
while(true) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
unsigned clocks = 1;
|
||||
if(link_run) clocks = link_run();
|
||||
step(clocks);
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#ifdef NECDSP_CPP
|
||||
|
||||
uint8 NECDSP::sr_read(unsigned) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
return regs.sr >> 8;
|
||||
}
|
||||
|
||||
void NECDSP::sr_write(unsigned, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
}
|
||||
|
||||
uint8 NECDSP::dr_read(unsigned) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
if(regs.sr.drc == 0) {
|
||||
//16-bit
|
||||
if(regs.sr.drs == 0) {
|
||||
|
@ -29,7 +29,7 @@ uint8 NECDSP::dr_read(unsigned) {
|
|||
}
|
||||
|
||||
void NECDSP::dr_write(unsigned, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
if(regs.sr.drc == 0) {
|
||||
//16-bit
|
||||
if(regs.sr.drs == 0) {
|
||||
|
@ -48,7 +48,7 @@ void NECDSP::dr_write(unsigned, uint8 data) {
|
|||
}
|
||||
|
||||
uint8 NECDSP::dp_read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
bool hi = addr & 1;
|
||||
addr = (addr >> 1) & 2047;
|
||||
|
||||
|
@ -60,7 +60,7 @@ uint8 NECDSP::dp_read(unsigned addr) {
|
|||
}
|
||||
|
||||
void NECDSP::dp_write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
bool hi = addr & 1;
|
||||
addr = (addr >> 1) & 2047;
|
||||
|
||||
|
|
|
@ -7,12 +7,12 @@ unsigned SA1::CPUIRAM::size() const {
|
|||
}
|
||||
|
||||
uint8 SA1::CPUIRAM::read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
return sa1.iram.read(addr);
|
||||
}
|
||||
|
||||
void SA1::CPUIRAM::write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
sa1.iram.write(addr, data);
|
||||
}
|
||||
|
||||
|
@ -21,13 +21,13 @@ unsigned SA1::CPUBWRAM::size() const {
|
|||
}
|
||||
|
||||
uint8 SA1::CPUBWRAM::read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
if(dma) return sa1.dma_cc1_read(addr);
|
||||
return cartridge.ram.read(addr);
|
||||
}
|
||||
|
||||
void SA1::CPUBWRAM::write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
cartridge.ram.write(addr, data);
|
||||
}
|
||||
|
||||
|
|
|
@ -178,13 +178,13 @@ void SA1::mmc_write(unsigned addr, uint8 data) {
|
|||
}
|
||||
|
||||
uint8 SA1::mmc_cpu_read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
||||
return cpubwram.read(addr);
|
||||
}
|
||||
|
||||
void SA1::mmc_cpu_write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
||||
cpubwram.write(addr, data);
|
||||
}
|
||||
|
|
|
@ -444,7 +444,7 @@ uint8 SA1::mmio_r230e() {
|
|||
}
|
||||
|
||||
uint8 SA1::mmio_read(unsigned addr) {
|
||||
(co_active() == cpu.thread ? cpu.synchronize_coprocessor() : synchronize_cpu());
|
||||
(co_active() == cpu.thread ? cpu.synchronize_coprocessors() : synchronize_cpu());
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
|
@ -469,7 +469,7 @@ uint8 SA1::mmio_read(unsigned addr) {
|
|||
}
|
||||
|
||||
void SA1::mmio_write(unsigned addr, uint8 data) {
|
||||
(co_active() == cpu.thread ? cpu.synchronize_coprocessor() : synchronize_cpu());
|
||||
(co_active() == cpu.thread ? cpu.synchronize_coprocessors() : synchronize_cpu());
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
|
|
|
@ -59,7 +59,7 @@ void Serial::write(uint8 data) {
|
|||
}
|
||||
|
||||
uint8 Serial::mmio_read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
switch(addr & 1) { default:
|
||||
case 0: return cpu.mmio_read(addr);
|
||||
case 1: return cpu.mmio_read(addr);
|
||||
|
@ -67,7 +67,7 @@ uint8 Serial::mmio_read(unsigned addr) {
|
|||
}
|
||||
|
||||
void Serial::mmio_write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
switch(addr & 1) { default:
|
||||
case 0: cpu.mmio_write(addr, data); break;
|
||||
case 1: cpu.mmio_write(addr, data); break;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifdef SUPERFX_CPP
|
||||
|
||||
uint8 SuperFX::mmio_read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
|
@ -53,7 +53,7 @@ uint8 SuperFX::mmio_read(unsigned addr) {
|
|||
}
|
||||
|
||||
void SuperFX::mmio_write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
|
|
|
@ -8,7 +8,28 @@ namespace SNES {
|
|||
#include "mouse/mouse.cpp"
|
||||
#include "superscope/superscope.cpp"
|
||||
#include "justifier/justifier.cpp"
|
||||
Controllers controllers;
|
||||
|
||||
void Controller::Enter() {
|
||||
if(co_active() == input.port1->thread) input.port1->enter();
|
||||
if(co_active() == input.port2->thread) input.port2->enter();
|
||||
}
|
||||
|
||||
void Controller::enter() {
|
||||
while(true) step(1);
|
||||
}
|
||||
|
||||
void Controller::step(unsigned clocks) {
|
||||
clock += clocks * (uint64)cpu.frequency;
|
||||
synchronize_cpu();
|
||||
}
|
||||
|
||||
void Controller::synchronize_cpu() {
|
||||
if(CPU::Threaded == true) {
|
||||
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
|
||||
} else {
|
||||
while(clock >= 0) cpu.enter();
|
||||
}
|
||||
}
|
||||
|
||||
bool Controller::iobit() {
|
||||
switch(port) {
|
||||
|
@ -19,45 +40,13 @@ bool Controller::iobit() {
|
|||
|
||||
void Controller::iobit(bool data) {
|
||||
switch(port) {
|
||||
case Controller::Port1: break;
|
||||
case Controller::Port2: break;
|
||||
case Controller::Port1: bus.write(0x4201, (cpu.pio() & ~0x40) | (data << 6)); break;
|
||||
case Controller::Port2: bus.write(0x4201, (cpu.pio() & ~0x80) | (data << 7)); break;
|
||||
}
|
||||
}
|
||||
|
||||
Controller::Controller(bool port) : port(port) {
|
||||
}
|
||||
|
||||
void Controllers::connect(bool port, Input::Device id) {
|
||||
Controller *&controller = (port == Controller::Port1 ? port1 : port2);
|
||||
if(controller) {
|
||||
delete controller;
|
||||
controller = 0;
|
||||
}
|
||||
|
||||
switch(id) { default:
|
||||
case Input::Device::None: controller = new Controller(port); break;
|
||||
case Input::Device::Joypad: controller = new Gamepad(port); break;
|
||||
case Input::Device::Multitap: controller = new Multitap(port); break;
|
||||
case Input::Device::Mouse: controller = new Mouse(port); break;
|
||||
case Input::Device::SuperScope: controller = new SuperScope(port); break;
|
||||
case Input::Device::Justifier: controller = new Justifier(port, false); break;
|
||||
case Input::Device::Justifiers: controller = new Justifier(port, true); break;
|
||||
}
|
||||
|
||||
switch(port) {
|
||||
case Controller::Port1: config.controller_port1 = id; break;
|
||||
case Controller::Port2: config.controller_port2 = id; break;
|
||||
}
|
||||
}
|
||||
|
||||
Controllers::Controllers() {
|
||||
connect(Controller::Port1, Input::Device::Joypad);
|
||||
connect(Controller::Port2, Input::Device::Joypad);
|
||||
}
|
||||
|
||||
Controllers::~Controllers() {
|
||||
if(port1) delete port1;
|
||||
if(port2) delete port2;
|
||||
if(!thread) create(Controller::Enter, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,11 @@ struct Controller : Processor {
|
|||
enum : bool { Port1 = 0, Port2 = 1 };
|
||||
const bool port;
|
||||
|
||||
static void Enter();
|
||||
virtual void enter();
|
||||
void step(unsigned clocks);
|
||||
void synchronize_cpu();
|
||||
|
||||
bool iobit();
|
||||
void iobit(bool data);
|
||||
virtual uint2 data() { return 0; }
|
||||
|
@ -22,17 +27,6 @@ struct Controller : Processor {
|
|||
Controller(bool port);
|
||||
};
|
||||
|
||||
struct Controllers {
|
||||
Controller *port1;
|
||||
Controller *port2;
|
||||
|
||||
void connect(bool port, Input::Device id);
|
||||
Controllers();
|
||||
~Controllers();
|
||||
};
|
||||
|
||||
extern Controllers controllers;
|
||||
|
||||
#include "gamepad/gamepad.hpp"
|
||||
#include "multitap/multitap.hpp"
|
||||
#include "mouse/mouse.hpp"
|
||||
|
|
|
@ -1,5 +1,45 @@
|
|||
#ifdef CONTROLLER_CPP
|
||||
|
||||
void Justifier::enter() {
|
||||
while(true) {
|
||||
static unsigned prev = 0;
|
||||
unsigned next = cpu.vcounter() * 1364 + cpu.hcounter();
|
||||
if(next >= target && prev < target) {
|
||||
iobit(0);
|
||||
iobit(1);
|
||||
}
|
||||
|
||||
if(next < prev) {
|
||||
int nx1 = system.interface->input_poll(port, Input::Device::Justifier, 0, (unsigned)Input::JustifierID::X);
|
||||
int ny1 = system.interface->input_poll(port, Input::Device::Justifier, 0, (unsigned)Input::JustifierID::Y);
|
||||
nx1 += x1;
|
||||
ny1 += y1;
|
||||
x1 = max(-16, min(256 + 16, nx1));
|
||||
y1 = max(-16, min(240 + 16, ny1));
|
||||
|
||||
if(chained == true) {
|
||||
int nx2 = system.interface->input_poll(port, Input::Device::Justifiers, 1, (unsigned)Input::JustifierID::X);
|
||||
int ny2 = system.interface->input_poll(port, Input::Device::Justifiers, 1, (unsigned)Input::JustifierID::Y);
|
||||
nx2 += x2;
|
||||
ny2 += y2;
|
||||
x2 = max(-16, min(256 + 16, nx2));
|
||||
y2 = max(-16, min(240 + 16, ny2));
|
||||
}
|
||||
|
||||
if(active == 0) {
|
||||
bool offscreen = (x1 < 0 || y1 < 0 || x1 >= 256 || y1 >= (ppu.overscan() ? 240 : 225));
|
||||
target = offscreen ? -1 : y1 * 1364 + (x1 + 24) * 4;
|
||||
} else {
|
||||
bool offscreen = (x2 < 0 || y2 < 0 || x2 >= 256 || y2 >= (ppu.overscan() ? 240 : 225));
|
||||
target = offscreen ? -1 : y2 * 1364 + (x2 + 24) * 4;
|
||||
}
|
||||
}
|
||||
|
||||
prev = next;
|
||||
step(4);
|
||||
}
|
||||
}
|
||||
|
||||
uint2 Justifier::data() {
|
||||
if(counter >= 32) return 1;
|
||||
|
||||
|
@ -56,25 +96,11 @@ void Justifier::latch(bool data) {
|
|||
if(latched == data) return;
|
||||
latched = data;
|
||||
counter = 0;
|
||||
if(chained) active = !active; //toggle between both controllers when chained
|
||||
|
||||
int nx1 = system.interface->input_poll(port, Input::Device::Justifier, 0, (unsigned)Input::JustifierID::X);
|
||||
int ny1 = system.interface->input_poll(port, Input::Device::Justifier, 0, (unsigned)Input::JustifierID::Y);
|
||||
nx1 += x1;
|
||||
ny1 += y1;
|
||||
x1 = max(-16, min(256 + 16, nx1));
|
||||
y1 = max(-16, min(240 + 16, ny1));
|
||||
|
||||
if(chained == false) return;
|
||||
int nx2 = system.interface->input_poll(port, Input::Device::Justifiers, 1, (unsigned)Input::JustifierID::X);
|
||||
int ny2 = system.interface->input_poll(port, Input::Device::Justifiers, 1, (unsigned)Input::JustifierID::Y);
|
||||
nx2 += x2;
|
||||
ny2 += y2;
|
||||
x2 = max(-16, min(256 + 16, nx2));
|
||||
y2 = max(-16, min(240 + 16, ny2));
|
||||
if(latched == 0) active = !active; //toggle between both controllers, even when unchained
|
||||
}
|
||||
|
||||
Justifier::Justifier(bool port, bool chained) : Controller(port), chained(chained) {
|
||||
create(Controller::Enter, 21477272);
|
||||
latched = 0;
|
||||
counter = 0;
|
||||
active = 0;
|
||||
|
@ -91,6 +117,8 @@ Justifier::Justifier(bool port, bool chained) : Controller(port), chained(chaine
|
|||
y2 = 240 / 2;
|
||||
}
|
||||
|
||||
target = -1;
|
||||
|
||||
trigger1 = false;
|
||||
trigger2 = false;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
struct Justifier : Controller {
|
||||
void enter();
|
||||
uint2 data();
|
||||
void latch(bool data);
|
||||
Justifier(bool port, bool chained);
|
||||
|
@ -9,8 +10,9 @@ struct Justifier : Controller {
|
|||
unsigned counter;
|
||||
|
||||
bool active;
|
||||
int x1, x2;
|
||||
int y1, y2;
|
||||
signed x1, x2;
|
||||
signed y1, y2;
|
||||
signed target;
|
||||
bool trigger1, trigger2;
|
||||
bool start1, start2;
|
||||
};
|
||||
|
|
|
@ -9,6 +9,32 @@
|
|||
//require manual polling of PIO ($4201.d6) to determine when iobit was written.
|
||||
//Note that no commercial game ever utilizes a Super Scope in port 1.
|
||||
|
||||
void SuperScope::enter() {
|
||||
while(true) {
|
||||
static unsigned prev = 0;
|
||||
unsigned next = cpu.vcounter() * 1364 + cpu.hcounter();
|
||||
if(next >= target && prev < target) {
|
||||
iobit(0);
|
||||
iobit(1);
|
||||
}
|
||||
|
||||
if(next < prev) {
|
||||
//Vcounter wrapped back to zero; update cursor coordinates for start of new frame
|
||||
int nx = system.interface->input_poll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::X);
|
||||
int ny = system.interface->input_poll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::Y);
|
||||
nx += x;
|
||||
ny += y;
|
||||
x = max(-16, min(256 + 16, nx));
|
||||
y = max(-16, min(240 + 16, ny));
|
||||
offscreen = (x < 0 || y < 0 || x >= 256 || y >= (ppu.overscan() ? 240 : 225));
|
||||
target = offscreen ? -1 : y * 1364 + (x + 24) * 4;
|
||||
}
|
||||
|
||||
prev = next;
|
||||
step(4);
|
||||
}
|
||||
}
|
||||
|
||||
uint2 SuperScope::data() {
|
||||
if(counter >= 8) return 1;
|
||||
|
||||
|
@ -50,7 +76,7 @@ uint2 SuperScope::data() {
|
|||
}
|
||||
|
||||
switch(counter++) {
|
||||
case 0: return trigger;
|
||||
case 0: return offscreen ? 0 : trigger;
|
||||
case 1: return cursor;
|
||||
case 2: return turbo;
|
||||
case 3: return pause;
|
||||
|
@ -65,22 +91,17 @@ void SuperScope::latch(bool data) {
|
|||
if(latched == data) return;
|
||||
latched = data;
|
||||
counter = 0;
|
||||
|
||||
int nx = system.interface->input_poll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::X);
|
||||
int ny = system.interface->input_poll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::Y);
|
||||
nx += x;
|
||||
ny += y;
|
||||
x = max(-16, min(256 + 16, nx));
|
||||
y = max(-16, min(240 + 16, ny));
|
||||
}
|
||||
|
||||
SuperScope::SuperScope(bool port) : Controller(port) {
|
||||
create(Controller::Enter, 21477272);
|
||||
latched = 0;
|
||||
counter = 0;
|
||||
|
||||
//center cursor onscreen
|
||||
x = 256 / 2;
|
||||
y = 240 / 2;
|
||||
target = -1;
|
||||
|
||||
trigger = false;
|
||||
cursor = false;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
struct SuperScope : Controller {
|
||||
void enter();
|
||||
uint2 data();
|
||||
void latch(bool data);
|
||||
SuperScope(bool port);
|
||||
|
@ -7,7 +8,7 @@ struct SuperScope : Controller {
|
|||
bool latched;
|
||||
unsigned counter;
|
||||
|
||||
int x, y;
|
||||
signed x, y, target;
|
||||
|
||||
bool trigger;
|
||||
bool cursor;
|
||||
|
|
|
@ -23,6 +23,9 @@ void CPU::step(unsigned clocks) {
|
|||
Processor &chip = *coprocessors[i];
|
||||
chip.clock -= clocks * (uint64)chip.frequency;
|
||||
}
|
||||
input.port1->clock -= clocks * (uint64)input.port1->frequency;
|
||||
input.port2->clock -= clocks * (uint64)input.port2->frequency;
|
||||
synchronize_controllers();
|
||||
}
|
||||
|
||||
void CPU::synchronize_smp() {
|
||||
|
@ -41,13 +44,18 @@ void CPU::synchronize_ppu() {
|
|||
}
|
||||
}
|
||||
|
||||
void CPU::synchronize_coprocessor() {
|
||||
void CPU::synchronize_coprocessors() {
|
||||
for(unsigned i = 0; i < coprocessors.size(); i++) {
|
||||
Processor &chip = *coprocessors[i];
|
||||
if(chip.clock < 0) co_switch(chip.thread);
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::synchronize_controllers() {
|
||||
if(input.port1->clock < 0) co_switch(input.port1->thread);
|
||||
if(input.port2->clock < 0) co_switch(input.port2->thread);
|
||||
}
|
||||
|
||||
void CPU::Enter() { cpu.enter(); }
|
||||
|
||||
void CPU::enter() {
|
||||
|
|
|
@ -7,7 +7,8 @@ public:
|
|||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_smp();
|
||||
void synchronize_ppu();
|
||||
void synchronize_coprocessor();
|
||||
void synchronize_coprocessors();
|
||||
void synchronize_controllers();
|
||||
|
||||
uint8 port_read(uint2 port) const;
|
||||
void port_write(uint2 port, uint8 data);
|
||||
|
|
|
@ -33,13 +33,8 @@ void CPU::mmio_w2183(uint8 data) {
|
|||
//strobing $4016.d0 affects both controller port latches.
|
||||
//$4017 bit 0 writes are ignored.
|
||||
void CPU::mmio_w4016(uint8 data) {
|
||||
//bool old_latch = status.joypad_strobe_latch;
|
||||
//bool new_latch = data & 1;
|
||||
//status.joypad_strobe_latch = new_latch;
|
||||
//if(old_latch != new_latch) input.poll();
|
||||
|
||||
controllers.port1->latch(data & 1);
|
||||
controllers.port2->latch(data & 1);
|
||||
input.port1->latch(data & 1);
|
||||
input.port2->latch(data & 1);
|
||||
}
|
||||
|
||||
//JOYSER0
|
||||
|
@ -47,8 +42,7 @@ void CPU::mmio_w4016(uint8 data) {
|
|||
//1-0 = Joypad serial data
|
||||
uint8 CPU::mmio_r4016() {
|
||||
uint8 r = regs.mdr & 0xfc;
|
||||
//r |= input.port_read(0) & 3;
|
||||
r |= controllers.port1->data();
|
||||
r |= input.port1->data();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -58,8 +52,7 @@ uint8 CPU::mmio_r4016() {
|
|||
//1-0 = Joypad serial data
|
||||
uint8 CPU::mmio_r4017() {
|
||||
uint8 r = (regs.mdr & 0xe0) | 0x1c;
|
||||
//r |= input.port_read(1) & 3;
|
||||
r |= controllers.port2->data();
|
||||
r |= input.port2->data();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,18 +6,17 @@ void CPU::step_auto_joypad_poll() {
|
|||
status.auto_joypad_active = status.auto_joypad_counter <= 15;
|
||||
|
||||
if(status.auto_joypad_active && status.auto_joypad_poll) {
|
||||
synchronize_controllers();
|
||||
|
||||
if(status.auto_joypad_counter == 0) {
|
||||
//input.poll();
|
||||
controllers.port1->latch(1);
|
||||
controllers.port2->latch(1);
|
||||
controllers.port1->latch(0);
|
||||
controllers.port2->latch(0);
|
||||
input.port1->latch(1);
|
||||
input.port2->latch(1);
|
||||
input.port1->latch(0);
|
||||
input.port2->latch(0);
|
||||
}
|
||||
|
||||
//uint8 port0 = input.port_read(0);
|
||||
//uint8 port1 = input.port_read(1);
|
||||
uint2 port0 = controllers.port1->data();
|
||||
uint2 port1 = controllers.port2->data();
|
||||
uint2 port0 = input.port1->data();
|
||||
uint2 port1 = input.port2->data();
|
||||
|
||||
status.joy1 = (status.joy1 << 1) | (bool)(port0 & 1);
|
||||
status.joy2 = (status.joy2 << 1) | (bool)(port1 & 1);
|
||||
|
|
|
@ -40,7 +40,7 @@ void CPU::scanline() {
|
|||
//forcefully sync S-CPU to other processors, in case chips are not communicating
|
||||
synchronize_ppu();
|
||||
synchronize_smp();
|
||||
synchronize_coprocessor();
|
||||
synchronize_coprocessors();
|
||||
system.scanline();
|
||||
|
||||
if(vcounter() == 0) {
|
||||
|
|
|
@ -1,344 +1,38 @@
|
|||
#ifdef SYSTEM_CPP
|
||||
|
||||
Input input1;
|
||||
Input input;
|
||||
|
||||
uint8 Input::port_read(bool portnumber) {
|
||||
if(cartridge.has_serial() && portnumber == 1) {
|
||||
return (serial.data2() << 1) | (serial.data1() << 0);
|
||||
void Input::connect(bool port, Input::Device id) {
|
||||
Controller *&controller = (port == Controller::Port1 ? port1 : port2);
|
||||
if(controller) {
|
||||
delete controller;
|
||||
controller = 0;
|
||||
}
|
||||
|
||||
port_t &p = port[portnumber];
|
||||
|
||||
switch(p.device) {
|
||||
case Device::Joypad: {
|
||||
if(cpu.joylatch() == 0) {
|
||||
if(p.counter0 >= 16) return 1;
|
||||
return system.interface->input_poll(portnumber, p.device, 0, p.counter0++);
|
||||
} else {
|
||||
return system.interface->input_poll(portnumber, p.device, 0, 0);
|
||||
}
|
||||
} //case Device::Joypad
|
||||
|
||||
case Device::Multitap: {
|
||||
if(cpu.joylatch()) return 2; //when latch is high -- data2 = 1, data1 = 0
|
||||
|
||||
unsigned deviceidx, deviceindex0, deviceindex1;
|
||||
uint8 mask = (portnumber == 0 ? 0x40 : 0x80);
|
||||
|
||||
if(cpu.pio() & mask) {
|
||||
deviceidx = p.counter0;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter0++;
|
||||
|
||||
deviceindex0 = 0; //controller 1
|
||||
deviceindex1 = 1; //controller 2
|
||||
} else {
|
||||
deviceidx = p.counter1;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter1++;
|
||||
|
||||
deviceindex0 = 2; //controller 3
|
||||
deviceindex1 = 3; //controller 4
|
||||
}
|
||||
|
||||
return (system.interface->input_poll(portnumber, p.device, deviceindex0, deviceidx) << 0)
|
||||
| (system.interface->input_poll(portnumber, p.device, deviceindex1, deviceidx) << 1);
|
||||
} //case Device::Multitap
|
||||
|
||||
case Device::Mouse: {
|
||||
if(p.counter0 >= 32) return 1;
|
||||
|
||||
int position_x = system.interface->input_poll(portnumber, p.device, 0, (unsigned)MouseID::X); //-n = left, 0 = center, +n = right
|
||||
int position_y = system.interface->input_poll(portnumber, p.device, 0, (unsigned)MouseID::Y); //-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
|
||||
|
||||
if(position_x < 0) position_x = -position_x; //abs(position_x)
|
||||
if(position_y < 0) position_y = -position_y; //abs(position_x)
|
||||
|
||||
position_x = min(127, position_x); //range = 0 - 127
|
||||
position_y = min(127, position_y); //range = 0 - 127
|
||||
|
||||
switch(p.counter0++) { default:
|
||||
case 0: return 0;
|
||||
case 1: return 0;
|
||||
case 2: return 0;
|
||||
case 3: return 0;
|
||||
case 4: return 0;
|
||||
case 5: return 0;
|
||||
case 6: return 0;
|
||||
case 7: return 0;
|
||||
|
||||
case 8: return system.interface->input_poll(portnumber, p.device, 0, (unsigned)MouseID::Right);
|
||||
case 9: return system.interface->input_poll(portnumber, p.device, 0, (unsigned)MouseID::Left);
|
||||
case 10: return 0; //speed (0 = slow, 1 = normal, 2 = fast, 3 = unused)
|
||||
case 11: return 0; // ||
|
||||
|
||||
case 12: return 0; //signature
|
||||
case 13: return 0; // ||
|
||||
case 14: return 0; // ||
|
||||
case 15: return 1; // ||
|
||||
|
||||
case 16: return (direction_y) & 1;
|
||||
case 17: return (position_y >> 6) & 1;
|
||||
case 18: return (position_y >> 5) & 1;
|
||||
case 19: return (position_y >> 4) & 1;
|
||||
case 20: return (position_y >> 3) & 1;
|
||||
case 21: return (position_y >> 2) & 1;
|
||||
case 22: return (position_y >> 1) & 1;
|
||||
case 23: return (position_y >> 0) & 1;
|
||||
|
||||
case 24: return (direction_x) & 1;
|
||||
case 25: return (position_x >> 6) & 1;
|
||||
case 26: return (position_x >> 5) & 1;
|
||||
case 27: return (position_x >> 4) & 1;
|
||||
case 28: return (position_x >> 3) & 1;
|
||||
case 29: return (position_x >> 2) & 1;
|
||||
case 30: return (position_x >> 1) & 1;
|
||||
case 31: return (position_x >> 0) & 1;
|
||||
}
|
||||
} //case Device::Mouse
|
||||
|
||||
case Device::SuperScope: {
|
||||
if(portnumber == 0) break; //Super Scope in port 1 not supported ...
|
||||
if(p.counter0 >= 8) return 1;
|
||||
|
||||
if(p.counter0 == 0) {
|
||||
//turbo is a switch; toggle is edge sensitive
|
||||
bool turbo = system.interface->input_poll(portnumber, p.device, 0, (unsigned)SuperScopeID::Turbo);
|
||||
if(turbo && !p.superscope.turbolock) {
|
||||
p.superscope.turbo = !p.superscope.turbo; //toggle state
|
||||
p.superscope.turbolock = true;
|
||||
} else if(!turbo) {
|
||||
p.superscope.turbolock = false;
|
||||
}
|
||||
|
||||
//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(portnumber, p.device, 0, (unsigned)SuperScopeID::Trigger);
|
||||
if(trigger && (p.superscope.turbo || !p.superscope.triggerlock)) {
|
||||
p.superscope.trigger = true;
|
||||
p.superscope.triggerlock = true;
|
||||
} else if(!trigger) {
|
||||
p.superscope.triggerlock = false;
|
||||
}
|
||||
|
||||
//cursor is a button; it is always level sensitive
|
||||
p.superscope.cursor = system.interface->input_poll(portnumber, p.device, 0, (unsigned)SuperScopeID::Cursor);
|
||||
|
||||
//pause is a button; it is always edge sensitive
|
||||
p.superscope.pause = false;
|
||||
bool pause = system.interface->input_poll(portnumber, p.device, 0, (unsigned)SuperScopeID::Pause);
|
||||
if(pause && !p.superscope.pauselock) {
|
||||
p.superscope.pause = true;
|
||||
p.superscope.pauselock = true;
|
||||
} else if(!pause) {
|
||||
p.superscope.pauselock = false;
|
||||
}
|
||||
|
||||
p.superscope.offscreen =
|
||||
p.superscope.x < 0 || p.superscope.x >= 256
|
||||
|| p.superscope.y < 0 || p.superscope.y >= (ppu.overscan() ? 240 : 225);
|
||||
}
|
||||
|
||||
switch(p.counter0++) {
|
||||
case 0: return p.superscope.trigger;
|
||||
case 1: return p.superscope.cursor;
|
||||
case 2: return p.superscope.turbo;
|
||||
case 3: return p.superscope.pause;
|
||||
case 4: return 0;
|
||||
case 5: return 0;
|
||||
case 6: return p.superscope.offscreen;
|
||||
case 7: return 0; //noise (1 = yes)
|
||||
}
|
||||
} //case Device::SuperScope
|
||||
|
||||
case Device::Justifier:
|
||||
case Device::Justifiers: {
|
||||
if(portnumber == 0) break; //Justifier in port 1 not supported ...
|
||||
if(p.counter0 >= 32) return 1;
|
||||
|
||||
if(p.counter0 == 0) {
|
||||
p.justifier.trigger1 = system.interface->input_poll(portnumber, p.device, 0, (unsigned)JustifierID::Trigger);
|
||||
p.justifier.start1 = system.interface->input_poll(portnumber, p.device, 0, (unsigned)JustifierID::Start);
|
||||
|
||||
if(p.device == Device::Justifiers) {
|
||||
p.justifier.trigger2 = system.interface->input_poll(portnumber, p.device, 1, (unsigned)JustifierID::Trigger);
|
||||
p.justifier.start2 = system.interface->input_poll(portnumber, p.device, 1, (unsigned)JustifierID::Start);
|
||||
} else {
|
||||
p.justifier.x2 = -1;
|
||||
p.justifier.y2 = -1;
|
||||
|
||||
p.justifier.trigger2 = false;
|
||||
p.justifier.start2 = false;
|
||||
}
|
||||
}
|
||||
|
||||
switch(p.counter0++) {
|
||||
case 0: return 0;
|
||||
case 1: return 0;
|
||||
case 2: return 0;
|
||||
case 3: return 0;
|
||||
case 4: return 0;
|
||||
case 5: return 0;
|
||||
case 6: return 0;
|
||||
case 7: return 0;
|
||||
case 8: return 0;
|
||||
case 9: return 0;
|
||||
case 10: return 0;
|
||||
case 11: return 0;
|
||||
|
||||
case 12: return 1; //signature
|
||||
case 13: return 1; // ||
|
||||
case 14: return 1; // ||
|
||||
case 15: return 0; // ||
|
||||
|
||||
case 16: return 0;
|
||||
case 17: return 1;
|
||||
case 18: return 0;
|
||||
case 19: return 1;
|
||||
case 20: return 0;
|
||||
case 21: return 1;
|
||||
case 22: return 0;
|
||||
case 23: return 1;
|
||||
|
||||
case 24: return p.justifier.trigger1;
|
||||
case 25: return p.justifier.trigger2;
|
||||
case 26: return p.justifier.start1;
|
||||
case 27: return p.justifier.start2;
|
||||
case 28: return p.justifier.active;
|
||||
|
||||
case 29: return 0;
|
||||
case 30: return 0;
|
||||
case 31: return 0;
|
||||
}
|
||||
} //case Device::Justifier(s)
|
||||
} //switch(p.device)
|
||||
|
||||
//no device connected
|
||||
return 0;
|
||||
}
|
||||
|
||||
//scan all input; update cursor positions if needed
|
||||
void Input::update() {
|
||||
system.interface->input_poll();
|
||||
port_t &p = port[1];
|
||||
|
||||
switch(p.device) {
|
||||
case Device::SuperScope: {
|
||||
int x = system.interface->input_poll(1, p.device, 0, (unsigned)SuperScopeID::X);
|
||||
int y = system.interface->input_poll(1, p.device, 0, (unsigned)SuperScopeID::Y);
|
||||
x += p.superscope.x;
|
||||
y += p.superscope.y;
|
||||
p.superscope.x = max(-16, min(256 + 16, x));
|
||||
p.superscope.y = max(-16, min(240 + 16, y));
|
||||
|
||||
latchx = p.superscope.x;
|
||||
latchy = p.superscope.y;
|
||||
} break;
|
||||
|
||||
case Device::Justifier:
|
||||
case Device::Justifiers: {
|
||||
int x1 = system.interface->input_poll(1, p.device, 0, (unsigned)JustifierID::X);
|
||||
int y1 = system.interface->input_poll(1, p.device, 0, (unsigned)JustifierID::Y);
|
||||
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(1, p.device, 1, (unsigned)JustifierID::X);
|
||||
int y2 = system.interface->input_poll(1, p.device, 1, (unsigned)JustifierID::Y);
|
||||
x2 += p.justifier.x2;
|
||||
y2 += p.justifier.y2;
|
||||
p.justifier.x2 = max(-16, min(256 + 16, x2));
|
||||
p.justifier.y2 = max(-16, min(240 + 16, y2));
|
||||
|
||||
if(p.justifier.active == 0) {
|
||||
latchx = p.justifier.x1;
|
||||
latchy = p.justifier.y1;
|
||||
} else {
|
||||
latchx = (p.device == Device::Justifiers ? p.justifier.x2 : -1);
|
||||
latchy = (p.device == Device::Justifiers ? p.justifier.y2 : -1);
|
||||
}
|
||||
} break;
|
||||
switch(id) { default:
|
||||
case Device::None: controller = new Controller(port); break;
|
||||
case Device::Joypad: controller = new Gamepad(port); break;
|
||||
case Device::Multitap: controller = new Multitap(port); break;
|
||||
case Device::Mouse: controller = new Mouse(port); break;
|
||||
case Device::SuperScope: controller = new SuperScope(port); break;
|
||||
case Device::Justifier: controller = new Justifier(port, false); break;
|
||||
case Device::Justifiers: controller = new Justifier(port, true); break;
|
||||
}
|
||||
|
||||
if(latchy < 0 || latchy >= (ppu.overscan() ? 240 : 225) || latchx < 0 || latchx >= 256) {
|
||||
//cursor is offscreen, set to invalid position so counters are not latched
|
||||
latchx = ~0;
|
||||
latchy = ~0;
|
||||
} else {
|
||||
//cursor is onscreen
|
||||
latchx += 40; //offset trigger position to simulate hardware latching delay
|
||||
latchx <<= 2; //dot -> clock conversion
|
||||
latchx += 2; //align trigger on half-dot ala interrupts (speed optimization for sCPU::add_clocks)
|
||||
switch(port) {
|
||||
case Controller::Port1: config.controller_port1 = id; break;
|
||||
case Controller::Port2: config.controller_port2 = id; break;
|
||||
}
|
||||
}
|
||||
|
||||
void Input::port_set_device_(bool portnumber, Device device) {
|
||||
port_t &p = port[portnumber];
|
||||
|
||||
p.device = device;
|
||||
p.counter0 = 0;
|
||||
p.counter1 = 0;
|
||||
|
||||
//set iobit to true if device is capable of latching PPU counters
|
||||
iobit = port[1].device == Device::SuperScope
|
||||
|| port[1].device == Device::Justifier
|
||||
|| port[1].device == Device::Justifiers;
|
||||
latchx = -1;
|
||||
latchy = -1;
|
||||
|
||||
if(device == Device::SuperScope) {
|
||||
p.superscope.x = 256 / 2;
|
||||
p.superscope.y = 240 / 2;
|
||||
|
||||
p.superscope.trigger = false;
|
||||
p.superscope.cursor = false;
|
||||
p.superscope.turbo = false;
|
||||
p.superscope.pause = false;
|
||||
p.superscope.offscreen = false;
|
||||
|
||||
p.superscope.turbolock = false;
|
||||
p.superscope.triggerlock = false;
|
||||
p.superscope.pauselock = false;
|
||||
} else if(device == Device::Justifier) {
|
||||
p.justifier.active = 0;
|
||||
p.justifier.x1 = 256 / 2;
|
||||
p.justifier.y1 = 240 / 2;
|
||||
p.justifier.x2 = -1;
|
||||
p.justifier.y2 = -1;
|
||||
|
||||
p.justifier.trigger1 = false;
|
||||
p.justifier.trigger2 = false;
|
||||
p.justifier.start1 = false;
|
||||
p.justifier.start2 = false;
|
||||
} else if(device == Device::Justifiers) {
|
||||
p.justifier.active = 0;
|
||||
p.justifier.x1 = 256 / 2 - 16;
|
||||
p.justifier.y1 = 240 / 2;
|
||||
p.justifier.x2 = 256 / 2 + 16;
|
||||
p.justifier.y2 = 240 / 2;
|
||||
|
||||
p.justifier.trigger1 = false;
|
||||
p.justifier.trigger2 = false;
|
||||
p.justifier.start1 = false;
|
||||
p.justifier.start2 = false;
|
||||
}
|
||||
Input::Input() {
|
||||
connect(Controller::Port1, Input::Device::Joypad);
|
||||
connect(Controller::Port2, Input::Device::Joypad);
|
||||
}
|
||||
|
||||
void Input::poll() {
|
||||
port[0].counter0 = 0;
|
||||
port[0].counter1 = 0;
|
||||
port[1].counter0 = 0;
|
||||
port[1].counter1 = 0;
|
||||
|
||||
port[1].justifier.active = !port[1].justifier.active;
|
||||
}
|
||||
|
||||
void Input::init() {
|
||||
Input::~Input() {
|
||||
if(port1) delete port1;
|
||||
if(port2) delete port2;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class Input {
|
||||
public:
|
||||
struct Input {
|
||||
enum class Device : unsigned {
|
||||
None,
|
||||
Joypad,
|
||||
|
@ -28,61 +27,12 @@ public:
|
|||
X = 0, Y = 1, Trigger = 2, Start = 3,
|
||||
};
|
||||
|
||||
uint8 port_read(bool port);
|
||||
void port_set_device_(bool port, Device device);
|
||||
void init();
|
||||
void poll();
|
||||
void update();
|
||||
Controller *port1;
|
||||
Controller *port2;
|
||||
|
||||
//light guns (Super Scope, Justifier(s)) strobe IOBit whenever the CRT
|
||||
//beam cannon is detected. this needs to be tested at the cycle level
|
||||
//(hence inlining here for speed) to avoid 'dead space' during DRAM refresh.
|
||||
//iobit is updated during port_set_device(),
|
||||
//latchx, latchy are updated during update() (once per frame)
|
||||
alwaysinline void tick() {
|
||||
//only test if Super Scope or Justifier is connected
|
||||
if(iobit && cpu.vcounter() == latchy && cpu.hcounter() == latchx) {
|
||||
ppu.latch_counters();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool iobit;
|
||||
int16_t latchx, latchy;
|
||||
|
||||
struct port_t {
|
||||
Device device;
|
||||
unsigned counter0; //read counters
|
||||
unsigned counter1;
|
||||
|
||||
struct superscope_t {
|
||||
int x, y;
|
||||
|
||||
bool trigger;
|
||||
bool cursor;
|
||||
bool turbo;
|
||||
bool pause;
|
||||
bool offscreen;
|
||||
|
||||
bool turbolock;
|
||||
bool triggerlock;
|
||||
bool pauselock;
|
||||
} superscope;
|
||||
|
||||
struct justifier_t {
|
||||
bool active;
|
||||
|
||||
int x1, x2;
|
||||
int y1, y2;
|
||||
|
||||
bool trigger1, trigger2;
|
||||
bool start1, start2;
|
||||
} justifier;
|
||||
} port[2];
|
||||
|
||||
friend class System;
|
||||
friend class Video;
|
||||
friend class CPU;
|
||||
void connect(bool port, Input::Device id);
|
||||
Input();
|
||||
~Input();
|
||||
};
|
||||
|
||||
extern Input input1;
|
||||
extern Input input;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "bsnes";
|
||||
static const char Version[] = "079.05";
|
||||
static const char Version[] = "079.06";
|
||||
static const unsigned SerializerVersion = 21;
|
||||
}
|
||||
}
|
||||
|
@ -130,8 +130,8 @@ namespace SNES {
|
|||
#include "profile-performance.hpp"
|
||||
#endif
|
||||
|
||||
#include <snes/system/system.hpp>
|
||||
#include <snes/controller/controller.hpp>
|
||||
#include <snes/system/system.hpp>
|
||||
#include <snes/chip/chip.hpp>
|
||||
#include <snes/cartridge/cartridge.hpp>
|
||||
#include <snes/cheat/cheat.hpp>
|
||||
|
|
|
@ -21,7 +21,6 @@ void System::run() {
|
|||
|
||||
scheduler.enter();
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) {
|
||||
//input.update();
|
||||
video.update();
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +58,6 @@ void System::runthreadtosave() {
|
|||
scheduler.enter();
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::SynchronizeEvent) break;
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) {
|
||||
//input.update();
|
||||
video.update();
|
||||
}
|
||||
}
|
||||
|
@ -89,10 +87,9 @@ void System::init(Interface *interface_) {
|
|||
|
||||
video.init();
|
||||
audio.init();
|
||||
//input.init();
|
||||
|
||||
controllers.connect(0, config.controller_port1);
|
||||
controllers.connect(1, config.controller_port2);
|
||||
input.connect(0, config.controller_port1);
|
||||
input.connect(1, config.controller_port2);
|
||||
}
|
||||
|
||||
void System::term() {
|
||||
|
@ -199,9 +196,8 @@ void System::power() {
|
|||
if(cartridge.has_link()) cpu.coprocessors.append(&link);
|
||||
|
||||
scheduler.init();
|
||||
controllers.connect(0, config.controller_port1);
|
||||
controllers.connect(1, config.controller_port2);
|
||||
//input.update();
|
||||
input.connect(0, config.controller_port1);
|
||||
input.connect(1, config.controller_port2);
|
||||
}
|
||||
|
||||
void System::reset() {
|
||||
|
@ -240,9 +236,8 @@ void System::reset() {
|
|||
if(cartridge.has_link()) cpu.coprocessors.append(&link);
|
||||
|
||||
scheduler.init();
|
||||
controllers.connect(0, config.controller_port1);
|
||||
controllers.connect(1, config.controller_port2);
|
||||
//input.update();
|
||||
input.connect(0, config.controller_port1);
|
||||
input.connect(1, config.controller_port2);
|
||||
}
|
||||
|
||||
void System::scanline() {
|
||||
|
|
|
@ -49,15 +49,15 @@ void Video::draw_cursor(uint16_t color, int x, int y) {
|
|||
void Video::update() {
|
||||
switch(config.controller_port2) {
|
||||
case Input::Device::SuperScope:
|
||||
if(dynamic_cast<SuperScope*>(controllers.port2)) {
|
||||
SuperScope &device = (SuperScope&)*controllers.port2;
|
||||
if(dynamic_cast<SuperScope*>(input.port2)) {
|
||||
SuperScope &device = (SuperScope&)*input.port2;
|
||||
draw_cursor(0x7c00, device.x, device.y);
|
||||
}
|
||||
break;
|
||||
case Input::Device::Justifier:
|
||||
case Input::Device::Justifiers:
|
||||
if(dynamic_cast<Justifier*>(controllers.port2)) {
|
||||
Justifier &device = (Justifier&)*controllers.port2;
|
||||
if(dynamic_cast<Justifier*>(input.port2)) {
|
||||
Justifier &device = (Justifier&)*input.port2;
|
||||
draw_cursor(0x001f, device.x1, device.y1);
|
||||
if(device.chained == false) break;
|
||||
draw_cursor(0x02e0, device.x2, device.y2);
|
||||
|
|
|
@ -40,20 +40,20 @@ void Utility::showMessage(const string &text) {
|
|||
|
||||
void Utility::setControllers() {
|
||||
switch(config.controller.port1) {
|
||||
case 0: SNES::controllers.connect(0, SNES::Input::Device::None); break;
|
||||
case 1: SNES::controllers.connect(0, SNES::Input::Device::Joypad); break;
|
||||
case 2: SNES::controllers.connect(0, SNES::Input::Device::Multitap); break;
|
||||
case 3: SNES::controllers.connect(0, SNES::Input::Device::Mouse); break;
|
||||
case 0: SNES::input.connect(SNES::Controller::Port1, SNES::Input::Device::None); break;
|
||||
case 1: SNES::input.connect(SNES::Controller::Port1, SNES::Input::Device::Joypad); break;
|
||||
case 2: SNES::input.connect(SNES::Controller::Port1, SNES::Input::Device::Multitap); break;
|
||||
case 3: SNES::input.connect(SNES::Controller::Port1, SNES::Input::Device::Mouse); break;
|
||||
}
|
||||
|
||||
switch(config.controller.port2) {
|
||||
case 0: SNES::controllers.connect(1, SNES::Input::Device::None); break;
|
||||
case 1: SNES::controllers.connect(1, SNES::Input::Device::Joypad); break;
|
||||
case 2: SNES::controllers.connect(1, SNES::Input::Device::Multitap); break;
|
||||
case 3: SNES::controllers.connect(1, SNES::Input::Device::Mouse); break;
|
||||
case 4: SNES::controllers.connect(1, SNES::Input::Device::SuperScope); break;
|
||||
case 5: SNES::controllers.connect(1, SNES::Input::Device::Justifier); break;
|
||||
case 6: SNES::controllers.connect(1, SNES::Input::Device::Justifiers); break;
|
||||
case 0: SNES::input.connect(SNES::Controller::Port2, SNES::Input::Device::None); break;
|
||||
case 1: SNES::input.connect(SNES::Controller::Port2, SNES::Input::Device::Joypad); break;
|
||||
case 2: SNES::input.connect(SNES::Controller::Port2, SNES::Input::Device::Multitap); break;
|
||||
case 3: SNES::input.connect(SNES::Controller::Port2, SNES::Input::Device::Mouse); break;
|
||||
case 4: SNES::input.connect(SNES::Controller::Port2, SNES::Input::Device::SuperScope); break;
|
||||
case 5: SNES::input.connect(SNES::Controller::Port2, SNES::Input::Device::Justifier); break;
|
||||
case 6: SNES::input.connect(SNES::Controller::Port2, SNES::Input::Device::Justifiers); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue