diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 4f0b27f4..ef070174 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -31,7 +31,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "106.84"; + static const string Version = "106.85"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/higan/emulator/interface.hpp b/higan/emulator/interface.hpp index 759ba7ee..c097925b 100644 --- a/higan/emulator/interface.hpp +++ b/higan/emulator/interface.hpp @@ -24,7 +24,6 @@ struct Interface { uint internalWidth = 0; uint internalHeight = 0; double aspectCorrection = 0; - double refreshRate = 0; }; struct Port { diff --git a/higan/fc/interface/interface.cpp b/higan/fc/interface/interface.cpp index 24fddf95..70b80e66 100644 --- a/higan/fc/interface/interface.cpp +++ b/higan/fc/interface/interface.cpp @@ -22,7 +22,6 @@ auto Interface::display() -> Display { display.internalWidth = 256; display.internalHeight = 240; display.aspectCorrection = 8.0 / 7.0; - display.refreshRate = system.frequency() / (ppu.vlines() * ppu.rate() * 341.0); return display; } diff --git a/higan/gb/interface/interface.cpp b/higan/gb/interface/interface.cpp index f7dc4ec8..8e612b14 100644 --- a/higan/gb/interface/interface.cpp +++ b/higan/gb/interface/interface.cpp @@ -16,7 +16,6 @@ auto Interface::display() -> Display { display.internalWidth = 160; display.internalHeight = 144; display.aspectCorrection = 1.0; - display.refreshRate = (4.0 * 1024.0 * 1024.0) / (154.0 * 456.0); return display; } diff --git a/higan/gba/interface/interface.cpp b/higan/gba/interface/interface.cpp index a7e54330..a681b910 100644 --- a/higan/gba/interface/interface.cpp +++ b/higan/gba/interface/interface.cpp @@ -21,7 +21,6 @@ auto Interface::display() -> Display { display.internalWidth = 240; display.internalHeight = 160; display.aspectCorrection = 1.0; - display.refreshRate = system.frequency() / (228.0 * 1232.0); if(settings.rotateLeft) { swap(display.width, display.height); swap(display.internalWidth, display.internalHeight); diff --git a/higan/md/interface/interface.cpp b/higan/md/interface/interface.cpp index 1c235378..d3e38d4f 100644 --- a/higan/md/interface/interface.cpp +++ b/higan/md/interface/interface.cpp @@ -22,7 +22,6 @@ auto Interface::display() -> Display { display.internalWidth = 1280; display.internalHeight = 480; display.aspectCorrection = 1.0; - display.refreshRate = (system.frequency() / 2.0) / (vdp.frameHeight() * 1710.0); return display; } diff --git a/higan/ms/interface/colecovision.cpp b/higan/ms/interface/colecovision.cpp index b0ff5fc7..808ee873 100644 --- a/higan/ms/interface/colecovision.cpp +++ b/higan/ms/interface/colecovision.cpp @@ -15,8 +15,6 @@ auto ColecoVisionInterface::display() -> Display { display.internalWidth = 256; display.internalHeight = 192; display.aspectCorrection = 1.0; - if(Region::NTSC()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0); - if(Region::PAL()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0); return display; } diff --git a/higan/ms/interface/game-gear.cpp b/higan/ms/interface/game-gear.cpp index b3844bec..a3329503 100644 --- a/higan/ms/interface/game-gear.cpp +++ b/higan/ms/interface/game-gear.cpp @@ -15,7 +15,6 @@ auto GameGearInterface::display() -> Display { display.internalWidth = 160; display.internalHeight = 144; display.aspectCorrection = 1.0; - display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0); return display; } diff --git a/higan/ms/interface/master-system.cpp b/higan/ms/interface/master-system.cpp index 5380f608..0e5ed284 100644 --- a/higan/ms/interface/master-system.cpp +++ b/higan/ms/interface/master-system.cpp @@ -15,8 +15,6 @@ auto MasterSystemInterface::display() -> Display { display.internalWidth = 256; display.internalHeight = 240; display.aspectCorrection = 8.0 / 7.0; - if(Region::NTSC()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0); - if(Region::PAL()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0); return display; } diff --git a/higan/ms/interface/sc-3000.cpp b/higan/ms/interface/sc-3000.cpp index 5f400814..f2fbd5ea 100644 --- a/higan/ms/interface/sc-3000.cpp +++ b/higan/ms/interface/sc-3000.cpp @@ -15,8 +15,6 @@ auto SC3000Interface::display() -> Display { display.internalWidth = 256; display.internalHeight = 192; display.aspectCorrection = 1.0; - if(Region::NTSC()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0); - if(Region::PAL()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0); return display; } diff --git a/higan/ms/interface/sg-1000.cpp b/higan/ms/interface/sg-1000.cpp index 28410927..1f94a4c8 100644 --- a/higan/ms/interface/sg-1000.cpp +++ b/higan/ms/interface/sg-1000.cpp @@ -15,8 +15,6 @@ auto SG1000Interface::display() -> Display { display.internalWidth = 256; display.internalHeight = 192; display.aspectCorrection = 1.0; - if(Region::NTSC()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0); - if(Region::PAL()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0); return display; } diff --git a/higan/msx/interface/interface.cpp b/higan/msx/interface/interface.cpp index 65122783..48b429a5 100644 --- a/higan/msx/interface/interface.cpp +++ b/higan/msx/interface/interface.cpp @@ -19,7 +19,6 @@ auto Interface::display() -> Display { display.internalWidth = 256; display.internalHeight = 192; display.aspectCorrection = 1.0; - display.refreshRate = 60.0; //todo: PAL return display; } diff --git a/higan/ngp/cpu/cpu.cpp b/higan/ngp/cpu/cpu.cpp index de3a165c..874d26e9 100644 --- a/higan/ngp/cpu/cpu.cpp +++ b/higan/ngp/cpu/cpu.cpp @@ -12,8 +12,7 @@ auto CPU::Enter() -> void { auto CPU::main() -> void { static uint ctr=0; -if(++ctr < 200) print(disassemble(), "\n"); -else return step(1); +if(++ctr<200) print(disassemble(), "\n"); instruction(); step(1); } @@ -30,6 +29,17 @@ auto CPU::power() -> void { create(CPU::Enter, system.frequency()); ram.allocate(0x3000); r.pc.l.l0 = 0xff1800; + io = {}; +} + +auto CPU::setInterruptHblank(boolean line) -> void { + io.irq.hblank = line; +//if(line) interrupt(0xffff0c); +} + +auto CPU::setInterruptVblank(boolean line) -> void { + io.irq.vblank = line; + if(line) interrupt(0xffff10); } } diff --git a/higan/ngp/cpu/cpu.hpp b/higan/ngp/cpu/cpu.hpp index 4d9e9cc3..7f2ae3fe 100644 --- a/higan/ngp/cpu/cpu.hpp +++ b/higan/ngp/cpu/cpu.hpp @@ -7,12 +7,23 @@ struct CPU : Processor::TLCS900H, Thread { auto step(uint clocks) -> void override; auto power() -> void; + auto setInterruptHblank(boolean line) -> void; + auto setInterruptVblank(boolean line) -> void; + //memory.cpp auto read(uint24 address) -> uint8 override; auto write(uint24 address, uint8 data) -> void override; //serialization.cpp auto serialize(serializer&) -> void; + +private: + struct IO { + struct IRQ { + boolean hblank; + boolean vblank; + } irq; + } io; }; extern CPU cpu; diff --git a/higan/ngp/interface/interface.cpp b/higan/ngp/interface/interface.cpp index c3d5217b..ed4ba344 100644 --- a/higan/ngp/interface/interface.cpp +++ b/higan/ngp/interface/interface.cpp @@ -15,7 +15,6 @@ auto Interface::display() -> Display { display.internalWidth = 160; display.internalHeight = 152; display.aspectCorrection = 1.0; - display.refreshRate = 60.0; return display; } diff --git a/higan/ngp/vpu/vpu.cpp b/higan/ngp/vpu/vpu.cpp index 74a7872c..505cb2f4 100644 --- a/higan/ngp/vpu/vpu.cpp +++ b/higan/ngp/vpu/vpu.cpp @@ -10,8 +10,34 @@ auto VPU::Enter() -> void { } auto VPU::main() -> void { - step(system.frequency() / 60.0); - scheduler.exit(Scheduler::Event::Frame); + cpu.setInterruptHblank(0); + for(uint hclock : range(480)) { + io.hcounter++; + step(1); + } + if(io.vcounter <= 150) { + if(ram[0x0000].bit(6)) cpu.setInterruptHblank(1); + } + for(uint hclock : range(35)) { + io.hcounter++; + step(1); + } + cpu.setInterruptHblank(0); + io.hcounter = 0; + io.vcounter++; + if(io.vcounter == 152) { + ram[0x0010].bit(6) = 1; + if(ram[0x0000].bit(7)) cpu.setInterruptVblank(1); + scheduler.exit(Scheduler::Event::Frame); + } + if(io.vcounter == 198) { + if(ram[0x0000].bit(6)) cpu.setInterruptHblank(1); + } + if(io.vcounter == 199) { + ram[0x0010].bit(6) = 0; + cpu.setInterruptVblank(0); + io.vcounter = 0; + } } auto VPU::step(uint clocks) -> void { @@ -20,12 +46,15 @@ auto VPU::step(uint clocks) -> void { } auto VPU::refresh() -> void { + for(uint address : range(0x4000)) buffer[address] = ram[address]; + for(uint address : range(0x1f00)) buffer[address + 0x4000] = cpu.ram[address + 0x3000 - 0x1f00]; Emulator::video.refresh(buffer, 160 * sizeof(uint32), 160, 152); } auto VPU::power() -> void { create(VPU::Enter, system.frequency()); ram.allocate(0x4000); + io = {}; } } diff --git a/higan/ngp/vpu/vpu.hpp b/higan/ngp/vpu/vpu.hpp index db64a926..f9fa3de5 100644 --- a/higan/ngp/vpu/vpu.hpp +++ b/higan/ngp/vpu/vpu.hpp @@ -16,6 +16,11 @@ struct VPU : Thread { private: uint32 buffer[160 * 152]; + + struct IO { + uint8 vcounter; + uint10 hcounter; + } io; }; extern VPU vpu; diff --git a/higan/pce/interface/interface.cpp b/higan/pce/interface/interface.cpp index 021e44fe..9cf4f42e 100644 --- a/higan/pce/interface/interface.cpp +++ b/higan/pce/interface/interface.cpp @@ -16,7 +16,6 @@ auto Interface::display() -> Display { display.internalWidth = 1120; display.internalHeight = 240; display.aspectCorrection = 8.0 / 7.0; - display.refreshRate = (system.colorburst() * 6.0) / (262.0 * 1365.0); return display; } diff --git a/higan/processor/tlcs900h/disassembler.cpp b/higan/processor/tlcs900h/disassembler.cpp index f685eaa2..c0362887 100644 --- a/higan/processor/tlcs900h/disassembler.cpp +++ b/higan/processor/tlcs900h/disassembler.cpp @@ -98,10 +98,10 @@ auto TLCS900H::disassemble() -> string { #define opSize opSizes[fetch.bits(4,5)] //extract the size from the opcode fetch switch(auto fetch = read8()) { case 0x00: name = "nop"; break; - case 0x01: break; + case 0x01: break; //"normal" (not present on 900/H) case 0x02: name = "push"; lhs.text("sr"); break; case 0x03: name = "pop"; lhs.text("sr"); break; - case 0x04: break; + case 0x04: break; //"max" or "min" (not present on 900/H) case 0x05: name = "halt"; break; case 0x06: name = "ei"; lhs.immediate(3, (uint3)read8()); if(lhs.immediate() == 7) name = "di", lhs.null(); break; case 0x07: name = "reti"; break; diff --git a/higan/processor/tlcs900h/instruction.cpp b/higan/processor/tlcs900h/instruction.cpp index 5db33d61..9face372 100644 --- a/higan/processor/tlcs900h/instruction.cpp +++ b/higan/processor/tlcs900h/instruction.cpp @@ -17,7 +17,7 @@ template auto TLCS900H::toRegister8(uint8 code) const -> Register template auto TLCS900H::toControlRegister(uint8 code) const -> ControlRegister { return {code}; } template auto TLCS900H::toMemory(uint32 address) const -> Memory { return {address}; } template auto TLCS900H::toImmediate(uint32 constant) const -> Immediate { return {constant}; } -template auto TLCS900H::toImmediate3(natural constant) const -> Immediate { return {constant.clip(3).orElse(8)}; } +template auto TLCS900H::toImmediate3(natural constant) const -> Immediate { return {constant.clip(3) ? constant.clip(3) : 8}; } //note: much of this code is split to multiple statements due to C++ not guaranteeing //the order of evaluations of function arguments. fetch() ordering is critical. @@ -27,16 +27,16 @@ auto TLCS900H::instruction() -> void { switch(r.prefix = data) { case 0x00: return instructionNoOperation(); - case 0x01: return (void)Undefined; + case 0x01: return (void)Undefined; //NORMAL (not present on 900/H) case 0x02: return instructionPush(SR); case 0x03: return instructionPop(SR); - case 0x04: return (void)Undefined; + case 0x04: return (void)Undefined; //MAX or MIN (not present on 900/H) case 0x05: return instructionHalt(); case 0x06: return instructionSetInterruptFlipFlop((uint3)fetch()); case 0x07: return instructionReturnInterrupt(); case 0x08: { auto memory = fetchMemory(); - return instructionLoad(memory, fetchImmediate()); } + return instructionLoad(memory, fetchImmediate()); } case 0x09: return instructionPush(fetchImmediate()); case 0x0a: { auto memory = fetchMemory(); diff --git a/higan/processor/tlcs900h/instructions.cpp b/higan/processor/tlcs900h/instructions.cpp index 6c1eae1a..97d1af1f 100644 --- a/higan/processor/tlcs900h/instructions.cpp +++ b/higan/processor/tlcs900h/instructions.cpp @@ -351,7 +351,8 @@ auto TLCS900H::instructionRotateLeftDigit(LHS lhs, RHS rhs) -> void { template auto TLCS900H::instructionRotateLeft(Target target, Amount amount) -> void { auto result = load(target); - for(uint n : range(load(amount).clip(4).orElse(16))) { + auto length = load(amount).clip(4); + for(uint n : range(length ? length : 16)) { uint cf = result.bit(-1); result = result << 1 | CF; CF = cf; @@ -362,7 +363,8 @@ auto TLCS900H::instructionRotateLeft(Target target, Amount amount) -> void { template auto TLCS900H::instructionRotateLeftWithoutCarry(Target target, Amount amount) -> void { auto result = load(target); - for(uint n : range(load(amount).clip(4).orElse(16))) { + auto length = load(amount).clip(4); + for(uint n : range(length ? length : 16)) { CF = result.bit(-1); result = result << 1 | CF; } @@ -389,7 +391,8 @@ auto TLCS900H::instructionRotateRightDigit(LHS lhs, RHS rhs) -> void { template auto TLCS900H::instructionRotateRight(Target target, Amount amount) -> void { auto result = load(target); - for(uint n : range(load(amount).clip(4).orElse(16))) { + auto length = load(amount).clip(4); + for(uint n : range(length ? length : 16)) { uint cf = result.bit(0); result = CF << Target::bits - 1 | result >> 1; CF = cf; @@ -400,7 +403,8 @@ auto TLCS900H::instructionRotateRight(Target target, Amount amount) -> void { template auto TLCS900H::instructionRotateRightWithoutCarry(Target target, Amount amount) -> void { auto result = load(target); - for(uint n : range(load(amount).clip(4).orElse(16))) { + auto length = load(amount).clip(4); + for(uint n : range(length ? length : 16)) { CF = result.bit(0); result = CF << Target::bits - 1 | result >> 1; } @@ -434,7 +438,8 @@ auto TLCS900H::instructionSetRegisterFilePointer(uint2 value) -> void { template auto TLCS900H::instructionShiftLeftArithmetic(Target target, Amount amount) -> void { auto result = load(target); - for(uint n : range(load(amount).clip(4).orElse(16))) { + auto length = load(amount).clip(4); + for(uint n : range(length ? length : 16)) { CF = result.bit(-1); result = result << 1; } @@ -444,7 +449,8 @@ auto TLCS900H::instructionShiftLeftArithmetic(Target target, Amount amount) -> v template auto TLCS900H::instructionShiftLeftLogical(Target target, Amount amount) -> void { auto result = load(target); - for(uint n : range(load(amount).clip(4).orElse(16))) { + auto length = load(amount).clip(4); + for(uint n : range(length ? length : 16)) { CF = result.bit(-1); result = result << 1; } @@ -454,7 +460,8 @@ auto TLCS900H::instructionShiftLeftLogical(Target target, Amount amount) -> void template auto TLCS900H::instructionShiftRightArithmetic(Target target, Amount amount) -> void { auto result = load(target); - for(uint n : range(load(amount).clip(4).orElse(16))) { + auto length = load(amount).clip(4); + for(uint n : range(length ? length : 16)) { CF = result.bit(0); result = result >> 1; result.bit(-1) = result.bit(-2); @@ -465,7 +472,8 @@ auto TLCS900H::instructionShiftRightArithmetic(Target target, Amount amount) -> template auto TLCS900H::instructionShiftRightLogical(Target target, Amount amount) -> void { auto result = load(target); - for(uint n : range(load(amount).clip(4).orElse(16))) { + auto length = load(amount).clip(4); + for(uint n : range(length ? length : 16)) { CF = result.bit(0); result = result >> 1; } diff --git a/higan/processor/tlcs900h/registers.cpp b/higan/processor/tlcs900h/registers.cpp index e69ffc61..92c73f7b 100644 --- a/higan/processor/tlcs900h/registers.cpp +++ b/higan/processor/tlcs900h/registers.cpp @@ -50,8 +50,8 @@ template<> auto TLCS900H::map(Register register) const -> maybe r(0x38, xde[3].w.w0) r(0x3a, xde[3].w.w1) r(0x3c, xhl[3].w.w0) r(0x3e, xhl[3].w.w1) r(0xd0, xwa[p].w.w0) r(0xd2, xwa[p].w.w1) r(0xd4, xbc[p].w.w0) r(0xd6, xbc[p].w.w1) r(0xd8, xde[p].w.w0) r(0xda, xde[p].w.w1) r(0xdc, xhl[p].w.w0) r(0xde, xhl[p].w.w1) - r(0xe0, xwa[p].w.w0) r(0xe2, xwa[p].w.w1) r(0xe4, xbc[p].w.w0) r(0xe6, xbc[p].w.w1) - r(0xe8, xde[p].w.w0) r(0xea, xde[p].w.w1) r(0xec, xhl[p].w.w0) r(0xee, xhl[p].w.w1) + r(0xe0, xwa[a].w.w0) r(0xe2, xwa[a].w.w1) r(0xe4, xbc[a].w.w0) r(0xe6, xbc[a].w.w1) + r(0xe8, xde[a].w.w0) r(0xea, xde[a].w.w1) r(0xec, xhl[a].w.w0) r(0xee, xhl[a].w.w1) r(0xf0, xix .w.w0) r(0xf2, xix .w.w1) r(0xf4, xiy .w.w0) r(0xf6, xiy .w.w1) r(0xf8, xiz .w.w0) r(0xfa, xiz .w.w1) r(0xfc, xsp .w.w0) r(0xfe, xsp .w.w0) #undef r @@ -106,12 +106,13 @@ auto TLCS900H::store(FlagRegister f, uint8 data) -> void { } auto TLCS900H::load(StatusRegister) const -> uint16 { - return load(F) | r.rfp << 8 | 1 << 11 | r.iff << 12 | 1 << 15; + //900/H: d10 = RFP2 (always 0); d11 = MAX (always 1); d15 = SYSM (always 1) + return load(F) | r.rfp << 8 | 0 << 10 | 1 << 11 | r.iff << 12 | 1 << 15; } auto TLCS900H::store(StatusRegister, uint16 data) -> void { - store(F, data); - r.rfp = data.bits( 8, 9); + store(F, data.bits(0,7)); + r.rfp = data.bits(8,9); r.iff = data.bits(12,14); } diff --git a/higan/processor/tlcs900h/tlcs900h.cpp b/higan/processor/tlcs900h/tlcs900h.cpp index e00b2488..17150030 100644 --- a/higan/processor/tlcs900h/tlcs900h.cpp +++ b/higan/processor/tlcs900h/tlcs900h.cpp @@ -33,6 +33,7 @@ auto TLCS900H::interrupt(uint24 address) -> void { auto TLCS900H::power() -> void { r = {}; + r.xsp.l.l0 = 0x100; } } diff --git a/higan/processor/tlcs900h/tlcs900h.hpp b/higan/processor/tlcs900h/tlcs900h.hpp index 12b9b614..a1840992 100644 --- a/higan/processor/tlcs900h/tlcs900h.hpp +++ b/higan/processor/tlcs900h/tlcs900h.hpp @@ -191,14 +191,14 @@ struct TLCS900H { DataRegister dmam[4]; DataRegister intnest; //16-bit - uint1 c, cp; //carry - uint1 n, np; //negative - uint1 v, vp; //overflow or parity - uint1 h, hp; //half carry - uint1 z, zp; //zero - uint1 s, sp; //sign - uint2 rfp; //register file pointer - uint3 iff = 7; //interrupt mask flip-flop + uint1 c, cp; //carry + uint1 n, np; //negative + uint1 v, vp; //overflow or parity + uint1 h, hp; //half carry + uint1 z, zp; //zero + uint1 s, sp; //sign + uint2 rfp; //register file pointer + uint3 iff = 7; //interrupt mask flip-flop uint1 halted; //set if halt instruction executed; waits for an interrupt to resume uint8 prefix; //first opcode byte; needed for [CP|LD][ID](R) instructions diff --git a/higan/sfc/interface/interface.cpp b/higan/sfc/interface/interface.cpp index ee17c0e6..f11824c6 100644 --- a/higan/sfc/interface/interface.cpp +++ b/higan/sfc/interface/interface.cpp @@ -23,8 +23,6 @@ auto Interface::display() -> Display { display.internalWidth = 512; display.internalHeight = 480; display.aspectCorrection = 8.0 / 7.0; - if(Region::NTSC()) display.refreshRate = system.cpuFrequency() / (262.0 * 1364.0); - if(Region::PAL()) display.refreshRate = system.cpuFrequency() / (312.0 * 1364.0); return display; } diff --git a/higan/ws/interface/interface.cpp b/higan/ws/interface/interface.cpp index abaeb33c..9c0378a8 100644 --- a/higan/ws/interface/interface.cpp +++ b/higan/ws/interface/interface.cpp @@ -16,7 +16,6 @@ auto Interface::display() -> Display { display.internalWidth = 224; display.internalHeight = 144; display.aspectCorrection = 1.0; - display.refreshRate = 3'072'000.0 / (159.0 * 256.0); if(settings.rotateLeft) { swap(display.width, display.height); swap(display.internalWidth, display.internalHeight); diff --git a/nall/primitives.hpp b/nall/primitives.hpp index f954e4e0..a1fc8fd4 100644 --- a/nall/primitives.hpp +++ b/nall/primitives.hpp @@ -5,8 +5,9 @@ namespace nall { struct Boolean; - template struct Natural; - template struct Integer; + template struct Natural; + template struct Integer; + template struct Real; } #include diff --git a/nall/primitives/bit-range.hpp b/nall/primitives/bit-range.hpp index 80b1be8d..f0f418ec 100644 --- a/nall/primitives/bit-range.hpp +++ b/nall/primitives/bit-range.hpp @@ -2,15 +2,18 @@ namespace nall { +//warning: so that BitRange can modify the underlying number directly, it must bind a reference. +//as a result, auto value = number.bits() will capture by-reference, rather than by-value. + template struct BitRange { static_assert(Precision >= 1 && Precision <= 64); static inline constexpr auto bits() -> uint { return Precision; } using utype = - typename conditional::type>::type>::type>::type; + conditional_t>>>; static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); } inline BitRange(utype& source, int lo, int hi) : source(source) { @@ -22,13 +25,14 @@ template struct BitRange { } inline auto& operator=(BitRange& source) { return set(source.get()); } + inline operator utype() const { return get(); } + 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); } - inline operator utype() const { return get(); } template inline auto& operator =(const T& value) { return set( value); } template inline auto& operator *=(const T& value) { return set(get() * value); } template inline auto& operator /=(const T& value) { return set(get() / value); } diff --git a/nall/primitives/boolean.hpp b/nall/primitives/boolean.hpp index f5832d26..78cbee87 100644 --- a/nall/primitives/boolean.hpp +++ b/nall/primitives/boolean.hpp @@ -4,7 +4,7 @@ namespace nall { struct Boolean { static inline constexpr auto bits() -> uint { return 1; } - using type = bool; + using btype = bool; inline Boolean() : data(false) {} template inline Boolean(const T& value) : data(value) {} @@ -23,7 +23,7 @@ struct Boolean { inline auto serialize(serializer& s) { s(data); } private: - type data; + btype data; }; } diff --git a/nall/primitives/integer.hpp b/nall/primitives/integer.hpp index 6b44c68a..c61c9fe1 100644 --- a/nall/primitives/integer.hpp +++ b/nall/primitives/integer.hpp @@ -2,7 +2,7 @@ namespace nall { -template struct Integer { +template struct Integer { static_assert(Precision >= 1 && Precision <= 64); static inline constexpr auto bits() -> uint { return Precision; } using stype = @@ -16,11 +16,10 @@ template struct Integer { static inline constexpr auto sign() -> utype { return 1ull << Precision - 1; } inline Integer() : data(0) {} - template inline Integer(Integer value) { data = mask(value); } + template inline Integer(Integer value) { data = mask(value); } template inline Integer(const T& value) { data = mask(value); } - explicit inline operator bool() const { return data; } - inline operator int64_t() const { return data; } + inline operator stype() const { return data; } inline auto operator++(int) { auto value = *this; data = mask(data + 1); return value; } inline auto operator--(int) { auto value = *this; data = mask(data - 1); return value; } @@ -28,29 +27,17 @@ template struct Integer { inline auto& operator++() { data = mask(data + 1); return *this; } inline auto& operator--() { data = mask(data - 1); return *this; } - inline auto operator!() const { return !data; } - inline auto operator~() const { return Integer<>{mask(~data)}; } - inline auto operator+() const { return Integer<>{+data}; } - inline auto operator-() const { return Integer<>{data == sign() ? data : -data}; } - - #define lhs data - #define rhs value - template inline auto& operator =(const T& value) { lhs = mask( rhs); return *this; } - template inline auto& operator *=(const T& value) { lhs = mask(lhs * rhs); return *this; } - template inline auto& operator /=(const T& value) { lhs = mask(lhs / rhs); return *this; } - template inline auto& operator %=(const T& value) { lhs = mask(lhs % rhs); return *this; } - template inline auto& operator +=(const T& value) { lhs = mask(lhs + rhs); return *this; } - template inline auto& operator -=(const T& value) { lhs = mask(lhs - rhs); return *this; } - template inline auto& operator<<=(const T& value) { lhs = mask(lhs << rhs); return *this; } - template inline auto& operator>>=(const T& value) { lhs = mask(lhs >> rhs); return *this; } - template inline auto& operator &=(const T& value) { lhs = mask(lhs & rhs); return *this; } - template inline auto& operator ^=(const T& value) { lhs = mask(lhs ^ rhs); return *this; } - template inline auto& operator |=(const T& value) { lhs = mask(lhs | rhs); return *this; } - #undef lhs - #undef rhs - - //warning: this does not and cannot short-circuit; value is always evaluated - template inline auto orElse(const T& value) { return Integer<>{data ? data : value}; } + template inline auto& operator =(const T& value) { data = mask( value); return *this; } + template inline auto& operator *=(const T& value) { data = mask(data * value); return *this; } + template inline auto& operator /=(const T& value) { data = mask(data / value); return *this; } + template inline auto& operator %=(const T& value) { data = mask(data % value); return *this; } + template inline auto& operator +=(const T& value) { data = mask(data + value); return *this; } + template inline auto& operator -=(const T& value) { data = mask(data - value); return *this; } + template inline auto& operator<<=(const T& value) { data = mask(data << value); return *this; } + template inline auto& operator>>=(const T& value) { data = mask(data >> value); return *this; } + template inline auto& operator &=(const T& value) { data = mask(data & value); return *this; } + template inline auto& operator ^=(const T& value) { data = mask(data ^ value); return *this; } + template inline auto& operator |=(const T& value) { data = mask(data | value); return *this; } inline auto bits(int lo, int hi) -> BitRange { return {(utype&)data, lo, hi}; } inline auto bit(int index) -> BitRange { return {(utype&)data, index, index}; } @@ -63,16 +50,16 @@ template struct Integer { inline auto slice(int index) const { return Natural<>{bit(index)}; } inline auto slice(int lo, int hi) const { return Natural<>{bit(lo, hi)}; } - inline auto clamp(uint bits) { + inline auto clamp(uint bits) -> stype { const int64_t b = 1ull << (bits - 1); const int64_t m = b - 1; - return Integer<>{data > m ? m : data < -b ? -b : data}; + return data > m ? m : data < -b ? -b : data; } - inline auto clip(uint bits) { + inline auto clip(uint bits) -> stype { const uint64_t b = 1ull << (bits - 1); const uint64_t m = b * 2 - 1; - return Integer<>{(data & m ^ b) - b}; + return (data & m ^ b) - b; } inline auto serialize(serializer& s) { s(data); } @@ -86,19 +73,4 @@ private: stype data; }; -#define lhs (int64_t)l -#define rhs r -template inline auto operator *(Integer l, Integer r) { return Integer{lhs * rhs}; } -template inline auto operator /(Integer l, Integer r) { return Integer{lhs / rhs}; } -template inline auto operator %(Integer l, Integer r) { return Integer{lhs % rhs}; } -template inline auto operator +(Integer l, Integer r) { return Integer{lhs + rhs}; } -template inline auto operator -(Integer l, Integer r) { return Integer{lhs - rhs}; } -template inline auto operator<<(Integer l, Integer r) { return Integer{lhs << rhs}; } -template inline auto operator>>(Integer l, Integer r) { return Integer{lhs >> rhs}; } -template inline auto operator &(Integer l, Integer r) { return Integer{lhs & rhs}; } -template inline auto operator ^(Integer l, Integer r) { return Integer{lhs ^ rhs}; } -template inline auto operator |(Integer l, Integer r) { return Integer{lhs | rhs}; } -#undef lhs -#undef rhs - } diff --git a/nall/primitives/natural.hpp b/nall/primitives/natural.hpp index 1a663abb..b609c5e7 100644 --- a/nall/primitives/natural.hpp +++ b/nall/primitives/natural.hpp @@ -2,7 +2,7 @@ namespace nall { -template struct Natural { +template struct Natural { static_assert(Precision >= 1 && Precision <= 64); static inline constexpr auto bits() -> uint { return Precision; } using utype = @@ -14,11 +14,10 @@ template struct Natural { static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); } inline Natural() : data(0) {} - template inline Natural(Natural value) { data = mask(value); } + template inline Natural(Natural value) { data = mask(value); } template inline Natural(const T& value) { data = mask(value); } - explicit inline operator bool() const { return data; } - inline operator uint64_t() const { return data; } + inline operator utype() const { return data; } inline auto operator++(int) { auto value = *this; data = mask(data + 1); return value; } inline auto operator--(int) { auto value = *this; data = mask(data - 1); return value; } @@ -26,29 +25,17 @@ template struct Natural { inline auto& operator++() { data = mask(data + 1); return *this; } inline auto& operator--() { data = mask(data - 1); return *this; } - inline auto operator!() const { return !data; } - inline auto operator~() const { return Natural<>{mask(~data)}; } - inline auto operator+() const { return Natural<>{+data}; } - inline auto operator-() const { return Natural<>{-(uint64_t)data}; } - - #define lhs data - #define rhs value - template inline auto& operator =(const T& value) { lhs = mask( rhs); return *this; } - template inline auto& operator *=(const T& value) { lhs = mask(lhs * rhs); return *this; } - template inline auto& operator /=(const T& value) { lhs = mask(lhs / rhs); return *this; } - template inline auto& operator %=(const T& value) { lhs = mask(lhs % rhs); return *this; } - template inline auto& operator +=(const T& value) { lhs = mask(lhs + rhs); return *this; } - template inline auto& operator -=(const T& value) { lhs = mask(lhs - rhs); return *this; } - template inline auto& operator<<=(const T& value) { lhs = mask(lhs << rhs); return *this; } - template inline auto& operator>>=(const T& value) { lhs = mask(lhs >> rhs); return *this; } - template inline auto& operator &=(const T& value) { lhs = mask(lhs & rhs); return *this; } - template inline auto& operator ^=(const T& value) { lhs = mask(lhs ^ rhs); return *this; } - template inline auto& operator |=(const T& value) { lhs = mask(lhs | rhs); return *this; } - #undef lhs - #undef rhs - - //warning: this does not and cannot short-circuit; value is always evaluated - template inline auto orElse(const T& value) { return Natural<>{data ? data : value}; } + template inline auto& operator =(const T& value) { data = mask( value); return *this; } + template inline auto& operator *=(const T& value) { data = mask(data * value); return *this; } + template inline auto& operator /=(const T& value) { data = mask(data / value); return *this; } + template inline auto& operator %=(const T& value) { data = mask(data % value); return *this; } + template inline auto& operator +=(const T& value) { data = mask(data + value); return *this; } + template inline auto& operator -=(const T& value) { data = mask(data - value); return *this; } + template inline auto& operator<<=(const T& value) { data = mask(data << value); return *this; } + template inline auto& operator>>=(const T& value) { data = mask(data >> value); return *this; } + template inline auto& operator &=(const T& value) { data = mask(data & value); return *this; } + template inline auto& operator ^=(const T& value) { data = mask(data ^ value); return *this; } + template inline auto& operator |=(const T& value) { data = mask(data | value); return *this; } inline auto bits(int lo, int hi) -> BitRange { return {(utype&)data, lo, hi}; } inline auto bit(int index) -> BitRange { return {(utype&)data, index, index}; } @@ -61,16 +48,16 @@ template struct Natural { inline auto slice(int index) const { return Natural<>{bit(index)}; } inline auto slice(int lo, int hi) const { return Natural<>{bits(lo, hi)}; } - inline auto clamp(uint bits) { + inline auto clamp(uint bits) -> utype { const uint64_t b = 1ull << (bits - 1); const uint64_t m = b * 2 - 1; - return Natural<>{data < m ? data : m}; + return data < m ? data : m; } - inline auto clip(uint bits) { + inline auto clip(uint bits) -> utype { const uint64_t b = 1ull << (bits - 1); const uint64_t m = b * 2 - 1; - return Natural<>{data & m}; + return data & m; } inline auto serialize(serializer& s) { s(data); } @@ -84,19 +71,4 @@ private: utype data; }; -#define lhs (uint64_t)l -#define rhs r -template inline auto operator *(Natural l, Natural r) { return Natural{lhs * rhs}; } -template inline auto operator /(Natural l, Natural r) { return Natural{lhs / rhs}; } -template inline auto operator %(Natural l, Natural r) { return Natural{lhs % rhs}; } -template inline auto operator +(Natural l, Natural r) { return Natural{lhs + rhs}; } -template inline auto operator -(Natural l, Natural r) { return Natural{lhs - rhs}; } -template inline auto operator<<(Natural l, Natural r) { return Natural{lhs << rhs}; } -template inline auto operator>>(Natural l, Natural r) { return Natural{lhs >> rhs}; } -template inline auto operator &(Natural l, Natural r) { return Natural{lhs & rhs}; } -template inline auto operator ^(Natural l, Natural r) { return Natural{lhs ^ rhs}; } -template inline auto operator |(Natural l, Natural r) { return Natural{lhs | rhs}; } -#undef lhs -#undef rhs - } diff --git a/nall/primitives/real.hpp b/nall/primitives/real.hpp index 99870024..1a5fe21e 100644 --- a/nall/primitives/real.hpp +++ b/nall/primitives/real.hpp @@ -2,7 +2,7 @@ namespace nall { -template struct Real { +template struct Real { static_assert(Precision == 32 || Precision == 64); static inline constexpr auto bits() -> uint { return Precision; } using ftype = @@ -14,8 +14,7 @@ template struct Real { template inline Real(Real value) : data((ftype)value) {} template inline Real(const T& value) : data((ftype)value) {} - explicit inline operator bool() const { return data; } - inline operator float64_t() const { return data; } + inline operator ftype() const { return data; } inline auto operator++(int) { auto value = *this; ++data; return value; } inline auto operator--(int) { auto value = *this; --data; return value; } @@ -36,14 +35,4 @@ private: ftype data; }; -#define lhs (float64_t)(typename Real::type)l -#define rhs (typename Real::type)r -template inline auto operator*(Real l, Real r) { return Real<>{lhs * rhs}; } -template inline auto operator/(Real l, Real r) { return Real<>{lhs / rhs}; } -template inline auto operator%(Real l, Real r) { return Real<>{lhs % rhs}; } -template inline auto operator+(Real l, Real r) { return Real<>{lhs + rhs}; } -template inline auto operator-(Real l, Real r) { return Real<>{lhs - rhs}; } -#undef lhs -#undef rhs - }