mirror of https://github.com/bsnes-emu/bsnes.git
Update to v079r05 release.
byuu says: - Fixed GCC-4.6 casting errors in ui/input/input.cpp. - Fixed some of the opcode mnemonics specified in the HG51B169 core (was unable to speed up the code) - Started on a new core input system: snes/controller. More on that here: http://board.byuu.org/viewtopic.php?f=16&t=1761 - Have not yet attempted to add threading support to the controllers, so serial is still there as a coprocessor. - I'm going to move the Controllers {} class back to Input {} once all individual controllers have been ported over. Note: Super Scope and Justifier do not have counter latching support yet, so you can't really use them. The gamepad, multitap and mouse all work great; and the SS/Justifier cursors work at least. I also colored the SS cursor red, so that all three (SS, Justifier, chained secondary Justifier) all have unique R/G/B colors now. Should prevent confusion between the SS and one Justifier.
This commit is contained in:
parent
724747ac9e
commit
cf09d41669
|
@ -1,4 +1,4 @@
|
|||
snes_objects := snes-system
|
||||
snes_objects := snes-system snes-controller
|
||||
snes_objects += snes-cartridge snes-cheat
|
||||
snes_objects += snes-memory snes-cpucore snes-smpcore
|
||||
snes_objects += snes-cpu snes-smp snes-dsp snes-ppu
|
||||
|
@ -28,16 +28,17 @@ else ifeq ($(profile),performance)
|
|||
snesppu := $(snes)/alt/ppu-performance
|
||||
endif
|
||||
|
||||
obj/snes-system.o : $(snes)/system/system.cpp $(call rwildcard,$(snes)/system/) $(call rwildcard,$(snes)/video/)
|
||||
obj/snes-memory.o : $(snes)/memory/memory.cpp $(call rwildcard,$(snes)/memory/)
|
||||
obj/snes-cpucore.o : $(snes)/cpu/core/core.cpp $(call rwildcard,$(snes)/cpu/core/)
|
||||
obj/snes-smpcore.o : $(snes)/smp/core/core.cpp $(call rwildcard,$(snes)/smp/core/)
|
||||
obj/snes-cpu.o : $(snescpu)/cpu.cpp $(call rwildcard,$(snescpu)/)
|
||||
obj/snes-smp.o : $(snessmp)/smp.cpp $(call rwildcard,$(snessmp)/)
|
||||
obj/snes-dsp.o : $(snesdsp)/dsp.cpp $(call rwildcard,$(snesdsp)/)
|
||||
obj/snes-ppu.o : $(snesppu)/ppu.cpp $(call rwildcard,$(snesppu)/)
|
||||
obj/snes-cartridge.o: $(snes)/cartridge/cartridge.cpp $(snes)/cartridge/*
|
||||
obj/snes-cheat.o : $(snes)/cheat/cheat.cpp $(snes)/cheat/*
|
||||
obj/snes-system.o : $(snes)/system/system.cpp $(call rwildcard,$(snes)/system/) $(call rwildcard,$(snes)/video/) $(call rwildcard,$(snes)/audio/) $(call rwildcard,$(snes)/input/)
|
||||
obj/snes-controller.o: $(snes)/controller/controller.cpp $(call rwildcard,$(snes)/controller/)
|
||||
obj/snes-memory.o : $(snes)/memory/memory.cpp $(call rwildcard,$(snes)/memory/)
|
||||
obj/snes-cpucore.o : $(snes)/cpu/core/core.cpp $(call rwildcard,$(snes)/cpu/core/)
|
||||
obj/snes-smpcore.o : $(snes)/smp/core/core.cpp $(call rwildcard,$(snes)/smp/core/)
|
||||
obj/snes-cpu.o : $(snescpu)/cpu.cpp $(call rwildcard,$(snescpu)/)
|
||||
obj/snes-smp.o : $(snessmp)/smp.cpp $(call rwildcard,$(snessmp)/)
|
||||
obj/snes-dsp.o : $(snesdsp)/dsp.cpp $(call rwildcard,$(snesdsp)/)
|
||||
obj/snes-ppu.o : $(snesppu)/ppu.cpp $(call rwildcard,$(snesppu)/)
|
||||
obj/snes-cartridge.o : $(snes)/cartridge/cartridge.cpp $(snes)/cartridge/*
|
||||
obj/snes-cheat.o : $(snes)/cheat/cheat.cpp $(snes)/cheat/*
|
||||
|
||||
obj/snes-nss.o : $(snes)/chip/nss/nss.cpp $(call rwildcard,$(snes)/chip/nss/)
|
||||
obj/snes-icd2.o : $(snes)/chip/icd2/icd2.cpp $(call rwildcard,$(snes)/chip/icd2/)
|
||||
|
|
|
@ -35,7 +35,7 @@ void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) {
|
|||
nvram.reset();
|
||||
|
||||
parse_xml(xml_list);
|
||||
print(xml_list[0], "\n\n");
|
||||
//print(xml_list[0], "\n\n");
|
||||
|
||||
if(ram_size > 0) {
|
||||
ram.map(allocate<uint8>(ram_size, 0xff), ram_size);
|
||||
|
|
|
@ -78,7 +78,7 @@ void HitachiDSP::exec() {
|
|||
|
||||
else if((opcode & 0xdd00) == 0x1400) {
|
||||
//00.1 01.0 .... ....
|
||||
//jumpmi
|
||||
//jumpmi i
|
||||
if(regs.n) {
|
||||
if(opcode & 0x2000) push();
|
||||
regs.pc = np();
|
||||
|
@ -87,7 +87,7 @@ void HitachiDSP::exec() {
|
|||
|
||||
else if((opcode & 0xffff) == 0x1c00) {
|
||||
//0001 1100 0000 0000
|
||||
//loop/wait?
|
||||
//loop?
|
||||
}
|
||||
|
||||
else if((opcode & 0xfffe) == 0x2500) {
|
||||
|
@ -110,6 +110,7 @@ void HitachiDSP::exec() {
|
|||
|
||||
else if((opcode & 0xffff) == 0x3c00) {
|
||||
//0011 1100 0000 0000
|
||||
//ret
|
||||
pull();
|
||||
}
|
||||
|
||||
|
@ -121,7 +122,7 @@ void HitachiDSP::exec() {
|
|||
|
||||
else if((opcode & 0xf800) == 0x4800) {
|
||||
//0100 1... .... ....
|
||||
//rcmp a<<n,ri
|
||||
//cmpr a<<n,ri
|
||||
int result = ri() - sa();
|
||||
regs.n = result & 0x800000;
|
||||
regs.z = (uint24)result == 0;
|
||||
|
@ -195,11 +196,13 @@ void HitachiDSP::exec() {
|
|||
|
||||
else if((opcode & 0xff00) == 0x7c00) {
|
||||
//0111 1100 .... ....
|
||||
//ld pl,i
|
||||
regs.p = (regs.p & 0xff00) | ((opcode & 0xff) << 0);
|
||||
}
|
||||
|
||||
else if((opcode & 0xff00) == 0x7d00) {
|
||||
//0111 1101 .... ....
|
||||
//ld ph,i
|
||||
regs.p = (regs.p & 0x00ff) | ((opcode & 0xff) << 8);
|
||||
}
|
||||
|
||||
|
@ -215,7 +218,7 @@ void HitachiDSP::exec() {
|
|||
|
||||
else if((opcode & 0xf800) == 0x8800) {
|
||||
//1000 1... .... ....
|
||||
//rsb a<<n,ri
|
||||
//subr a<<n,ri
|
||||
int result = ri() - sa();
|
||||
regs.a = result;
|
||||
regs.n = regs.a & 0x800000;
|
||||
|
@ -247,7 +250,7 @@ void HitachiDSP::exec() {
|
|||
|
||||
else if((opcode & 0xf800) == 0xa800) {
|
||||
//1010 1... .... ....
|
||||
//xor a,ri
|
||||
//xor a<<n,ri
|
||||
regs.a = sa() ^ ri();
|
||||
regs.n = regs.a & 0x800000;
|
||||
regs.z = regs.a == 0;
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
#include <snes/snes.hpp>
|
||||
|
||||
#define CONTROLLER_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "gamepad/gamepad.cpp"
|
||||
#include "multitap/multitap.cpp"
|
||||
#include "mouse/mouse.cpp"
|
||||
#include "superscope/superscope.cpp"
|
||||
#include "justifier/justifier.cpp"
|
||||
Controllers controllers;
|
||||
|
||||
bool Controller::iobit() {
|
||||
switch(port) {
|
||||
case Controller::Port1: return cpu.pio() & 0x40;
|
||||
case Controller::Port2: return cpu.pio() & 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::iobit(bool data) {
|
||||
switch(port) {
|
||||
case Controller::Port1: break;
|
||||
case Controller::Port2: 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// SNES controller port pinout:
|
||||
// -------------------------------
|
||||
// | (1) (2) (3) (4) | (5) (6) (7) )
|
||||
// -------------------------------
|
||||
// pin name port1 port2
|
||||
// 1: +5v
|
||||
// 2: clock $4016 read $4017 read
|
||||
// 3: latch $4016.d0 write $4016.d0 write
|
||||
// 4: data1 $4016.d0 read $4017.d0 read
|
||||
// 5: data2 $4016.d1 read $4017.d1 read
|
||||
// 6: iobit $4201.d6 write; $4213.d6 read $4201.d7 write; $4213.d7 read
|
||||
// 7: gnd
|
||||
|
||||
struct Controller : Processor {
|
||||
enum : bool { Port1 = 0, Port2 = 1 };
|
||||
const bool port;
|
||||
|
||||
bool iobit();
|
||||
void iobit(bool data);
|
||||
virtual uint2 data() { return 0; }
|
||||
virtual void latch(bool data) {}
|
||||
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"
|
||||
#include "superscope/superscope.hpp"
|
||||
#include "justifier/justifier.hpp"
|
|
@ -0,0 +1,21 @@
|
|||
#ifdef CONTROLLER_CPP
|
||||
|
||||
uint2 Gamepad::data() {
|
||||
if(counter >= 16) return 1;
|
||||
uint2 result = system.interface->input_poll(port, Input::Device::Joypad, 0, counter);
|
||||
if(latched == 0) counter++;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Gamepad::latch(bool data) {
|
||||
if(latched == data) return;
|
||||
latched = data;
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
Gamepad::Gamepad(bool port) : Controller(port) {
|
||||
latched = 0;
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
struct Gamepad : Controller {
|
||||
uint2 data();
|
||||
void latch(bool data);
|
||||
Gamepad(bool port);
|
||||
|
||||
private:
|
||||
bool latched;
|
||||
unsigned counter;
|
||||
};
|
|
@ -0,0 +1,101 @@
|
|||
#ifdef CONTROLLER_CPP
|
||||
|
||||
uint2 Justifier::data() {
|
||||
if(counter >= 32) return 1;
|
||||
|
||||
if(counter == 0) {
|
||||
trigger1 = system.interface->input_poll(port, Input::Device::Justifier, 0, (unsigned)Input::JustifierID::Trigger);
|
||||
start1 = system.interface->input_poll(port, Input::Device::Justifier, 0, (unsigned)Input::JustifierID::Start);
|
||||
if(chained) {
|
||||
trigger2 = system.interface->input_poll(port, Input::Device::Justifiers, 1, (unsigned)Input::JustifierID::Trigger);
|
||||
start2 = system.interface->input_poll(port, Input::Device::Justifiers, 1, (unsigned)Input::JustifierID::Start);
|
||||
}
|
||||
}
|
||||
|
||||
switch(counter++) {
|
||||
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 trigger1;
|
||||
case 25: return trigger2;
|
||||
case 26: return start1;
|
||||
case 27: return start2;
|
||||
case 28: return active;
|
||||
|
||||
case 29: return 0;
|
||||
case 30: return 0;
|
||||
case 31: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
Justifier::Justifier(bool port, bool chained) : Controller(port), chained(chained) {
|
||||
latched = 0;
|
||||
counter = 0;
|
||||
active = 0;
|
||||
|
||||
if(chained == false) {
|
||||
x1 = 256 / 2;
|
||||
y1 = 240 / 2;
|
||||
x2 = -1;
|
||||
y2 = -1;
|
||||
} else {
|
||||
x1 = 256 / 2 - 16;
|
||||
y1 = 240 / 2;
|
||||
x2 = 256 / 2 + 16;
|
||||
y2 = 240 / 2;
|
||||
}
|
||||
|
||||
trigger1 = false;
|
||||
trigger2 = false;
|
||||
|
||||
start1 = false;
|
||||
start2 = false;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
struct Justifier : Controller {
|
||||
uint2 data();
|
||||
void latch(bool data);
|
||||
Justifier(bool port, bool chained);
|
||||
|
||||
//private:
|
||||
const bool chained; //true if the second justifier is attached to the first
|
||||
bool latched;
|
||||
unsigned counter;
|
||||
|
||||
bool active;
|
||||
int x1, x2;
|
||||
int y1, y2;
|
||||
bool trigger1, trigger2;
|
||||
bool start1, start2;
|
||||
};
|
|
@ -0,0 +1,69 @@
|
|||
#ifdef CONTROLLER_CPP
|
||||
|
||||
uint2 Mouse::data() {
|
||||
if(counter >= 32) return 1;
|
||||
|
||||
int position_x = system.interface->input_poll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::X); //-n = left, 0 = center, +n = right
|
||||
int position_y = system.interface->input_poll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::Y); //-n = up, 0 = center, +n = down
|
||||
|
||||
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_y)
|
||||
|
||||
position_x = min(127, position_x); //range = 0 - 127
|
||||
position_y = min(127, position_y);
|
||||
|
||||
switch(counter++) { 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(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::Right);
|
||||
case 9: return system.interface->input_poll(port, Input::Device::Mouse, 0, (unsigned)Input::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);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void Mouse::latch(bool data) {
|
||||
if(latched == data) return;
|
||||
latched = data;
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
Mouse::Mouse(bool port) : Controller(port) {
|
||||
latched = 0;
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
struct Mouse : Controller {
|
||||
uint2 data();
|
||||
void latch(bool data);
|
||||
Mouse(bool port);
|
||||
|
||||
private:
|
||||
bool latched;
|
||||
unsigned counter;
|
||||
};
|
|
@ -0,0 +1,39 @@
|
|||
#ifdef CONTROLLER_CPP
|
||||
|
||||
uint2 Multitap::data() {
|
||||
if(latched) return 2; //multitap detection
|
||||
unsigned index, port1, port2;
|
||||
|
||||
if(iobit()) {
|
||||
index = counter1;
|
||||
if(index >= 16) return 3;
|
||||
counter1++;
|
||||
port1 = 0; //controller 1
|
||||
port2 = 1; //controller 2
|
||||
} else {
|
||||
index = counter2;
|
||||
if(index >= 16) return 3;
|
||||
counter2++;
|
||||
port1 = 2; //controller 3
|
||||
port2 = 3; //controller 4
|
||||
}
|
||||
|
||||
bool data1 = system.interface->input_poll(port, Input::Device::Multitap, port1, index);
|
||||
bool data2 = system.interface->input_poll(port, Input::Device::Multitap, port2, index);
|
||||
return (data2 << 1) | (data1 << 0);
|
||||
}
|
||||
|
||||
void Multitap::latch(bool data) {
|
||||
if(latched == data) return;
|
||||
latched = data;
|
||||
counter1 = 0;
|
||||
counter2 = 0;
|
||||
}
|
||||
|
||||
Multitap::Multitap(bool port) : Controller(port) {
|
||||
latched = 0;
|
||||
counter1 = 0;
|
||||
counter2 = 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,10 @@
|
|||
struct Multitap : Controller {
|
||||
uint2 data();
|
||||
void latch(bool data);
|
||||
Multitap(bool port);
|
||||
|
||||
private:
|
||||
bool latched;
|
||||
unsigned counter1;
|
||||
unsigned counter2;
|
||||
};
|
|
@ -0,0 +1,96 @@
|
|||
#ifdef CONTROLLER_CPP
|
||||
|
||||
//The Super Scope is a light-gun: it detects the CRT beam cannon position,
|
||||
//and latches the counters by toggling iobit. This only works on controller
|
||||
//port 2, as iobit there is connected to the PPU H/V counter latch.
|
||||
//(PIO $4201.d7)
|
||||
|
||||
//A Super Scope can still technically be used in port 1, however it would
|
||||
//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.
|
||||
|
||||
uint2 SuperScope::data() {
|
||||
if(counter >= 8) return 1;
|
||||
|
||||
if(counter == 0) {
|
||||
//turbo is a switch; toggle is edge sensitive
|
||||
bool newturbo = system.interface->input_poll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::Turbo);
|
||||
if(newturbo && !turbo) {
|
||||
turbo = !turbo; //toggle state
|
||||
turbolock = true;
|
||||
} else {
|
||||
turbolock = false;
|
||||
}
|
||||
|
||||
//trigger is a button
|
||||
//if turbo is active, trigger is level sensitive; otherwise, it is edge sensitive
|
||||
trigger = false;
|
||||
bool newtrigger = system.interface->input_poll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::Trigger);
|
||||
if(newtrigger && (turbo || !triggerlock)) {
|
||||
trigger = true;
|
||||
triggerlock = true;
|
||||
} else if(!newtrigger) {
|
||||
triggerlock = false;
|
||||
}
|
||||
|
||||
//cursor is a button; it is always level sensitive
|
||||
cursor = system.interface->input_poll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::Cursor);
|
||||
|
||||
//pause is a button; it is always edge sensitive
|
||||
pause = false;
|
||||
bool newpause = system.interface->input_poll(port, Input::Device::SuperScope, 0, (unsigned)Input::SuperScopeID::Pause);
|
||||
if(newpause && !pauselock) {
|
||||
pause = true;
|
||||
pauselock = true;
|
||||
} else if(!newpause) {
|
||||
pauselock = false;
|
||||
}
|
||||
|
||||
offscreen = (x < 0 || y < 0 || x >= 256 || y >= (ppu.overscan() ? 240 : 225));
|
||||
}
|
||||
|
||||
switch(counter++) {
|
||||
case 0: return trigger;
|
||||
case 1: return cursor;
|
||||
case 2: return turbo;
|
||||
case 3: return pause;
|
||||
case 4: return 0;
|
||||
case 5: return 0;
|
||||
case 6: return offscreen;
|
||||
case 7: return 0; //noise (1 = yes)
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
latched = 0;
|
||||
counter = 0;
|
||||
|
||||
//center cursor onscreen
|
||||
x = 256 / 2;
|
||||
y = 240 / 2;
|
||||
|
||||
trigger = false;
|
||||
cursor = false;
|
||||
turbo = false;
|
||||
pause = false;
|
||||
offscreen = false;
|
||||
|
||||
turbolock = false;
|
||||
triggerlock = false;
|
||||
pauselock = false;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
struct SuperScope : Controller {
|
||||
uint2 data();
|
||||
void latch(bool data);
|
||||
SuperScope(bool port);
|
||||
|
||||
//private:
|
||||
bool latched;
|
||||
unsigned counter;
|
||||
|
||||
int x, y;
|
||||
|
||||
bool trigger;
|
||||
bool cursor;
|
||||
bool turbo;
|
||||
bool pause;
|
||||
bool offscreen;
|
||||
|
||||
bool turbolock;
|
||||
bool triggerlock;
|
||||
bool pauselock;
|
||||
};
|
|
@ -33,10 +33,13 @@ 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();
|
||||
//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);
|
||||
}
|
||||
|
||||
//JOYSER0
|
||||
|
@ -44,7 +47,8 @@ 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 |= input.port_read(0) & 3;
|
||||
r |= controllers.port1->data();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -54,7 +58,8 @@ 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 |= input.port_read(1) & 3;
|
||||
r |= controllers.port2->data();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,10 +6,18 @@ void CPU::step_auto_joypad_poll() {
|
|||
status.auto_joypad_active = status.auto_joypad_counter <= 15;
|
||||
|
||||
if(status.auto_joypad_active && status.auto_joypad_poll) {
|
||||
if(status.auto_joypad_counter == 0) input.poll();
|
||||
if(status.auto_joypad_counter == 0) {
|
||||
//input.poll();
|
||||
controllers.port1->latch(1);
|
||||
controllers.port2->latch(1);
|
||||
controllers.port1->latch(0);
|
||||
controllers.port2->latch(0);
|
||||
}
|
||||
|
||||
uint8 port0 = input.port_read(0);
|
||||
uint8 port1 = input.port_read(1);
|
||||
//uint8 port0 = input.port_read(0);
|
||||
//uint8 port1 = input.port_read(1);
|
||||
uint2 port0 = controllers.port1->data();
|
||||
uint2 port1 = controllers.port2->data();
|
||||
|
||||
status.joy1 = (status.joy1 << 1) | (bool)(port0 & 1);
|
||||
status.joy2 = (status.joy2 << 1) | (bool)(port1 & 1);
|
||||
|
|
|
@ -13,7 +13,7 @@ void CPU::add_clocks(unsigned clocks) {
|
|||
while(ticks--) {
|
||||
tick();
|
||||
if(hcounter() & 2) {
|
||||
input.tick();
|
||||
//input.tick();
|
||||
poll_interrupts();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#ifdef SYSTEM_CPP
|
||||
|
||||
Input input;
|
||||
Input input1;
|
||||
|
||||
uint8 Input::port_read(bool portnumber) {
|
||||
if(cartridge.has_serial() && portnumber == 1) {
|
||||
|
@ -277,7 +277,7 @@ void Input::update() {
|
|||
}
|
||||
}
|
||||
|
||||
void Input::port_set_device(bool portnumber, Device device) {
|
||||
void Input::port_set_device_(bool portnumber, Device device) {
|
||||
port_t &p = port[portnumber];
|
||||
|
||||
p.device = device;
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
};
|
||||
|
||||
uint8 port_read(bool port);
|
||||
void port_set_device(bool port, Device device);
|
||||
void port_set_device_(bool port, Device device);
|
||||
void init();
|
||||
void poll();
|
||||
void update();
|
||||
|
@ -85,4 +85,4 @@ private:
|
|||
friend class CPU;
|
||||
};
|
||||
|
||||
extern Input input;
|
||||
extern Input input1;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "bsnes";
|
||||
static const char Version[] = "079.04";
|
||||
static const char Version[] = "079.05";
|
||||
static const unsigned SerializerVersion = 21;
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +131,7 @@ namespace SNES {
|
|||
#endif
|
||||
|
||||
#include <snes/system/system.hpp>
|
||||
#include <snes/controller/controller.hpp>
|
||||
#include <snes/chip/chip.hpp>
|
||||
#include <snes/cartridge/cartridge.hpp>
|
||||
#include <snes/cheat/cheat.hpp>
|
||||
|
|
|
@ -21,7 +21,7 @@ void System::run() {
|
|||
|
||||
scheduler.enter();
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) {
|
||||
input.update();
|
||||
//input.update();
|
||||
video.update();
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ void System::runthreadtosave() {
|
|||
scheduler.enter();
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::SynchronizeEvent) break;
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) {
|
||||
input.update();
|
||||
//input.update();
|
||||
video.update();
|
||||
}
|
||||
}
|
||||
|
@ -89,10 +89,10 @@ void System::init(Interface *interface_) {
|
|||
|
||||
video.init();
|
||||
audio.init();
|
||||
input.init();
|
||||
//input.init();
|
||||
|
||||
input.port_set_device(0, config.controller_port1);
|
||||
input.port_set_device(1, config.controller_port2);
|
||||
controllers.connect(0, config.controller_port1);
|
||||
controllers.connect(1, config.controller_port2);
|
||||
}
|
||||
|
||||
void System::term() {
|
||||
|
@ -199,7 +199,9 @@ void System::power() {
|
|||
if(cartridge.has_link()) cpu.coprocessors.append(&link);
|
||||
|
||||
scheduler.init();
|
||||
input.update();
|
||||
controllers.connect(0, config.controller_port1);
|
||||
controllers.connect(1, config.controller_port2);
|
||||
//input.update();
|
||||
}
|
||||
|
||||
void System::reset() {
|
||||
|
@ -238,9 +240,9 @@ void System::reset() {
|
|||
if(cartridge.has_link()) cpu.coprocessors.append(&link);
|
||||
|
||||
scheduler.init();
|
||||
input.port_set_device(0, config.controller_port1);
|
||||
input.port_set_device(1, config.controller_port2);
|
||||
input.update();
|
||||
controllers.connect(0, config.controller_port1);
|
||||
controllers.connect(1, config.controller_port2);
|
||||
//input.update();
|
||||
}
|
||||
|
||||
void System::scanline() {
|
||||
|
|
|
@ -47,10 +47,22 @@ void Video::draw_cursor(uint16_t color, int x, int y) {
|
|||
}
|
||||
|
||||
void Video::update() {
|
||||
switch(input.port[1].device) {
|
||||
case Input::Device::SuperScope: draw_cursor(0x001f, input.port[1].superscope.x, input.port[1].superscope.y); break;
|
||||
case Input::Device::Justifiers: draw_cursor(0x02e0, input.port[1].justifier.x2, input.port[1].justifier.y2); //fallthrough
|
||||
case Input::Device::Justifier: draw_cursor(0x001f, input.port[1].justifier.x1, input.port[1].justifier.y1); break;
|
||||
switch(config.controller_port2) {
|
||||
case Input::Device::SuperScope:
|
||||
if(dynamic_cast<SuperScope*>(controllers.port2)) {
|
||||
SuperScope &device = (SuperScope&)*controllers.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;
|
||||
draw_cursor(0x001f, device.x1, device.y1);
|
||||
if(device.chained == false) break;
|
||||
draw_cursor(0x02e0, device.x2, device.y2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t *data = (uint16_t*)ppu.output;
|
||||
|
|
|
@ -82,7 +82,7 @@ void InputMapper::Gamepad::create(const char *deviceName, const char *configName
|
|||
}
|
||||
|
||||
int16_t InputMapper::Gamepad::poll(unsigned id) {
|
||||
switch(id) {
|
||||
switch((SNES::Input::JoypadID)id) {
|
||||
case SNES::Input::JoypadID::Up: return up.poll();
|
||||
case SNES::Input::JoypadID::Down: return down.poll() & !up.poll();
|
||||
case SNES::Input::JoypadID::Left: return left.poll();
|
||||
|
@ -118,7 +118,7 @@ void InputMapper::Mouse::create(const char *deviceName, const char *configName)
|
|||
}
|
||||
|
||||
int16_t InputMapper::Mouse::poll(unsigned id) {
|
||||
switch(id) {
|
||||
switch((SNES::Input::MouseID)id) {
|
||||
case SNES::Input::MouseID::X: return x.poll();
|
||||
case SNES::Input::MouseID::Y: return y.poll();
|
||||
case SNES::Input::MouseID::Left: return left.poll();
|
||||
|
@ -150,7 +150,7 @@ void InputMapper::SuperScope::create(const char *deviceName, const char *configN
|
|||
}
|
||||
|
||||
int16_t InputMapper::SuperScope::poll(unsigned id) {
|
||||
switch(id) {
|
||||
switch((SNES::Input::SuperScopeID)id) {
|
||||
case SNES::Input::SuperScopeID::X: return x.poll();
|
||||
case SNES::Input::SuperScopeID::Y: return y.poll();
|
||||
case SNES::Input::SuperScopeID::Trigger: return trigger.poll();
|
||||
|
@ -182,7 +182,7 @@ void InputMapper::Justifier::create(const char *deviceName, const char *configNa
|
|||
}
|
||||
|
||||
int16_t InputMapper::Justifier::poll(unsigned id) {
|
||||
switch(id) {
|
||||
switch((SNES::Input::JustifierID)id) {
|
||||
case SNES::Input::JustifierID::X: return x.poll();
|
||||
case SNES::Input::JustifierID::Y: return y.poll();
|
||||
case SNES::Input::JustifierID::Trigger: return trigger.poll();
|
||||
|
|
|
@ -40,20 +40,20 @@ void Utility::showMessage(const string &text) {
|
|||
|
||||
void Utility::setControllers() {
|
||||
switch(config.controller.port1) {
|
||||
case 0: SNES::input.port_set_device(0, SNES::Input::Device::None); break;
|
||||
case 1: SNES::input.port_set_device(0, SNES::Input::Device::Joypad); break;
|
||||
case 2: SNES::input.port_set_device(0, SNES::Input::Device::Multitap); break;
|
||||
case 3: SNES::input.port_set_device(0, SNES::Input::Device::Mouse); break;
|
||||
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;
|
||||
}
|
||||
|
||||
switch(config.controller.port2) {
|
||||
case 0: SNES::input.port_set_device(1, SNES::Input::Device::None); break;
|
||||
case 1: SNES::input.port_set_device(1, SNES::Input::Device::Joypad); break;
|
||||
case 2: SNES::input.port_set_device(1, SNES::Input::Device::Multitap); break;
|
||||
case 3: SNES::input.port_set_device(1, SNES::Input::Device::Mouse); break;
|
||||
case 4: SNES::input.port_set_device(1, SNES::Input::Device::SuperScope); break;
|
||||
case 5: SNES::input.port_set_device(1, SNES::Input::Device::Justifier); break;
|
||||
case 6: SNES::input.port_set_device(1, SNES::Input::Device::Justifiers); break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue