bsnes/nall/emulation/21fx.hpp
Tim Allen c6fc15f8d2 Update to v101r18 release.
byuu says:

Changelog:

  - added 30 new PAL games to icarus (courtesy of Mikerochip)
  - new version of libco no longer requires mprotect nor W|X permissions
  - nall: default C compiler to -std=c11 instead of -std=c99
  - nall: use `-fno-strict-aliasing` during compilation
  - updated nall/certificates (hopefully for the last time)
  - updated nall/http to newer coding conventions
  - nall: improve handling of range() function

I didn't really work on higan at all, this is mostly just a release
because lots of other things have changed.

The most interesting is `-fno-strict-aliasing` ... basically, it joins
`-fwrapv` as being "stop the GCC developers from doing *really* evil
shit that could lead to security vulnerabilities or instabilities."

For the most part, it's a ~2% speed penalty for higan. Except for the
Sega Genesis, where it's a ~10% speedup. I have no idea how that's
possible, but clearly something's going very wrong with strict aliasing
on the Genesis core.

So ... it is what it is. If you need the performance for the non-Genesis
cores, you can turn it off in your builds. But I'm getting quite sick of
C++'s "surprises" and clever compiler developers, so I'm keeping it on
in all of my software going forward.
2016-09-14 21:55:53 +10:00

147 lines
3.2 KiB
C++

#pragma once
#include <nall/nall.hpp>
#include <nall/serial.hpp>
using namespace nall;
using int8 = Integer< 8>;
using int16 = Integer<16>;
using int24 = Integer<24>;
using int32 = Integer<32>;
using int64 = Integer<64>;
using uint8 = Natural< 8>;
using uint16 = Natural<16>;
using uint24 = Natural<24>;
using uint32 = Natural<32>;
using uint64 = Natural<64>;
struct FX {
auto open(string_vector& args) -> bool;
auto close() -> void;
auto readable() -> bool;
auto read() -> uint8_t;
auto writable() -> bool;
auto write(uint8_t data) -> void;
auto read(uint offset, uint length) -> vector<uint8_t>;
auto write(uint offset, const void* buffer, uint length) -> void;
auto write(uint offset, const vector<uint8_t>& buffer) -> void { write(offset, buffer.data(), buffer.size()); }
auto execute(uint offset) -> void;
auto read(uint offset) -> uint8_t;
auto write(uint offset, uint8_t data) -> void;
serial device;
};
auto FX::open(string_vector& args) -> bool {
//device name override support
string name;
for(uint n : range(args)) {
if(args[n].beginsWith("--device=")) {
name = args.take(n).trimLeft("--device=", 1L);
break;
}
}
if(!device.open(name)) {
print("[21fx] error: unable to open hardware device\n");
return false;
}
//flush the device (to clear floating inputs)
while(true) {
while(readable()) read();
auto iplrom = read(0x2184, 122);
auto sha256 = Hash::SHA256(iplrom.data(), iplrom.size()).digest();
if(sha256 == "41b79712a4a2d16d39894ae1b38cde5c41dad22eadc560df631d39f13df1e4b9") break;
}
return true;
}
auto FX::close() -> void {
device.close();
}
auto FX::readable() -> bool {
return device.readable();
}
//1000ns delay avoids burning CPU core at 100%; does not slow down max transfer rate at all
auto FX::read() -> uint8_t {
while(!readable()) usleep(1000);
uint8_t buffer[1] = {0};
device.read(buffer, 1);
return buffer[0];
}
auto FX::writable() -> bool {
return device.writable();
}
auto FX::write(uint8_t data) -> void {
while(!writable()) usleep(1000);
uint8_t buffer[1] = {data};
device.write(buffer, 1);
}
//
auto FX::read(uint offset, uint length) -> vector<uint8_t> {
write(0x21);
write(0x66);
write(0x78);
write(offset >> 16);
write(offset >> 8);
write(offset >> 0);
write(0x01);
write(length >> 8);
write(length >> 0);
write(0x00);
vector<uint8_t> buffer;
while(length--) buffer.append(read());
return buffer;
}
auto FX::write(uint offset, const void* data, uint length) -> void {
write(0x21);
write(0x66);
write(0x78);
write(offset >> 16);
write(offset >> 8);
write(offset >> 0);
write(0x01);
write(length >> 8);
write(length >> 0);
write(0x01);
auto buffer = (uint8_t*)data;
for(auto n : range(length)) write(buffer[n]);
write(0x00);
}
auto FX::execute(uint offset) -> void {
write(0x21);
write(0x66);
write(0x78);
write(offset >> 16);
write(offset >> 8);
write(offset >> 0);
write(0x00);
}
//
auto FX::read(uint offset) -> uint8_t {
auto buffer = read(offset, 1);
return buffer[0];
}
auto FX::write(uint offset, uint8_t data) -> void {
vector<uint8_t> buffer = {data};
write(offset, buffer);
}