mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-10-05 03:41:57 +02:00
Changelog: - S-SMP core code style updated - S-SMP loads reset vector from IPLROM ($fffe-ffff) - sfc/base => sfc/expansion - system/input => system/device - added expansion/eBoot (simulation of defparam's SNES-Boot device) - expansion port device can now be selected from Super Famicom menu option - improved GBA MROM/SRAM reading endrift's memory test is up to 1388/1552. Note: I added the expansion port devices to the same group as controller ports. I also had to move "None" to the top of the list. Before v096, I am going to have to add caching of port selections to the configuration file, check the proper default item in the system menu, and remove the items with no mappings from the input configuration window. Lots of work >_>
138 lines
2.5 KiB
C++
138 lines
2.5 KiB
C++
#ifdef CONTROLLER_CPP
|
|
|
|
//Synchronous serial communications cable emulation
|
|
|
|
//Hardware:
|
|
//Teensy++ 2.0 USB
|
|
//AT90USB1286
|
|
|
|
//Connection Diagram:
|
|
//SNES GND <> Teensy GND
|
|
//SNES IOBit <> Teensy B0
|
|
//SNES Latch <> Teensy D2
|
|
//SNES Data1 <> Teensy D3
|
|
//SNES Clock <> 1Kohm Resistor <> Teensy D5
|
|
//Teensy D5 <> Teensy D7
|
|
|
|
USART::USART(bool port) : Controller(port) {
|
|
latched = 0;
|
|
data1 = 0;
|
|
data2 = 0;
|
|
counter = 0;
|
|
|
|
rxlength = 0;
|
|
rxdata = 0;
|
|
|
|
txlength = 0;
|
|
txdata = 0;
|
|
|
|
string filename{interface->path(ID::SuperFamicom), "usart.so"};
|
|
if(openAbsolute(filename)) {
|
|
init = sym("usart_init");
|
|
main = sym("usart_main");
|
|
if(init && main) create(Controller::Enter, 10000000);
|
|
}
|
|
}
|
|
|
|
USART::~USART() {
|
|
if(open()) close();
|
|
}
|
|
|
|
auto USART::enter() -> void {
|
|
if(init && main) {
|
|
init(
|
|
{&USART::quit, this},
|
|
{&USART::usleep, this},
|
|
{&USART::readable, this},
|
|
{&USART::read, this},
|
|
{&USART::writable, this},
|
|
{&USART::write, this}
|
|
);
|
|
main();
|
|
}
|
|
while(true) step(10000000);
|
|
}
|
|
|
|
auto USART::quit() -> bool {
|
|
step(1);
|
|
return false;
|
|
}
|
|
|
|
auto USART::usleep(unsigned milliseconds) -> void {
|
|
step(10 * milliseconds);
|
|
}
|
|
|
|
auto USART::readable() -> bool {
|
|
step(1);
|
|
return txbuffer.size();
|
|
}
|
|
|
|
//SNES -> USART
|
|
auto USART::read() -> uint8 {
|
|
step(1);
|
|
while(txbuffer.size() == 0) step(1);
|
|
uint8 data = txbuffer[0];
|
|
txbuffer.remove(0);
|
|
return data;
|
|
}
|
|
|
|
auto USART::writable() -> bool {
|
|
step(1);
|
|
return true;
|
|
}
|
|
|
|
//USART -> SNES
|
|
auto USART::write(uint8 data) -> void {
|
|
step(1);
|
|
rxbuffer.append(data ^ 0xff);
|
|
}
|
|
|
|
//clock
|
|
auto USART::data() -> uint2 {
|
|
//Joypad
|
|
if(iobit()) {
|
|
if(counter >= 16) return 1;
|
|
uint2 result = 0;
|
|
if(counter < 12) result = interface->inputPoll(port, (unsigned)Device::ID::Gamepad, counter);
|
|
if(latched == 0) counter++;
|
|
return result;
|
|
}
|
|
|
|
//SNES -> USART
|
|
if(txlength == 0) {
|
|
if(latched == 0) txlength++;
|
|
} else if(txlength <= 8) {
|
|
txdata = (latched << 7) | (txdata >> 1);
|
|
txlength++;
|
|
} else {
|
|
if(latched == 1) txbuffer.append(txdata);
|
|
txlength = 0;
|
|
}
|
|
|
|
//USART -> SNES
|
|
if(rxlength == 0 && rxbuffer.size()) {
|
|
data1 = 1;
|
|
rxdata = rxbuffer[0];
|
|
rxbuffer.remove(0);
|
|
rxlength++;
|
|
} else if(rxlength <= 8) {
|
|
data1 = rxdata & 1;
|
|
rxdata >>= 1;
|
|
rxlength++;
|
|
} else {
|
|
data1 = 0;
|
|
rxlength = 0;
|
|
}
|
|
|
|
return (data2 << 1) | (data1 << 0);
|
|
}
|
|
|
|
//latch
|
|
auto USART::latch(bool data) -> void {
|
|
if(latched == data) return;
|
|
latched = data;
|
|
counter = 0;
|
|
}
|
|
|
|
#endif
|