bsnes/nall/varint.hpp

123 lines
3.6 KiB
C++
Raw Normal View History

#pragma once
#include <nall/primitives.hpp>
#include <nall/serializer.hpp>
#include <nall/stdint.hpp>
namespace nall {
struct varint {
virtual auto read() -> uint8_t = 0;
virtual auto write(uint8_t) -> void = 0;
Update to v099r14 release. byuu says: Changelog: - (u)int(max,ptr) abbreviations removed; use _t suffix now [didn't feel like they were contributing enough to be worth it] - cleaned up nall::integer,natural,real functionality - toInteger, toNatural, toReal for parsing strings to numbers - fromInteger, fromNatural, fromReal for creating strings from numbers - (string,Markup::Node,SQL-based-classes)::(integer,natural,real) left unchanged - template<typename T> numeral(T value, long padding, char padchar) -> string for print() formatting - deduces integer,natural,real based on T ... cast the value if you want to override - there still exists binary,octal,hex,pointer for explicit print() formatting - lstring -> string_vector [but using lstring = string_vector; is declared] - would be nice to remove the using lstring eventually ... but that'd probably require 10,000 lines of changes >_> - format -> string_format [no using here; format was too ambiguous] - using integer = Integer<sizeof(int)*8>; and using natural = Natural<sizeof(uint)*8>; declared - for consistency with boolean. These three are meant for creating zero-initialized values implicitly (various uses) - R65816::io() -> idle() and SPC700::io() -> idle() [more clear; frees up struct IO {} io; naming] - SFC CPU, PPU, SMP use struct IO {} io; over struct (Status,Registers) {} (status,registers); now - still some CPU::Status status values ... they didn't really fit into IO functionality ... will have to think about this more - SFC CPU, PPU, SMP now use step() exclusively instead of addClocks() calling into step() - SFC CPU joypad1_bits, joypad2_bits were unused; killed them - SFC PPU CGRAM moved into PPU::Screen; since nothing else uses it - SFC PPU OAM moved into PPU::Object; since nothing else uses it - the raw uint8[544] array is gone. OAM::read() constructs values from the OAM::Object[512] table now - this avoids having to determine how we want to sub-divide the two OAM memory sections - this also eliminates the OAM::synchronize() functionality - probably more I'm forgetting The FPS fluctuations are driving me insane. This WIP went from 128fps to 137fps. Settled on 133.5fps for the final build. But nothing I changed should have affected performance at all. This level of fluctuation makes it damn near impossible to know whether I'm speeding things up or slowing things down with changes.
2016-07-01 11:50:32 +00:00
auto readvu() -> uintmax_t {
uintmax_t data = 0, shift = 1;
while(true) {
uint8_t x = read();
data += (x & 0x7f) * shift;
if(x & 0x80) break;
shift <<= 7;
data += shift;
}
return data;
}
Update to v099r14 release. byuu says: Changelog: - (u)int(max,ptr) abbreviations removed; use _t suffix now [didn't feel like they were contributing enough to be worth it] - cleaned up nall::integer,natural,real functionality - toInteger, toNatural, toReal for parsing strings to numbers - fromInteger, fromNatural, fromReal for creating strings from numbers - (string,Markup::Node,SQL-based-classes)::(integer,natural,real) left unchanged - template<typename T> numeral(T value, long padding, char padchar) -> string for print() formatting - deduces integer,natural,real based on T ... cast the value if you want to override - there still exists binary,octal,hex,pointer for explicit print() formatting - lstring -> string_vector [but using lstring = string_vector; is declared] - would be nice to remove the using lstring eventually ... but that'd probably require 10,000 lines of changes >_> - format -> string_format [no using here; format was too ambiguous] - using integer = Integer<sizeof(int)*8>; and using natural = Natural<sizeof(uint)*8>; declared - for consistency with boolean. These three are meant for creating zero-initialized values implicitly (various uses) - R65816::io() -> idle() and SPC700::io() -> idle() [more clear; frees up struct IO {} io; naming] - SFC CPU, PPU, SMP use struct IO {} io; over struct (Status,Registers) {} (status,registers); now - still some CPU::Status status values ... they didn't really fit into IO functionality ... will have to think about this more - SFC CPU, PPU, SMP now use step() exclusively instead of addClocks() calling into step() - SFC CPU joypad1_bits, joypad2_bits were unused; killed them - SFC PPU CGRAM moved into PPU::Screen; since nothing else uses it - SFC PPU OAM moved into PPU::Object; since nothing else uses it - the raw uint8[544] array is gone. OAM::read() constructs values from the OAM::Object[512] table now - this avoids having to determine how we want to sub-divide the two OAM memory sections - this also eliminates the OAM::synchronize() functionality - probably more I'm forgetting The FPS fluctuations are driving me insane. This WIP went from 128fps to 137fps. Settled on 133.5fps for the final build. But nothing I changed should have affected performance at all. This level of fluctuation makes it damn near impossible to know whether I'm speeding things up or slowing things down with changes.
2016-07-01 11:50:32 +00:00
auto readvs() -> intmax_t {
uintmax_t data = readvu();
bool negate = data & 1;
data >>= 1;
if(negate) data = ~data;
return data;
}
Update to v099r14 release. byuu says: Changelog: - (u)int(max,ptr) abbreviations removed; use _t suffix now [didn't feel like they were contributing enough to be worth it] - cleaned up nall::integer,natural,real functionality - toInteger, toNatural, toReal for parsing strings to numbers - fromInteger, fromNatural, fromReal for creating strings from numbers - (string,Markup::Node,SQL-based-classes)::(integer,natural,real) left unchanged - template<typename T> numeral(T value, long padding, char padchar) -> string for print() formatting - deduces integer,natural,real based on T ... cast the value if you want to override - there still exists binary,octal,hex,pointer for explicit print() formatting - lstring -> string_vector [but using lstring = string_vector; is declared] - would be nice to remove the using lstring eventually ... but that'd probably require 10,000 lines of changes >_> - format -> string_format [no using here; format was too ambiguous] - using integer = Integer<sizeof(int)*8>; and using natural = Natural<sizeof(uint)*8>; declared - for consistency with boolean. These three are meant for creating zero-initialized values implicitly (various uses) - R65816::io() -> idle() and SPC700::io() -> idle() [more clear; frees up struct IO {} io; naming] - SFC CPU, PPU, SMP use struct IO {} io; over struct (Status,Registers) {} (status,registers); now - still some CPU::Status status values ... they didn't really fit into IO functionality ... will have to think about this more - SFC CPU, PPU, SMP now use step() exclusively instead of addClocks() calling into step() - SFC CPU joypad1_bits, joypad2_bits were unused; killed them - SFC PPU CGRAM moved into PPU::Screen; since nothing else uses it - SFC PPU OAM moved into PPU::Object; since nothing else uses it - the raw uint8[544] array is gone. OAM::read() constructs values from the OAM::Object[512] table now - this avoids having to determine how we want to sub-divide the two OAM memory sections - this also eliminates the OAM::synchronize() functionality - probably more I'm forgetting The FPS fluctuations are driving me insane. This WIP went from 128fps to 137fps. Settled on 133.5fps for the final build. But nothing I changed should have affected performance at all. This level of fluctuation makes it damn near impossible to know whether I'm speeding things up or slowing things down with changes.
2016-07-01 11:50:32 +00:00
auto writevu(uintmax_t data) -> void {
while(true) {
uint8_t x = data & 0x7f;
data >>= 7;
if(data == 0) return write(0x80 | x);
write(x);
data--;
}
}
Update to v099r14 release. byuu says: Changelog: - (u)int(max,ptr) abbreviations removed; use _t suffix now [didn't feel like they were contributing enough to be worth it] - cleaned up nall::integer,natural,real functionality - toInteger, toNatural, toReal for parsing strings to numbers - fromInteger, fromNatural, fromReal for creating strings from numbers - (string,Markup::Node,SQL-based-classes)::(integer,natural,real) left unchanged - template<typename T> numeral(T value, long padding, char padchar) -> string for print() formatting - deduces integer,natural,real based on T ... cast the value if you want to override - there still exists binary,octal,hex,pointer for explicit print() formatting - lstring -> string_vector [but using lstring = string_vector; is declared] - would be nice to remove the using lstring eventually ... but that'd probably require 10,000 lines of changes >_> - format -> string_format [no using here; format was too ambiguous] - using integer = Integer<sizeof(int)*8>; and using natural = Natural<sizeof(uint)*8>; declared - for consistency with boolean. These three are meant for creating zero-initialized values implicitly (various uses) - R65816::io() -> idle() and SPC700::io() -> idle() [more clear; frees up struct IO {} io; naming] - SFC CPU, PPU, SMP use struct IO {} io; over struct (Status,Registers) {} (status,registers); now - still some CPU::Status status values ... they didn't really fit into IO functionality ... will have to think about this more - SFC CPU, PPU, SMP now use step() exclusively instead of addClocks() calling into step() - SFC CPU joypad1_bits, joypad2_bits were unused; killed them - SFC PPU CGRAM moved into PPU::Screen; since nothing else uses it - SFC PPU OAM moved into PPU::Object; since nothing else uses it - the raw uint8[544] array is gone. OAM::read() constructs values from the OAM::Object[512] table now - this avoids having to determine how we want to sub-divide the two OAM memory sections - this also eliminates the OAM::synchronize() functionality - probably more I'm forgetting The FPS fluctuations are driving me insane. This WIP went from 128fps to 137fps. Settled on 133.5fps for the final build. But nothing I changed should have affected performance at all. This level of fluctuation makes it damn near impossible to know whether I'm speeding things up or slowing things down with changes.
2016-07-01 11:50:32 +00:00
auto writevs(intmax_t data) -> void {
bool negate = data < 0;
if(negate) data = ~data;
data = (data << 1) | negate;
writevu(data);
}
};
struct VariadicNatural {
inline VariadicNatural() : mask(~0ull) { assign(0); }
template<typename T> inline VariadicNatural(const T& value) : mask(~0ull) { assign(value); }
inline operator uint64_t() const { return data; }
template<typename T> inline auto& operator=(const T& value) { return assign(value); }
inline auto operator++(int) { auto value = data; assign(data + 1); return value; }
inline auto operator--(int) { auto value = data; assign(data - 1); return value; }
inline auto& operator++() { return assign(data + 1); }
inline auto& operator--() { return assign(data - 1); }
inline auto& operator &=(const uint64_t value) { return assign(data & value); }
inline auto& operator |=(const uint64_t value) { return assign(data | value); }
inline auto& operator ^=(const uint64_t value) { return assign(data ^ value); }
inline auto& operator<<=(const uint64_t value) { return assign(data << value); }
inline auto& operator>>=(const uint64_t value) { return assign(data >> value); }
inline auto& operator +=(const uint64_t value) { return assign(data + value); }
inline auto& operator -=(const uint64_t value) { return assign(data - value); }
inline auto& operator *=(const uint64_t value) { return assign(data * value); }
inline auto& operator /=(const uint64_t value) { return assign(data / value); }
inline auto& operator %=(const uint64_t value) { return assign(data % value); }
inline auto resize(uint bits) {
assert(bits <= 64);
mask = ~0ull >> (64 - bits);
data &= mask;
}
inline auto serialize(serializer& s) {
s(data);
s(mask);
}
struct Reference {
inline Reference(VariadicNatural& self, uint lo, uint hi) : self(self), Lo(lo), Hi(hi) {}
inline operator uint64_t() const {
const uint64_t RangeBits = Hi - Lo + 1;
const uint64_t RangeMask = (((1ull << RangeBits) - 1) << Lo) & self.mask;
return (self & RangeMask) >> Lo;
}
inline auto& operator=(const uint64_t value) {
const uint64_t RangeBits = Hi - Lo + 1;
const uint64_t RangeMask = (((1ull << RangeBits) - 1) << Lo) & self.mask;
self.data = (self.data & ~RangeMask) | ((value << Lo) & RangeMask);
return *this;
}
private:
VariadicNatural& self;
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}; }
private:
auto assign(uint64_t value) -> VariadicNatural& {
data = value & mask;
return *this;
}
uint64_t data;
uint64_t mask;
};
Update to v087r30 release. byuu says: Changelog: - DMA channel masks added (some are 27-bit source/target and some are 14-bit length -- hooray, varuint_t class.) - No more state.pending flags. Instead, we set dma.pending flag when we want a transfer (fixes GBA Video - Pokemon audio) [Cydrak] - fixed OBJ Vmosaic [Cydrak, krom] - OBJ cannot read <=0x13fff in BG modes 3-5 (fixes the garbled tile at the top-left of some games) - DMA timing should be much closer to hardware now, but probably not perfect - PPU frame blending uses blargg's bit-perfect, rounded method (slower, but what can you do?) - GBA carts really unload now - added nall/gba/cartridge.hpp: used when there is no manifest. Scans ROMs for library tags, and selects the first valid one found - added EEPROM auto-detection when EEPROM size=0. Forces disk/save state size to 8192 (otherwise states could crash between pre and post detect.) - detects first read after a set read address command when the size is zero, and sets all subsequent bit-lengths to that value, prints detected size to terminal - added nall/nes/cartridge.hpp: moves iNES detection out of emulation core. Important to note: long-term goal is to remove all nall/(system)/cartridge.hpp detections from the core and replace with databases. All in good time. Anyway, the GBA workarounds should work for ~98.5% of the library, if my pre-scanning was correct (~40 games with odd tags. I reject ones without numeric versions now, too.) I think we're basically at a point where we can release a new version now. Compatibility should be relatively high (at least for a first release), and fixes are only going to affect one or two games at a time. I'd like to start doing some major cleaning house internally (rename NES->Famicom, SNES->SuperFamicom and such.) Would be much wiser to do that on a .01 WIP to minimize regressions. The main problems with a release now: - speed is pretty bad, haven't really optimized much yet (not sure how much we can improve it yet, this usually isn't easy) - sound isn't -great-, but the GBA audio sucks anyway :P - couple of known bugs (Sonic X video, etc.)
2012-04-22 10:49:19 +00:00
}