mirror of https://github.com/bsnes-emu/bsnes.git
Update to v101r19 release.
byuu says: Changelog: - added \~130 new PAL games to icarus (courtesy of Smarthuman and aquaman) - added all three Korean-localized games to icarus - sfc: removed SuperDisc emulation (it was going nowhere) - sfc: fixed MSU1 regression where the play/repeat flags were not being cleared on track select - nall: cryptography support added; will be used to sign future databases (validation will always be optional) - minor shims to fix compilation issues due to nall changes The real magic is that we now have 25-30% of the PAL SNES library in icarus! Signing will be tricky. Obviously if I put the public key inside the higan archive, then all anyone has to do is change that public key for their own releases. And if you download from my site (which is now over HTTPS), then you don't need the signing to verify integrity. I may just put the public key on my site on my site and leave it at that, we'll see.
This commit is contained in:
parent
c6fc15f8d2
commit
f3e67da937
|
@ -12,7 +12,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "101.18";
|
static const string Version = "101.19";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
|
|
|
@ -29,8 +29,8 @@ auto Cartridge::load() -> bool {
|
||||||
if(!board) return false;
|
if(!board) return false;
|
||||||
|
|
||||||
Hash::SHA256 sha;
|
Hash::SHA256 sha;
|
||||||
sha.data(board->prgrom.data, board->prgrom.size);
|
sha.input(board->prgrom.data, board->prgrom.size);
|
||||||
sha.data(board->chrrom.data, board->chrrom.size);
|
sha.input(board->chrrom.data, board->chrrom.size);
|
||||||
information.sha256 = sha.digest();
|
information.sha256 = sha.digest();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
static auto hex(uintmax value, long precision = 0, char padchar = '0') -> string {
|
||||||
|
return nall::hex(value, precision, padchar);
|
||||||
|
}
|
||||||
|
|
||||||
auto LR35902::disassemble(uint16 pc) -> string {
|
auto LR35902::disassemble(uint16 pc) -> string {
|
||||||
char output[80];
|
char output[80];
|
||||||
memset(output, ' ', sizeof output);
|
memset(output, ' ', sizeof output);
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
static auto hex(uintmax value, long precision = 0, char padchar = '0') -> string {
|
||||||
|
return nall::hex(value, precision, padchar);
|
||||||
|
}
|
||||||
|
|
||||||
auto R65816::dreadb(uint24 addr) -> uint8 {
|
auto R65816::dreadb(uint24 addr) -> uint8 {
|
||||||
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
|
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
|
||||||
//$00-3f|80-bf:2000-5fff
|
//$00-3f|80-bf:2000-5fff
|
||||||
|
|
|
@ -3,14 +3,13 @@ processors += r65816 spc700 arm gsu hg51b upd96050
|
||||||
objects += sfc-interface sfc-system sfc-controller
|
objects += sfc-interface sfc-system sfc-controller
|
||||||
objects += sfc-cartridge sfc-memory
|
objects += sfc-cartridge sfc-memory
|
||||||
objects += sfc-cpu sfc-smp sfc-dsp sfc-ppu
|
objects += sfc-cpu sfc-smp sfc-dsp sfc-ppu
|
||||||
objects += sfc-expansion sfc-satellaview sfc-superdisc
|
objects += sfc-expansion sfc-satellaview sfc-21fx
|
||||||
objects += sfc-21fx
|
|
||||||
objects += sfc-icd2 sfc-mcc sfc-nss sfc-event
|
objects += sfc-icd2 sfc-mcc sfc-nss sfc-event
|
||||||
objects += sfc-sa1 sfc-superfx
|
objects += sfc-sa1 sfc-superfx
|
||||||
objects += sfc-armdsp sfc-hitachidsp sfc-necdsp
|
objects += sfc-armdsp sfc-hitachidsp sfc-necdsp
|
||||||
objects += sfc-epsonrtc sfc-sharprtc
|
objects += sfc-epsonrtc sfc-sharprtc
|
||||||
objects += sfc-spc7110 sfc-sdd1 sfc-obc1
|
objects += sfc-spc7110 sfc-sdd1
|
||||||
objects += sfc-msu1
|
objects += sfc-obc1 sfc-msu1
|
||||||
objects += sfc-bsmemory sfc-sufamiturbo
|
objects += sfc-bsmemory sfc-sufamiturbo
|
||||||
|
|
||||||
obj/sfc-interface.o: sfc/interface/interface.cpp $(call rwildcard,sfc/interface)
|
obj/sfc-interface.o: sfc/interface/interface.cpp $(call rwildcard,sfc/interface)
|
||||||
|
@ -26,7 +25,6 @@ obj/sfc-ppu.o: sfc/ppu/ppu.cpp $(call rwildcard,sfc/ppu/)
|
||||||
|
|
||||||
obj/sfc-expansion.o: sfc/expansion/expansion.cpp $(call rwildcard,sfc/expansion/)
|
obj/sfc-expansion.o: sfc/expansion/expansion.cpp $(call rwildcard,sfc/expansion/)
|
||||||
obj/sfc-satellaview.o: sfc/expansion/satellaview/satellaview.cpp $(call rwildcard,sfc/expansion/satellaview/)
|
obj/sfc-satellaview.o: sfc/expansion/satellaview/satellaview.cpp $(call rwildcard,sfc/expansion/satellaview/)
|
||||||
obj/sfc-superdisc.o: sfc/expansion/superdisc/superdisc.cpp $(call rwildcard,sfc/expansion/superdisc/)
|
|
||||||
obj/sfc-21fx.o: sfc/expansion/21fx/21fx.cpp $(call rwildcard,sfc/expansion/21fx/)
|
obj/sfc-21fx.o: sfc/expansion/21fx/21fx.cpp $(call rwildcard,sfc/expansion/21fx/)
|
||||||
|
|
||||||
obj/sfc-icd2.o: sfc/coprocessor/icd2/icd2.cpp $(call rwildcard,sfc/coprocessor/icd2/)
|
obj/sfc-icd2.o: sfc/coprocessor/icd2/icd2.cpp $(call rwildcard,sfc/coprocessor/icd2/)
|
||||||
|
|
|
@ -52,8 +52,8 @@ auto Cartridge::load() -> bool {
|
||||||
//Sufami Turbo
|
//Sufami Turbo
|
||||||
else if(cartridge.has.SufamiTurboSlots) {
|
else if(cartridge.has.SufamiTurboSlots) {
|
||||||
Hash::SHA256 sha;
|
Hash::SHA256 sha;
|
||||||
sha.data(sufamiturboA.rom.data(), sufamiturboA.rom.size());
|
sha.input(sufamiturboA.rom.data(), sufamiturboA.rom.size());
|
||||||
sha.data(sufamiturboB.rom.data(), sufamiturboB.rom.size());
|
sha.input(sufamiturboB.rom.data(), sufamiturboB.rom.size());
|
||||||
information.sha256 = sha.digest();
|
information.sha256 = sha.digest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,22 +61,22 @@ auto Cartridge::load() -> bool {
|
||||||
else {
|
else {
|
||||||
Hash::SHA256 sha;
|
Hash::SHA256 sha;
|
||||||
//hash each ROM image that exists; any with size() == 0 is ignored by sha256_chunk()
|
//hash each ROM image that exists; any with size() == 0 is ignored by sha256_chunk()
|
||||||
sha.data(rom.data(), rom.size());
|
sha.input(rom.data(), rom.size());
|
||||||
sha.data(mcc.rom.data(), mcc.rom.size());
|
sha.input(mcc.rom.data(), mcc.rom.size());
|
||||||
sha.data(sa1.rom.data(), sa1.rom.size());
|
sha.input(sa1.rom.data(), sa1.rom.size());
|
||||||
sha.data(superfx.rom.data(), superfx.rom.size());
|
sha.input(superfx.rom.data(), superfx.rom.size());
|
||||||
sha.data(hitachidsp.rom.data(), hitachidsp.rom.size());
|
sha.input(hitachidsp.rom.data(), hitachidsp.rom.size());
|
||||||
sha.data(spc7110.prom.data(), spc7110.prom.size());
|
sha.input(spc7110.prom.data(), spc7110.prom.size());
|
||||||
sha.data(spc7110.drom.data(), spc7110.drom.size());
|
sha.input(spc7110.drom.data(), spc7110.drom.size());
|
||||||
sha.data(sdd1.rom.data(), sdd1.rom.size());
|
sha.input(sdd1.rom.data(), sdd1.rom.size());
|
||||||
//hash all firmware that exists
|
//hash all firmware that exists
|
||||||
vector<uint8> buffer;
|
vector<uint8> buffer;
|
||||||
buffer = armdsp.firmware();
|
buffer = armdsp.firmware();
|
||||||
sha.data(buffer.data(), buffer.size());
|
sha.input(buffer.data(), buffer.size());
|
||||||
buffer = hitachidsp.firmware();
|
buffer = hitachidsp.firmware();
|
||||||
sha.data(buffer.data(), buffer.size());
|
sha.input(buffer.data(), buffer.size());
|
||||||
buffer = necdsp.firmware();
|
buffer = necdsp.firmware();
|
||||||
sha.data(buffer.data(), buffer.size());
|
sha.input(buffer.data(), buffer.size());
|
||||||
//finalize hash
|
//finalize hash
|
||||||
information.sha256 = sha.digest();
|
information.sha256 = sha.digest();
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,9 +116,8 @@ auto MSU1::audioOpen() -> void {
|
||||||
|
|
||||||
auto MSU1::readIO(uint24 addr, uint8) -> uint8 {
|
auto MSU1::readIO(uint24 addr, uint8) -> uint8 {
|
||||||
cpu.synchronize(*this);
|
cpu.synchronize(*this);
|
||||||
addr = 0x2000 | (addr & 7);
|
|
||||||
|
|
||||||
switch(addr) {
|
switch(0x2000 | (addr & 7)) {
|
||||||
case 0x2000:
|
case 0x2000:
|
||||||
return (
|
return (
|
||||||
Revision << 0
|
Revision << 0
|
||||||
|
@ -145,9 +144,8 @@ auto MSU1::readIO(uint24 addr, uint8) -> uint8 {
|
||||||
|
|
||||||
auto MSU1::writeIO(uint24 addr, uint8 data) -> void {
|
auto MSU1::writeIO(uint24 addr, uint8 data) -> void {
|
||||||
cpu.synchronize(*this);
|
cpu.synchronize(*this);
|
||||||
addr = 0x2000 | (addr & 7);
|
|
||||||
|
|
||||||
switch(addr) {
|
switch(0x2000 | (addr & 7)) {
|
||||||
case 0x2000: io.dataSeekOffset.byte(0) = data; break;
|
case 0x2000: io.dataSeekOffset.byte(0) = data; break;
|
||||||
case 0x2001: io.dataSeekOffset.byte(1) = data; break;
|
case 0x2001: io.dataSeekOffset.byte(1) = data; break;
|
||||||
case 0x2002: io.dataSeekOffset.byte(2) = data; break;
|
case 0x2002: io.dataSeekOffset.byte(2) = data; break;
|
||||||
|
@ -157,6 +155,8 @@ auto MSU1::writeIO(uint24 addr, uint8 data) -> void {
|
||||||
break;
|
break;
|
||||||
case 0x2004: io.audioTrack.byte(0) = data; break;
|
case 0x2004: io.audioTrack.byte(0) = data; break;
|
||||||
case 0x2005: io.audioTrack.byte(1) = data;
|
case 0x2005: io.audioTrack.byte(1) = data;
|
||||||
|
io.audioPlay = false;
|
||||||
|
io.audioRepeat = false;
|
||||||
io.audioPlayOffset = 8;
|
io.audioPlayOffset = 8;
|
||||||
if(io.audioTrack == io.audioResumeTrack) {
|
if(io.audioTrack == io.audioResumeTrack) {
|
||||||
io.audioPlayOffset = io.audioResumeOffset;
|
io.audioPlayOffset = io.audioResumeOffset;
|
||||||
|
|
|
@ -5,5 +5,4 @@ struct Expansion : Thread {
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <sfc/expansion/satellaview/satellaview.hpp>
|
#include <sfc/expansion/satellaview/satellaview.hpp>
|
||||||
#include <sfc/expansion/superdisc/superdisc.hpp>
|
|
||||||
#include <sfc/expansion/21fx/21fx.hpp>
|
#include <sfc/expansion/21fx/21fx.hpp>
|
||||||
|
|
|
@ -1,202 +0,0 @@
|
||||||
//NEC D75P308GF
|
|
||||||
//4-bit microcontroller
|
|
||||||
//CD-player interface
|
|
||||||
|
|
||||||
auto SuperDisc::necPollIRQ() -> uint8 {
|
|
||||||
auto match = [&](const string& compare) -> bool {
|
|
||||||
if(nec.command.size() != compare.size()) return false;
|
|
||||||
for(auto n : range(nec.command)) {
|
|
||||||
char c = compare[n];
|
|
||||||
if(c == '?') continue;
|
|
||||||
if(c >= '0' && c <= '9') c -= '0';
|
|
||||||
if(c >= 'a' && c <= 'f') c -= 'a' - 10;
|
|
||||||
if(nec.command[n] != c) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
//access ??/??/??
|
|
||||||
if(match("b" )) return 0x8f;
|
|
||||||
if(match("b?" )) return 0x8f;
|
|
||||||
if(match("b??" )) return 0x8f;
|
|
||||||
if(match("b???" )) return 0x8f;
|
|
||||||
if(match("b????" )) return 0x8f;
|
|
||||||
if(match("b?????" )) return 0x8f;
|
|
||||||
if(match("b??????" )) return 0x8f;
|
|
||||||
if(match("b??????f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//access t??/i??
|
|
||||||
if(match("c" )) return 0x8f;
|
|
||||||
if(match("c?" )) return 0x8f;
|
|
||||||
if(match("c??" )) return 0x8f;
|
|
||||||
if(match("c???" )) return 0x8f;
|
|
||||||
if(match("c????" )) return 0x8f;
|
|
||||||
if(match("c????f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//d-prefixes
|
|
||||||
if(match("d" )) return 0x8f;
|
|
||||||
if(match("d0")) return 0x8f;
|
|
||||||
if(match("d1")) return 0x8f;
|
|
||||||
if(match("d4")) return 0x8f;
|
|
||||||
if(match("d5")) return 0x8f;
|
|
||||||
|
|
||||||
//stop
|
|
||||||
if(match("d01" )) return 0x8f;
|
|
||||||
if(match("d01f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//play
|
|
||||||
if(match("d02" )) return 0x8f;
|
|
||||||
if(match("d02f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//pause
|
|
||||||
if(match("d03" )) return 0x8f;
|
|
||||||
if(match("d03f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//open / close
|
|
||||||
if(match("d04" )) return 0x8f;
|
|
||||||
if(match("d04f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//fast forward
|
|
||||||
if(match("d10" )) return 0x8f;
|
|
||||||
if(match("d10f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//fast reverse
|
|
||||||
if(match("d11" )) return 0x8f;
|
|
||||||
if(match("d11f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//forward
|
|
||||||
if(match("d12" )) return 0x8f;
|
|
||||||
if(match("d12f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//reverse
|
|
||||||
if(match("d13" )) return 0x8f;
|
|
||||||
if(match("d13f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//key direct
|
|
||||||
if(match("d40" )) return 0x8f;
|
|
||||||
if(match("d40f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//key ignore
|
|
||||||
if(match("d41" )) return 0x8f;
|
|
||||||
if(match("d41f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//continuous play
|
|
||||||
if(match("d42" )) return 0x8f;
|
|
||||||
if(match("d42f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//auto track pause
|
|
||||||
if(match("d43" )) return 0x8f;
|
|
||||||
if(match("d43f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//auto index pause
|
|
||||||
if(match("d44" )) return 0x8f;
|
|
||||||
if(match("d44f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//normal speed
|
|
||||||
if(match("d45" )) return 0x8f;
|
|
||||||
if(match("d45f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//double speed
|
|
||||||
if(match("d46" )) return 0x8f;
|
|
||||||
if(match("d46f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//q-data request
|
|
||||||
if(match("d50" )) return 0x8f;
|
|
||||||
if(match("d50f" )) return 0x8f;
|
|
||||||
if(match("d50f?" )) return 0x80;
|
|
||||||
if(match("d50f??" )) return 0x80;
|
|
||||||
if(match("d50f???" )) return 0x80;
|
|
||||||
if(match("d50f????" )) return 0x80;
|
|
||||||
if(match("d50f?????" )) return 0x80;
|
|
||||||
if(match("d50f??????" )) return 0x80;
|
|
||||||
if(match("d50f???????" )) return 0x80;
|
|
||||||
if(match("d50f????????" )) return 0x80;
|
|
||||||
if(match("d50f?????????" )) return 0x80;
|
|
||||||
if(match("d50f??????????" )) return 0x80;
|
|
||||||
if(match("d50f???????????" )) return 0x80;
|
|
||||||
if(match("d50f????????????" )) return 0x80;
|
|
||||||
if(match("d50f?????????????" )) return 0x80;
|
|
||||||
if(match("d50f??????????????" )) return 0x80;
|
|
||||||
if(match("d50f???????????????" )) return 0x80;
|
|
||||||
if(match("d50f????????????????" )) return 0x80;
|
|
||||||
if(match("d50f????????????????f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//status request
|
|
||||||
if(match("d51" )) return 0x8f;
|
|
||||||
if(match("d51f" )) return 0x8f;
|
|
||||||
if(match("d51f0" )) return 0x81;
|
|
||||||
if(match("d51f01" )) return 0x80;
|
|
||||||
if(match("d51f012" )) return 0x81;
|
|
||||||
if(match("d51f0123" )) return 0x80;
|
|
||||||
if(match("d51f01234" )) return 0x80;
|
|
||||||
if(match("d51f01234f")) {
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
nec.command.reset();
|
|
||||||
return 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperDisc::necReadData() -> uint8 {
|
|
||||||
return nec.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperDisc::necWriteCommand(uint4 data) -> void {
|
|
||||||
if(nec.command.size() >= 32) return;
|
|
||||||
nec.command.append(data);
|
|
||||||
}
|
|
|
@ -1,143 +0,0 @@
|
||||||
//Sony CXD1800Q
|
|
||||||
//CD-ROM decoder
|
|
||||||
|
|
||||||
auto SuperDisc::sonyPollIRQ() -> uint8 {
|
|
||||||
return 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperDisc::sonyReadData() -> uint8 {
|
|
||||||
uint8 command = sony.command++;
|
|
||||||
|
|
||||||
auto match = [&](const string& compare) -> bool {
|
|
||||||
char hi = compare[0];
|
|
||||||
if(hi == '?') hi = 0;
|
|
||||||
if(hi >= '0' && hi <= '9') hi -= '0';
|
|
||||||
if(hi >= 'a' && hi <= 'f') hi -= 'a' - 10;
|
|
||||||
if(hi != '?' && hi != command.bits(4,7)) return false;
|
|
||||||
|
|
||||||
char lo = compare[1];
|
|
||||||
if(lo == '?') lo = 0;
|
|
||||||
if(lo >= '0' && lo <= '9') lo -= '0';
|
|
||||||
if(lo >= 'a' && lo <= 'f') lo -= 'a' - 10;
|
|
||||||
if(lo != '?' && lo != command.bits(0,3)) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
//DMA
|
|
||||||
if(match("00")) return 0x00;
|
|
||||||
|
|
||||||
//INST
|
|
||||||
if(match("01")) return 0x10;
|
|
||||||
|
|
||||||
//STS
|
|
||||||
if(match("02")) return 0x00;
|
|
||||||
|
|
||||||
//HFLG
|
|
||||||
if(match("03")) return 0x00;
|
|
||||||
|
|
||||||
//HMIN
|
|
||||||
if(match("?4")) return 0x00;
|
|
||||||
|
|
||||||
//HSEC
|
|
||||||
if(match("?5")) return 0x00;
|
|
||||||
|
|
||||||
//HBLK
|
|
||||||
if(match("?6")) return 0x00;
|
|
||||||
|
|
||||||
//HMOD
|
|
||||||
if(match("?7")) return 0x00;
|
|
||||||
|
|
||||||
//SFIL
|
|
||||||
if(match("08")) return 0x00;
|
|
||||||
|
|
||||||
//SCH
|
|
||||||
if(match("09")) return 0x00;
|
|
||||||
|
|
||||||
//SMOD
|
|
||||||
if(match("0a")) return 0x00;
|
|
||||||
|
|
||||||
//SCI
|
|
||||||
if(match("0b")) return 0x00;
|
|
||||||
|
|
||||||
//CMAD
|
|
||||||
if(match("0c")) return 0x00;
|
|
||||||
if(match("0d")) return 0x00;
|
|
||||||
|
|
||||||
//MDFM
|
|
||||||
if(match("?e")) return 0x00;
|
|
||||||
|
|
||||||
//ADPC
|
|
||||||
if(match("?f")) return 0x00;
|
|
||||||
|
|
||||||
//DMXF
|
|
||||||
if(match("18")) return 0x00;
|
|
||||||
if(match("19")) return 0x00;
|
|
||||||
|
|
||||||
//DMAD
|
|
||||||
if(match("1a")) return 0x00;
|
|
||||||
if(match("1b")) return 0x00;
|
|
||||||
|
|
||||||
//DRAD
|
|
||||||
if(match("1c")) return 0x00;
|
|
||||||
if(match("1d")) return 0x00;
|
|
||||||
|
|
||||||
return 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperDisc::sonyWriteCommand(uint8 data) -> void {
|
|
||||||
sony.command = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperDisc::sonyWriteData(uint8 data) -> void {
|
|
||||||
uint8 command = sony.command++;
|
|
||||||
|
|
||||||
auto match = [&](const string& compare) -> bool {
|
|
||||||
char hi = compare[0];
|
|
||||||
if(hi == '?') hi = 0;
|
|
||||||
if(hi >= '0' && hi <= '9') hi -= '0';
|
|
||||||
if(hi >= 'a' && hi <= 'f') hi -= 'a' - 10;
|
|
||||||
if(hi != '?' && hi != command.bits(4,7)) return false;
|
|
||||||
|
|
||||||
char lo = compare[1];
|
|
||||||
if(lo == '?') lo = 0;
|
|
||||||
if(lo >= '0' && lo <= '9') lo -= '0';
|
|
||||||
if(lo >= 'a' && lo <= 'f') lo -= 'a' - 10;
|
|
||||||
if(lo != '?' && lo != command.bits(0,3)) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
//DRIF
|
|
||||||
if(match("?1")) return;
|
|
||||||
|
|
||||||
//CHCT
|
|
||||||
if(match("?2")) return;
|
|
||||||
|
|
||||||
//DECT
|
|
||||||
if(match("?3")) return;
|
|
||||||
|
|
||||||
//INMS
|
|
||||||
if(match("?4")) return;
|
|
||||||
|
|
||||||
//INCL
|
|
||||||
if(match("?5")) return;
|
|
||||||
|
|
||||||
//CI
|
|
||||||
if(match("?6")) return;
|
|
||||||
|
|
||||||
//DMAD
|
|
||||||
if(match("?7")) return;
|
|
||||||
if(match("?8")) return;
|
|
||||||
|
|
||||||
//DMXF
|
|
||||||
if(match("?9")) return;
|
|
||||||
if(match("?a")) return;
|
|
||||||
|
|
||||||
//DRAD
|
|
||||||
if(match("?b")) return;
|
|
||||||
if(match("?c")) return;
|
|
||||||
|
|
||||||
//PLBA
|
|
||||||
if(match("0d")) return;
|
|
||||||
}
|
|
|
@ -1,106 +0,0 @@
|
||||||
#include <sfc/sfc.hpp>
|
|
||||||
|
|
||||||
namespace SuperFamicom {
|
|
||||||
|
|
||||||
#include "nec.cpp"
|
|
||||||
#include "sony.cpp"
|
|
||||||
|
|
||||||
SuperDisc::SuperDisc() {
|
|
||||||
create(&SuperDisc::Enter, 75);
|
|
||||||
|
|
||||||
bus.map({&SuperDisc::read, this}, {&SuperDisc::write, this}, "00-3f,80-bf:21e0-21e5");
|
|
||||||
|
|
||||||
r.irqEnable = 0x00;
|
|
||||||
|
|
||||||
nec.command.reset();
|
|
||||||
nec.data = 0x00;
|
|
||||||
|
|
||||||
sony.command = 0x00;
|
|
||||||
sony.data = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
SuperDisc::~SuperDisc() {
|
|
||||||
scheduler.remove(*this);
|
|
||||||
bus.unmap("00-3f,80-bf:21e0-21e5");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperDisc::Enter() -> void {
|
|
||||||
while(true) scheduler.synchronize(), peripherals.expansionPort->main();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperDisc::main() -> void {
|
|
||||||
cpu.r.irq = 0;
|
|
||||||
|
|
||||||
if(r.irqEnable.bit(3)) {
|
|
||||||
cpu.r.irq = 1;
|
|
||||||
nec.data = necPollIRQ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(r.irqEnable.bit(2)) {
|
|
||||||
cpu.r.irq = 1;
|
|
||||||
sony.data = sonyPollIRQ();
|
|
||||||
}
|
|
||||||
|
|
||||||
step(1);
|
|
||||||
synchronize(cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperDisc::read(uint24 addr, uint8 data) -> uint8 {
|
|
||||||
addr = 0x21e0 | (addr & 7);
|
|
||||||
|
|
||||||
if(addr == 0x21e0) {
|
|
||||||
data = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x21e1) {
|
|
||||||
cpu.r.irq = 0;
|
|
||||||
data = necReadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x21e2) {
|
|
||||||
data = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x21e3) {
|
|
||||||
cpu.r.irq = 0;
|
|
||||||
data = sonyReadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x21e4) {
|
|
||||||
data = r.irqEnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x21e5) {
|
|
||||||
data = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperDisc::write(uint24 addr, uint8 data) -> void {
|
|
||||||
addr = 0x21e0 | (addr & 7);
|
|
||||||
|
|
||||||
if(addr == 0x21e0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x21e1) {
|
|
||||||
necWriteCommand(data.bits(0,3));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x21e2) {
|
|
||||||
sonyWriteCommand(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x21e3) {
|
|
||||||
sonyWriteData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x21e4) {
|
|
||||||
r.irqEnable = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x21e5) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
struct SuperDisc : Expansion {
|
|
||||||
SuperDisc();
|
|
||||||
~SuperDisc();
|
|
||||||
|
|
||||||
static auto Enter() -> void;
|
|
||||||
auto main() -> void;
|
|
||||||
|
|
||||||
auto read(uint24 addr, uint8 data) -> uint8;
|
|
||||||
auto write(uint24 addr, uint8 data) -> void;
|
|
||||||
|
|
||||||
//nec.cpp
|
|
||||||
auto necPollIRQ() -> uint8;
|
|
||||||
auto necReadData() -> uint8;
|
|
||||||
auto necWriteCommand(uint4 data) -> void;
|
|
||||||
|
|
||||||
//sony.cpp
|
|
||||||
auto sonyPollIRQ() -> uint8;
|
|
||||||
auto sonyReadData() -> uint8;
|
|
||||||
auto sonyWriteCommand(uint8 data) -> void;
|
|
||||||
auto sonyWriteData(uint8 data) -> void;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Registers {
|
|
||||||
uint8 irqEnable;
|
|
||||||
} r;
|
|
||||||
|
|
||||||
//NEC
|
|
||||||
struct NEC {
|
|
||||||
vector<uint4> command;
|
|
||||||
uint8 data;
|
|
||||||
} nec;
|
|
||||||
|
|
||||||
//Sony
|
|
||||||
struct Sony {
|
|
||||||
uint8 command;
|
|
||||||
uint8 data;
|
|
||||||
} sony;
|
|
||||||
};
|
|
|
@ -108,10 +108,6 @@ Interface::Interface() {
|
||||||
expansionPort.devices.append(device);
|
expansionPort.devices.append(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
{ Device device{ID::Device::SuperDisc, "Super Disc"};
|
|
||||||
expansionPort.devices.append(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
{ Device device{ID::Device::S21FX, "21fx"};
|
{ Device device{ID::Device::S21FX, "21fx"};
|
||||||
expansionPort.devices.append(device);
|
expansionPort.devices.append(device);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ struct ID {
|
||||||
Justifiers,
|
Justifiers,
|
||||||
|
|
||||||
Satellaview,
|
Satellaview,
|
||||||
SuperDisc,
|
|
||||||
S21FX,
|
S21FX,
|
||||||
};};
|
};};
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,7 +52,6 @@ auto Peripherals::connect(uint port, uint device) -> void {
|
||||||
switch(device) { default:
|
switch(device) { default:
|
||||||
case ID::Device::None: expansionPort = new Expansion; break;
|
case ID::Device::None: expansionPort = new Expansion; break;
|
||||||
case ID::Device::Satellaview: expansionPort = new Satellaview; break;
|
case ID::Device::Satellaview: expansionPort = new Satellaview; break;
|
||||||
case ID::Device::SuperDisc: expansionPort = new SuperDisc; break;
|
|
||||||
case ID::Device::S21FX: expansionPort = new S21FX; break;
|
case ID::Device::S21FX: expansionPort = new S21FX; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,26 +17,24 @@ auto pDesktop::workspace() -> Geometry {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(DISPLAY_XORG)
|
#if defined(DISPLAY_XORG)
|
||||||
XlibDisplay* display = XOpenDisplay(nullptr);
|
auto display = XOpenDisplay(nullptr);
|
||||||
int screen = DefaultScreen(display);
|
int screen = DefaultScreen(display);
|
||||||
|
|
||||||
static Atom atom = XlibNone;
|
|
||||||
if(atom == XlibNone) atom = XInternAtom(display, "_NET_WORKAREA", True);
|
|
||||||
|
|
||||||
int format;
|
int format;
|
||||||
unsigned char* data = nullptr;
|
unsigned char* data = nullptr;
|
||||||
unsigned long items, after;
|
unsigned long items, after;
|
||||||
Atom returnAtom;
|
XlibAtom returnAtom;
|
||||||
|
|
||||||
int result = XGetWindowProperty(
|
int result = XGetWindowProperty(
|
||||||
display, RootWindow(display, screen), atom, 0, 4, False, XA_CARDINAL, &returnAtom, &format, &items, &after, &data
|
display, RootWindow(display, screen), XInternAtom(display, "_NET_WORKAREA", XlibTrue), 0, 4, XlibFalse,
|
||||||
|
XInternAtom(display, "CARDINAL", XlibTrue), &returnAtom, &format, &items, &after, &data
|
||||||
);
|
);
|
||||||
|
|
||||||
XCloseDisplay(display);
|
XCloseDisplay(display);
|
||||||
|
|
||||||
if(result == Success && returnAtom == XA_CARDINAL && format == 32 && items == 4) {
|
if(result == Success && returnAtom == XInternAtom(display, "CARDINAL", XlibTrue) && format == 32 && items == 4) {
|
||||||
unsigned long* workarea = (unsigned long*)data;
|
unsigned long* workarea = (unsigned long*)data;
|
||||||
return {(signed)workarea[0], (signed)workarea[1], (signed)workarea[2], (signed)workarea[3]};
|
return {(int)workarea[0], (int)workarea[1], (int)workarea[2], (int)workarea[3]};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -66,10 +66,10 @@ auto pCanvas::_rasterize() -> void {
|
||||||
qtImageHeight = height;
|
qtImageHeight = height;
|
||||||
|
|
||||||
if(!qtImage) qtImage = new QImage(width, height, QImage::Format_ARGB32);
|
if(!qtImage) qtImage = new QImage(width, height, QImage::Format_ARGB32);
|
||||||
auto buffer = (uint32*)qtImage->bits();
|
auto buffer = (uint32_t*)qtImage->bits();
|
||||||
|
|
||||||
if(auto& icon = state().icon) {
|
if(auto& icon = state().icon) {
|
||||||
memory::copy(buffer, state().icon.data(), width * height * sizeof(uint32));
|
memory::copy(buffer, state().icon.data(), width * height * sizeof(uint32_t));
|
||||||
} else if(auto& gradient = state().gradient) {
|
} else if(auto& gradient = state().gradient) {
|
||||||
auto& colors = gradient.state.colors;
|
auto& colors = gradient.state.colors;
|
||||||
image fill;
|
image fill;
|
||||||
|
@ -77,7 +77,7 @@ auto pCanvas::_rasterize() -> void {
|
||||||
fill.gradient(colors[0].value(), colors[1].value(), colors[2].value(), colors[3].value());
|
fill.gradient(colors[0].value(), colors[1].value(), colors[2].value(), colors[3].value());
|
||||||
memory::copy(buffer, fill.data(), fill.size());
|
memory::copy(buffer, fill.data(), fill.size());
|
||||||
} else {
|
} else {
|
||||||
uint32 color = state().color.value();
|
uint32_t color = state().color.value();
|
||||||
for(auto n : range(width * height)) buffer[n] = color;
|
for(auto n : range(width * height)) buffer[n] = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -39,7 +39,7 @@ struct any {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> auto operator=(const T& value) -> any& {
|
template<typename T> auto operator=(const T& value) -> any& {
|
||||||
using auto_t = type_if<is_array<T>, typename remove_extent<typename add_const<T>::type>::type*, T>;
|
using auto_t = typename conditional<is_array<T>::value, typename remove_extent<typename add_const<T>::type>::type*, T>::type;
|
||||||
|
|
||||||
if(type() == typeid(auto_t)) {
|
if(type() == typeid(auto_t)) {
|
||||||
static_cast<holder<auto_t>*>(container)->value = (auto_t)value;
|
static_cast<holder<auto_t>*>(container)->value = (auto_t)value;
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//multi-precision arithmetic
|
||||||
|
//warning: each size is quadratically more expensive than the size before it!
|
||||||
|
|
||||||
|
#include <nall/stdint.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
#include <nall/range.hpp>
|
||||||
|
#include <nall/traits.hpp>
|
||||||
|
|
||||||
|
#include <nall/arithmetic/unsigned.hpp>
|
||||||
|
|
||||||
|
#if !defined(__SIZEOF_INT128__)
|
||||||
|
#define PairBits 128
|
||||||
|
#define TypeBits 64
|
||||||
|
#define HalfBits 32
|
||||||
|
#include <nall/arithmetic/natural.hpp>
|
||||||
|
#undef PairBits
|
||||||
|
#undef TypeBits
|
||||||
|
#undef HalfBits
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PairBits 256
|
||||||
|
#define TypeBits 128
|
||||||
|
#define HalfBits 64
|
||||||
|
#include <nall/arithmetic/natural.hpp>
|
||||||
|
#undef PairBits
|
||||||
|
#undef TypeBits
|
||||||
|
#undef HalfBits
|
||||||
|
|
||||||
|
#define PairBits 512
|
||||||
|
#define TypeBits 256
|
||||||
|
#define HalfBits 128
|
||||||
|
#include <nall/arithmetic/natural.hpp>
|
||||||
|
#undef PairBits
|
||||||
|
#undef TypeBits
|
||||||
|
#undef HalfBits
|
||||||
|
|
||||||
|
#define PairBits 1024
|
||||||
|
#define TypeBits 512
|
||||||
|
#define HalfBits 256
|
||||||
|
#include <nall/arithmetic/natural.hpp>
|
||||||
|
#undef PairBits
|
||||||
|
#undef TypeBits
|
||||||
|
#undef HalfBits
|
||||||
|
|
||||||
|
#define PairBits 2048
|
||||||
|
#define TypeBits 1024
|
||||||
|
#define HalfBits 512
|
||||||
|
#include <nall/arithmetic/natural.hpp>
|
||||||
|
#undef PairBits
|
||||||
|
#undef TypeBits
|
||||||
|
#undef HalfBits
|
||||||
|
|
||||||
|
#define PairBits 4096
|
||||||
|
#define TypeBits 2048
|
||||||
|
#define HalfBits 1024
|
||||||
|
#include <nall/arithmetic/natural.hpp>
|
||||||
|
#undef PairBits
|
||||||
|
#undef TypeBits
|
||||||
|
#undef HalfBits
|
||||||
|
|
||||||
|
#define PairBits 8192
|
||||||
|
#define TypeBits 4096
|
||||||
|
#define HalfBits 2048
|
||||||
|
#include <nall/arithmetic/natural.hpp>
|
||||||
|
#undef PairBits
|
||||||
|
#undef TypeBits
|
||||||
|
#undef HalfBits
|
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
struct BarrettReduction {
|
||||||
|
BarrettReduction(uint256_t modulo) : modulo(modulo), factor((1_u1024 << 512) / modulo) {}
|
||||||
|
|
||||||
|
//return = value % modulo
|
||||||
|
inline auto operator()(uint512_t value) const -> uint256_t {
|
||||||
|
uint512_t hi, lo;
|
||||||
|
nall::mul(value, factor, hi, lo);
|
||||||
|
uint512_t remainder = value - hi * modulo;
|
||||||
|
return remainder < modulo ? remainder : remainder - modulo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const uint512_t modulo;
|
||||||
|
const uint512_t factor;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,353 @@
|
||||||
|
#define ConcatenateType(Size) uint##Size##_t
|
||||||
|
#define DeclareType(Size) ConcatenateType(Size)
|
||||||
|
|
||||||
|
#define Pair DeclareType(PairBits)
|
||||||
|
#define Type DeclareType(TypeBits)
|
||||||
|
#define Half DeclareType(HalfBits)
|
||||||
|
|
||||||
|
//pick the larger of two types to prevent unnecessary data clamping
|
||||||
|
#define Cast (typename conditional<sizeof(Pair) >= sizeof(T), Pair, T>::type)
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
//namespace Arithmetic {
|
||||||
|
|
||||||
|
struct Pair {
|
||||||
|
Pair() = default;
|
||||||
|
explicit constexpr Pair(const Pair& source) : hi(source.hi), lo(source.lo) {}
|
||||||
|
template<typename Hi, typename Lo> constexpr Pair(const Hi& hi, const Lo& lo) : hi(hi), lo(lo) {}
|
||||||
|
template<typename T> Pair(const T& source) { _set(*this, source); }
|
||||||
|
|
||||||
|
explicit operator bool() const { return hi | lo; }
|
||||||
|
template<typename T> operator T() const { T value; _get(*this, value); return value; }
|
||||||
|
|
||||||
|
auto operator~() const -> Pair { return {~hi, ~lo}; }
|
||||||
|
auto operator!() const -> bool { return !(hi || lo); }
|
||||||
|
|
||||||
|
auto operator++() -> Pair& { lo++; hi += lo == 0; return *this; }
|
||||||
|
auto operator--() -> Pair& { hi -= lo == 0; lo--; }
|
||||||
|
|
||||||
|
auto operator++(int) -> Pair { Pair r = *this; lo++; hi += lo == 0; return r; }
|
||||||
|
auto operator--(int) -> Pair { Pair r = *this; hi -= lo == 0; lo--; return r; }
|
||||||
|
|
||||||
|
auto operator* (const Pair& rhs) const -> Pair { return mul(*this, rhs); }
|
||||||
|
auto operator/ (const Pair& rhs) const -> Pair { Pair q, r; div(*this, rhs, q, r); return q; }
|
||||||
|
auto operator% (const Pair& rhs) const -> Pair { Pair q, r; div(*this, rhs, q, r); return r; }
|
||||||
|
auto operator+ (const Pair& rhs) const -> Pair { return {hi + rhs.hi + (lo + rhs.lo < lo), lo + rhs.lo}; }
|
||||||
|
auto operator- (const Pair& rhs) const -> Pair { return {hi - rhs.hi - (lo - rhs.lo > lo), lo - rhs.lo}; }
|
||||||
|
auto operator<<(const Pair& rhs) const -> Pair { return shl(*this, rhs); }
|
||||||
|
auto operator>>(const Pair& rhs) const -> Pair { return shr(*this, rhs); }
|
||||||
|
auto operator& (const Pair& rhs) const -> Pair { return {hi & rhs.hi, lo & rhs.lo}; }
|
||||||
|
auto operator| (const Pair& rhs) const -> Pair { return {hi | rhs.hi, lo | rhs.lo}; }
|
||||||
|
auto operator^ (const Pair& rhs) const -> Pair { return {hi ^ rhs.hi, lo ^ rhs.lo}; }
|
||||||
|
auto operator==(const Pair& rhs) const -> bool { return hi == rhs.hi && lo == rhs.lo; }
|
||||||
|
auto operator!=(const Pair& rhs) const -> bool { return hi != rhs.hi || lo != rhs.lo; }
|
||||||
|
auto operator>=(const Pair& rhs) const -> bool { return hi > rhs.hi || (hi == rhs.hi && lo >= rhs.lo); }
|
||||||
|
auto operator<=(const Pair& rhs) const -> bool { return hi < rhs.hi || (hi == rhs.hi && lo <= rhs.lo); }
|
||||||
|
auto operator> (const Pair& rhs) const -> bool { return hi > rhs.hi || (hi == rhs.hi && lo > rhs.lo); }
|
||||||
|
auto operator< (const Pair& rhs) const -> bool { return hi < rhs.hi || (hi == rhs.hi && lo < rhs.lo); }
|
||||||
|
|
||||||
|
template<typename T> auto& operator*= (const T& rhs) { return *this = *this * Pair(rhs); }
|
||||||
|
template<typename T> auto& operator/= (const T& rhs) { return *this = *this / Pair(rhs); }
|
||||||
|
template<typename T> auto& operator%= (const T& rhs) { return *this = *this % Pair(rhs); }
|
||||||
|
template<typename T> auto& operator+= (const T& rhs) { return *this = *this + Pair(rhs); }
|
||||||
|
template<typename T> auto& operator-= (const T& rhs) { return *this = *this - Pair(rhs); }
|
||||||
|
template<typename T> auto& operator<<=(const T& rhs) { return *this = *this << Pair(rhs); }
|
||||||
|
template<typename T> auto& operator>>=(const T& rhs) { return *this = *this >> Pair(rhs); }
|
||||||
|
template<typename T> auto& operator&= (const T& rhs) { return *this = *this & Pair(rhs); }
|
||||||
|
template<typename T> auto& operator|= (const T& rhs) { return *this = *this | Pair(rhs); }
|
||||||
|
template<typename T> auto& operator^= (const T& rhs) { return *this = *this ^ Pair(rhs); }
|
||||||
|
|
||||||
|
template<typename T> auto operator* (const T& rhs) const { return Cast(*this) * Cast(rhs); }
|
||||||
|
template<typename T> auto operator/ (const T& rhs) const { return Cast(*this) / Cast(rhs); }
|
||||||
|
template<typename T> auto operator% (const T& rhs) const { return Cast(*this) % Cast(rhs); }
|
||||||
|
template<typename T> auto operator+ (const T& rhs) const { return Cast(*this) + Cast(rhs); }
|
||||||
|
template<typename T> auto operator- (const T& rhs) const { return Cast(*this) - Cast(rhs); }
|
||||||
|
template<typename T> auto operator<<(const T& rhs) const { return Cast(*this) << Cast(rhs); }
|
||||||
|
template<typename T> auto operator>>(const T& rhs) const { return Cast(*this) >> Cast(rhs); }
|
||||||
|
template<typename T> auto operator& (const T& rhs) const { return Cast(*this) & Cast(rhs); }
|
||||||
|
template<typename T> auto operator| (const T& rhs) const { return Cast(*this) | Cast(rhs); }
|
||||||
|
template<typename T> auto operator^ (const T& rhs) const { return Cast(*this) ^ Cast(rhs); }
|
||||||
|
|
||||||
|
template<typename T> auto operator==(const T& rhs) const -> bool { return Cast(*this) == Cast(rhs); }
|
||||||
|
template<typename T> auto operator!=(const T& rhs) const -> bool { return Cast(*this) != Cast(rhs); }
|
||||||
|
template<typename T> auto operator>=(const T& rhs) const -> bool { return Cast(*this) >= Cast(rhs); }
|
||||||
|
template<typename T> auto operator<=(const T& rhs) const -> bool { return Cast(*this) <= Cast(rhs); }
|
||||||
|
template<typename T> auto operator> (const T& rhs) const -> bool { return Cast(*this) > Cast(rhs); }
|
||||||
|
template<typename T> auto operator< (const T& rhs) const -> bool { return Cast(*this) < Cast(rhs); }
|
||||||
|
|
||||||
|
explicit Pair(const vector<uint8_t>& value) : hi(0), lo(0) {
|
||||||
|
for(auto n : rrange(value)) {
|
||||||
|
operator<<=(8);
|
||||||
|
operator|=(value[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type lo;
|
||||||
|
Type hi;
|
||||||
|
|
||||||
|
friend auto upper(const Pair&) -> Type;
|
||||||
|
friend auto lower(const Pair&) -> Type;
|
||||||
|
friend auto bits(Pair) -> uint;
|
||||||
|
friend auto square(const Pair&) -> Pair;
|
||||||
|
friend auto square(const Pair&, Pair&, Pair&) -> void;
|
||||||
|
friend auto mul(const Pair&, const Pair&) -> Pair;
|
||||||
|
friend auto mul(const Pair&, const Pair&, Pair&, Pair&) -> void;
|
||||||
|
friend auto div(const Pair&, const Pair&, Pair&, Pair&) -> void;
|
||||||
|
template<typename T> friend auto shl(const Pair&, const T&) -> Pair;
|
||||||
|
template<typename T> friend auto shr(const Pair&, const T&) -> Pair;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ConcatenateUDL(Size) _u##Size
|
||||||
|
#define DeclareUDL(Size) ConcatenateUDL(Size)
|
||||||
|
|
||||||
|
alwaysinline auto operator"" DeclareUDL(PairBits)(const char* s) -> Pair {
|
||||||
|
Pair p = 0;
|
||||||
|
if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
|
||||||
|
s += 2;
|
||||||
|
while(*s) {
|
||||||
|
auto c = *s++;
|
||||||
|
if(c == '\'');
|
||||||
|
else if(c >= '0' && c <= '9') p = (p << 4) + (c - '0');
|
||||||
|
else if(c >= 'a' && c <= 'f') p = (p << 4) + (c - 'a' + 10);
|
||||||
|
else if(c >= 'A' && c <= 'F') p = (p << 4) + (c - 'A' + 10);
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while(*s) {
|
||||||
|
auto c = *s++;
|
||||||
|
if(c == '\'');
|
||||||
|
else if(c >= '0' && c <= '9') p = (p << 3) + (p << 1) + (c - '0');
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef ConcatenateUDL
|
||||||
|
#undef DeclareUDL
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto _set(Pair& lhs, const T& rhs) -> enable_if_t<(sizeof(Pair) == sizeof(T))> {
|
||||||
|
lhs = rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto _set(Pair& lhs, const T& rhs) -> enable_if_t<(sizeof(Pair) > sizeof(T))> {
|
||||||
|
lhs = {0, rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto _set(Pair& lhs, const T& rhs) -> enable_if_t<(sizeof(Pair) < sizeof(T))> {
|
||||||
|
lhs = {lower(rhs) >> TypeBits, lower(rhs)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto _get(const Pair& lhs, T& rhs) -> enable_if_t<(sizeof(T) == sizeof(Pair))> {
|
||||||
|
rhs = lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto _get(const Pair& lhs, T& rhs) -> enable_if_t<(sizeof(T) > sizeof(Pair))> {
|
||||||
|
rhs = {0, lhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto _get(const Pair& lhs, T& rhs) -> enable_if_t<(sizeof(T) < sizeof(Pair))> {
|
||||||
|
rhs = lower(lhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
alwaysinline auto upper(const Pair& value) -> Type { return value.hi; }
|
||||||
|
alwaysinline auto lower(const Pair& value) -> Type { return value.lo; }
|
||||||
|
|
||||||
|
alwaysinline auto bits(Pair value) -> uint {
|
||||||
|
if(value.hi) {
|
||||||
|
uint bits = TypeBits;
|
||||||
|
while(value.hi) value.hi >>= 1, bits++;
|
||||||
|
return bits;
|
||||||
|
} else {
|
||||||
|
uint bits = 0;
|
||||||
|
while(value.lo) value.lo >>= 1, bits++;
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bits * Bits => Bits
|
||||||
|
inline auto square(const Pair& lhs) -> Pair {
|
||||||
|
static const Type Mask = (Type(0) - 1) >> HalfBits;
|
||||||
|
Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
|
||||||
|
Type dd = square(d), dc = d * c, db = d * b, da = d * a;
|
||||||
|
Type cc = square(c), cb = c * b;
|
||||||
|
|
||||||
|
Pair r0 = Pair(dd);
|
||||||
|
Pair r1 = Pair(dc) + Pair(dc) + Pair(r0 >> HalfBits);
|
||||||
|
Pair r2 = Pair(db) + Pair(cc) + Pair(db) + Pair(r1 >> HalfBits);
|
||||||
|
Pair r3 = Pair(da) + Pair(cb) + Pair(cb) + Pair(da) + Pair(r2 >> HalfBits);
|
||||||
|
|
||||||
|
return {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bits * Bits => 2 * Bits
|
||||||
|
inline auto square(const Pair& lhs, Pair& hi, Pair& lo) -> void {
|
||||||
|
static const Type Mask = (Type(0) - 1) >> HalfBits;
|
||||||
|
Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
|
||||||
|
Type dd = square(d), dc = d * c, db = d * b, da = d * a;
|
||||||
|
Type cc = square(c), cb = c * b, ca = c * a;
|
||||||
|
Type bb = square(b), ba = b * a;
|
||||||
|
Type aa = square(a);
|
||||||
|
|
||||||
|
Pair r0 = Pair(dd);
|
||||||
|
Pair r1 = Pair(dc) + Pair(dc) + Pair(r0 >> HalfBits);
|
||||||
|
Pair r2 = Pair(db) + Pair(cc) + Pair(db) + Pair(r1 >> HalfBits);
|
||||||
|
Pair r3 = Pair(da) + Pair(cb) + Pair(cb) + Pair(da) + Pair(r2 >> HalfBits);
|
||||||
|
Pair r4 = Pair(ca) + Pair(bb) + Pair(ca) + Pair(r3 >> HalfBits);
|
||||||
|
Pair r5 = Pair(ba) + Pair(ba) + Pair(r4 >> HalfBits);
|
||||||
|
Pair r6 = Pair(aa) + Pair(r5 >> HalfBits);
|
||||||
|
Pair r7 = Pair(r6 >> HalfBits);
|
||||||
|
|
||||||
|
hi = {(r7.lo & Mask) << HalfBits | (r6.lo & Mask), (r5.lo & Mask) << HalfBits | (r4.lo & Mask)};
|
||||||
|
lo = {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bits * Bits => Bits
|
||||||
|
alwaysinline auto mul(const Pair& lhs, const Pair& rhs) -> Pair {
|
||||||
|
static const Type Mask = (Type(0) - 1) >> HalfBits;
|
||||||
|
Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
|
||||||
|
Type e = rhs.hi >> HalfBits, f = rhs.hi & Mask, g = rhs.lo >> HalfBits, h = rhs.lo & Mask;
|
||||||
|
|
||||||
|
Pair r0 = Pair(d * h);
|
||||||
|
Pair r1 = Pair(c * h) + Pair(d * g) + Pair(r0 >> HalfBits);
|
||||||
|
Pair r2 = Pair(b * h) + Pair(c * g) + Pair(d * f) + Pair(r1 >> HalfBits);
|
||||||
|
Pair r3 = Pair(a * h) + Pair(b * g) + Pair(c * f) + Pair(d * e) + Pair(r2 >> HalfBits);
|
||||||
|
|
||||||
|
return {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bits * Bits => 2 * Bits
|
||||||
|
alwaysinline auto mul(const Pair& lhs, const Pair& rhs, Pair& hi, Pair& lo) -> void {
|
||||||
|
static const Type Mask = (Type(0) - 1) >> HalfBits;
|
||||||
|
Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
|
||||||
|
Type e = rhs.hi >> HalfBits, f = rhs.hi & Mask, g = rhs.lo >> HalfBits, h = rhs.lo & Mask;
|
||||||
|
|
||||||
|
Pair r0 = Pair(d * h);
|
||||||
|
Pair r1 = Pair(c * h) + Pair(d * g) + Pair(r0 >> HalfBits);
|
||||||
|
Pair r2 = Pair(b * h) + Pair(c * g) + Pair(d * f) + Pair(r1 >> HalfBits);
|
||||||
|
Pair r3 = Pair(a * h) + Pair(b * g) + Pair(c * f) + Pair(d * e) + Pair(r2 >> HalfBits);
|
||||||
|
Pair r4 = Pair(a * g) + Pair(b * f) + Pair(c * e) + Pair(r3 >> HalfBits);
|
||||||
|
Pair r5 = Pair(a * f) + Pair(b * e) + Pair(r4 >> HalfBits);
|
||||||
|
Pair r6 = Pair(a * e) + Pair(r5 >> HalfBits);
|
||||||
|
Pair r7 = Pair(r6 >> HalfBits);
|
||||||
|
|
||||||
|
hi = {(r7.lo & Mask) << HalfBits | (r6.lo & Mask), (r5.lo & Mask) << HalfBits | (r4.lo & Mask)};
|
||||||
|
lo = {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
|
||||||
|
}
|
||||||
|
|
||||||
|
alwaysinline auto div(const Pair& lhs, const Pair& rhs, Pair& quotient, Pair& remainder) -> void {
|
||||||
|
if(!rhs) throw std::runtime_error("division by zero");
|
||||||
|
quotient = 0, remainder = lhs;
|
||||||
|
if(!lhs || lhs < rhs) return;
|
||||||
|
|
||||||
|
auto count = bits(lhs) - bits(rhs);
|
||||||
|
Pair x = rhs << count;
|
||||||
|
Pair y = Pair(1) << count;
|
||||||
|
if(x > remainder) x >>= 1, y >>= 1;
|
||||||
|
while(remainder >= rhs) {
|
||||||
|
if(remainder >= x) remainder -= x, quotient |= y;
|
||||||
|
x >>= 1, y >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto shl(const Pair& lhs, const T& rhs) -> Pair {
|
||||||
|
if(!rhs) return lhs;
|
||||||
|
auto shift = (uint)rhs;
|
||||||
|
if(shift < TypeBits) {
|
||||||
|
return {lhs.hi << shift | lhs.lo >> (TypeBits - shift), lhs.lo << shift};
|
||||||
|
} else {
|
||||||
|
return {lhs.lo << (shift - TypeBits), 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto shr(const Pair& lhs, const T& rhs) -> Pair {
|
||||||
|
if(!rhs) return lhs;
|
||||||
|
auto shift = (uint)rhs;
|
||||||
|
if(shift < TypeBits) {
|
||||||
|
return {lhs.hi >> shift, lhs.hi << (TypeBits - shift) | lhs.lo >> shift};
|
||||||
|
} else {
|
||||||
|
return {0, lhs.hi >> (shift - TypeBits)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto rol(const Pair& lhs, const T& rhs) -> Pair {
|
||||||
|
return lhs << rhs | lhs >> (PairBits - rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto ror(const Pair& lhs, const T& rhs) -> Pair {
|
||||||
|
return lhs >> rhs | lhs << (PairBits - rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define EI enable_if_t<is_integral<T>::value>
|
||||||
|
|
||||||
|
template<typename T, EI> auto& operator*= (T& lhs, const Pair& rhs) { return lhs = lhs * T(rhs); }
|
||||||
|
template<typename T, EI> auto& operator/= (T& lhs, const Pair& rhs) { return lhs = lhs / T(rhs); }
|
||||||
|
template<typename T, EI> auto& operator%= (T& lhs, const Pair& rhs) { return lhs = lhs % T(rhs); }
|
||||||
|
template<typename T, EI> auto& operator+= (T& lhs, const Pair& rhs) { return lhs = lhs + T(rhs); }
|
||||||
|
template<typename T, EI> auto& operator-= (T& lhs, const Pair& rhs) { return lhs = lhs - T(rhs); }
|
||||||
|
template<typename T, EI> auto& operator<<=(T& lhs, const Pair& rhs) { return lhs = lhs << T(rhs); }
|
||||||
|
template<typename T, EI> auto& operator>>=(T& lhs, const Pair& rhs) { return lhs = lhs >> T(rhs); }
|
||||||
|
template<typename T, EI> auto& operator&= (T& lhs, const Pair& rhs) { return lhs = lhs & T(rhs); }
|
||||||
|
template<typename T, EI> auto& operator|= (T& lhs, const Pair& rhs) { return lhs = lhs | T(rhs); }
|
||||||
|
template<typename T, EI> auto& operator^= (T& lhs, const Pair& rhs) { return lhs = lhs ^ T(rhs); }
|
||||||
|
|
||||||
|
template<typename T, EI> auto operator* (const T& lhs, const Pair& rhs) { return Cast(lhs) * Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator/ (const T& lhs, const Pair& rhs) { return Cast(lhs) / Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator% (const T& lhs, const Pair& rhs) { return Cast(lhs) % Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator+ (const T& lhs, const Pair& rhs) { return Cast(lhs) + Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator- (const T& lhs, const Pair& rhs) { return Cast(lhs) - Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator<<(const T& lhs, const Pair& rhs) { return Cast(lhs) << Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator>>(const T& lhs, const Pair& rhs) { return Cast(lhs) >> Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator& (const T& lhs, const Pair& rhs) { return Cast(lhs) & Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator| (const T& lhs, const Pair& rhs) { return Cast(lhs) | Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator^ (const T& lhs, const Pair& rhs) { return Cast(lhs) ^ Cast(rhs); }
|
||||||
|
|
||||||
|
template<typename T, EI> auto operator==(const T& lhs, const Pair& rhs) { return Cast(lhs) == Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator!=(const T& lhs, const Pair& rhs) { return Cast(lhs) != Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator>=(const T& lhs, const Pair& rhs) { return Cast(lhs) >= Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator<=(const T& lhs, const Pair& rhs) { return Cast(lhs) <= Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator> (const T& lhs, const Pair& rhs) { return Cast(lhs) > Cast(rhs); }
|
||||||
|
template<typename T, EI> auto operator< (const T& lhs, const Pair& rhs) { return Cast(lhs) < Cast(rhs); }
|
||||||
|
|
||||||
|
#undef EI
|
||||||
|
|
||||||
|
template<> struct stringify<Pair> {
|
||||||
|
stringify(Pair source) {
|
||||||
|
char _output[1 + sizeof(Pair) * 3];
|
||||||
|
auto p = (char*)&_output;
|
||||||
|
do {
|
||||||
|
Pair quotient, remainder;
|
||||||
|
div(source, 10, quotient, remainder);
|
||||||
|
*p++ = '0' + remainder;
|
||||||
|
source = quotient;
|
||||||
|
} while(source);
|
||||||
|
_size = p - _output;
|
||||||
|
*p = 0;
|
||||||
|
for(int x = _size - 1, y = 0; x >= 0 && y < _size; x--, y++) _data[x] = _output[y];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data() const -> const char* { return _data; }
|
||||||
|
auto size() const -> uint { return _size; }
|
||||||
|
char _data[1 + sizeof(Pair) * 3];
|
||||||
|
uint _size;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline auto to_vector(Pair value) -> vector<uint8_t> {
|
||||||
|
vector<uint8_t> result;
|
||||||
|
result.resize(PairBits / 8);
|
||||||
|
for(auto& byte : result) {
|
||||||
|
byte = value;
|
||||||
|
value >>= 8;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef ConcatenateType
|
||||||
|
#undef DeclareType
|
||||||
|
#undef Pair
|
||||||
|
#undef Type
|
||||||
|
#undef Half
|
||||||
|
#undef Cast
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
template<typename T, enable_if_t<is_unsigned<T>::value>> alwaysinline auto upper(T value) -> T {
|
||||||
|
return value >> sizeof(T) * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, enable_if_t<is_unsigned<T>::value>> alwaysinline auto lower(T value) -> T {
|
||||||
|
static const T Mask = T(0) - 1 >> sizeof(T) * 4;
|
||||||
|
return value & Mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
alwaysinline auto square(uintmax value) -> uintmax {
|
||||||
|
return value * value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U> alwaysinline auto rol(const T& lhs, const U& rhs, enable_if_t<is_unsigned<T>::value>* = 0) -> T {
|
||||||
|
return lhs << rhs | lhs >> (sizeof(T) * 8 - rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U> alwaysinline auto ror(const T& lhs, const U& rhs, enable_if_t<is_unsigned<T>::value>* = 0) -> T {
|
||||||
|
return lhs >> rhs | lhs << (sizeof(T) * 8 - rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if INTMAX_BITS >= 128
|
||||||
|
inline auto operator"" _u128(const char* s) -> uint128_t {
|
||||||
|
uint128_t p = 0;
|
||||||
|
while(*s) {
|
||||||
|
auto c = *s++;
|
||||||
|
if(c == '\'') continue;
|
||||||
|
if(c < '0' || c > '9') break;
|
||||||
|
p = (p << 3) + (p << 1) + (c - '0');
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
|
@ -42,14 +42,14 @@ auto Archive::create(const string& beatname, const string& pathname, const strin
|
||||||
auto size = input.size();
|
auto size = input.size();
|
||||||
beat.writevu(size);
|
beat.writevu(size);
|
||||||
while(size--) beat.write(input.read());
|
while(size--) beat.write(input.read());
|
||||||
beat.writel(input.checksum.value(), 4);
|
beat.writel(input.checksum.digest().hex(), 4);
|
||||||
} else {
|
} else {
|
||||||
beat.writevu(0);
|
beat.writevu(0);
|
||||||
beat.writel(0x00000000, 4);
|
beat.writel(0x00000000, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
beat.writel(beat.checksum.value(), 4);
|
beat.writel(beat.checksum.digest().hex(), 4);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,11 +82,11 @@ auto Archive::unpack(const string& beatname, const string& pathname) -> bool {
|
||||||
|
|
||||||
auto size = beat.readvu();
|
auto size = beat.readvu();
|
||||||
while(size--) output.write(beat.read());
|
while(size--) output.write(beat.read());
|
||||||
if(beat.readl(4) != output.checksum.value()) return false;
|
if(beat.readl(4) != output.checksum.digest().hex()) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t checksum = beat.checksum.value();
|
uint32_t checksum = beat.checksum.digest().hex();
|
||||||
return beat.readl(4) == checksum;
|
return beat.readl(4) == checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ auto Archive::extract(const string& beatname, const string& filename) -> vector<
|
||||||
result.resize(size);
|
result.resize(size);
|
||||||
beat.checksum.reset();
|
beat.checksum.reset();
|
||||||
for(auto n : range(size)) result[n] = beat.read();
|
for(auto n : range(size)) result[n] = beat.read();
|
||||||
uint32_t checksum = beat.checksum.value();
|
uint32_t checksum = beat.checksum.digest().hex();
|
||||||
if(beat.readl(4) != checksum) return {};
|
if(beat.readl(4) != checksum) return {};
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ auto bpsdelta::create(const string& filename, const string& metadata) -> bool {
|
||||||
|
|
||||||
auto write = [&](uint8_t data) {
|
auto write = [&](uint8_t data) {
|
||||||
modifyFile.write(data);
|
modifyFile.write(data);
|
||||||
modifyChecksum.data(data);
|
modifyChecksum.input(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto encode = [&](uint64_t data) {
|
auto encode = [&](uint64_t data) {
|
||||||
|
@ -102,7 +102,7 @@ auto bpsdelta::create(const string& filename, const string& metadata) -> bool {
|
||||||
//source tree creation
|
//source tree creation
|
||||||
for(uint offset = 0; offset < sourceSize; offset++) {
|
for(uint offset = 0; offset < sourceSize; offset++) {
|
||||||
uint16_t symbol = sourceData[offset + 0];
|
uint16_t symbol = sourceData[offset + 0];
|
||||||
sourceChecksum.data(symbol);
|
sourceChecksum.input(symbol);
|
||||||
if(offset < sourceSize - 1) symbol |= sourceData[offset + 1] << 8;
|
if(offset < sourceSize - 1) symbol |= sourceData[offset + 1] << 8;
|
||||||
Node *node = new Node;
|
Node *node = new Node;
|
||||||
node->offset = offset;
|
node->offset = offset;
|
||||||
|
@ -198,10 +198,10 @@ auto bpsdelta::create(const string& filename, const string& metadata) -> bool {
|
||||||
|
|
||||||
targetReadFlush();
|
targetReadFlush();
|
||||||
|
|
||||||
for(uint n = 0; n < 32; n += 8) write(sourceChecksum.value() >> n);
|
for(uint n = 0; n < 32; n += 8) write(sourceChecksum.digest().hex() >> n);
|
||||||
uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).value();
|
uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).digest().hex();
|
||||||
for(uint n = 0; n < 32; n += 8) write(targetChecksum >> n);
|
for(uint n = 0; n < 32; n += 8) write(targetChecksum >> n);
|
||||||
uint32_t outputChecksum = modifyChecksum.value();
|
uint32_t outputChecksum = modifyChecksum.digest().hex();
|
||||||
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
|
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
|
||||||
|
|
||||||
modifyFile.close();
|
modifyFile.close();
|
||||||
|
|
|
@ -11,12 +11,12 @@ struct File : file {
|
||||||
|
|
||||||
auto File::read() -> uint8_t {
|
auto File::read() -> uint8_t {
|
||||||
uint8_t data = file::read();
|
uint8_t data = file::read();
|
||||||
checksum.data(data);
|
checksum.input(data);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto File::write(uint8_t data) -> void {
|
auto File::write(uint8_t data) -> void {
|
||||||
checksum.data(data);
|
checksum.input(data);
|
||||||
return file::write(data);
|
return file::write(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ auto bpslinear::create(const string& filename, const string& metadata) -> bool {
|
||||||
|
|
||||||
auto write = [&](uint8_t data) {
|
auto write = [&](uint8_t data) {
|
||||||
modifyFile.write(data);
|
modifyFile.write(data);
|
||||||
modifyChecksum.data(data);
|
modifyChecksum.input(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto encode = [&](uint64_t data) {
|
auto encode = [&](uint64_t data) {
|
||||||
|
@ -134,11 +134,11 @@ auto bpslinear::create(const string& filename, const string& metadata) -> bool {
|
||||||
|
|
||||||
targetReadFlush();
|
targetReadFlush();
|
||||||
|
|
||||||
uint32_t sourceChecksum = Hash::CRC32(sourceData, sourceSize).value();
|
uint32_t sourceChecksum = Hash::CRC32(sourceData, sourceSize).digest().hex();
|
||||||
for(uint n = 0; n < 32; n += 8) write(sourceChecksum >> n);
|
for(uint n = 0; n < 32; n += 8) write(sourceChecksum >> n);
|
||||||
uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).value();
|
uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).digest().hex();
|
||||||
for(uint n = 0; n < 32; n += 8) write(targetChecksum >> n);
|
for(uint n = 0; n < 32; n += 8) write(targetChecksum >> n);
|
||||||
uint32_t outputChecksum = modifyChecksum.value();
|
uint32_t outputChecksum = modifyChecksum.digest().hex();
|
||||||
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
|
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
|
||||||
|
|
||||||
modifyFile.close();
|
modifyFile.close();
|
||||||
|
|
|
@ -77,7 +77,7 @@ auto bpsmetadata::save(const string& filename, const string& metadata) -> bool {
|
||||||
|
|
||||||
auto write = [&](uint8_t data) {
|
auto write = [&](uint8_t data) {
|
||||||
targetFile.write(data);
|
targetFile.write(data);
|
||||||
checksum.data(data);
|
checksum.input(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto encode = [&](uint64_t data) {
|
auto encode = [&](uint64_t data) {
|
||||||
|
@ -103,7 +103,7 @@ auto bpsmetadata::save(const string& filename, const string& metadata) -> bool {
|
||||||
for(uint n = 0; n < targetLength; n++) write(metadata[n]);
|
for(uint n = 0; n < targetLength; n++) write(metadata[n]);
|
||||||
uint length = sourceFile.size() - sourceFile.offset() - 4;
|
uint length = sourceFile.size() - sourceFile.offset() - 4;
|
||||||
for(uint n = 0; n < length; n++) write(read());
|
for(uint n = 0; n < length; n++) write(read());
|
||||||
uint32_t outputChecksum = checksum.value();
|
uint32_t outputChecksum = checksum.digest().hex();
|
||||||
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
|
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
|
||||||
|
|
||||||
targetFile.close();
|
targetFile.close();
|
||||||
|
|
|
@ -48,14 +48,14 @@ struct bpsmulti {
|
||||||
for(uint n = 0; n < sp.size(); n++) {
|
for(uint n = 0; n < sp.size(); n++) {
|
||||||
uint8_t byte = sp.read();
|
uint8_t byte = sp.read();
|
||||||
if(identical && byte != dp.read()) identical = false;
|
if(identical && byte != dp.read()) identical = false;
|
||||||
cksum.data(byte);
|
cksum.input(byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(identical) {
|
if(identical) {
|
||||||
writeNumber(MirrorFile | ((targetName.length() - 1) << 2));
|
writeNumber(MirrorFile | ((targetName.length() - 1) << 2));
|
||||||
writeString(targetName);
|
writeString(targetName);
|
||||||
writeNumber(OriginSource);
|
writeNumber(OriginSource);
|
||||||
writeChecksum(cksum.value());
|
writeChecksum(cksum.digest().hex());
|
||||||
} else {
|
} else {
|
||||||
writeNumber(ModifyFile | ((targetName.length() - 1) << 2));
|
writeNumber(ModifyFile | ((targetName.length() - 1) << 2));
|
||||||
writeString(targetName);
|
writeString(targetName);
|
||||||
|
@ -83,12 +83,12 @@ struct bpsmulti {
|
||||||
auto buffer = file::read({targetPath, targetName});
|
auto buffer = file::read({targetPath, targetName});
|
||||||
writeNumber(buffer.size());
|
writeNumber(buffer.size());
|
||||||
for(auto& byte : buffer) write(byte);
|
for(auto& byte : buffer) write(byte);
|
||||||
writeChecksum(Hash::CRC32(buffer.data(), buffer.size()).value());
|
writeChecksum(Hash::CRC32(buffer.data(), buffer.size()).digest().hex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//checksum
|
//checksum
|
||||||
writeChecksum(checksum.value());
|
writeChecksum(checksum.digest().hex());
|
||||||
fp.close();
|
fp.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ struct bpsmulti {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t cksum = checksum.value();
|
uint32_t cksum = checksum.digest().hex();
|
||||||
if(read() != (uint8_t)(cksum >> 0)) return false;
|
if(read() != (uint8_t)(cksum >> 0)) return false;
|
||||||
if(read() != (uint8_t)(cksum >> 8)) return false;
|
if(read() != (uint8_t)(cksum >> 8)) return false;
|
||||||
if(read() != (uint8_t)(cksum >> 16)) return false;
|
if(read() != (uint8_t)(cksum >> 16)) return false;
|
||||||
|
@ -171,7 +171,7 @@ protected:
|
||||||
|
|
||||||
auto write(uint8_t data) -> void {
|
auto write(uint8_t data) -> void {
|
||||||
fp.write(data);
|
fp.write(data);
|
||||||
checksum.data(data);
|
checksum.input(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto writeNumber(uint64_t data) -> void {
|
auto writeNumber(uint64_t data) -> void {
|
||||||
|
@ -202,7 +202,7 @@ protected:
|
||||||
//apply() functions
|
//apply() functions
|
||||||
auto read() -> uint8_t {
|
auto read() -> uint8_t {
|
||||||
uint8_t data = fp.read();
|
uint8_t data = fp.read();
|
||||||
checksum.data(data);
|
checksum.input(data);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ auto bpspatch::apply() -> result {
|
||||||
|
|
||||||
auto read = [&]() -> uint8_t {
|
auto read = [&]() -> uint8_t {
|
||||||
uint8_t data = modifyData[modifyOffset++];
|
uint8_t data = modifyData[modifyOffset++];
|
||||||
modifyChecksum.data(data);
|
modifyChecksum.input(data);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ auto bpspatch::apply() -> result {
|
||||||
|
|
||||||
auto write = [&](uint8_t data) {
|
auto write = [&](uint8_t data) {
|
||||||
targetData[outputOffset++] = data;
|
targetData[outputOffset++] = data;
|
||||||
targetChecksum.data(data);
|
targetChecksum.input(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
if(read() != 'B') return result::patch_invalid_header;
|
if(read() != 'B') return result::patch_invalid_header;
|
||||||
|
@ -199,13 +199,13 @@ auto bpspatch::apply() -> result {
|
||||||
uint32_t modifySourceChecksum = 0, modifyTargetChecksum = 0, modifyModifyChecksum = 0;
|
uint32_t modifySourceChecksum = 0, modifyTargetChecksum = 0, modifyModifyChecksum = 0;
|
||||||
for(uint n = 0; n < 32; n += 8) modifySourceChecksum |= read() << n;
|
for(uint n = 0; n < 32; n += 8) modifySourceChecksum |= read() << n;
|
||||||
for(uint n = 0; n < 32; n += 8) modifyTargetChecksum |= read() << n;
|
for(uint n = 0; n < 32; n += 8) modifyTargetChecksum |= read() << n;
|
||||||
uint32_t checksum = modifyChecksum.value();
|
uint32_t checksum = modifyChecksum.digest().hex();
|
||||||
for(uint n = 0; n < 32; n += 8) modifyModifyChecksum |= read() << n;
|
for(uint n = 0; n < 32; n += 8) modifyModifyChecksum |= read() << n;
|
||||||
|
|
||||||
uint32_t sourceChecksum = Hash::CRC32(sourceData, modifySourceSize).value();
|
uint32_t sourceChecksum = Hash::CRC32(sourceData, modifySourceSize).digest().hex();
|
||||||
|
|
||||||
if(sourceChecksum != modifySourceChecksum) return result::source_checksum_invalid;
|
if(sourceChecksum != modifySourceChecksum) return result::source_checksum_invalid;
|
||||||
if(targetChecksum.value() != modifyTargetChecksum) return result::target_checksum_invalid;
|
if(targetChecksum.digest().hex() != modifyTargetChecksum) return result::target_checksum_invalid;
|
||||||
if(checksum != modifyModifyChecksum) return result::patch_checksum_invalid;
|
if(checksum != modifyModifyChecksum) return result::patch_checksum_invalid;
|
||||||
|
|
||||||
return result::success;
|
return result::success;
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIByTCCAU6gAwIBAgIJAMGBxB7ujnmaMAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
|
|
||||||
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwOTExMTM1MjE3WhgPMjA5MTA4MjQx
|
|
||||||
MzUyMTdaMB4xDTALBgNVBAMMBGJ5dXUxDTALBgNVBAoMBGJ5dXUwdjAQBgcqhkjO
|
|
||||||
PQIBBgUrgQQAIgNiAATgdIzJOkXMo3vfw+wshinYYt76IAox5sRcXYfbkTHZ5dGU
|
|
||||||
Sf/DlrCe/kTIhXe6mKUI6eUjPH7U5UruvHtwi6I7QILHoar1tp4rVGKp7mB3KuIS
|
|
||||||
qfuu90JhXMfUcwQp3WOjVjBUMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE
|
|
||||||
FKD7mEF6/bmtxOUSu05E0iYjRCrJMB8GA1UdIwQYMBaAFKD7mEF6/bmtxOUSu05E
|
|
||||||
0iYjRCrJMAoGCCqGSM49BAMDA2kAMGYCMQD3Nv8o4qbHOZUd8GUh4ye6Y08WkJ2w
|
|
||||||
8BZWTJFzAp+4nP9XZJeROQJd97+kQOCdLAICMQC2DtybVIQXaxefAaGi7IvtYcbL
|
|
||||||
fAWdtu5/dc7bzMpy9GicQkpw8uluxauX8gdnU/4=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,13 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIB6jCCAXCgAwIBAgIJAOrEeJHQ9mppMAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
|
|
||||||
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwOTExMTM1NDIwWhgPMjA5MTA4MjQx
|
|
||||||
MzU0MjBaMCIxETAPBgNVBAMMCGJ5dXUubmV0MQ0wCwYDVQQKDARieXV1MHYwEAYH
|
|
||||||
KoZIzj0CAQYFK4EEACIDYgAEL4l9yJtcslBRuaTr7wHJ/Wc7DIspKGv2S2+LYsxE
|
|
||||||
k3dZI902+J726IX2yiurWlLUEc3B+ooKs3VmhaW1QsStKdYVJVVGBD29zz3rvD/V
|
|
||||||
oeWjw63yZrSqNQ5S41qXNcMho3QwcjAMBgNVHRMBAf8EAjAAMCIGA1UdEQEB/wQY
|
|
||||||
MBaCCGJ5dXUubmV0ggoqLmJ5dXUubmV0MB0GA1UdDgQWBBTeXV7JKLjCikQbk+Um
|
|
||||||
ayFF8yRiSTAfBgNVHSMEGDAWgBSg+5hBev25rcTlErtORNImI0QqyTAKBggqhkjO
|
|
||||||
PQQDAwNoADBlAjEAgk0ud6h0OAfWNH6pSvMiyHAWQuh24cvkQY3mUNsZzAy36QEQ
|
|
||||||
X4UBWewxz1lyaFzLAjACXJZ1rZsMnGIgWXvFAsO2v53A612Ba3vH76naExASKbmx
|
|
||||||
VafrFb6bHXEc3aH/Xws=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,13 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIB6jCCAXCgAwIBAgIJAOrEeJHQ9mpoMAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
|
|
||||||
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwOTExMTM1MzU1WhgPMjA5MTA4MjQx
|
|
||||||
MzUzNTVaMCIxETAPBgNVBAMMCGJ5dXUub3JnMQ0wCwYDVQQKDARieXV1MHYwEAYH
|
|
||||||
KoZIzj0CAQYFK4EEACIDYgAEH+ny1an5De9P1TJ0vmpGlpmrZszuV1lKTPut28Vx
|
|
||||||
98ieuBdmSNG493sJ+ga+adXPtItkck5M0jITR1NxcWvVlZtJG8L6ctEuVF6smkoy
|
|
||||||
1dbxzEeTIs+xjRQqaLN4U67ho3QwcjAMBgNVHRMBAf8EAjAAMCIGA1UdEQEB/wQY
|
|
||||||
MBaCCGJ5dXUub3JnggoqLmJ5dXUub3JnMB0GA1UdDgQWBBRhhKSsc+qUaBUNiyJX
|
|
||||||
j17UDBFuuTAfBgNVHSMEGDAWgBSg+5hBev25rcTlErtORNImI0QqyTAKBggqhkjO
|
|
||||||
PQQDAwNoADBlAjEApEbI/wT/cU7DRFvBEmfFMtVDJCJCTz4UEo1lJI9SPOEtgX3x
|
|
||||||
gJZg4deqeoAEffVGAjB2RWI1UPi/jnpJwTsuw4sp5UqFhY48qfqddPiSO4qlmb8s
|
|
||||||
1aEdP6gHoji22pHrKbY=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/arithmetic.hpp>
|
||||||
|
|
||||||
|
namespace nall { namespace Cipher {
|
||||||
|
|
||||||
|
struct ChaCha20 {
|
||||||
|
auto initialize(uint256_t key, uint64_t nonce, uint64_t counter = 0) -> void {
|
||||||
|
static const uint256_t sigma = 0x6b20657479622d323320646e61707865_u256; //"expand 32-byte k"
|
||||||
|
|
||||||
|
input[ 0] = sigma >> 0;
|
||||||
|
input[ 1] = sigma >> 32;
|
||||||
|
input[ 2] = sigma >> 64;
|
||||||
|
input[ 3] = sigma >> 96;
|
||||||
|
input[ 4] = key >> 0;
|
||||||
|
input[ 5] = key >> 32;
|
||||||
|
input[ 6] = key >> 64;
|
||||||
|
input[ 7] = key >> 96;
|
||||||
|
input[ 8] = key >> 128;
|
||||||
|
input[ 9] = key >> 160;
|
||||||
|
input[10] = key >> 192;
|
||||||
|
input[11] = key >> 224;
|
||||||
|
input[12] = counter >> 0;
|
||||||
|
input[13] = counter >> 32;
|
||||||
|
input[14] = nonce >> 0;
|
||||||
|
input[15] = nonce >> 32;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto encrypt(const uint8_t* input, uint8_t* output, uint64_t length) -> void {
|
||||||
|
while(length--) {
|
||||||
|
if(!offset) cipher();
|
||||||
|
auto byte = offset++;
|
||||||
|
*output++ = *input++ ^ (block[byte >> 2] >> (byte & 3) * 8);
|
||||||
|
offset &= 63;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto decrypt(const uint8_t* input, uint8_t* output, uint64_t length) -> void {
|
||||||
|
encrypt(input, output, length); //reciprocal cipher
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline auto rol(uint32_t value, uint bits) -> uint32_t {
|
||||||
|
return value << bits | value >> (32 - bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto quarterRound(uint32_t x[16], uint a, uint b, uint c, uint d) -> void {
|
||||||
|
x[a] += x[b]; x[d] = rol(x[d] ^ x[a], 16);
|
||||||
|
x[c] += x[d]; x[b] = rol(x[b] ^ x[c], 12);
|
||||||
|
x[a] += x[b]; x[d] = rol(x[d] ^ x[a], 8);
|
||||||
|
x[c] += x[d]; x[b] = rol(x[b] ^ x[c], 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cipher() -> void {
|
||||||
|
memory::copy(block, input, 64);
|
||||||
|
for(auto n : range(10)) {
|
||||||
|
quarterRound(block, 0, 4, 8, 12);
|
||||||
|
quarterRound(block, 1, 5, 9, 13);
|
||||||
|
quarterRound(block, 2, 6, 10, 14);
|
||||||
|
quarterRound(block, 3, 7, 11, 15);
|
||||||
|
quarterRound(block, 0, 5, 10, 15);
|
||||||
|
quarterRound(block, 1, 6, 11, 12);
|
||||||
|
quarterRound(block, 2, 7, 8, 13);
|
||||||
|
quarterRound(block, 3, 4, 9, 14);
|
||||||
|
}
|
||||||
|
for(auto n : range(16)) {
|
||||||
|
block[n] += input[n];
|
||||||
|
}
|
||||||
|
if(!++input[12]) ++input[13];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t input[16];
|
||||||
|
uint32_t block[16];
|
||||||
|
uint64_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/arithmetic.hpp>
|
||||||
|
|
||||||
|
namespace nall { namespace Decode {
|
||||||
|
|
||||||
|
template<typename T> inline auto Base57(const string& value) -> T {
|
||||||
|
T result = 0;
|
||||||
|
for(auto n : rrange(value.size())) {
|
||||||
|
auto byte = value[n];
|
||||||
|
if(byte >= '2' && byte <= '9') byte -= '2' - 0;
|
||||||
|
else if(byte >= 'A' && byte <= 'H') byte -= 'A' - 8;
|
||||||
|
else if(byte >= 'J' && byte <= 'N') byte -= 'J' - 16;
|
||||||
|
else if(byte >= 'P' && byte <= 'Z') byte -= 'P' - 21;
|
||||||
|
else if(byte >= 'a' && byte <= 'k') byte -= 'a' - 32;
|
||||||
|
else if(byte >= 'm' && byte <= 'z') byte -= 'm' - 43;
|
||||||
|
else return 0;
|
||||||
|
result = result * 57 + byte;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
|
@ -5,13 +5,19 @@ namespace nall { namespace Decode {
|
||||||
//returns empty string on malformed content
|
//returns empty string on malformed content
|
||||||
inline auto URL(const string& input) -> string {
|
inline auto URL(const string& input) -> string {
|
||||||
string output;
|
string output;
|
||||||
for(unsigned n = 0; n < input.size();) {
|
for(uint n = 0; n < input.size();) {
|
||||||
char c = input[n];
|
char c = input[n];
|
||||||
|
|
||||||
|
//unreserved characters
|
||||||
if(c >= 'A' && c <= 'Z') { output.append(c); n++; continue; }
|
if(c >= 'A' && c <= 'Z') { output.append(c); n++; continue; }
|
||||||
if(c >= 'a' && c <= 'z') { output.append(c); n++; continue; }
|
if(c >= 'a' && c <= 'z') { output.append(c); n++; continue; }
|
||||||
if(c >= '0' && c <= '9') { output.append(c); n++; continue; }
|
if(c >= '0' && c <= '9') { output.append(c); n++; continue; }
|
||||||
if(c == '-' || c == '_' || c == '.' || c == '~') { output.append(c); n++; continue; }
|
if(c == '-' || c == '_' || c == '.' || c == '~') { output.append(c); n++; continue; }
|
||||||
|
|
||||||
|
//special characters
|
||||||
if(c == '+') { output.append(' '); n++; continue; }
|
if(c == '+') { output.append(' '); n++; continue; }
|
||||||
|
|
||||||
|
//reserved characters
|
||||||
if(c != '%' || n + 2 >= input.size()) return "";
|
if(c != '%' || n + 2 >= input.size()) return "";
|
||||||
char hi = input[n + 1];
|
char hi = input[n + 1];
|
||||||
char lo = input[n + 2];
|
char lo = input[n + 2];
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(EC_REFERENCE)
|
||||||
|
#include <nall/elliptic-curve/modulo25519-reference.hpp>
|
||||||
|
#else
|
||||||
|
#include <nall/elliptic-curve/modulo25519.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace nall { namespace EllipticCurve {
|
||||||
|
|
||||||
|
struct Curve25519 {
|
||||||
|
auto sharedKey(uint256_t secretKey, uint256_t basepoint = 9) const -> uint256_t {
|
||||||
|
secretKey &= ((0_u256 - 1) >> 2) - 7;
|
||||||
|
secretKey |= 1_u256 << 254;
|
||||||
|
basepoint &= (0_u256 - 1) >> 1;
|
||||||
|
|
||||||
|
point p = scalarMultiply(secretKey, modP(basepoint));
|
||||||
|
return p.x * p.z.reciprocal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
using field = Modulo25519;
|
||||||
|
struct point { field x, z; };
|
||||||
|
|
||||||
|
inline auto montgomeryAdd(point p, point q, field b) const -> point {
|
||||||
|
return {
|
||||||
|
(p.x * q.x - p.z * q.z).square(),
|
||||||
|
(p.x * q.z - p.z * q.x).square() * b
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto montgomeryDouble(point p) const -> point {
|
||||||
|
field a = (p.x + p.z).square();
|
||||||
|
field b = (p.x - p.z).square();
|
||||||
|
field c = a - b;
|
||||||
|
field d = a + c * 121665;
|
||||||
|
return {a * b, c * d};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto scalarMultiply(uint256_t e, field b) const -> point {
|
||||||
|
point p{1, 0}, q{b, 1};
|
||||||
|
for(uint n : rrange(255)) {
|
||||||
|
bool bit = e >> n & 1;
|
||||||
|
cswap(bit, p.x, q.x);
|
||||||
|
cswap(bit, p.z, q.z);
|
||||||
|
q = montgomeryAdd(p, q, b);
|
||||||
|
p = montgomeryDouble(p);
|
||||||
|
cswap(bit, p.x, q.x);
|
||||||
|
cswap(bit, p.z, q.z);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
|
@ -0,0 +1,164 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/hash/sha512.hpp>
|
||||||
|
#if defined(EC_REFERENCE)
|
||||||
|
#include <nall/elliptic-curve/modulo25519-reference.hpp>
|
||||||
|
#else
|
||||||
|
#include <nall/elliptic-curve/modulo25519.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace nall { namespace EllipticCurve {
|
||||||
|
|
||||||
|
struct Ed25519 {
|
||||||
|
Ed25519() {
|
||||||
|
field y = field(4) * field(5).reciprocal();
|
||||||
|
field x = recoverX(y);
|
||||||
|
point B{x, y, 1, x * y};
|
||||||
|
for(uint n : range(253)) {
|
||||||
|
Bscalar[n] = B;
|
||||||
|
B = edwardsDouble(B);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto publicKey(uint256_t privateKey) const -> uint256_t {
|
||||||
|
auto H = uint512_t{Hash::SHA512(to_vector(privateKey)).output()};
|
||||||
|
auto a = clamp(H);
|
||||||
|
auto A = compress(scalarMultiplyB(modL(a)));
|
||||||
|
return A;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sign(const vector<uint8_t>& message, uint256_t privateKey) const -> uint512_t {
|
||||||
|
auto H = uint512_t{Hash::SHA512(to_vector(privateKey)).output()};
|
||||||
|
auto a = clamp(H);
|
||||||
|
auto A = compress(scalarMultiplyB(modL(a)));
|
||||||
|
|
||||||
|
Hash::SHA512 hash1;
|
||||||
|
hash1.input(to_vector(upper(H)));
|
||||||
|
hash1.input(message);
|
||||||
|
auto r = uint512_t{hash1.output()};
|
||||||
|
auto R = compress(scalarMultiplyB(modL(r)));
|
||||||
|
|
||||||
|
Hash::SHA512 hash2;
|
||||||
|
hash2.input(to_vector(R));
|
||||||
|
hash2.input(to_vector(A));
|
||||||
|
hash2.input(message);
|
||||||
|
uint512_t k = modL(uint512_t{hash2.output()});
|
||||||
|
uint256_t S = modL(k * a + r);
|
||||||
|
|
||||||
|
return uint512_t(S) << 256 | R;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto verify(const vector<uint8_t>& message, uint512_t signature, uint256_t publicKey) const -> bool {
|
||||||
|
auto R = decompress(lower(signature));
|
||||||
|
auto A = decompress(publicKey);
|
||||||
|
if(!R || !A) return false;
|
||||||
|
uint256_t S = upper(signature);
|
||||||
|
|
||||||
|
Hash::SHA512 hash;
|
||||||
|
hash.input(to_vector(lower(signature)));
|
||||||
|
hash.input(to_vector(publicKey));
|
||||||
|
hash.input(message);
|
||||||
|
auto r = uint512_t{hash.output()};
|
||||||
|
|
||||||
|
auto p = scalarMultiplyB(modL(S));
|
||||||
|
auto q = edwardsAdd(R(), scalarMultiply(modL(r), A()));
|
||||||
|
if(!onCurve(p) || !onCurve(q)) return false;
|
||||||
|
if(p.x * q.z - q.x * p.z) return false;
|
||||||
|
if(p.y * q.z - q.y * p.z) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
using field = Modulo25519;
|
||||||
|
struct point { field x, y, z, t; };
|
||||||
|
point Bscalar[253];
|
||||||
|
const field D = -field(121665) * field(121666).reciprocal();
|
||||||
|
|
||||||
|
inline auto clamp(uint256_t p) const -> uint256_t {
|
||||||
|
p &= ((0_u256 - 1) >> 2) - 7;
|
||||||
|
p |= 1_u256 << 254;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto recoverX(field y) const -> field {
|
||||||
|
field y2 = y.square();
|
||||||
|
field x = ((y2 - 1) * (D * y2 + 1).reciprocal()).squareRoot();
|
||||||
|
return x() & 1 ? -x : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto onCurve(point p) const -> bool {
|
||||||
|
if(!p.z) return false;
|
||||||
|
if(p.x * p.y != p.z * p.t) return false;
|
||||||
|
if(p.y.square() - p.x.square() - p.z.square() - p.t.square() * D) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto decompress(uint256_t c) const -> maybe<point> {
|
||||||
|
field y = c & (1_u256 << 255) - 1;
|
||||||
|
field x = recoverX(y);
|
||||||
|
if(c >> 255) x = -x;
|
||||||
|
point p{x, y, 1, x * y};
|
||||||
|
if(!onCurve(p)) return nothing;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto compress(point p) const -> uint256_t {
|
||||||
|
field r = p.z.reciprocal();
|
||||||
|
field x = p.x * r;
|
||||||
|
field y = p.y * r;
|
||||||
|
return (x() & 1) << 255 | (y() & ((0_u256 - 1) >> 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto edwardsDouble(point p) const -> point {
|
||||||
|
field a = p.x.square();
|
||||||
|
field b = p.y.square();
|
||||||
|
field c = p.z.square();
|
||||||
|
field d = -a;
|
||||||
|
field e = (p.x + p.y).square() - a - b;
|
||||||
|
field g = d + b;
|
||||||
|
field f = g - (c + c);
|
||||||
|
field h = d - b;
|
||||||
|
return {e * f, g * h, f * g, e * h};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto edwardsAdd(point p, point q) const -> point {
|
||||||
|
field a = (p.y - p.x) * (q.y - q.x);
|
||||||
|
field b = (p.y + p.x) * (q.y + q.x);
|
||||||
|
field c = (p.t + p.t) * q.t * D;
|
||||||
|
field d = (p.z + p.z) * q.z;
|
||||||
|
field e = b - a;
|
||||||
|
field f = d - c;
|
||||||
|
field g = d + c;
|
||||||
|
field h = b + a;
|
||||||
|
return {e * f, g * h, f * g, e * h};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto scalarMultiply(uint512_t e, point q) const -> point {
|
||||||
|
point p{0, 1, 1, 0}, c;
|
||||||
|
for(uint n : rrange(253)) {
|
||||||
|
p = edwardsDouble(p);
|
||||||
|
c = edwardsAdd(p, q);
|
||||||
|
bool bit = e >> n & 1;
|
||||||
|
cmove(bit, p.x, c.x);
|
||||||
|
cmove(bit, p.y, c.y);
|
||||||
|
cmove(bit, p.z, c.z);
|
||||||
|
cmove(bit, p.t, c.t);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto scalarMultiplyB(uint512_t e) const -> point {
|
||||||
|
point p{0, 1, 1, 0}, c;
|
||||||
|
for(uint n : rrange(253)) {
|
||||||
|
bool bit = e >> n & 1;
|
||||||
|
c = edwardsAdd(p, Bscalar[n]);
|
||||||
|
cmove(bit, p.x, c.x);
|
||||||
|
cmove(bit, p.y, c.y);
|
||||||
|
cmove(bit, p.z, c.z);
|
||||||
|
cmove(bit, p.t, c.t);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
|
@ -0,0 +1,79 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/arithmetic/barrett.hpp>
|
||||||
|
|
||||||
|
namespace nall { namespace EllipticCurve {
|
||||||
|
|
||||||
|
static const uint256_t P = (1_u256 << 255) - 19;
|
||||||
|
static const uint256_t L = (1_u256 << 252) + 27742317777372353535851937790883648493_u256;
|
||||||
|
|
||||||
|
static BarrettReduction modP{P};
|
||||||
|
static BarrettReduction modL{L};
|
||||||
|
|
||||||
|
struct Modulo25519 : uint256_t {
|
||||||
|
using type = Modulo25519;
|
||||||
|
using uint256_t::uint256_t;
|
||||||
|
|
||||||
|
alwaysinline auto operator()() const -> uint256_t {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
alwaysinline auto operator-() const -> type {
|
||||||
|
return P.operator-(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto operator+(const T& rhs) const -> type {
|
||||||
|
auto lhs = (uint512_t)*this + rhs;
|
||||||
|
if(lhs >= P) lhs -= P;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto operator-(const T& rhs) const -> type {
|
||||||
|
auto lhs = (uint512_t)*this;
|
||||||
|
if(lhs < rhs) lhs += P;
|
||||||
|
return lhs - rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> alwaysinline auto operator*(const T& rhs) const -> type {
|
||||||
|
uint256_t hi, lo;
|
||||||
|
nall::mul(*this, rhs, hi, lo);
|
||||||
|
return modP(uint512_t{hi, lo});
|
||||||
|
}
|
||||||
|
|
||||||
|
alwaysinline auto square() const -> type {
|
||||||
|
uint256_t hi, lo;
|
||||||
|
nall::square(*this, hi, lo);
|
||||||
|
return modP(uint512_t{hi, lo});
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto expmod(uint256_t e) const -> type {
|
||||||
|
type x = 1;
|
||||||
|
for(auto n : rrange(256)) {
|
||||||
|
x = x.square();
|
||||||
|
if(e >> n & 1) x = operator*(x);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto reciprocal() const -> type {
|
||||||
|
return expmod(P - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto squareRoot() const -> type {
|
||||||
|
static const type i = type(2).expmod((P - 1) >> 2); //i = sqrt(-1)
|
||||||
|
type x = expmod((P + 3) >> 3);
|
||||||
|
if(operator!=(x.square())) x = x * i;
|
||||||
|
if(x & 1) x = -x;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline auto cmove(bool bit, Modulo25519& lhs, const Modulo25519& rhs) -> void {
|
||||||
|
if(bit) lhs = rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto cswap(bool bit, Modulo25519& lhs, Modulo25519& rhs) -> void {
|
||||||
|
if(bit) swap(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
|
@ -0,0 +1,234 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/arithmetic/barrett.hpp>
|
||||||
|
|
||||||
|
namespace nall { namespace EllipticCurve {
|
||||||
|
|
||||||
|
static const uint256_t P = (1_u256 << 255) - 19;
|
||||||
|
static const uint256_t L = (1_u256 << 252) + 27742317777372353535851937790883648493_u256;
|
||||||
|
|
||||||
|
static BarrettReduction modP{P};
|
||||||
|
static BarrettReduction modL{L};
|
||||||
|
|
||||||
|
struct Modulo25519;
|
||||||
|
auto cmove(bool move, Modulo25519& l, const Modulo25519& r) -> void;
|
||||||
|
auto cswap(bool swap, Modulo25519& l, Modulo25519& r) -> void;
|
||||||
|
|
||||||
|
struct Modulo25519 {
|
||||||
|
using type = Modulo25519;
|
||||||
|
#define Mask ((1ull << 51) - 1)
|
||||||
|
|
||||||
|
inline Modulo25519() = default;
|
||||||
|
inline Modulo25519(const Modulo25519&) = default;
|
||||||
|
inline Modulo25519(uint64_t a, uint64_t b = 0, uint64_t c = 0, uint64_t d = 0, uint64_t e = 0) : l{a, b, c, d, e} {}
|
||||||
|
|
||||||
|
inline Modulo25519(uint256_t n) {
|
||||||
|
l[0] = n >> 0 & Mask;
|
||||||
|
l[1] = n >> 51 & Mask;
|
||||||
|
l[2] = n >> 102 & Mask;
|
||||||
|
l[3] = n >> 153 & Mask;
|
||||||
|
l[4] = n >> 204 & Mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto operator()() const -> uint256_t { return operator uint256_t(); }
|
||||||
|
inline auto& operator[](uint index) { return l[index]; }
|
||||||
|
inline auto operator[](uint index) const { return l[index]; }
|
||||||
|
|
||||||
|
inline explicit operator bool() const {
|
||||||
|
return operator uint256_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline operator uint256_t() const {
|
||||||
|
type o = *this;
|
||||||
|
|
||||||
|
o[1] += (o[0] >> 51); o[0] &= Mask;
|
||||||
|
o[2] += (o[1] >> 51); o[1] &= Mask;
|
||||||
|
o[3] += (o[2] >> 51); o[2] &= Mask;
|
||||||
|
o[4] += (o[3] >> 51); o[3] &= Mask;
|
||||||
|
o[0] += 19 * (o[4] >> 51); o[4] &= Mask;
|
||||||
|
|
||||||
|
o[1] += (o[0] >> 51); o[0] &= Mask;
|
||||||
|
o[2] += (o[1] >> 51); o[1] &= Mask;
|
||||||
|
o[3] += (o[2] >> 51); o[2] &= Mask;
|
||||||
|
o[4] += (o[3] >> 51); o[3] &= Mask;
|
||||||
|
o[0] += 19 * (o[4] >> 51); o[4] &= Mask;
|
||||||
|
|
||||||
|
o[0] += 19;
|
||||||
|
o[1] += (o[0] >> 51); o[0] &= Mask;
|
||||||
|
o[2] += (o[1] >> 51); o[1] &= Mask;
|
||||||
|
o[3] += (o[2] >> 51); o[2] &= Mask;
|
||||||
|
o[4] += (o[3] >> 51); o[3] &= Mask;
|
||||||
|
o[0] += 19 * (o[4] >> 51); o[4] &= Mask;
|
||||||
|
|
||||||
|
o[0] += Mask - 18;
|
||||||
|
o[1] += Mask;
|
||||||
|
o[2] += Mask;
|
||||||
|
o[3] += Mask;
|
||||||
|
o[4] += Mask;
|
||||||
|
|
||||||
|
o[1] += o[0] >> 51; o[0] &= Mask;
|
||||||
|
o[2] += o[1] >> 51; o[1] &= Mask;
|
||||||
|
o[3] += o[2] >> 51; o[2] &= Mask;
|
||||||
|
o[4] += o[3] >> 51; o[3] &= Mask;
|
||||||
|
o[4] &= Mask;
|
||||||
|
|
||||||
|
return (uint256_t)o[0] << 0 | (uint256_t)o[1] << 51 | (uint256_t)o[2] << 102 | (uint256_t)o[3] << 153 | (uint256_t)o[4] << 204;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto operator!=(type r) const -> bool {
|
||||||
|
bool e = 1;
|
||||||
|
e &= l[0] == r[0];
|
||||||
|
e &= l[1] == r[1];
|
||||||
|
e &= l[2] == r[2];
|
||||||
|
e &= l[3] == r[3];
|
||||||
|
e &= l[4] == r[4];
|
||||||
|
return e == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto operator-() const -> type { //P - l
|
||||||
|
type o;
|
||||||
|
uint64_t c;
|
||||||
|
o[0] = 0xfffffffffffda - l[0]; c = o[0] >> 51; o[0] &= Mask;
|
||||||
|
o[1] = 0xffffffffffffe - l[1] + c; c = o[1] >> 51; o[1] &= Mask;
|
||||||
|
o[2] = 0xffffffffffffe - l[2] + c; c = o[2] >> 51; o[2] &= Mask;
|
||||||
|
o[3] = 0xffffffffffffe - l[3] + c; c = o[3] >> 51; o[3] &= Mask;
|
||||||
|
o[4] = 0xffffffffffffe - l[4] + c; c = o[4] >> 51; o[4] &= Mask;
|
||||||
|
o[0] += c * 19;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto operator+(type r) const -> type {
|
||||||
|
type o;
|
||||||
|
uint64_t c;
|
||||||
|
o[0] = l[0] + r[0]; c = o[0] >> 51; o[0] &= Mask;
|
||||||
|
o[1] = l[1] + r[1] + c; c = o[1] >> 51; o[1] &= Mask;
|
||||||
|
o[2] = l[2] + r[2] + c; c = o[2] >> 51; o[2] &= Mask;
|
||||||
|
o[3] = l[3] + r[3] + c; c = o[3] >> 51; o[3] &= Mask;
|
||||||
|
o[4] = l[4] + r[4] + c; c = o[4] >> 51; o[4] &= Mask;
|
||||||
|
o[0] += c * 19;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto operator-(type r) const -> type {
|
||||||
|
type o;
|
||||||
|
uint64_t c;
|
||||||
|
o[0] = l[0] + 0x1fffffffffffb4 - r[0]; c = o[0] >> 51; o[0] &= Mask;
|
||||||
|
o[1] = l[1] + 0x1ffffffffffffc - r[1] + c; c = o[1] >> 51; o[1] &= Mask;
|
||||||
|
o[2] = l[2] + 0x1ffffffffffffc - r[2] + c; c = o[2] >> 51; o[2] &= Mask;
|
||||||
|
o[3] = l[3] + 0x1ffffffffffffc - r[3] + c; c = o[3] >> 51; o[3] &= Mask;
|
||||||
|
o[4] = l[4] + 0x1ffffffffffffc - r[4] + c; c = o[4] >> 51; o[4] &= Mask;
|
||||||
|
o[0] += c * 19;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto operator*(uint64_t scalar) const -> type {
|
||||||
|
type o;
|
||||||
|
uint128_t a;
|
||||||
|
a = (uint128_t)l[0] * scalar; o[0] = a & Mask;
|
||||||
|
a = (uint128_t)l[1] * scalar + (a >> 51 & Mask); o[1] = a & Mask;
|
||||||
|
a = (uint128_t)l[2] * scalar + (a >> 51 & Mask); o[2] = a & Mask;
|
||||||
|
a = (uint128_t)l[3] * scalar + (a >> 51 & Mask); o[3] = a & Mask;
|
||||||
|
a = (uint128_t)l[4] * scalar + (a >> 51 & Mask); o[4] = a & Mask;
|
||||||
|
o[0] += (a >> 51) * 19;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto operator*(type r) const -> type {
|
||||||
|
uint128_t t[] = {
|
||||||
|
(uint128_t)r[0] * l[0],
|
||||||
|
(uint128_t)r[0] * l[1] + (uint128_t)r[1] * l[0],
|
||||||
|
(uint128_t)r[0] * l[2] + (uint128_t)r[1] * l[1] + (uint128_t)r[2] * l[0],
|
||||||
|
(uint128_t)r[0] * l[3] + (uint128_t)r[1] * l[2] + (uint128_t)r[2] * l[1] + (uint128_t)r[3] * l[0],
|
||||||
|
(uint128_t)r[0] * l[4] + (uint128_t)r[1] * l[3] + (uint128_t)r[2] * l[2] + (uint128_t)r[3] * l[1] + (uint128_t)r[4] * l[0]
|
||||||
|
};
|
||||||
|
|
||||||
|
r[1] *= 19, r[2] *= 19, r[3] *= 19, r[4] *= 19;
|
||||||
|
|
||||||
|
t[0] += (uint128_t)r[4] * l[1] + (uint128_t)r[3] * l[2] + (uint128_t)r[2] * l[3] + (uint128_t)r[1] * l[4];
|
||||||
|
t[1] += (uint128_t)r[4] * l[2] + (uint128_t)r[3] * l[3] + (uint128_t)r[2] * l[4];
|
||||||
|
t[2] += (uint128_t)r[4] * l[3] + (uint128_t)r[3] * l[4];
|
||||||
|
t[3] += (uint128_t)r[4] * l[4];
|
||||||
|
|
||||||
|
uint64_t c; r[0] = t[0] & Mask; c = (uint64_t)(t[0] >> 51);
|
||||||
|
t[1] += c; r[1] = t[1] & Mask; c = (uint64_t)(t[1] >> 51);
|
||||||
|
t[2] += c; r[2] = t[2] & Mask; c = (uint64_t)(t[2] >> 51);
|
||||||
|
t[3] += c; r[3] = t[3] & Mask; c = (uint64_t)(t[3] >> 51);
|
||||||
|
t[4] += c; r[4] = t[4] & Mask; c = (uint64_t)(t[4] >> 51);
|
||||||
|
|
||||||
|
r[0] += c * 19; c = r[0] >> 51; r[0] &= Mask;
|
||||||
|
r[1] += c; c = r[1] >> 51; r[1] &= Mask;
|
||||||
|
r[2] += c;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto square() const -> type {
|
||||||
|
type r{*this};
|
||||||
|
type d{r[0] * 2, r[1] * 2, r[2] * 2 * 19, r[4] * 19, r[4] * 19 * 2};
|
||||||
|
|
||||||
|
uint128_t t[5];
|
||||||
|
t[0] = (uint128_t)r[0] * r[0] + (uint128_t)d[4] * r[1] + (uint128_t)d[2] * r[3];
|
||||||
|
t[1] = (uint128_t)d[0] * r[1] + (uint128_t)d[4] * r[2] + (uint128_t)r[3] * r[3] * 19;
|
||||||
|
t[2] = (uint128_t)d[0] * r[2] + (uint128_t)r[1] * r[1] + (uint128_t)d[4] * r[3];
|
||||||
|
t[3] = (uint128_t)d[0] * r[3] + (uint128_t)d[1] * r[2] + (uint128_t)r[4] * d[3];
|
||||||
|
t[4] = (uint128_t)d[0] * r[4] + (uint128_t)d[1] * r[3] + (uint128_t)r[2] * r[2];
|
||||||
|
|
||||||
|
uint64_t c; r[0] = t[0] & Mask; c = (uint64_t)(t[0] >> 51);
|
||||||
|
t[1] += c; r[1] = t[1] & Mask; c = (uint64_t)(t[1] >> 51);
|
||||||
|
t[2] += c; r[2] = t[2] & Mask; c = (uint64_t)(t[2] >> 51);
|
||||||
|
t[3] += c; r[3] = t[3] & Mask; c = (uint64_t)(t[3] >> 51);
|
||||||
|
t[4] += c; r[4] = t[4] & Mask; c = (uint64_t)(t[4] >> 51);
|
||||||
|
|
||||||
|
r[0] += c * 19; c = r[0] >> 51; r[0] &= Mask;
|
||||||
|
r[1] += c; c = r[1] >> 51; r[1] &= Mask;
|
||||||
|
r[2] += c;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto expmod(uint256_t e) const -> type {
|
||||||
|
type x = 1, y;
|
||||||
|
for(uint n : rrange(256)) {
|
||||||
|
x = x.square();
|
||||||
|
y = operator*(x);
|
||||||
|
cmove(e >> n & 1, x, y);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto reciprocal() const -> type {
|
||||||
|
return expmod(P - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto squareRoot() const -> type {
|
||||||
|
static const type i = type(2).expmod((P - 1) >> 2); //i == sqrt(-1)
|
||||||
|
type x = expmod((P + 3) >> 3);
|
||||||
|
type y = x * i;
|
||||||
|
cmove(operator!=(x.square()), x, y);
|
||||||
|
y = -x;
|
||||||
|
cmove(x() & 1, x, y);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t l[5]; //51-bits per limb; 255-bits total
|
||||||
|
#undef Mask
|
||||||
|
};
|
||||||
|
|
||||||
|
inline auto cmove(bool move, Modulo25519& l, const Modulo25519& r) -> void {
|
||||||
|
uint64_t mask = -move;
|
||||||
|
l[0] ^= mask & (l[0] ^ r[0]);
|
||||||
|
l[1] ^= mask & (l[1] ^ r[1]);
|
||||||
|
l[2] ^= mask & (l[2] ^ r[2]);
|
||||||
|
l[3] ^= mask & (l[3] ^ r[3]);
|
||||||
|
l[4] ^= mask & (l[4] ^ r[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto cswap(bool swap, Modulo25519& l, Modulo25519& r) -> void {
|
||||||
|
uint64_t mask = -swap, x;
|
||||||
|
x = mask & (l[0] ^ r[0]); l[0] ^= x; r[0] ^= x;
|
||||||
|
x = mask & (l[1] ^ r[1]); l[1] ^= x; r[1] ^= x;
|
||||||
|
x = mask & (l[2] ^ r[2]); l[2] ^= x; r[2] ^= x;
|
||||||
|
x = mask & (l[3] ^ r[3]); l[3] ^= x; r[3] ^= x;
|
||||||
|
x = mask & (l[4] ^ r[4]); l[4] ^= x; r[4] ^= x;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/arithmetic.hpp>
|
||||||
|
|
||||||
|
namespace nall { namespace Encode {
|
||||||
|
|
||||||
|
template<typename T> inline auto Base57(T value) -> string {
|
||||||
|
static const char lookup[] = "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||||
|
static const uint size = ceil(sizeof(T) * 8 / log2(57));
|
||||||
|
|
||||||
|
string result;
|
||||||
|
for(auto n : range(size)) {
|
||||||
|
result.append(lookup[value % 57]);
|
||||||
|
value /= 57;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
|
@ -5,13 +5,18 @@ namespace nall { namespace Encode {
|
||||||
inline auto URL(const string& input) -> string {
|
inline auto URL(const string& input) -> string {
|
||||||
string output;
|
string output;
|
||||||
for(auto c : input) {
|
for(auto c : input) {
|
||||||
|
//unreserved characters
|
||||||
if(c >= 'A' && c <= 'Z') { output.append(c); continue; }
|
if(c >= 'A' && c <= 'Z') { output.append(c); continue; }
|
||||||
if(c >= 'a' && c <= 'z') { output.append(c); continue; }
|
if(c >= 'a' && c <= 'z') { output.append(c); continue; }
|
||||||
if(c >= '0' && c <= '9') { output.append(c); continue; }
|
if(c >= '0' && c <= '9') { output.append(c); continue; }
|
||||||
if(c == '-' || c == '_' || c == '.' || c == '~') { output.append(c); continue; }
|
if(c == '-' || c == '_' || c == '.' || c == '~') { output.append(c); continue; }
|
||||||
|
|
||||||
|
//special characters
|
||||||
if(c == ' ') { output.append('+'); continue; }
|
if(c == ' ') { output.append('+'); continue; }
|
||||||
unsigned hi = (c >> 4) & 15;
|
|
||||||
unsigned lo = (c >> 0) & 15;
|
//reserved characters
|
||||||
|
uint hi = (c >> 4) & 15;
|
||||||
|
uint lo = (c >> 0) & 15;
|
||||||
output.append('%');
|
output.append('%');
|
||||||
output.append((char)(hi < 10 ? ('0' + hi) : ('a' + hi - 10)));
|
output.append((char)(hi < 10 ? ('0' + hi) : ('a' + hi - 10)));
|
||||||
output.append((char)(lo < 10 ? ('0' + lo) : ('a' + lo - 10)));
|
output.append((char)(lo < 10 ? ('0' + lo) : ('a' + lo - 10)));
|
||||||
|
|
|
@ -20,7 +20,7 @@ struct ZIP {
|
||||||
//append file: append("path/file", data, size);
|
//append file: append("path/file", data, size);
|
||||||
auto append(string filename, const uint8_t* data = nullptr, unsigned size = 0u) -> void {
|
auto append(string filename, const uint8_t* data = nullptr, unsigned size = 0u) -> void {
|
||||||
filename.transform("\\", "/");
|
filename.transform("\\", "/");
|
||||||
uint32_t checksum = Hash::CRC32(data, size).value();
|
uint32_t checksum = Hash::CRC32(data, size).digest().hex();
|
||||||
directory.append({filename, checksum, size, fp.offset()});
|
directory.append({filename, checksum, size, fp.offset()});
|
||||||
|
|
||||||
fp.writel(0x04034b50, 4); //signature
|
fp.writel(0x04034b50, 4); //signature
|
||||||
|
|
|
@ -20,7 +20,7 @@ template<typename R, typename... P> struct function<auto (P...) -> R> {
|
||||||
function(auto (*function)(P...) -> R) { callback = new global(function); }
|
function(auto (*function)(P...) -> R) { callback = new global(function); }
|
||||||
template<typename C> function(auto (C::*function)(P...) -> R, C* object) { callback = new member<C>(function, object); }
|
template<typename C> function(auto (C::*function)(P...) -> R, C* object) { callback = new member<C>(function, object); }
|
||||||
template<typename C> function(auto (C::*function)(P...) const -> R, C* object) { callback = new member<C>((auto (C::*)(P...) -> R)function, object); }
|
template<typename C> function(auto (C::*function)(P...) const -> R, C* object) { callback = new member<C>((auto (C::*)(P...) -> R)function, object); }
|
||||||
template<typename L, typename = enable_if<is_compatible<L>>> function(const L& object) { callback = new lambda<L>(object); }
|
template<typename L, typename = enable_if_t<is_compatible<L>::value>> function(const L& object) { callback = new lambda<L>(object); }
|
||||||
~function() { if(callback) delete callback; }
|
~function() { if(callback) delete callback; }
|
||||||
|
|
||||||
explicit operator bool() const { return callback; }
|
explicit operator bool() const { return callback; }
|
||||||
|
|
|
@ -1,45 +1,30 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <nall/range.hpp>
|
#include <nall/hash/hash.hpp>
|
||||||
#include <nall/string.hpp>
|
|
||||||
|
|
||||||
namespace nall { namespace Hash {
|
namespace nall { namespace Hash {
|
||||||
|
|
||||||
struct CRC16 {
|
struct CRC16 : Hash {
|
||||||
CRC16() { reset(); }
|
nallHash(CRC16)
|
||||||
CRC16(const void* values, uint size) : CRC16() { data(values, size); }
|
|
||||||
CRC16(const vector<uint8_t>& values) : CRC16() { data(values); }
|
|
||||||
CRC16(const string& values) : CRC16() { data(values); }
|
|
||||||
|
|
||||||
auto reset() -> void {
|
auto reset() -> void override {
|
||||||
checksum = ~0;
|
checksum = ~0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data(uint8_t value) -> void {
|
auto input(uint8_t value) -> void override {
|
||||||
checksum = (checksum >> 8) ^ table(checksum ^ value);
|
checksum = (checksum >> 8) ^ table(checksum ^ value);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data(const void* values, uint size) -> void {
|
auto output() const -> vector<uint8_t> override {
|
||||||
auto p = (const uint8_t*)values;
|
vector<uint8_t> result;
|
||||||
while(size--) data(*p++);
|
for(auto n : rrange(2)) result.append(~checksum >> n * 8);
|
||||||
}
|
return result;
|
||||||
|
|
||||||
auto data(const vector<uint8_t>& values) -> void {
|
|
||||||
for(auto value : values) data(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto data(const string& values) -> void {
|
|
||||||
for(auto value : values) data(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto value() const -> uint16_t {
|
auto value() const -> uint16_t {
|
||||||
return ~checksum;
|
return ~checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto digest() const -> string {
|
|
||||||
return hex(value(), 4L);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static auto table(uint8_t index) -> uint16_t {
|
static auto table(uint8_t index) -> uint16_t {
|
||||||
static uint16_t table[256] = {0};
|
static uint16_t table[256] = {0};
|
||||||
|
@ -59,7 +44,7 @@ private:
|
||||||
return table[index];
|
return table[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t checksum;
|
uint16_t checksum = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,45 +1,30 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <nall/range.hpp>
|
#include <nall/hash/hash.hpp>
|
||||||
#include <nall/string.hpp>
|
|
||||||
|
|
||||||
namespace nall { namespace Hash {
|
namespace nall { namespace Hash {
|
||||||
|
|
||||||
struct CRC32 {
|
struct CRC32 : Hash {
|
||||||
CRC32() { reset(); }
|
nallHash(CRC32)
|
||||||
CRC32(const void* values, uint size) : CRC32() { data(values, size); }
|
|
||||||
CRC32(const vector<uint8_t>& values) : CRC32() { data(values); }
|
|
||||||
CRC32(const string& values) : CRC32() { data(values); }
|
|
||||||
|
|
||||||
auto reset() -> void {
|
auto reset() -> void override {
|
||||||
checksum = ~0;
|
checksum = ~0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data(uint8_t value) -> void {
|
auto input(uint8_t value) -> void override {
|
||||||
checksum = (checksum >> 8) ^ table(checksum ^ value);
|
checksum = (checksum >> 8) ^ table(checksum ^ value);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data(const void* values, uint size) -> void {
|
auto output() const -> vector<uint8_t> {
|
||||||
auto p = (const uint8_t*)values;
|
vector<uint8_t> result;
|
||||||
while(size--) data(*p++);
|
for(auto n : rrange(4)) result.append(~checksum >> n * 8);
|
||||||
}
|
return result;
|
||||||
|
|
||||||
auto data(const vector<uint8_t>& values) -> void {
|
|
||||||
for(auto value : values) data(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto data(const string& values) -> void {
|
|
||||||
for(auto value : values) data(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto value() const -> uint32_t {
|
auto value() const -> uint32_t {
|
||||||
return ~checksum;
|
return ~checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto digest() const -> string {
|
|
||||||
return hex(value(), 8L);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static auto table(uint8_t index) -> uint32_t {
|
static auto table(uint8_t index) -> uint32_t {
|
||||||
static uint32_t table[256] = {0};
|
static uint32_t table[256] = {0};
|
||||||
|
@ -59,7 +44,7 @@ private:
|
||||||
return table[index];
|
return table[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t checksum;
|
uint32_t checksum = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,45 +1,30 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <nall/range.hpp>
|
#include <nall/hash/hash.hpp>
|
||||||
#include <nall/string.hpp>
|
|
||||||
|
|
||||||
namespace nall { namespace Hash {
|
namespace nall { namespace Hash {
|
||||||
|
|
||||||
struct CRC64 {
|
struct CRC64 : Hash {
|
||||||
CRC64() { reset(); }
|
nallHash(CRC64)
|
||||||
CRC64(const void* values, uint size) : CRC64() { data(values, size); }
|
|
||||||
CRC64(const vector<uint8_t>& values) : CRC64() { data(values); }
|
|
||||||
CRC64(const string& values) : CRC64() { data(values); }
|
|
||||||
|
|
||||||
auto reset() -> void {
|
auto reset() -> void override {
|
||||||
checksum = ~0;
|
checksum = ~0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data(uint8_t value) -> void {
|
auto input(uint8_t value) -> void override {
|
||||||
checksum = (checksum >> 8) ^ table(checksum ^ value);
|
checksum = (checksum >> 8) ^ table(checksum ^ value);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data(const void* values, uint size) -> void {
|
auto output() const -> vector<uint8_t> {
|
||||||
auto p = (const uint8_t*)values;
|
vector<uint8_t> result;
|
||||||
while(size--) data(*p++);
|
for(auto n : rrange(8)) result.append(~checksum >> n * 8);
|
||||||
}
|
return result;
|
||||||
|
|
||||||
auto data(const vector<uint8_t>& values) -> void {
|
|
||||||
for(auto value : values) data(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto data(const string& values) -> void {
|
|
||||||
for(auto value : values) data(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto value() const -> uint64_t {
|
auto value() const -> uint64_t {
|
||||||
return ~checksum;
|
return ~checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto digest() const -> string {
|
|
||||||
return hex(value(), 16L);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static auto table(uint8_t index) -> uint64_t {
|
static auto table(uint8_t index) -> uint64_t {
|
||||||
static uint64_t table[256] = {0};
|
static uint64_t table[256] = {0};
|
||||||
|
@ -59,7 +44,7 @@ private:
|
||||||
return table[index];
|
return table[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t checksum;
|
uint64_t checksum = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/arithmetic.hpp>
|
||||||
|
#include <nall/range.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
|
//cannot use constructor inheritance due to needing to call virtual reset();
|
||||||
|
//instead, define a macro to reduce boilerplate code in every Hash subclass
|
||||||
|
#define nallHash(Name) \
|
||||||
|
Name() { reset(); } \
|
||||||
|
Name(const void* data, uint64_t size) : Name() { input(data, size); } \
|
||||||
|
Name(const vector<uint8_t>& data) : Name() { input(data); } \
|
||||||
|
Name(const string& data) : Name() { input(data); } \
|
||||||
|
using Hash::input; \
|
||||||
|
|
||||||
|
namespace nall { namespace Hash {
|
||||||
|
|
||||||
|
struct Hash {
|
||||||
|
virtual auto reset() -> void = 0;
|
||||||
|
virtual auto input(uint8_t data) -> void = 0;
|
||||||
|
virtual auto output() const -> vector<uint8_t> = 0;
|
||||||
|
|
||||||
|
auto input(const void* data, uint64_t size) -> void {
|
||||||
|
auto p = (const uint8_t*)data;
|
||||||
|
while(size--) input(*p++);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input(const vector<uint8_t>& data) -> void {
|
||||||
|
for(auto byte : data) input(byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input(const string& data) -> void {
|
||||||
|
for(auto byte : data) input(byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto digest() const -> string {
|
||||||
|
string result;
|
||||||
|
for(auto n : output()) result.append(hex(n, 2L));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
|
@ -0,0 +1,101 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/hash/hash.hpp>
|
||||||
|
|
||||||
|
namespace nall { namespace Hash {
|
||||||
|
|
||||||
|
struct SHA224 : Hash {
|
||||||
|
nallHash(SHA224)
|
||||||
|
|
||||||
|
auto reset() -> void override {
|
||||||
|
for(auto& n : queue) n = 0;
|
||||||
|
for(auto& n : w) n = 0;
|
||||||
|
for(auto n : range(8)) h[n] = square(n);
|
||||||
|
queued = length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input(uint8_t value) -> void override {
|
||||||
|
byte(value);
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto output() const -> vector<uint8_t> override {
|
||||||
|
SHA224 self(*this);
|
||||||
|
self.finish();
|
||||||
|
vector<uint8_t> result;
|
||||||
|
for(auto h : range(7)) {
|
||||||
|
for(auto n : rrange(4)) result.append(self.h[h] >> n * 8);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto value() const -> uint256_t {
|
||||||
|
uint256_t value = 0;
|
||||||
|
for(auto byte : output()) value = value << 8 | byte;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto byte(uint8_t value) -> void {
|
||||||
|
uint32_t shift = (3 - (queued & 3)) * 8;
|
||||||
|
queue[queued >> 2] &= ~(0xff << shift);
|
||||||
|
queue[queued >> 2] |= (value << shift);
|
||||||
|
if(++queued == 64) block(), queued = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto block() -> void {
|
||||||
|
for(auto n : range(16)) w[n] = queue[n];
|
||||||
|
for(auto n : range(16, 64)) {
|
||||||
|
uint32_t a = ror(w[n - 15], 7) ^ ror(w[n - 15], 18) ^ (w[n - 15] >> 3);
|
||||||
|
uint32_t b = ror(w[n - 2], 17) ^ ror(w[n - 2], 19) ^ (w[n - 2] >> 10);
|
||||||
|
w[n] = w[n - 16] + w[n - 7] + a + b;
|
||||||
|
}
|
||||||
|
uint32_t t[8];
|
||||||
|
for(auto n : range(8)) t[n] = h[n];
|
||||||
|
for(auto n : range(64)) {
|
||||||
|
uint32_t a = ror(t[0], 2) ^ ror(t[0], 13) ^ ror(t[0], 22);
|
||||||
|
uint32_t b = ror(t[4], 6) ^ ror(t[4], 11) ^ ror(t[4], 25);
|
||||||
|
uint32_t c = (t[0] & t[1]) ^ (t[0] & t[2]) ^ (t[1] & t[2]);
|
||||||
|
uint32_t d = (t[4] & t[5]) ^ (~t[4] & t[6]);
|
||||||
|
uint32_t e = t[7] + w[n] + cube(n) + b + d;
|
||||||
|
t[7] = t[6]; t[6] = t[5]; t[5] = t[4]; t[4] = t[3] + e;
|
||||||
|
t[3] = t[2]; t[2] = t[1]; t[1] = t[0]; t[0] = a + c + e;
|
||||||
|
}
|
||||||
|
for(auto n : range(8)) h[n] += t[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto finish() -> void {
|
||||||
|
byte(0x80);
|
||||||
|
while(queued != 56) byte(0x00);
|
||||||
|
for(auto n : range(8)) byte(length * 8 >> (7 - n) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto square(uint n) -> uint32_t {
|
||||||
|
static const uint32_t value[8] = {
|
||||||
|
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
|
||||||
|
};
|
||||||
|
return value[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cube(uint n) -> uint32_t {
|
||||||
|
static const uint32_t value[64] = {
|
||||||
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||||
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||||
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||||
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||||
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||||
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
||||||
|
};
|
||||||
|
return value[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t queue[16] = {0};
|
||||||
|
uint32_t w[64] = {0};
|
||||||
|
uint32_t h[8] = {0};
|
||||||
|
uint32_t queued = 0;
|
||||||
|
uint64_t length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
|
@ -1,66 +1,50 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <nall/range.hpp>
|
#include <nall/hash/hash.hpp>
|
||||||
#include <nall/string.hpp>
|
|
||||||
|
|
||||||
namespace nall { namespace Hash {
|
namespace nall { namespace Hash {
|
||||||
|
|
||||||
struct SHA256 {
|
struct SHA256 : Hash {
|
||||||
SHA256() { reset(); }
|
nallHash(SHA256)
|
||||||
SHA256(const void* values, uint size) : SHA256() { data(values, size); }
|
|
||||||
SHA256(const vector<uint8_t>& values) : SHA256() { data(values); }
|
|
||||||
SHA256(const string& values) : SHA256() { data(values); }
|
|
||||||
|
|
||||||
auto reset() -> void {
|
auto reset() -> void override {
|
||||||
for(auto n : input) n = 0;
|
for(auto& n : queue) n = 0;
|
||||||
for(auto n : w) n = 0;
|
for(auto& n : w) n = 0;
|
||||||
for(auto n : range(8)) h[n] = square(n);
|
for(auto n : range(8)) h[n] = square(n);
|
||||||
queued = length = 0;
|
queued = length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data(uint8_t value) -> void {
|
auto input(uint8_t value) -> void override {
|
||||||
byte(value);
|
byte(value);
|
||||||
length++;
|
length++;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data(const void* values, uint size) -> void {
|
auto output() const -> vector<uint8_t> override {
|
||||||
length += size;
|
|
||||||
auto p = (const uint8_t*)values;
|
|
||||||
while(size--) byte(*p++);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto data(const vector<uint8_t>& values) -> void {
|
|
||||||
for(auto value : values) data(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto data(const string& values) -> void {
|
|
||||||
for(auto value : values) data(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto value() const -> vector<uint8_t> {
|
|
||||||
SHA256 self(*this);
|
SHA256 self(*this);
|
||||||
self.finish();
|
self.finish();
|
||||||
vector<uint8_t> result;
|
vector<uint8_t> result;
|
||||||
for(auto n : range(32)) result.append(self.h[n >> 2] >> ((3 - (n & 3)) << 3));
|
for(auto h : self.h) {
|
||||||
|
for(auto n : rrange(4)) result.append(h >> n * 8);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto digest() const -> string {
|
auto value() const -> uint256_t {
|
||||||
string result;
|
uint256_t value = 0;
|
||||||
for(auto n : value()) result.append(hex(n, 2L));
|
for(auto byte : output()) value = value << 8 | byte;
|
||||||
return result;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto byte(uint8_t value) -> void {
|
auto byte(uint8_t value) -> void {
|
||||||
auto shift = (3 - (queued & 3)) * 8;
|
uint32_t shift = (3 - (queued & 3)) * 8;
|
||||||
input[queued >> 2] &= ~(0xff << shift);
|
queue[queued >> 2] &= ~(0xff << shift);
|
||||||
input[queued >> 2] |= (value << shift);
|
queue[queued >> 2] |= (value << shift);
|
||||||
if(++queued == 64) block(), queued = 0;
|
if(++queued == 64) block(), queued = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto block() -> void {
|
auto block() -> void {
|
||||||
for(auto n : range(16)) w[n] = input[n];
|
for(auto n : range(16)) w[n] = queue[n];
|
||||||
for(auto n : range(16, 64)) {
|
for(auto n : range(16, 64)) {
|
||||||
uint32_t a = ror(w[n - 15], 7) ^ ror(w[n - 15], 18) ^ (w[n - 15] >> 3);
|
uint32_t a = ror(w[n - 15], 7) ^ ror(w[n - 15], 18) ^ (w[n - 15] >> 3);
|
||||||
uint32_t b = ror(w[n - 2], 17) ^ ror(w[n - 2], 19) ^ (w[n - 2] >> 10);
|
uint32_t b = ror(w[n - 2], 17) ^ ror(w[n - 2], 19) ^ (w[n - 2] >> 10);
|
||||||
|
@ -83,11 +67,7 @@ private:
|
||||||
auto finish() -> void {
|
auto finish() -> void {
|
||||||
byte(0x80);
|
byte(0x80);
|
||||||
while(queued != 56) byte(0x00);
|
while(queued != 56) byte(0x00);
|
||||||
for(auto n : range(8)) byte((length << 3) >> ((7 - n) << 3));
|
for(auto n : range(8)) byte(length * 8 >> (7 - n) * 8);
|
||||||
}
|
|
||||||
|
|
||||||
auto ror(uint32_t x, uint32_t n) -> uint32_t {
|
|
||||||
return (x >> n) | (x << 32 - n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto square(uint n) -> uint32_t {
|
auto square(uint n) -> uint32_t {
|
||||||
|
@ -111,11 +91,11 @@ private:
|
||||||
return value[n];
|
return value[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t input[16];
|
uint32_t queue[16] = {0};
|
||||||
uint32_t queued;
|
uint32_t w[64] = {0};
|
||||||
uint32_t w[64];
|
uint32_t h[8] = {0};
|
||||||
uint32_t h[8];
|
uint32_t queued = 0;
|
||||||
uint64_t length;
|
uint64_t length = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/hash/hash.hpp>
|
||||||
|
|
||||||
|
namespace nall { namespace Hash {
|
||||||
|
|
||||||
|
struct SHA384 : Hash {
|
||||||
|
nallHash(SHA384)
|
||||||
|
|
||||||
|
auto reset() -> void override {
|
||||||
|
for(auto& n : queue) n = 0;
|
||||||
|
for(auto& n : w) n = 0;
|
||||||
|
for(auto n : range(8)) h[n] = square(n);
|
||||||
|
queued = length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input(uint8_t data) -> void override {
|
||||||
|
byte(data);
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto output() const -> vector<uint8_t> override {
|
||||||
|
SHA384 self(*this);
|
||||||
|
self.finish();
|
||||||
|
vector<uint8_t> result;
|
||||||
|
for(auto h : range(6)) {
|
||||||
|
for(auto n : rrange(8)) result.append(self.h[h] >> n * 8);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto value() const -> uint512_t {
|
||||||
|
uint512_t value = 0;
|
||||||
|
for(auto byte : output()) value = value << 8 | byte;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto byte(uint8_t data) -> void {
|
||||||
|
uint64_t shift = (7 - (queued & 7)) * 8;
|
||||||
|
queue[queued >> 3] &=~((uint64_t)0xff << shift);
|
||||||
|
queue[queued >> 3] |= ((uint64_t)data << shift);
|
||||||
|
if(++queued == 128) block(), queued = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto block() -> void {
|
||||||
|
for(auto n : range(16)) w[n] = queue[n];
|
||||||
|
for(auto n : range(16, 80)) {
|
||||||
|
uint64_t a = ror(w[n - 15], 1) ^ ror(w[n - 15], 8) ^ (w[n - 15] >> 7);
|
||||||
|
uint64_t b = ror(w[n - 2], 19) ^ ror(w[n - 2], 61) ^ (w[n - 2] >> 6);
|
||||||
|
w[n] = w[n - 16] + w[n - 7] + a + b;
|
||||||
|
}
|
||||||
|
uint64_t t[8];
|
||||||
|
for(auto n : range(8)) t[n] = h[n];
|
||||||
|
for(auto n : range(80)) {
|
||||||
|
uint64_t a = ror(t[0], 28) ^ ror(t[0], 34) ^ ror(t[0], 39);
|
||||||
|
uint64_t b = ror(t[4], 14) ^ ror(t[4], 18) ^ ror(t[4], 41);
|
||||||
|
uint64_t c = (t[0] & t[1]) ^ (t[0] & t[2]) ^ (t[1] & t[2]);
|
||||||
|
uint64_t d = (t[4] & t[5]) ^ (~t[4] & t[6]);
|
||||||
|
uint64_t e = t[7] + w[n] + cube(n) + b + d;
|
||||||
|
t[7] = t[6]; t[6] = t[5]; t[5] = t[4]; t[4] = t[3] + e;
|
||||||
|
t[3] = t[2]; t[2] = t[1]; t[1] = t[0]; t[0] = a + c + e;
|
||||||
|
}
|
||||||
|
for(auto n : range(8)) h[n] += t[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto finish() -> void {
|
||||||
|
byte(0x80);
|
||||||
|
while(queued != 112) byte(0x00);
|
||||||
|
for(auto n : range(16)) byte(length * 8 >> (15 - n) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto square(uint n) -> uint64_t {
|
||||||
|
static const uint64_t data[8] = {
|
||||||
|
0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939,
|
||||||
|
0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4,
|
||||||
|
};
|
||||||
|
return data[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cube(uint n) -> uint64_t {
|
||||||
|
static const uint64_t data[80] = {
|
||||||
|
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
|
||||||
|
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
|
||||||
|
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
|
||||||
|
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
|
||||||
|
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
|
||||||
|
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
|
||||||
|
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
|
||||||
|
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
|
||||||
|
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
|
||||||
|
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
|
||||||
|
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
|
||||||
|
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
|
||||||
|
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
|
||||||
|
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
|
||||||
|
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
|
||||||
|
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
|
||||||
|
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
|
||||||
|
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
|
||||||
|
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
|
||||||
|
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
|
||||||
|
};
|
||||||
|
return data[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t queue[16] = {0};
|
||||||
|
uint64_t w[80] = {0};
|
||||||
|
uint64_t h[8] = {0};
|
||||||
|
uint64_t queued = 0;
|
||||||
|
uint128_t length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
|
@ -0,0 +1,114 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/hash/hash.hpp>
|
||||||
|
|
||||||
|
namespace nall { namespace Hash {
|
||||||
|
|
||||||
|
struct SHA512 : Hash {
|
||||||
|
nallHash(SHA512)
|
||||||
|
|
||||||
|
auto reset() -> void override {
|
||||||
|
for(auto& n : queue) n = 0;
|
||||||
|
for(auto& n : w) n = 0;
|
||||||
|
for(auto n : range(8)) h[n] = square(n);
|
||||||
|
queued = length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input(uint8_t data) -> void override {
|
||||||
|
byte(data);
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto output() const -> vector<uint8_t> override {
|
||||||
|
SHA512 self(*this);
|
||||||
|
self.finish();
|
||||||
|
vector<uint8_t> result;
|
||||||
|
for(auto h : self.h) {
|
||||||
|
for(auto n : rrange(8)) result.append(h >> n * 8);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto value() const -> uint512_t {
|
||||||
|
uint512_t value = 0;
|
||||||
|
for(auto byte : output()) value = value << 8 | byte;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto byte(uint8_t data) -> void {
|
||||||
|
uint64_t shift = (7 - (queued & 7)) * 8;
|
||||||
|
queue[queued >> 3] &=~((uint64_t)0xff << shift);
|
||||||
|
queue[queued >> 3] |= ((uint64_t)data << shift);
|
||||||
|
if(++queued == 128) block(), queued = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto block() -> void {
|
||||||
|
for(auto n : range(16)) w[n] = queue[n];
|
||||||
|
for(auto n : range(16, 80)) {
|
||||||
|
uint64_t a = ror(w[n - 15], 1) ^ ror(w[n - 15], 8) ^ (w[n - 15] >> 7);
|
||||||
|
uint64_t b = ror(w[n - 2], 19) ^ ror(w[n - 2], 61) ^ (w[n - 2] >> 6);
|
||||||
|
w[n] = w[n - 16] + w[n - 7] + a + b;
|
||||||
|
}
|
||||||
|
uint64_t t[8];
|
||||||
|
for(auto n : range(8)) t[n] = h[n];
|
||||||
|
for(auto n : range(80)) {
|
||||||
|
uint64_t a = ror(t[0], 28) ^ ror(t[0], 34) ^ ror(t[0], 39);
|
||||||
|
uint64_t b = ror(t[4], 14) ^ ror(t[4], 18) ^ ror(t[4], 41);
|
||||||
|
uint64_t c = (t[0] & t[1]) ^ (t[0] & t[2]) ^ (t[1] & t[2]);
|
||||||
|
uint64_t d = (t[4] & t[5]) ^ (~t[4] & t[6]);
|
||||||
|
uint64_t e = t[7] + w[n] + cube(n) + b + d;
|
||||||
|
t[7] = t[6]; t[6] = t[5]; t[5] = t[4]; t[4] = t[3] + e;
|
||||||
|
t[3] = t[2]; t[2] = t[1]; t[1] = t[0]; t[0] = a + c + e;
|
||||||
|
}
|
||||||
|
for(auto n : range(8)) h[n] += t[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto finish() -> void {
|
||||||
|
byte(0x80);
|
||||||
|
while(queued != 112) byte(0x00);
|
||||||
|
for(auto n : range(16)) byte(length * 8 >> (15 - n) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto square(uint n) -> uint64_t {
|
||||||
|
static const uint64_t data[8] = {
|
||||||
|
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
|
||||||
|
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
|
||||||
|
};
|
||||||
|
return data[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cube(uint n) -> uint64_t {
|
||||||
|
static const uint64_t data[80] = {
|
||||||
|
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
|
||||||
|
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
|
||||||
|
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
|
||||||
|
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
|
||||||
|
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
|
||||||
|
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
|
||||||
|
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
|
||||||
|
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
|
||||||
|
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
|
||||||
|
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
|
||||||
|
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
|
||||||
|
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
|
||||||
|
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
|
||||||
|
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
|
||||||
|
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
|
||||||
|
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
|
||||||
|
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
|
||||||
|
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
|
||||||
|
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
|
||||||
|
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
|
||||||
|
};
|
||||||
|
return data[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t queue[16] = {0};
|
||||||
|
uint64_t w[80] = {0};
|
||||||
|
uint64_t h[8] = {0};
|
||||||
|
uint64_t queued = 0;
|
||||||
|
uint128_t length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
|
@ -0,0 +1,116 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/arithmetic.hpp>
|
||||||
|
|
||||||
|
namespace nall { namespace MAC {
|
||||||
|
|
||||||
|
struct Poly1305 {
|
||||||
|
auto initialize(uint256_t key) -> void {
|
||||||
|
uint64_t t0 = key >> 0;
|
||||||
|
uint64_t t1 = key >> 64;
|
||||||
|
pad[0] = key >> 128;
|
||||||
|
pad[1] = key >> 192;
|
||||||
|
|
||||||
|
r[0] = (t0 ) & 0xffc0fffffff;
|
||||||
|
r[1] = (t0 >> 44 | t1 << 20) & 0xfffffc0ffff;
|
||||||
|
r[2] = ( t1 >> 24) & 0x00ffffffc0f;
|
||||||
|
|
||||||
|
h[0] = 0, h[1] = 0, h[2] = 0;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto process(const uint8_t* data, uint64_t size) -> void {
|
||||||
|
while(size--) {
|
||||||
|
buffer[offset++] = *data++;
|
||||||
|
if(offset >= 16) {
|
||||||
|
block();
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto finish() -> uint128_t {
|
||||||
|
if(offset) {
|
||||||
|
buffer[offset++] = 1;
|
||||||
|
while(offset < 16) buffer[offset++] = 0;
|
||||||
|
block(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t h0 = h[0], h1 = h[1], h2 = h[2];
|
||||||
|
|
||||||
|
uint64_t c = h1 >> 44; h1 &= 0xfffffffffff;
|
||||||
|
h2 += c; c = h2 >> 42; h2 &= 0x3ffffffffff;
|
||||||
|
h0 += c * 5; c = h0 >> 44; h0 &= 0xfffffffffff;
|
||||||
|
h1 += c; c = h1 >> 44; h1 &= 0xfffffffffff;
|
||||||
|
h2 += c; c = h2 >> 42; h2 &= 0x3ffffffffff;
|
||||||
|
h0 += c * 5; c = h0 >> 44; h0 &= 0xfffffffffff;
|
||||||
|
h1 += c;
|
||||||
|
|
||||||
|
uint64_t g0 = h0 + 5; c = g0 >> 44; g0 &= 0xfffffffffff;
|
||||||
|
uint64_t g1 = h1 + c; c = g1 >> 44; g1 &= 0xfffffffffff;
|
||||||
|
uint64_t g2 = h2 + c - (1ull << 42);
|
||||||
|
|
||||||
|
c = (g2 >> 63) - 1;
|
||||||
|
g0 &= c, g1 &= c, g2 &= c;
|
||||||
|
c = ~c;
|
||||||
|
h0 = (h0 & c) | g0;
|
||||||
|
h1 = (h1 & c) | g1;
|
||||||
|
h2 = (h2 & c) | g2;
|
||||||
|
|
||||||
|
uint64_t t0 = pad[0], t1 = pad[1];
|
||||||
|
|
||||||
|
h0 += ((t0 ) & 0xfffffffffff) ; c = h0 >> 44; h0 &= 0xfffffffffff;
|
||||||
|
h1 += ((t0 >> 44 | t1 << 20) & 0xfffffffffff) + c; c = h1 >> 44; h1 &= 0xfffffffffff;
|
||||||
|
h2 += (( t1 >> 24) & 0x3ffffffffff) + c; h2 &= 0x3ffffffffff;
|
||||||
|
|
||||||
|
h0 = (h0 >> 0 | h1 << 44);
|
||||||
|
h1 = (h1 >> 20 | h2 << 24);
|
||||||
|
|
||||||
|
r[0] = 0, r[1] = 0, r[2] = 0;
|
||||||
|
h[0] = 0, h[1] = 0, h[2] = 0;
|
||||||
|
pad[0] = 0, pad[1] = 0;
|
||||||
|
memory::fill(buffer, 16);
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
return uint128_t(h1) << 64 | h0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto block(bool last = false) -> void {
|
||||||
|
uint64_t r0 = r[0], r1 = r[1], r2 = r[2];
|
||||||
|
uint64_t h0 = h[0], h1 = h[1], h2 = h[2];
|
||||||
|
|
||||||
|
uint64_t s1 = r1 * 20;
|
||||||
|
uint64_t s2 = r2 * 20;
|
||||||
|
|
||||||
|
uint64_t t0 = memory::readl<8>(buffer + 0);
|
||||||
|
uint64_t t1 = memory::readl<8>(buffer + 8);
|
||||||
|
|
||||||
|
h0 += ((t0 ) & 0xfffffffffff);
|
||||||
|
h1 += ((t0 >> 44 | t1 << 20) & 0xfffffffffff);
|
||||||
|
h2 += (( t1 >> 24) & 0x3ffffffffff) | (last ? 0 : 1ull << 40);
|
||||||
|
|
||||||
|
uint128_t d, d0, d1, d2;
|
||||||
|
d0 = (uint128_t)h0 * r0; d = (uint128_t)h1 * s2; d0 += d; d = (uint128_t)h2 * s1; d0 += d;
|
||||||
|
d1 = (uint128_t)h0 * r1; d = (uint128_t)h1 * r0; d1 += d; d = (uint128_t)h2 * s2; d1 += d;
|
||||||
|
d2 = (uint128_t)h0 * r2; d = (uint128_t)h1 * r1; d2 += d; d = (uint128_t)h2 * r0; d2 += d;
|
||||||
|
|
||||||
|
uint64_t c = (uint64_t)(d0 >> 44); h0 = (uint64_t)d0 & 0xfffffffffff;
|
||||||
|
d1 += c; c = (uint64_t)(d1 >> 44); h1 = (uint64_t)d1 & 0xfffffffffff;
|
||||||
|
d2 += c; c = (uint64_t)(d2 >> 42); h2 = (uint64_t)d2 & 0x3ffffffffff;
|
||||||
|
|
||||||
|
h0 += c * 5; c = h0 >> 44; h0 &= 0xfffffffffff;
|
||||||
|
h1 += c;
|
||||||
|
|
||||||
|
h[0] = h0, h[1] = h1, h[2] = h2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t r[3];
|
||||||
|
uint64_t h[3];
|
||||||
|
uint64_t pad[2];
|
||||||
|
|
||||||
|
uint8_t buffer[16];
|
||||||
|
uint offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
|
@ -27,6 +27,12 @@ namespace nall { namespace memory {
|
||||||
|
|
||||||
template<typename T> inline auto assign(T* target) -> void {}
|
template<typename T> inline auto assign(T* target) -> void {}
|
||||||
template<typename T, typename U, typename... P> inline auto assign(T* target, const U& value, P&&... p) -> void;
|
template<typename T, typename U, typename... P> inline auto assign(T* target, const U& value, P&&... p) -> void;
|
||||||
|
|
||||||
|
template<uint size, typename T = uint64_t> inline auto readl(const void* source) -> T;
|
||||||
|
template<uint size, typename T = uint64_t> inline auto readm(const void* source) -> T;
|
||||||
|
|
||||||
|
template<uint size, typename T = uint64_t> inline auto writel(void* target, T data) -> void;
|
||||||
|
template<uint size, typename T = uint64_t> inline auto writem(void* target, T data) -> void;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
@ -130,4 +136,28 @@ auto memory::assign(T* target, const U& value, P&&... p) -> void {
|
||||||
assign(target, forward<P>(p)...);
|
assign(target, forward<P>(p)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<uint size, typename T> auto memory::readl(const void* source) -> T {
|
||||||
|
auto p = (const uint8_t*)source;
|
||||||
|
T data = 0;
|
||||||
|
for(uint n = 0; n < size; n++) data |= T(*p++) << n * 8;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint size, typename T> auto memory::readm(const void* source) -> T {
|
||||||
|
auto p = (const uint8_t*)source;
|
||||||
|
T data = 0;
|
||||||
|
for(int n = size - 1; n >= 0; n--) data |= T(*p++) << n * 8;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint size, typename T> auto memory::writel(void* target, T data) -> void {
|
||||||
|
auto p = (uint8_t*)target;
|
||||||
|
for(uint n = 0; n < size; n++) *p++ = data >> n * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint size, typename T> auto memory::writem(void* target, T data) -> void {
|
||||||
|
auto p = (uint8_t*)target;
|
||||||
|
for(int n = size - 1; n >= 0; n--) *p++ = data >> n * 8;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include <nall/algorithm.hpp>
|
#include <nall/algorithm.hpp>
|
||||||
#include <nall/any.hpp>
|
#include <nall/any.hpp>
|
||||||
|
#include <nall/arithmetic.hpp>
|
||||||
#include <nall/array.hpp>
|
#include <nall/array.hpp>
|
||||||
#include <nall/atoi.hpp>
|
#include <nall/atoi.hpp>
|
||||||
#include <nall/bit.hpp>
|
#include <nall/bit.hpp>
|
||||||
|
|
|
@ -104,18 +104,12 @@ namespace Math {
|
||||||
#if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
|
#if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
|
||||||
#define neverinline __attribute__((noinline))
|
#define neverinline __attribute__((noinline))
|
||||||
#define alwaysinline inline __attribute__((always_inline))
|
#define alwaysinline inline __attribute__((always_inline))
|
||||||
#if !defined(PLATFORM_MACOSX)
|
|
||||||
//todo: we want this prefix; but it causes compilation errors
|
|
||||||
#define deprecated __attribute__((deprecated))
|
|
||||||
#endif
|
|
||||||
#elif defined(COMPILER_VISUALCPP)
|
#elif defined(COMPILER_VISUALCPP)
|
||||||
#define neverinline __declspec(noinline)
|
#define neverinline __declspec(noinline)
|
||||||
#define alwaysinline inline __forceinline
|
#define alwaysinline inline __forceinline
|
||||||
#define deprecated __declspec(deprecated)
|
|
||||||
#else
|
#else
|
||||||
#define neverinline
|
#define neverinline
|
||||||
#define alwaysinline inline
|
#define alwaysinline inline
|
||||||
#define deprecated
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
|
#if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
|
||||||
|
|
|
@ -24,11 +24,11 @@ private:
|
||||||
|
|
||||||
template<uint Bits> struct Natural {
|
template<uint Bits> struct Natural {
|
||||||
using type =
|
using type =
|
||||||
type_if<expression<Bits <= 8>, uint8_t,
|
typename conditional<Bits <= 8, uint8_t,
|
||||||
type_if<expression<Bits <= 16>, uint16_t,
|
typename conditional<Bits <= 16, uint16_t,
|
||||||
type_if<expression<Bits <= 32>, uint32_t,
|
typename conditional<Bits <= 32, uint32_t,
|
||||||
type_if<expression<Bits <= 64>, uint64_t,
|
typename conditional<Bits <= 64, uint64_t,
|
||||||
void>>>>;
|
void>::type>::type>::type>::type;
|
||||||
|
|
||||||
enum : type { Mask = ~0ull >> (64 - Bits) };
|
enum : type { Mask = ~0ull >> (64 - Bits) };
|
||||||
|
|
||||||
|
@ -127,11 +127,11 @@ private:
|
||||||
|
|
||||||
template<uint Bits> struct Integer {
|
template<uint Bits> struct Integer {
|
||||||
using type =
|
using type =
|
||||||
type_if<expression<Bits <= 8>, int8_t,
|
typename conditional<Bits <= 8, int8_t,
|
||||||
type_if<expression<Bits <= 16>, int16_t,
|
typename conditional<Bits <= 16, int16_t,
|
||||||
type_if<expression<Bits <= 32>, int32_t,
|
typename conditional<Bits <= 32, int32_t,
|
||||||
type_if<expression<Bits <= 64>, int64_t,
|
typename conditional<Bits <= 64, int64_t,
|
||||||
void>>>>;
|
void>::type>::type>::type>::type;
|
||||||
using utype = typename Natural<Bits>::type;
|
using utype = typename Natural<Bits>::type;
|
||||||
|
|
||||||
enum : utype { Mask = ~0ull >> (64 - Bits), Sign = 1ull << (Bits - 1) };
|
enum : utype { Mask = ~0ull >> (64 - Bits), Sign = 1ull << (Bits - 1) };
|
||||||
|
@ -231,10 +231,9 @@ private:
|
||||||
|
|
||||||
template<uint Bits> struct Real {
|
template<uint Bits> struct Real {
|
||||||
using type =
|
using type =
|
||||||
type_if<expression<Bits == 32>, float32_t,
|
typename conditional<Bits == 32, float32_t,
|
||||||
type_if<expression<Bits == 64>, float64_t,
|
typename conditional<Bits == 64, float64_t,
|
||||||
//type_if<expression<Bits == 80>, float80_t,
|
void>::type>::type;
|
||||||
void>>;
|
|
||||||
|
|
||||||
inline Real() : data(0.0) {}
|
inline Real() : data(0.0) {}
|
||||||
template<typename T> inline Real(const T& value) : data((type)value) {}
|
template<typename T> inline Real(const T& value) : data((type)value) {}
|
||||||
|
|
|
@ -52,22 +52,22 @@ struct shared_pointer {
|
||||||
operator=(move(source));
|
operator=(move(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename = enable_if<is_compatible<U>>>
|
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
|
||||||
shared_pointer(const shared_pointer<U>& source) {
|
shared_pointer(const shared_pointer<U>& source) {
|
||||||
operator=<U>(source);
|
operator=<U>(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename = enable_if<is_compatible<U>>>
|
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
|
||||||
shared_pointer(shared_pointer<U>&& source) {
|
shared_pointer(shared_pointer<U>&& source) {
|
||||||
operator=<U>(move(source));
|
operator=<U>(move(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename = enable_if<is_compatible<U>>>
|
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
|
||||||
shared_pointer(const shared_pointer_weak<U>& source) {
|
shared_pointer(const shared_pointer_weak<U>& source) {
|
||||||
operator=<U>(source);
|
operator=<U>(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename = enable_if<is_compatible<U>>>
|
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
|
||||||
shared_pointer(const shared_pointer<U>& source, T* pointer) {
|
shared_pointer(const shared_pointer<U>& source, T* pointer) {
|
||||||
if((bool)source && (T*)source.manager->pointer == pointer) {
|
if((bool)source && (T*)source.manager->pointer == pointer) {
|
||||||
manager = source.manager;
|
manager = source.manager;
|
||||||
|
@ -108,7 +108,7 @@ struct shared_pointer {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename = enable_if<is_compatible<U>>>
|
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
|
||||||
auto operator=(const shared_pointer<U>& source) -> shared_pointer& {
|
auto operator=(const shared_pointer<U>& source) -> shared_pointer& {
|
||||||
if((uintptr)this != (uintptr)&source) {
|
if((uintptr)this != (uintptr)&source) {
|
||||||
reset();
|
reset();
|
||||||
|
@ -120,7 +120,7 @@ struct shared_pointer {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename = enable_if<is_compatible<U>>>
|
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
|
||||||
auto operator=(shared_pointer&& source) -> shared_pointer& {
|
auto operator=(shared_pointer&& source) -> shared_pointer& {
|
||||||
if((uintptr)this != (uintptr)&source) {
|
if((uintptr)this != (uintptr)&source) {
|
||||||
reset();
|
reset();
|
||||||
|
@ -130,7 +130,7 @@ struct shared_pointer {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename = enable_if<is_compatible<U>>>
|
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
|
||||||
auto operator=(const shared_pointer_weak<U>& source) -> shared_pointer& {
|
auto operator=(const shared_pointer_weak<U>& source) -> shared_pointer& {
|
||||||
reset();
|
reset();
|
||||||
if((bool)source) {
|
if((bool)source) {
|
||||||
|
|
|
@ -63,9 +63,9 @@ template<typename T> struct stringify;
|
||||||
template<typename... P> inline auto print(P&&...) -> void;
|
template<typename... P> inline auto print(P&&...) -> void;
|
||||||
template<typename... P> inline auto print(FILE*, P&&...) -> void;
|
template<typename... P> inline auto print(FILE*, P&&...) -> void;
|
||||||
template<typename T> inline auto pad(const T& value, long precision = 0, char padchar = ' ') -> string;
|
template<typename T> inline auto pad(const T& value, long precision = 0, char padchar = ' ') -> string;
|
||||||
inline auto hex(uintmax value, long precision = 0, char padchar = '0') -> string;
|
template<typename T> inline auto hex(T value, long precision = 0, char padchar = '0') -> string;
|
||||||
inline auto octal(uintmax value, long precision = 0, char padchar = '0') -> string;
|
template<typename T> inline auto octal(T value, long precision = 0, char padchar = '0') -> string;
|
||||||
inline auto binary(uintmax value, long precision = 0, char padchar = '0') -> string;
|
template<typename T> inline auto binary(T value, long precision = 0, char padchar = '0') -> string;
|
||||||
template<typename T> inline auto pointer(const T* value, long precision = 0) -> string;
|
template<typename T> inline auto pointer(const T* value, long precision = 0) -> string;
|
||||||
inline auto pointer(uintptr value, long precision = 0) -> string;
|
inline auto pointer(uintptr value, long precision = 0) -> string;
|
||||||
|
|
||||||
|
@ -75,9 +75,9 @@ inline auto tokenize(string_vector& list, const char* s, const char* p) -> bool;
|
||||||
|
|
||||||
//utility.hpp
|
//utility.hpp
|
||||||
inline auto slice(string_view self, int offset = 0, int length = -1) -> string;
|
inline auto slice(string_view self, int offset = 0, int length = -1) -> string;
|
||||||
inline auto fromInteger(char* result, intmax value) -> char*;
|
template<typename T> inline auto fromInteger(char* result, T value) -> char*;
|
||||||
inline auto fromNatural(char* result, uintmax value) -> char*;
|
template<typename T> inline auto fromNatural(char* result, T value) -> char*;
|
||||||
inline auto fromReal(char* str, long double value) -> uint;
|
template<typename T> inline auto fromReal(char* str, T value) -> uint;
|
||||||
|
|
||||||
struct string {
|
struct string {
|
||||||
using type = string;
|
using type = string;
|
||||||
|
@ -177,6 +177,10 @@ public:
|
||||||
inline auto operator[](int) const -> const char&;
|
inline auto operator[](int) const -> const char&;
|
||||||
inline auto operator()(int, char) const -> char;
|
inline auto operator()(int, char) const -> char;
|
||||||
template<typename... P> inline auto assign(P&&...) -> type&;
|
template<typename... P> inline auto assign(P&&...) -> type&;
|
||||||
|
template<typename T, typename... P> inline auto prepend(const T&, P&&...) -> type&;
|
||||||
|
template<typename... P> inline auto prepend(const nall::string_format&, P&&...) -> type&;
|
||||||
|
inline auto prepend() -> type&;
|
||||||
|
template<typename T> inline auto _prepend(const stringify<T>&) -> string&;
|
||||||
template<typename T, typename... P> inline auto append(const T&, P&&...) -> type&;
|
template<typename T, typename... P> inline auto append(const T&, P&&...) -> type&;
|
||||||
template<typename... P> inline auto append(const nall::string_format&, P&&...) -> type&;
|
template<typename... P> inline auto append(const nall::string_format&, P&&...) -> type&;
|
||||||
inline auto append() -> type&;
|
inline auto append() -> type&;
|
||||||
|
|
|
@ -67,7 +67,7 @@ template<> struct stringify<signed long long> {
|
||||||
char _data[2 + sizeof(signed long long) * 3];
|
char _data[2 + sizeof(signed long long) * 3];
|
||||||
};
|
};
|
||||||
|
|
||||||
#if INTMAX_BITS >= 128
|
#if defined(__SIZEOF_INT128__)
|
||||||
template<> struct stringify<int128_t> {
|
template<> struct stringify<int128_t> {
|
||||||
stringify(int128_t source) { fromInteger(_data, source); }
|
stringify(int128_t source) { fromInteger(_data, source); }
|
||||||
auto data() const -> const char* { return _data; }
|
auto data() const -> const char* { return _data; }
|
||||||
|
@ -120,7 +120,7 @@ template<> struct stringify<unsigned long long> {
|
||||||
char _data[1 + sizeof(unsigned long long) * 3];
|
char _data[1 + sizeof(unsigned long long) * 3];
|
||||||
};
|
};
|
||||||
|
|
||||||
#if INTMAX_BITS >= 128
|
#if defined(__SIZEOF_INT128__)
|
||||||
template<> struct stringify<uint128_t> {
|
template<> struct stringify<uint128_t> {
|
||||||
stringify(uint128_t source) { fromNatural(_data, source); }
|
stringify(uint128_t source) { fromNatural(_data, source); }
|
||||||
auto data() const -> const char* { return _data; }
|
auto data() const -> const char* { return _data; }
|
||||||
|
|
|
@ -30,6 +30,26 @@ template<typename... P> auto string::assign(P&&... p) -> string& {
|
||||||
return append(forward<P>(p)...);
|
return append(forward<P>(p)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... P> auto string::prepend(const T& value, P&&... p) -> string& {
|
||||||
|
prepend(forward<P>(p)...);
|
||||||
|
return _prepend(make_string(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... P> auto string::prepend(const nall::string_format& value, P&&... p) -> string& {
|
||||||
|
prepend(forward<P>(p)...);
|
||||||
|
return format(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto string::prepend() -> string& {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> auto string::_prepend(const stringify<T>& source) -> string& {
|
||||||
|
resize(source.size() + size());
|
||||||
|
memory::move(get() + source.size(), get(), size() - source.size());
|
||||||
|
memory::copy(get(), source.data(), source.size());
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, typename... P> auto string::append(const T& value, P&&... p) -> string& {
|
template<typename T, typename... P> auto string::append(const T& value, P&&... p) -> string& {
|
||||||
_append(make_string(value));
|
_append(make_string(value));
|
||||||
return append(forward<P>(p)...);
|
return append(forward<P>(p)...);
|
||||||
|
|
|
@ -84,9 +84,9 @@ template<typename T> auto pad(const T& value, long precision, char padchar) -> s
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto hex(uintmax value, long precision, char padchar) -> string {
|
template<typename T> auto hex(T value, long precision, char padchar) -> string {
|
||||||
string buffer;
|
string buffer;
|
||||||
buffer.resize(sizeof(uintmax) * 2);
|
buffer.resize(sizeof(T) * 2);
|
||||||
char* p = buffer.get();
|
char* p = buffer.get();
|
||||||
|
|
||||||
uint size = 0;
|
uint size = 0;
|
||||||
|
@ -101,9 +101,9 @@ auto hex(uintmax value, long precision, char padchar) -> string {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto octal(uintmax value, long precision, char padchar) -> string {
|
template<typename T> auto octal(T value, long precision, char padchar) -> string {
|
||||||
string buffer;
|
string buffer;
|
||||||
buffer.resize(sizeof(uintmax) * 3);
|
buffer.resize(sizeof(T) * 3);
|
||||||
char* p = buffer.get();
|
char* p = buffer.get();
|
||||||
|
|
||||||
uint size = 0;
|
uint size = 0;
|
||||||
|
@ -117,9 +117,9 @@ auto octal(uintmax value, long precision, char padchar) -> string {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto binary(uintmax value, long precision, char padchar) -> string {
|
template<typename T> auto binary(T value, long precision, char padchar) -> string {
|
||||||
string buffer;
|
string buffer;
|
||||||
buffer.resize(sizeof(uintmax) * 8);
|
buffer.resize(sizeof(T) * 8);
|
||||||
char* p = buffer.get();
|
char* p = buffer.get();
|
||||||
|
|
||||||
uint size = 0;
|
uint size = 0;
|
||||||
|
|
|
@ -87,7 +87,7 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool
|
||||||
if(state.sections++) state.output.append("</section>");
|
if(state.sections++) state.output.append("</section>");
|
||||||
state.output.append("<section>");
|
state.output.append("<section>");
|
||||||
}
|
}
|
||||||
auto content = lines.takeLeft().trimLeft("# ", 1L).split("::", 1L);
|
auto content = lines.takeLeft().trimLeft("# ", 1L).split("::", 1L).strip();
|
||||||
auto data = markup(content[0]);
|
auto data = markup(content[0]);
|
||||||
auto name = escape(content(1, data.hash()));
|
auto name = escape(content(1, data.hash()));
|
||||||
state.output.append("<header id=\"", name, "\">", data);
|
state.output.append("<header id=\"", name, "\">", data);
|
||||||
|
@ -100,7 +100,7 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool
|
||||||
|
|
||||||
//header
|
//header
|
||||||
else if(auto depth = count(block, '=')) {
|
else if(auto depth = count(block, '=')) {
|
||||||
auto content = slice(lines.takeLeft(), depth + 1).split("::", 1L);
|
auto content = slice(lines.takeLeft(), depth + 1).split("::", 1L).strip();
|
||||||
auto data = markup(content[0]);
|
auto data = markup(content[0]);
|
||||||
auto name = escape(content(1, data.hash()));
|
auto name = escape(content(1, data.hash()));
|
||||||
if(depth <= 6) {
|
if(depth <= 6) {
|
||||||
|
@ -121,7 +121,7 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool
|
||||||
if(auto depth = count(line, '-')) {
|
if(auto depth = count(line, '-')) {
|
||||||
while(level < depth) level++, state.output.append("<ul>\n");
|
while(level < depth) level++, state.output.append("<ul>\n");
|
||||||
while(level > depth) level--, state.output.append("</ul>\n");
|
while(level > depth) level--, state.output.append("</ul>\n");
|
||||||
auto content = slice(line, depth + 1).split("::", 1L);
|
auto content = slice(line, depth + 1).split("::", 1L).strip();
|
||||||
auto data = markup(content[0]);
|
auto data = markup(content[0]);
|
||||||
auto name = escape(content(1, data.hash()));
|
auto name = escape(content(1, data.hash()));
|
||||||
state.output.append("<li><a href=\"#", name, "\">", data, "</a></li>\n");
|
state.output.append("<li><a href=\"#", name, "\">", data, "</a></li>\n");
|
||||||
|
@ -204,69 +204,6 @@ auto DML::escape(const string& text) -> string {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* //revision 0.03 parser
|
|
||||||
auto DML::markup(const string& text) -> string {
|
|
||||||
string output;
|
|
||||||
|
|
||||||
char match = 0;
|
|
||||||
uint offset = 0;
|
|
||||||
for(uint n = 0; n < text.size();) {
|
|
||||||
char a = n ? text[n - 1] : 0;
|
|
||||||
char b = text[n];
|
|
||||||
char c = text[n++ + 1];
|
|
||||||
|
|
||||||
bool d = !a || a == ' ' || a == '\t' || a == '\r' || a == '\n'; //is previous character whitespace?
|
|
||||||
bool e = !c || c == ' ' || c == '\t' || c == '\r' || c == '\n'; //is next character whitespace?
|
|
||||||
bool f = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); //is next character alphanumeric?
|
|
||||||
|
|
||||||
if(!match && d && !e) {
|
|
||||||
if(b == '*') { match = '*'; offset = n; continue; }
|
|
||||||
if(b == '/') { match = '/'; offset = n; continue; }
|
|
||||||
if(b == '_') { match = '_'; offset = n; continue; }
|
|
||||||
if(b == '~') { match = '~'; offset = n; continue; }
|
|
||||||
if(b == '|') { match = '|'; offset = n; continue; }
|
|
||||||
if(b == '[') { match = ']'; offset = n; continue; }
|
|
||||||
if(b == '{') { match = '}'; offset = n; continue; }
|
|
||||||
}
|
|
||||||
|
|
||||||
//if we reach the end of the string without a match; force a match so the content is still output
|
|
||||||
if(match && b != match && !c) { b = match; f = 0; n++; }
|
|
||||||
|
|
||||||
if(match && b == match && !f) {
|
|
||||||
match = 0;
|
|
||||||
auto content = slice(text, offset, n - offset - 1);
|
|
||||||
if(b == '*') { output.append("<strong>", escape(content), "</strong>"); continue; }
|
|
||||||
if(b == '/') { output.append("<em>", escape(content), "</em>"); continue; }
|
|
||||||
if(b == '_') { output.append("<ins>", escape(content), "</ins>"); continue; }
|
|
||||||
if(b == '~') { output.append("<del>", escape(content), "</del>"); continue; }
|
|
||||||
if(b == '|') { output.append("<code>", escape(content), "</code>"); continue; }
|
|
||||||
if(b == ']') {
|
|
||||||
auto p = content.split(" => ", 1L);
|
|
||||||
p[0].replace("@/", settings.host);
|
|
||||||
output.append("<a href=\"", escape(p[0]), "\">", escape(p(1, p[0])), "</a>");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(b == '}') {
|
|
||||||
auto p = content.split(" => ", 1L);
|
|
||||||
p[0].replace("@/", settings.host);
|
|
||||||
output.append("<img src=\"", escape(p[0]), "\" alt=\"", escape(p(1, "")), "\">");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(match) continue;
|
|
||||||
if(b == '\\' && c) { output.append(c); n++; continue; } //character escaping
|
|
||||||
if(b == '&') { output.append("&"); continue; } //entity escaping
|
|
||||||
if(b == '<') { output.append("<"); continue; } //...
|
|
||||||
if(b == '>') { output.append(">"); continue; } //...
|
|
||||||
if(b == '"') { output.append("""); continue; } //...
|
|
||||||
output.append(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
} */
|
|
||||||
|
|
||||||
auto DML::markup(const string& s) -> string {
|
auto DML::markup(const string& s) -> string {
|
||||||
string t;
|
string t;
|
||||||
|
|
||||||
|
|
|
@ -92,11 +92,11 @@ auto slice(string_view self, int offset, int length) -> string {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fromInteger(char* result, intmax value) -> char* {
|
template<typename T> auto fromInteger(char* result, T value) -> char* {
|
||||||
bool negative = value < 0;
|
bool negative = value < 0;
|
||||||
if(negative) value = -value;
|
if(negative) value = -value;
|
||||||
|
|
||||||
char buffer[64];
|
char buffer[1 + sizeof(T) * 3];
|
||||||
uint size = 0;
|
uint size = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -111,8 +111,8 @@ auto fromInteger(char* result, intmax value) -> char* {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fromNatural(char* result, uintmax value) -> char* {
|
template<typename T> auto fromNatural(char* result, T value) -> char* {
|
||||||
char buffer[64];
|
char buffer[1 + sizeof(T) * 3];
|
||||||
uint size = 0;
|
uint size = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -129,13 +129,13 @@ auto fromNatural(char* result, uintmax value) -> char* {
|
||||||
//using sprintf is certainly not the most ideal method to convert
|
//using sprintf is certainly not the most ideal method to convert
|
||||||
//a double to a string ... but attempting to parse a double by
|
//a double to a string ... but attempting to parse a double by
|
||||||
//hand, digit-by-digit, results in subtle rounding errors.
|
//hand, digit-by-digit, results in subtle rounding errors.
|
||||||
auto fromReal(char* result, long double value) -> uint {
|
template<typename T> auto fromReal(char* result, T value) -> uint {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
//Windows C-runtime does not support long double via sprintf()
|
//Windows C-runtime does not support long double via sprintf()
|
||||||
sprintf(buffer, "%f", (double)value);
|
sprintf(buffer, "%f", (double)value);
|
||||||
#else
|
#else
|
||||||
sprintf(buffer, "%Lf", value);
|
sprintf(buffer, "%Lf", (long double)value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//remove excess 0's in fraction (2.500000 -> 2.5)
|
//remove excess 0's in fraction (2.500000 -> 2.5)
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
|
||||||
|
//pull all type traits used by nall from std namespace into nall namespace
|
||||||
|
//this removes the requirement to prefix type traits with std:: within nall
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
using std::add_const;
|
using std::add_const;
|
||||||
|
using std::conditional;
|
||||||
using std::decay;
|
using std::decay;
|
||||||
using std::declval;
|
using std::declval;
|
||||||
|
using std::enable_if;
|
||||||
|
using std::enable_if_t;
|
||||||
using std::false_type;
|
using std::false_type;
|
||||||
using std::forward;
|
using std::forward;
|
||||||
using std::initializer_list;
|
using std::initializer_list;
|
||||||
|
@ -15,6 +20,8 @@ namespace nall {
|
||||||
using std::is_function;
|
using std::is_function;
|
||||||
using std::is_integral;
|
using std::is_integral;
|
||||||
using std::is_same;
|
using std::is_same;
|
||||||
|
using std::is_signed;
|
||||||
|
using std::is_unsigned;
|
||||||
using std::move;
|
using std::move;
|
||||||
using std::nullptr_t;
|
using std::nullptr_t;
|
||||||
using std::remove_extent;
|
using std::remove_extent;
|
||||||
|
@ -22,32 +29,3 @@ namespace nall {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
using std::true_type;
|
using std::true_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
template<bool C> struct expression { static constexpr bool value = C; };
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
namespace traits {
|
|
||||||
enum class enable_type {};
|
|
||||||
enum class disable_type {};
|
|
||||||
|
|
||||||
template<bool C, typename T = void> struct enable_if { using type = T; };
|
|
||||||
template<typename T> struct enable_if<false, T> {};
|
|
||||||
|
|
||||||
template<bool C, typename T = void> struct disable_if { using type = T; };
|
|
||||||
template<typename T> struct disable_if<true, T> {};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename C, typename T = void> using enable_if = typename traits::enable_if<C::value, T>::type;
|
|
||||||
template<typename C, typename T = void> using disable_if = typename traits::disable_if<C::value, T>::type;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
namespace traits {
|
|
||||||
template<bool C, typename T, typename F> struct type_if { using type = T; };
|
|
||||||
template<typename T, typename F> struct type_if<false, T, F> { using type = F; };
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename C, typename T, typename F> using type_if = typename traits::type_if<C::value, T, F>::type;
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct shared_memory {
|
||||||
auto empty() const -> bool { return true; }
|
auto empty() const -> bool { return true; }
|
||||||
auto size() const -> uint { return 0; }
|
auto size() const -> uint { return 0; }
|
||||||
auto acquired() const -> bool { return false; }
|
auto acquired() const -> bool { return false; }
|
||||||
auto acquire() -> uint8* { return nullptr; }
|
auto acquire() -> uint8_t* { return nullptr; }
|
||||||
auto release() -> void {}
|
auto release() -> void {}
|
||||||
auto reset() -> void {}
|
auto reset() -> void {}
|
||||||
auto create(const string& name, uint size) -> bool { return false; }
|
auto create(const string& name, uint size) -> bool { return false; }
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nall/xorg/xorg.hpp>
|
||||||
|
|
||||||
|
namespace nall { namespace Clipboard {
|
||||||
|
|
||||||
|
auto clear() -> void {
|
||||||
|
XDisplay display;
|
||||||
|
if(auto atom = XInternAtom(display, "CLIPBOARD", XlibTrue)) {
|
||||||
|
XSetSelectionOwner(display, atom, XlibNone, XlibCurrentTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
|
@ -1,15 +1,8 @@
|
||||||
#ifndef NALL_XORG_GUARD_HPP
|
#ifndef NALL_XORG_GUARD_HPP
|
||||||
#define NALL_XORG_GUARD_HPP
|
#define NALL_XORG_GUARD_HPP
|
||||||
|
|
||||||
#define None
|
#define Atom XlibAtom
|
||||||
#undef XlibNone
|
|
||||||
#define XlibNone 0L
|
|
||||||
#define Bool XlibBool
|
#define Bool XlibBool
|
||||||
#define Button1 XlibButton1
|
|
||||||
#define Button2 XlibButton2
|
|
||||||
#define Button3 XlibButton3
|
|
||||||
#define Button4 XlibButton4
|
|
||||||
#define Button5 XlibButton5
|
|
||||||
#define Display XlibDisplay
|
#define Display XlibDisplay
|
||||||
#define Screen XlibScreen
|
#define Screen XlibScreen
|
||||||
#define Window XlibWindow
|
#define Window XlibWindow
|
||||||
|
@ -17,15 +10,35 @@
|
||||||
#else
|
#else
|
||||||
#undef NALL_XORG_GUARD_HPP
|
#undef NALL_XORG_GUARD_HPP
|
||||||
|
|
||||||
#undef None
|
#undef Atom
|
||||||
#undef Bool
|
#undef Bool
|
||||||
|
#undef Display
|
||||||
|
#undef Screen
|
||||||
|
#undef Window
|
||||||
|
|
||||||
|
#ifndef NALL_XORG_GUARD_CONSTANTS
|
||||||
|
#define NALL_XORG_GUARD_CONSTANTS
|
||||||
|
enum XlibConstants : int {
|
||||||
|
XlibButton1 = Button1,
|
||||||
|
XlibButton2 = Button2,
|
||||||
|
XlibButton3 = Button3,
|
||||||
|
XlibButton4 = Button4,
|
||||||
|
XlibButton5 = Button5,
|
||||||
|
XlibCurrentTime = CurrentTime,
|
||||||
|
XlibFalse = False,
|
||||||
|
XlibNone = None,
|
||||||
|
XlibTrue = True,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef Button1
|
#undef Button1
|
||||||
#undef Button2
|
#undef Button2
|
||||||
#undef Button3
|
#undef Button3
|
||||||
#undef Button4
|
#undef Button4
|
||||||
#undef Button5
|
#undef Button5
|
||||||
#undef Display
|
#undef CurrentTime
|
||||||
#undef Screen
|
#undef False
|
||||||
#undef Window
|
#undef None
|
||||||
|
#undef True
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,3 +7,12 @@
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <nall/xorg/guard.hpp>
|
#include <nall/xorg/guard.hpp>
|
||||||
|
|
||||||
|
struct XDisplay {
|
||||||
|
XDisplay() { _display = XOpenDisplay(nullptr); }
|
||||||
|
~XDisplay() { XCloseDisplay(_display); }
|
||||||
|
operator XlibDisplay*() const { return _display; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
XlibDisplay* _display;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue