bsnes-libretro/nall/primitives.hpp
Tim Allen f3e67da937 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.
2016-10-28 08:16:58 +11:00

268 lines
11 KiB
C++

#pragma once
#include <nall/serializer.hpp>
#include <nall/traits.hpp>
namespace nall {
struct Boolean {
inline Boolean() : data(false) {}
template<typename T> inline Boolean(const T& value) : data(value) {}
inline operator bool() const { return data; }
template<typename T> inline auto& operator=(const T& value) { data = value; return *this; }
inline auto flip() { return data ^= 1; }
inline auto raise() { return data == 0 ? data = 1, true : false; }
inline auto lower() { return data == 1 ? data = 0, true : false; }
inline auto serialize(serializer& s) { s(data); }
private:
bool data;
};
template<uint Bits> struct Natural {
using type =
typename conditional<Bits <= 8, uint8_t,
typename conditional<Bits <= 16, uint16_t,
typename conditional<Bits <= 32, uint32_t,
typename conditional<Bits <= 64, uint64_t,
void>::type>::type>::type>::type;
enum : type { Mask = ~0ull >> (64 - Bits) };
inline Natural() : data(0) {}
template<typename T> inline Natural(const T& value) { set(value); }
inline operator type() const { return data; }
template<typename T> inline auto& operator=(const T& value) { set(value); return *this; }
inline auto operator++(int) { type value = data; set(data + 1); return value; }
inline auto operator--(int) { type value = data; set(data - 1); return value; }
inline auto& operator++() { set(data + 1); return *this; }
inline auto& operator--() { set(data - 1); return *this; }
inline auto& operator &=(const type value) { set(data & value); return *this; }
inline auto& operator |=(const type value) { set(data | value); return *this; }
inline auto& operator ^=(const type value) { set(data ^ value); return *this; }
inline auto& operator<<=(const type value) { set(data << value); return *this; }
inline auto& operator>>=(const type value) { set(data >> value); return *this; }
inline auto& operator +=(const type value) { set(data + value); return *this; }
inline auto& operator -=(const type value) { set(data - value); return *this; }
inline auto& operator *=(const type value) { set(data * value); return *this; }
inline auto& operator /=(const type value) { set(data / value); return *this; }
inline auto& operator %=(const type value) { set(data % value); return *this; }
inline auto serialize(serializer& s) { s(data); }
struct Reference {
inline Reference(Natural& source, uint lo, uint hi) : source(source), Lo(lo), Hi(hi) {}
inline auto& operator=(Reference& source) { return set(source.get()); }
inline auto get() const -> type {
const type RangeBits = Hi - Lo + 1;
const type RangeMask = (((1ull << RangeBits) - 1) << Lo) & Mask;
return (source & RangeMask) >> Lo;
}
inline auto& set(const type value) {
const type RangeBits = Hi - Lo + 1;
const type RangeMask = (((1ull << RangeBits) - 1) << Lo) & Mask;
source = (source & ~RangeMask) | ((value << Lo) & RangeMask);
return *this;
}
inline operator type() const { return get(); }
inline auto& operator =(const type value) { return set( value); }
inline auto& operator &=(const type value) { return set(get() & value); }
inline auto& operator |=(const type value) { return set(get() | value); }
inline auto& operator ^=(const type value) { return set(get() ^ value); }
inline auto& operator<<=(const type value) { return set(get() << value); }
inline auto& operator>>=(const type value) { return set(get() >> value); }
inline auto& operator +=(const type value) { return set(get() + value); }
inline auto& operator -=(const type value) { return set(get() - value); }
inline auto& operator *=(const type value) { return set(get() * value); }
inline auto& operator /=(const type value) { return set(get() / value); }
inline auto& operator %=(const type value) { return set(get() % value); }
inline auto operator++(int) { auto value = get(); set(value + 1); return value; }
inline auto operator--(int) { auto value = get(); set(value - 1); return value; }
inline auto& operator++() { return set(get() + 1); }
inline auto& operator--() { return set(get() - 1); }
private:
Natural& source;
const type Lo;
const type Hi;
};
inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; }
inline auto bit(uint index) -> Reference { return {*this, index, index}; }
inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
inline auto bits(uint lo, uint hi) const -> const Reference { return {(Natural&)*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; }
inline auto bit(uint index) const -> const Reference { return {(Natural&)*this, index, index}; }
inline auto byte(uint index) const -> const Reference { return {(Natural&)*this, index * 8 + 0, index * 8 + 7}; }
inline auto clamp(uint bits) -> uintmax {
const uintmax b = 1ull << (bits - 1);
const uintmax m = b * 2 - 1;
return data < m ? data : m;
}
inline auto clip(uint bits) -> uintmax {
const uintmax b = 1ull << (bits - 1);
const uintmax m = b * 2 - 1;
return data & m;
}
private:
auto set(type value) -> void {
data = value & Mask;
}
type data;
};
template<uint Bits> struct Integer {
using type =
typename conditional<Bits <= 8, int8_t,
typename conditional<Bits <= 16, int16_t,
typename conditional<Bits <= 32, int32_t,
typename conditional<Bits <= 64, int64_t,
void>::type>::type>::type>::type;
using utype = typename Natural<Bits>::type;
enum : utype { Mask = ~0ull >> (64 - Bits), Sign = 1ull << (Bits - 1) };
inline Integer() : data(0) {}
template<typename T> inline Integer(const T& value) { set(value); }
inline operator type() const { return data; }
template<typename T> inline auto& operator=(const T& value) { set(value); return *this; }
inline auto operator++(int) { type value = data; set(data + 1); return value; }
inline auto operator--(int) { type value = data; set(data - 1); return value; }
inline auto& operator++() { set(data + 1); return *this; }
inline auto& operator--() { set(data - 1); return *this; }
inline auto& operator &=(const type value) { set(data & value); return *this; }
inline auto& operator |=(const type value) { set(data | value); return *this; }
inline auto& operator ^=(const type value) { set(data ^ value); return *this; }
inline auto& operator<<=(const type value) { set(data << value); return *this; }
inline auto& operator>>=(const type value) { set(data >> value); return *this; }
inline auto& operator +=(const type value) { set(data + value); return *this; }
inline auto& operator -=(const type value) { set(data - value); return *this; }
inline auto& operator *=(const type value) { set(data * value); return *this; }
inline auto& operator /=(const type value) { set(data / value); return *this; }
inline auto& operator %=(const type value) { set(data % value); return *this; }
inline auto serialize(serializer& s) { s(data); }
struct Reference {
inline Reference(Integer& source, uint lo, uint hi) : source(source), Lo(lo), Hi(hi) {}
inline auto& operator=(const Reference& source) { return set(source.get()); }
inline auto get() const -> utype {
const type RangeBits = Hi - Lo + 1;
const type RangeMask = (((1ull << RangeBits) - 1) << Lo) & Mask;
return ((utype)source & RangeMask) >> Lo;
}
inline auto& set(const utype value) {
const type RangeBits = Hi - Lo + 1;
const type RangeMask = (((1ull << RangeBits) - 1) << Lo) & Mask;
source = ((utype)source & ~RangeMask) | ((value << Lo) & RangeMask);
return *this;
}
inline operator utype() const { return get(); }
inline auto& operator =(const utype value) { return set( value); }
inline auto& operator &=(const utype value) { return set(get() & value); }
inline auto& operator |=(const utype value) { return set(get() | value); }
inline auto& operator ^=(const utype value) { return set(get() ^ value); }
inline auto& operator<<=(const utype value) { return set(get() << value); }
inline auto& operator>>=(const utype value) { return set(get() >> value); }
inline auto& operator +=(const utype value) { return set(get() + value); }
inline auto& operator -=(const utype value) { return set(get() - value); }
inline auto& operator *=(const utype value) { return set(get() * value); }
inline auto& operator /=(const utype value) { return set(get() / value); }
inline auto& operator %=(const utype value) { return set(get() % value); }
inline auto operator++(int) { auto value = get(); set(value + 1); return value; }
inline auto operator--(int) { auto value = get(); set(value - 1); return value; }
inline auto& operator++() { return set(get() + 1); }
inline auto& operator--() { return set(get() - 1); }
private:
Integer& source;
const uint Lo;
const uint Hi;
};
inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; }
inline auto bit(uint index) -> Reference { return {*this, index, index}; }
inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
inline auto bits(uint lo, uint hi) const -> const Reference { return {(Integer&)*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; }
inline auto bit(uint index) const -> const Reference { return {(Integer&)*this, index, index}; }
inline auto byte(uint index) const -> const Reference { return {(Integer&)*this, index * 8 + 0, index * 8 + 7}; }
inline auto clamp(uint bits) -> intmax {
const intmax b = 1ull << (bits - 1);
const intmax m = b - 1;
return data > m ? m : data < -b ? -b : data;
}
inline auto clip(uint bits) -> intmax {
const uintmax b = 1ull << (bits - 1);
const uintmax m = b * 2 - 1;
return ((data & m) ^ b) - b;
}
private:
auto set(type value) -> void {
data = ((value & Mask) ^ Sign) - Sign;
}
type data;
};
template<uint Bits> struct Real {
using type =
typename conditional<Bits == 32, float32_t,
typename conditional<Bits == 64, float64_t,
void>::type>::type;
inline Real() : data(0.0) {}
template<typename T> inline Real(const T& value) : data((type)value) {}
inline operator type() const { return data; }
template<typename T> inline auto& operator=(const T& value) { data = (type)value; return *this; }
inline auto operator++(int) { type value = data; ++data; return value; }
inline auto operator--(int) { type value = data; --data; return value; }
inline auto& operator++() { data++; return *this; }
inline auto& operator--() { data--; return *this; }
inline auto& operator+=(const type value) { data = data + value; return *this; }
inline auto& operator-=(const type value) { data = data - value; return *this; }
inline auto& operator*=(const type value) { data = data * value; return *this; }
inline auto& operator/=(const type value) { data = data / value; return *this; }
inline auto& operator%=(const type value) { data = data % value; return *this; }
inline auto serialize(serializer& s) { s(data); }
private:
type data;
};
using boolean = nall::Boolean;
using natural = nall::Natural<sizeof(uint) * 8>;
using integer = nall::Integer<sizeof(int) * 8>;
using real = nall::Real<sizeof(double) * 8>;
}