Update to v068r01 release.

byuu says:

This adds RTS/CTS support to the serial communications emulation. Okay,
well the PC acts as if it is always ready, because it always is even on
the real thing, but the PC-waiting-for-SNES side works.

Source only, hardware communication only works on OS X and Linux
(Windows serial communication is totally different, I don't feel like
writing a Windows version), more documentation will come later.
This commit is contained in:
Tim Allen 2010-08-23 18:02:38 +10:00
parent a59ecb3dd4
commit 920d139302
10 changed files with 33 additions and 25 deletions

View File

@ -1,7 +1,7 @@
#ifndef NALL_FUNCTION_HPP #ifndef NALL_FUNCTION_HPP
#define NALL_FUNCTION_HPP #define NALL_FUNCTION_HPP
#include <malloc.h> #include <stdlib.h>
#include <functional> #include <functional>
#include <type_traits> #include <type_traits>

View File

@ -23,7 +23,7 @@ namespace nall {
return ::write(port, (void*)data, length); return ::write(port, (void*)data, length);
} }
bool open(const char *portname, unsigned rate) { bool open(const char *portname, unsigned rate, bool flowcontrol) {
close(); close();
port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
@ -41,8 +41,13 @@ namespace nall {
attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY); attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY);
attr.c_iflag |= (IGNBRK | IGNPAR); attr.c_iflag |= (IGNBRK | IGNPAR);
attr.c_oflag &=~ (OPOST); attr.c_oflag &=~ (OPOST);
attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB); attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB | CLOCAL);
attr.c_cflag |= (CS8 | CREAD | CLOCAL); attr.c_cflag |= (CS8 | CREAD);
if(flowcontrol == false) {
attr.c_cflag &= ~CRTSCTS;
} else {
attr.c_cflag |= CRTSCTS;
}
attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0; attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0;
if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; } if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; }

View File

@ -27,7 +27,6 @@ void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) {
supergameboy_version = SuperGameBoyVersion::Version1; supergameboy_version = SuperGameBoyVersion::Version1;
supergameboy_ram_size = 0; supergameboy_ram_size = 0;
supergameboy_rtc_size = 0; supergameboy_rtc_size = 0;
serial_baud_rate = 57600;
has_bsx_slot = false; has_bsx_slot = false;
has_superfx = false; has_superfx = false;

View File

@ -33,7 +33,6 @@ public:
readonly<SuperGameBoyVersion> supergameboy_version; readonly<SuperGameBoyVersion> supergameboy_version;
readonly<unsigned> supergameboy_ram_size; readonly<unsigned> supergameboy_ram_size;
readonly<unsigned> supergameboy_rtc_size; readonly<unsigned> supergameboy_rtc_size;
readonly<unsigned> serial_baud_rate;
readonly<bool> has_bsx_slot; readonly<bool> has_bsx_slot;
readonly<bool> has_superfx; readonly<bool> has_superfx;

View File

@ -608,12 +608,6 @@ void Cartridge::xml_parse_msu1(xml_element &root) {
void Cartridge::xml_parse_serial(xml_element &root) { void Cartridge::xml_parse_serial(xml_element &root) {
has_serial = true; has_serial = true;
foreach(attr, root.attribute) {
if(attr.name == "baud") {
serial_baud_rate = strunsigned(attr.content);
}
}
} }
void Cartridge::xml_parse_address(Mapping &m, const string &data) { void Cartridge::xml_parse_address(Mapping &m, const string &data) {

View File

@ -14,9 +14,11 @@ static void snesserial_write(uint8 data) { serial.write(data); }
void Serial::Enter() { serial.enter(); } void Serial::Enter() { serial.enter(); }
void Serial::enter() { void Serial::enter() {
latch = 0; data1 = 0;
data2 = 0;
add_clocks(256 * 8); //warm-up add_clocks(256 * 8); //warm-up
if(snesserial_main) snesserial_main(snesserial_tick, snesserial_read, snesserial_write); if(flowcontrol()) data2 = 1;
if(main) main(snesserial_tick, snesserial_read, snesserial_write);
while(true) add_clocks(frequency); //snesserial_main() fallback while(true) add_clocks(frequency); //snesserial_main() fallback
} }
@ -40,16 +42,19 @@ uint8 Serial::read() {
} }
void Serial::write(uint8 data) { void Serial::write(uint8 data) {
latch = 1; if(flowcontrol()) while(cpu.pio() & 0x80) add_clocks(1);
add_clocks(8);
data1 = 1;
add_clocks(8); add_clocks(8);
for(unsigned i = 0; i < 8; i++) { for(unsigned i = 0; i < 8; i++) {
latch = (data & 1) ^ 1; data1 = (data & 1) ^ 1;
data >>= 1; data >>= 1;
add_clocks(8); add_clocks(8);
} }
latch = 0; data1 = 0;
add_clocks(8); add_clocks(8);
} }
@ -82,7 +87,9 @@ void Serial::enable() {
string name = notdir(cartridge.basename()); string name = notdir(cartridge.basename());
string path = dir(cartridge.basename()); string path = dir(cartridge.basename());
if(open(name, path)) { if(open(name, path)) {
snesserial_main = sym("snesserial_main"); baudrate = sym("snesserial_baudrate");
flowcontrol = sym("snesserial_flowcontrol");
main = sym("snesserial_main");
} }
} }
@ -91,7 +98,7 @@ void Serial::power() {
} }
void Serial::reset() { void Serial::reset() {
create(Serial::Enter, cartridge.serial_baud_rate() * 8); create(Serial::Enter, baudrate() * 8);
} }
} }

View File

@ -8,7 +8,8 @@ public:
void reset(); void reset();
void serialize(serializer&); void serialize(serializer&);
readonly<bool> latch; readonly<bool> data1;
readonly<bool> data2;
void add_clocks(unsigned clocks); void add_clocks(unsigned clocks);
uint8 read(); uint8 read();
@ -19,7 +20,9 @@ public:
private: private:
MMIO *r4016, *r4017; MMIO *r4016, *r4017;
function<void (void (*)(unsigned), uint8_t (*)(), void (*)(uint8_t))> snesserial_main; function<unsigned ()> baudrate;
function<bool ()> flowcontrol;
function<void (void (*)(unsigned), uint8_t (*)(), void (*)(uint8_t))> main;
}; };
extern Serial serial; extern Serial serial;

View File

@ -2,7 +2,8 @@
void Serial::serialize(serializer &s) { void Serial::serialize(serializer &s) {
Processor::serialize(s); Processor::serialize(s);
s.integer((bool&)latch); s.integer((bool&)data1);
s.integer((bool&)data2);
} }
#endif #endif

View File

@ -4,7 +4,7 @@ Input input;
uint8 Input::port_read(bool portnumber) { uint8 Input::port_read(bool portnumber) {
if(cartridge.has_serial() && portnumber == 1) { if(cartridge.has_serial() && portnumber == 1) {
return serial.latch(); return (serial.data2() << 1) | (serial.data1() << 0);
} }
port_t &p = port[portnumber]; port_t &p = port[portnumber];

View File

@ -1,12 +1,12 @@
namespace SNES { namespace SNES {
namespace Info { namespace Info {
static const char Name[] = "bsnes"; static const char Name[] = "bsnes";
static const char Version[] = "068"; static const char Version[] = "068.01";
static const unsigned SerializerVersion = 12; static const unsigned SerializerVersion = 12;
} }
} }
//#define DEBUGGER #define DEBUGGER
#define CHEAT_SYSTEM #define CHEAT_SYSTEM
#include <libco/libco.h> #include <libco/libco.h>