mirror of
https://github.com/TomHarte/CLK.git
synced 2026-04-26 03:29:40 +00:00
Be more rigorous about static constexpr.
This commit is contained in:
@@ -167,8 +167,8 @@ Analyser::Static::TargetList Analyser::Static::Acorn::GetTargets(
|
||||
// Take whatever else comes with a preference for things that don't
|
||||
// have 'boot' or 'read' in them (the latter of which will tend to be
|
||||
// read_me or read_this or similar).
|
||||
constexpr char read[] = "read";
|
||||
constexpr char boot[] = "boot";
|
||||
static constexpr char read[] = "read";
|
||||
static constexpr char boot[] = "boot";
|
||||
const auto has = [&](const char *begin, const char *end) {
|
||||
return std::search(
|
||||
file.name.begin(), file.name.end(),
|
||||
|
||||
@@ -60,11 +60,11 @@ private:
|
||||
bool overrun_ = false;
|
||||
};
|
||||
|
||||
constexpr uint8_t x(uint8_t v) { return v >> 6; }
|
||||
constexpr uint8_t y(uint8_t v) { return (v >> 3) & 7; }
|
||||
constexpr uint8_t q(uint8_t v) { return (v >> 3) & 1; }
|
||||
constexpr uint8_t p(uint8_t v) { return (v >> 4) & 3; }
|
||||
constexpr uint8_t z(uint8_t v) { return v & 7; }
|
||||
constexpr uint8_t x(const uint8_t v) { return v >> 6; }
|
||||
constexpr uint8_t y(const uint8_t v) { return (v >> 3) & 7; }
|
||||
constexpr uint8_t q(const uint8_t v) { return (v >> 3) & 1; }
|
||||
constexpr uint8_t p(const uint8_t v) { return (v >> 4) & 3; }
|
||||
constexpr uint8_t z(const uint8_t v) { return v & 7; }
|
||||
|
||||
Instruction::Condition condition_table[] = {
|
||||
Instruction::Condition::NZ, Instruction::Condition::Z,
|
||||
@@ -92,7 +92,7 @@ Instruction::Location RegisterTableEntry(
|
||||
Instruction &instruction,
|
||||
const bool needs_indirect_offset
|
||||
) {
|
||||
constexpr Instruction::Location register_table[] = {
|
||||
static constexpr Instruction::Location register_table[] = {
|
||||
Instruction::Location::B, Instruction::Location::C,
|
||||
Instruction::Location::D, Instruction::Location::E,
|
||||
Instruction::Location::H, Instruction::Location::L,
|
||||
|
||||
@@ -16,10 +16,10 @@ template <int DeferredDepth, typename ValueT> class DeferredValue {
|
||||
private:
|
||||
static_assert(sizeof(ValueT) <= 4);
|
||||
|
||||
constexpr int elements_per_uint32 = sizeof(uint32_t) / sizeof(ValueT);
|
||||
constexpr int unit_shift = sizeof(ValueT) * 8;
|
||||
constexpr int insert_shift = (DeferredDepth & (elements_per_uint32 - 1)) * unit_shift;
|
||||
constexpr uint32_t insert_mask = ~(0xffff'ffff << insert_shift);
|
||||
static constexpr int elements_per_uint32 = sizeof(uint32_t) / sizeof(ValueT);
|
||||
static constexpr int unit_shift = sizeof(ValueT) * 8;
|
||||
static constexpr int insert_shift = (DeferredDepth & (elements_per_uint32 - 1)) * unit_shift;
|
||||
static constexpr uint32_t insert_mask = ~(0xffff'ffff << insert_shift);
|
||||
|
||||
std::array<uint32_t, (DeferredDepth + elements_per_uint32 - 1) / elements_per_uint32> backlog;
|
||||
|
||||
|
||||
@@ -125,11 +125,11 @@ private:
|
||||
uint32_t alarm_ = 0xff'ffff;
|
||||
|
||||
public:
|
||||
template <int byte> void write(uint8_t v) {
|
||||
template <int byte> void write(const uint8_t v) {
|
||||
if constexpr (byte == 3) {
|
||||
return;
|
||||
}
|
||||
constexpr int shift = byte << 3;
|
||||
static constexpr int shift = byte << 3;
|
||||
|
||||
// Write to either the alarm or the current value as directed;
|
||||
// writing to any part of the current value other than the LSB
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
if constexpr (byte == 3) {
|
||||
return 0xff; // Assumed. Just a guess.
|
||||
}
|
||||
constexpr int shift = byte << 3;
|
||||
static constexpr int shift = byte << 3;
|
||||
|
||||
if constexpr (byte == 2) {
|
||||
latch_ = value_ | 0xff00'0000;
|
||||
@@ -163,7 +163,7 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
bool advance(int count) {
|
||||
bool advance(const int count) {
|
||||
// The 8250 uses a simple binary counter to replace the
|
||||
// 6526's time-of-day clock. So this is easy.
|
||||
const uint32_t distance_to_alarm = (alarm_ - value_) & 0xff'ffff;
|
||||
|
||||
@@ -114,7 +114,7 @@ void MFP68901::write(int address, const uint8_t value) {
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr int timer_prescales[] = {
|
||||
static constexpr int timer_prescales[] = {
|
||||
1, 4, 10, 16, 50, 64, 100, 200
|
||||
};
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ void TMS9918<personality>::run_for(const HalfCycles cycles) {
|
||||
// TODO: where did this magic constant come from? https://www.smspower.org/forums/17970-RoadRashHow#111000 mentioned in passing
|
||||
// that "the vertical scroll register is latched at the start of the active display" and this is two clocks before that, so it's
|
||||
// not uncompelling. I can just no longer find my source.
|
||||
constexpr auto latch_time = LineLayout<personality>::EndOfLeftBorder - 2;
|
||||
static constexpr auto latch_time = LineLayout<personality>::EndOfLeftBorder - 2;
|
||||
static_assert(latch_time > 0);
|
||||
if(this->fetch_pointer_.column < latch_time && end_column >= latch_time) {
|
||||
if(!this->fetch_pointer_.row) {
|
||||
@@ -1211,7 +1211,7 @@ uint8_t TMS9918<personality>::read(const int address) {
|
||||
template <Personality personality>
|
||||
int Base<personality>::fetch_line() const {
|
||||
// This is the proper Master System value; TODO: what's correct for Yamaha, etc?
|
||||
constexpr int row_change_position = 31;
|
||||
static constexpr int row_change_position = 31;
|
||||
|
||||
return
|
||||
(this->fetch_pointer_.column < row_change_position)
|
||||
|
||||
@@ -87,8 +87,8 @@ template <Personality personality> struct Base: public Storage<personality> {
|
||||
/// applicable @c memory_mask.
|
||||
template <int shift, int length = 8> void install_field(AddressT &target, const uint8_t source) {
|
||||
static_assert(length > 0 && length <= 8);
|
||||
constexpr auto source_mask = (1 << length) - 1;
|
||||
constexpr auto mask = AddressT(~(source_mask << shift));
|
||||
static constexpr auto source_mask = (1 << length) - 1;
|
||||
static constexpr auto mask = AddressT(~(source_mask << shift));
|
||||
target = (
|
||||
(target & mask) |
|
||||
AddressT((source & source_mask) << shift)
|
||||
@@ -545,8 +545,8 @@ template <Personality personality> struct Base: public Storage<personality> {
|
||||
if(Storage<personality>::cram_is_selected_) {
|
||||
// Adjust the palette. In a Master System blue has a slightly different
|
||||
// scale; cf. https://www.retrorgb.com/sega-master-system-non-linear-blue-channel-findings.html
|
||||
constexpr uint8_t rg_scale[] = {0, 85, 170, 255};
|
||||
constexpr uint8_t b_scale[] = {0, 104, 170, 255};
|
||||
static constexpr uint8_t rg_scale[] = {0, 85, 170, 255};
|
||||
static constexpr uint8_t b_scale[] = {0, 104, 170, 255};
|
||||
Storage<personality>::colour_ram_[address & 0x1f] = palette_pack(
|
||||
rg_scale[(read_ahead_buffer_ >> 0) & 3],
|
||||
rg_scale[(read_ahead_buffer_ >> 2) & 3],
|
||||
|
||||
@@ -93,8 +93,8 @@ void Base<personality>::draw_sprites(
|
||||
assert(!buffer.is_filling);
|
||||
}
|
||||
|
||||
constexpr uint32_t sprite_colour_selection_masks[2] = {0x00000000, 0xffffffff};
|
||||
constexpr int colour_masks[16] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
static constexpr uint32_t sprite_colour_selection_masks[2] = {0x00000000, 0xffffffff};
|
||||
static constexpr int colour_masks[16] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
const int sprite_width = sprites_16x16_ ? 16 : 8;
|
||||
const int shifter_target = sprite_width << 1;
|
||||
const int pixel_width = sprites_magnified_ ? sprite_width << 1 : sprite_width;
|
||||
|
||||
@@ -407,8 +407,8 @@ struct TextSequencer {
|
||||
return;
|
||||
} else {
|
||||
// For the 120 slots in between follow a three-step pattern of:
|
||||
constexpr int offset = cycle - 30;
|
||||
constexpr auto column = AddressT(offset / 3);
|
||||
static constexpr int offset = cycle - 30;
|
||||
static constexpr auto column = AddressT(offset / 3);
|
||||
switch(offset % 3) {
|
||||
case 0: // (1) fetch tile name.
|
||||
fetcher.fetch_name(column);
|
||||
@@ -457,16 +457,16 @@ struct CharacterSequencer {
|
||||
|
||||
// Body of line: tiles themselves, plus some additional potential sprites.
|
||||
if(cycle >= 27 && cycle < 155) {
|
||||
constexpr int offset = cycle - 27;
|
||||
constexpr int block = offset >> 2;
|
||||
constexpr int sub_block = offset & 3;
|
||||
static constexpr int offset = cycle - 27;
|
||||
static constexpr int block = offset >> 2;
|
||||
static constexpr int sub_block = offset & 3;
|
||||
switch(sub_block) {
|
||||
case 0: character_fetcher.fetch_name(block); break;
|
||||
case 1:
|
||||
if(!(block & 3)) {
|
||||
character_fetcher.base->do_external_slot(to_internal<personality, Clock::TMSMemoryWindow, Clock::FromStartOfSync>(cycle));
|
||||
} else {
|
||||
constexpr int sprite = 8 + ((block >> 2) * 3) + ((block & 3) - 1);
|
||||
static constexpr int sprite = 8 + ((block >> 2) * 3) + ((block & 3) - 1);
|
||||
sprite_fetcher.fetch_y(sprite);
|
||||
}
|
||||
break;
|
||||
@@ -549,9 +549,9 @@ struct SMSSequencer {
|
||||
}
|
||||
|
||||
if(cycle >= 25 && cycle < 153) {
|
||||
constexpr int offset = cycle - 25;
|
||||
constexpr int block = offset >> 2;
|
||||
constexpr int sub_block = offset & 3;
|
||||
static constexpr int offset = cycle - 25;
|
||||
static constexpr int block = offset >> 2;
|
||||
static constexpr int sub_block = offset & 3;
|
||||
|
||||
switch(sub_block) {
|
||||
default: break;
|
||||
@@ -561,7 +561,7 @@ struct SMSSequencer {
|
||||
if(!(block & 3)) {
|
||||
fetcher.base->do_external_slot(to_internal<personality, Clock::TMSMemoryWindow, Clock::FromStartOfSync>(cycle));
|
||||
} else {
|
||||
constexpr int sprite = (8 + ((block >> 2) * 3) + ((block & 3) - 1)) << 1;
|
||||
static constexpr int sprite = (8 + ((block >> 2) * 3) + ((block & 3) - 1)) << 1;
|
||||
fetcher.posit_sprite(sprite);
|
||||
fetcher.posit_sprite(sprite+1);
|
||||
}
|
||||
|
||||
@@ -29,49 +29,49 @@ template <Personality personality, typename Enable = void> struct LineLayout;
|
||||
// * text mode on all VDPs adjusts border width.
|
||||
|
||||
template <Personality personality> struct LineLayout<personality, std::enable_if_t<is_classic_vdp(personality)>> {
|
||||
constexpr static int StartOfSync = 0;
|
||||
constexpr static int EndOfSync = 26;
|
||||
constexpr static int StartOfColourBurst = 29;
|
||||
constexpr static int EndOfColourBurst = 43;
|
||||
constexpr static int EndOfLeftErase = 50;
|
||||
constexpr static int EndOfLeftBorder = 63;
|
||||
constexpr static int EndOfPixels = 319;
|
||||
constexpr static int EndOfRightBorder = 334;
|
||||
static constexpr int StartOfSync = 0;
|
||||
static constexpr int EndOfSync = 26;
|
||||
static constexpr int StartOfColourBurst = 29;
|
||||
static constexpr int EndOfColourBurst = 43;
|
||||
static constexpr int EndOfLeftErase = 50;
|
||||
static constexpr int EndOfLeftBorder = 63;
|
||||
static constexpr int EndOfPixels = 319;
|
||||
static constexpr int EndOfRightBorder = 334;
|
||||
|
||||
constexpr static int CyclesPerLine = 342;
|
||||
static constexpr int CyclesPerLine = 342;
|
||||
|
||||
constexpr static int TextModeEndOfLeftBorder = 69;
|
||||
constexpr static int TextModeEndOfPixels = 309;
|
||||
static constexpr int TextModeEndOfLeftBorder = 69;
|
||||
static constexpr int TextModeEndOfPixels = 309;
|
||||
|
||||
constexpr static int ModeLatchCycle = 36; // Just a guess; correlates with the known 144 for the Yamaha VDPs,
|
||||
static constexpr int ModeLatchCycle = 36; // Just a guess; correlates with the known 144 for the Yamaha VDPs,
|
||||
// and falls into the collection gap between the final sprite
|
||||
// graphics and the initial tiles or pixels.
|
||||
|
||||
/// The number of internal cycles that must elapse between a request to read or write and
|
||||
/// it becoming a candidate for action.
|
||||
constexpr static int VRAMAccessDelay = 6;
|
||||
static constexpr int VRAMAccessDelay = 6;
|
||||
};
|
||||
|
||||
template <Personality personality> struct LineLayout<personality, std::enable_if_t<is_yamaha_vdp(personality)>> {
|
||||
constexpr static int StartOfSync = 0;
|
||||
constexpr static int EndOfSync = 100;
|
||||
constexpr static int StartOfColourBurst = 113;
|
||||
constexpr static int EndOfColourBurst = 167;
|
||||
constexpr static int EndOfLeftErase = 202;
|
||||
constexpr static int EndOfLeftBorder = 258;
|
||||
constexpr static int EndOfPixels = 1282;
|
||||
constexpr static int EndOfRightBorder = 1341;
|
||||
static constexpr int StartOfSync = 0;
|
||||
static constexpr int EndOfSync = 100;
|
||||
static constexpr int StartOfColourBurst = 113;
|
||||
static constexpr int EndOfColourBurst = 167;
|
||||
static constexpr int EndOfLeftErase = 202;
|
||||
static constexpr int EndOfLeftBorder = 258;
|
||||
static constexpr int EndOfPixels = 1282;
|
||||
static constexpr int EndOfRightBorder = 1341;
|
||||
|
||||
constexpr static int CyclesPerLine = 1368;
|
||||
static constexpr int CyclesPerLine = 1368;
|
||||
|
||||
constexpr static int TextModeEndOfLeftBorder = 294;
|
||||
constexpr static int TextModeEndOfPixels = 1254;
|
||||
static constexpr int TextModeEndOfLeftBorder = 294;
|
||||
static constexpr int TextModeEndOfPixels = 1254;
|
||||
|
||||
constexpr static int ModeLatchCycle = 144;
|
||||
static constexpr int ModeLatchCycle = 144;
|
||||
|
||||
/// The number of internal cycles that must elapse between a request to read or write and
|
||||
/// it becoming a candidate for action.
|
||||
constexpr static int VRAMAccessDelay = 16;
|
||||
static constexpr int VRAMAccessDelay = 16;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ struct Vector {
|
||||
|
||||
template <int offset, bool high> void set(const uint8_t value) {
|
||||
constexpr uint8_t mask = high ? (offset ? 0x3 : 0x1) : 0xff;
|
||||
constexpr int shift = high ? 8 : 0;
|
||||
static constexpr int shift = high ? 8 : 0;
|
||||
v[offset] = (v[offset] & ~(mask << shift)) | ((value & mask) << shift);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ public:
|
||||
this is used to select a key scaling rate if key-rate scaling is enabled.
|
||||
*/
|
||||
void set_period(const int period, const int octave) {
|
||||
constexpr int key_level_scales[16] = {0, 48, 64, 74, 80, 86, 90, 94, 96, 100, 102, 104, 106, 108, 110, 112};
|
||||
constexpr int masks[2] = {~0, 0};
|
||||
static constexpr int key_level_scales[16] = {0, 48, 64, 74, 80, 86, 90, 94, 96, 100, 102, 104, 106, 108, 110, 112};
|
||||
static constexpr int masks[2] = {~0, 0};
|
||||
|
||||
// A two's complement assumption is embedded below; the use of masks relies
|
||||
// on the sign bit to clamp to zero.
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
/*!
|
||||
@returns The output of waveform @c form at [integral] phase @c phase.
|
||||
*/
|
||||
static constexpr LogSign wave(Waveform form, int phase) {
|
||||
static constexpr LogSign wave(const Waveform form, const int phase) {
|
||||
constexpr int waveforms[4][4] = {
|
||||
{1023, 1023, 1023, 1023}, // Sine: don't mask in any quadrant.
|
||||
{511, 511, 0, 0}, // Half sine: keep the first half intact, lock to 0 in the second half.
|
||||
|
||||
@@ -47,7 +47,7 @@ void RP5C01::run_for(const HalfCycles cycles) {
|
||||
// Update time within day.
|
||||
seconds_ += elapsed_seconds;
|
||||
|
||||
constexpr int day_length = 60 * 60 * 24;
|
||||
static constexpr int day_length = 60 * 60 * 24;
|
||||
if(seconds_ < day_length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ template <Operation operation, AddressingMode addressing_mode> void Executor::pe
|
||||
case Operation::ADC: case Operation::AND: case Operation::CMP: case Operation::EOR:
|
||||
case Operation::LDA: case Operation::ORA: case Operation::SBC:
|
||||
{
|
||||
constexpr int t_lengths[] = {
|
||||
static constexpr int t_lengths[] = {
|
||||
0,
|
||||
operation == Operation::LDA ? 2 : (operation == Operation::CMP ? 1 : 3)
|
||||
};
|
||||
@@ -444,7 +444,7 @@ template <Operation operation, AddressingMode addressing_mode> void Executor::pe
|
||||
case Operation::BBS0: case Operation::BBS1: case Operation::BBS2: case Operation::BBS3:
|
||||
case Operation::BBS4: case Operation::BBS5: case Operation::BBS6: case Operation::BBS7: {
|
||||
if constexpr (operation >= Operation::BBS0 && operation <= Operation::BBS7) {
|
||||
constexpr uint8_t mask = 1 << (int(operation) - int(Operation::BBS0));
|
||||
static constexpr uint8_t mask = 1 << (int(operation) - int(Operation::BBS0));
|
||||
if(value & mask) {
|
||||
set_program_counter(uint16_t(address));
|
||||
subtract_duration(2);
|
||||
@@ -454,7 +454,7 @@ template <Operation operation, AddressingMode addressing_mode> void Executor::pe
|
||||
case Operation::BBC0: case Operation::BBC1: case Operation::BBC2: case Operation::BBC3:
|
||||
case Operation::BBC4: case Operation::BBC5: case Operation::BBC6: case Operation::BBC7: {
|
||||
if constexpr (operation >= Operation::BBC0 && operation <= Operation::BBC7) {
|
||||
constexpr uint8_t mask = 1 << (int(operation) - int(Operation::BBC0));
|
||||
static constexpr uint8_t mask = 1 << (int(operation) - int(Operation::BBC0));
|
||||
if(!(value & mask)) {
|
||||
set_program_counter(uint16_t(address));
|
||||
subtract_duration(2);
|
||||
@@ -805,8 +805,9 @@ inline void Executor::subtract_duration(const int duration) {
|
||||
cycles_since_port_handler_ += Cycles(duration);
|
||||
|
||||
// Update timer 1 and 2 prescaler.
|
||||
constexpr int t12_divider = 4; // A divide by 4 has already been applied before counting instruction lengths; therefore
|
||||
// this additional divide by 4 produces the correct net divide by 16.
|
||||
static constexpr int t12_divider = 4; // A divide by 4 has already been applied before counting instruction
|
||||
// lengths; therefore this additional divide by 4 produces the correct net
|
||||
// divide by 16.
|
||||
|
||||
timer_divider_ += duration;
|
||||
const int clock_ticks = timer_divider_ / t12_divider;
|
||||
|
||||
@@ -34,7 +34,7 @@ static void add_sub(const IntT source, IntT &destination, Status &status) {
|
||||
static_assert(!std::numeric_limits<IntT>::is_signed);
|
||||
|
||||
static_assert(operation == Numeric::Operation::Add || operation == Numeric::Operation::Subtract);
|
||||
constexpr bool is_add = operation == Numeric::Operation::Add;
|
||||
static constexpr bool is_add = operation == Numeric::Operation::Add;
|
||||
IntT result = is_add ?
|
||||
destination + source :
|
||||
destination - source;
|
||||
@@ -313,7 +313,7 @@ void shift(const uint32_t source, IntT &destination, Status &status, FlowControl
|
||||
operation == Operation::LSRb || operation == Operation::LSRw || operation == Operation::LSRl
|
||||
);
|
||||
|
||||
constexpr auto size = Numeric::bit_size<IntT>();
|
||||
static constexpr auto size = Numeric::bit_size<IntT>();
|
||||
const auto shift = shift_count<IntT>(uint8_t(source), flow_controller);
|
||||
|
||||
if(!shift) {
|
||||
@@ -408,7 +408,7 @@ void rotate(const uint32_t source, IntT &destination, Status &status, FlowContro
|
||||
operation == Operation::RORb || operation == Operation::RORw || operation == Operation::RORl
|
||||
);
|
||||
|
||||
constexpr auto size = Numeric::bit_size<IntT>();
|
||||
static constexpr auto size = Numeric::bit_size<IntT>();
|
||||
auto shift = shift_count<IntT>(uint8_t(source), flow_controller);
|
||||
|
||||
if(!shift) {
|
||||
@@ -440,7 +440,7 @@ void rox(const uint32_t source, IntT &destination, Status &status, FlowControlle
|
||||
operation == Operation::ROXRb || operation == Operation::ROXRw || operation == Operation::ROXRl
|
||||
);
|
||||
|
||||
constexpr auto size = Numeric::bit_size<IntT>();
|
||||
static constexpr auto size = Numeric::bit_size<IntT>();
|
||||
auto shift = shift_count<IntT>(uint8_t(source), flow_controller) % (size + 1);
|
||||
|
||||
if(!shift) {
|
||||
|
||||
@@ -86,8 +86,8 @@ template <typename IntT>
|
||||
void cbw(
|
||||
IntT &ax
|
||||
) {
|
||||
constexpr IntT test_bit = 1 << (sizeof(IntT) * 4 - 1);
|
||||
constexpr IntT low_half = (1 << (sizeof(IntT) * 4)) - 1;
|
||||
static constexpr IntT test_bit = 1 << (sizeof(IntT) * 4 - 1);
|
||||
static constexpr IntT low_half = (1 << (sizeof(IntT) * 4)) - 1;
|
||||
|
||||
if(ax & test_bit) {
|
||||
ax |= ~low_half;
|
||||
|
||||
@@ -415,8 +415,8 @@ private:
|
||||
case CursorAction::Type::MoveTo: {
|
||||
// A measure of where within the tip lies within
|
||||
// the default RISC OS cursor.
|
||||
constexpr int ActionPointOffset = 20;
|
||||
constexpr int MaxStep = 24;
|
||||
static constexpr int ActionPointOffset = 20;
|
||||
static constexpr int MaxStep = 24;
|
||||
|
||||
const auto position = executor_.bus.video().cursor_location();
|
||||
if(!position) break;
|
||||
|
||||
@@ -108,7 +108,7 @@ bool Audio::advance_dma(int channel) {
|
||||
}
|
||||
|
||||
void Audio::output() {
|
||||
constexpr InterruptFlag::FlagT interrupts[] = {
|
||||
static constexpr InterruptFlag::FlagT interrupts[] = {
|
||||
InterruptFlag::AudioChannel0,
|
||||
InterruptFlag::AudioChannel1,
|
||||
InterruptFlag::AudioChannel2,
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
|
||||
/// Shifts either two pixels (in low-res mode) or four pixels (in high-res).
|
||||
void shift(bool high_res) {
|
||||
constexpr int shifts[] = {16, 32};
|
||||
static constexpr int shifts[] = {16, 32};
|
||||
|
||||
data_[1] = (data_[1] << shifts[high_res]) | (data_[0] >> (64 - shifts[high_res]));
|
||||
data_[0] <<= shifts[high_res];
|
||||
|
||||
@@ -351,10 +351,10 @@ bool Blitter<record_bus>::advance_dma() {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr int LEFT = 1 << 0;
|
||||
constexpr int RIGHT = 1 << 1;
|
||||
constexpr int UP = 1 << 2;
|
||||
constexpr int DOWN = 1 << 3;
|
||||
static constexpr int LEFT = 1 << 0;
|
||||
static constexpr int RIGHT = 1 << 1;
|
||||
static constexpr int UP = 1 << 2;
|
||||
static constexpr int DOWN = 1 << 3;
|
||||
int step = (line_direction_ & 4) ?
|
||||
((line_direction_ & 1) ? LEFT : RIGHT) :
|
||||
((line_direction_ & 1) ? UP : DOWN);
|
||||
|
||||
@@ -389,12 +389,12 @@ template <int cycle> void Chipset::output() {
|
||||
//
|
||||
// (???)
|
||||
|
||||
constexpr int end_of_pixels = 15;
|
||||
constexpr int blank1 = 3 + end_of_pixels;
|
||||
constexpr int sync = 17 + blank1;
|
||||
constexpr int blank2 = 3 + sync;
|
||||
constexpr int burst = 9 + blank2;
|
||||
constexpr int blank3 = 6 + burst;
|
||||
static constexpr int end_of_pixels = 15;
|
||||
static constexpr int blank1 = 3 + end_of_pixels;
|
||||
static constexpr int sync = 17 + blank1;
|
||||
static constexpr int blank2 = 3 + sync;
|
||||
static constexpr int burst = 9 + blank2;
|
||||
static constexpr int blank3 = 6 + burst;
|
||||
static_assert(blank3 == 53);
|
||||
|
||||
#define LINK(location, action, length) \
|
||||
|
||||
@@ -101,10 +101,11 @@ bool Sprite::advance_dma(int offset, int y, bool is_first_line) {
|
||||
}
|
||||
|
||||
template <int sprite> void TwoSpriteShifter::load(
|
||||
uint16_t lsb,
|
||||
uint16_t msb,
|
||||
int delay) {
|
||||
constexpr int sprite_shift = sprite << 1;
|
||||
const uint16_t lsb,
|
||||
const uint16_t msb,
|
||||
const int delay
|
||||
) {
|
||||
static constexpr int sprite_shift = sprite << 1;
|
||||
const int delay_shift = delay << 2;
|
||||
|
||||
// Clear out any current sprite pixels; this is a reload.
|
||||
|
||||
@@ -260,16 +260,16 @@ private:
|
||||
Implicitly adds an extra half a colour clock at the end of
|
||||
line.
|
||||
*/
|
||||
void advance(Cycles cycles) {
|
||||
void advance(const Cycles cycles) {
|
||||
/*
|
||||
Addressing scheme used throughout is that column 0 is the first column with pixels in it;
|
||||
row 0 is the first row with pixels in it.
|
||||
|
||||
A frame is oriented around 65 cycles across, 262 lines down.
|
||||
*/
|
||||
constexpr int first_sync_line = 220; // A complete guess. Information needed.
|
||||
constexpr int first_sync_column = 49; // Also a guess.
|
||||
constexpr int sync_length = 4; // One of the two likely candidates.
|
||||
static constexpr int first_sync_line = 220; // A complete guess. Information needed.
|
||||
static constexpr int first_sync_column = 49; // Also a guess.
|
||||
static constexpr int sync_length = 4; // One of the two likely candidates.
|
||||
|
||||
int int_cycles = int(cycles.as_integral());
|
||||
while(int_cycles) {
|
||||
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
bool enabled;
|
||||
};
|
||||
static_assert(sizeof(MemoryWrite) == 8);
|
||||
constexpr static int StoreBufferSize = 16384;
|
||||
static constexpr int StoreBufferSize = 16384;
|
||||
|
||||
std::atomic<MemoryWrite> pending_stores_[StoreBufferSize];
|
||||
uint32_t pending_store_read_ = 0, pending_store_read_time_ = 0;
|
||||
|
||||
@@ -195,7 +195,7 @@ Cycles Video::next_sequence_point() const {
|
||||
const int cycles_into_row = cycles_into_frame_ % CyclesPerLine;
|
||||
const int row = cycles_into_frame_ / CyclesPerLine;
|
||||
|
||||
constexpr int sequence_point_offset = (blank_ticks + left_border_ticks) * CyclesPerTick;
|
||||
static constexpr int sequence_point_offset = (blank_ticks + left_border_ticks) * CyclesPerTick;
|
||||
|
||||
// Seed as the distance to the next row 0.
|
||||
int result = CyclesPerLine + sequence_point_offset - cycles_into_row + (Lines - row - 1)*CyclesPerLine;
|
||||
@@ -241,7 +241,7 @@ void Video::output_row(int row, int start, int end) {
|
||||
|
||||
// The pixel buffer will actually be allocated a column early, to allow double high/low res to start
|
||||
// half a column before everything else.
|
||||
constexpr int pixel_buffer_allocation = start_of_pixels - 1;
|
||||
static constexpr int pixel_buffer_allocation = start_of_pixels - 1;
|
||||
|
||||
// Possibly output border, pixels, border, if this is a pixel line.
|
||||
if(row < 192 + ((new_video_&0x80) >> 4)) { // i.e. 192 lines for classic Apple II video, 200 for IIgs video.
|
||||
|
||||
@@ -671,7 +671,7 @@ void Video::VideoStream::shift(int duration) {
|
||||
|
||||
// TODO: turn this into a template on current BPP, perhaps? Would avoid reevaluation of the conditional.
|
||||
void Video::VideoStream::output_pixels(int duration) {
|
||||
constexpr int allocation_size = 352; // i.e. 320 plus a spare 32.
|
||||
static constexpr int allocation_size = 352; // i.e. 320 plus a spare 32.
|
||||
|
||||
// Convert from duration to pixels.
|
||||
int pixels = duration;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
namespace Commodore::Plus4 {
|
||||
|
||||
constexpr int clock_rate(bool is_ntsc) {
|
||||
constexpr int clock_rate(const bool is_ntsc) {
|
||||
return is_ntsc ?
|
||||
14'318'180 : // i.e. colour subcarrier * 4.
|
||||
17'734'448; // i.e. very close to colour subcarrier * 4 — only about 0.1% off.
|
||||
@@ -1013,7 +1013,7 @@ private:
|
||||
|
||||
template <int length, bool is_leftovers>
|
||||
void draw_2bpp_segment(uint16_t *const target, const uint16_t *colours) {
|
||||
constexpr int leftover = is_leftovers && (length & 1);
|
||||
static constexpr int leftover = is_leftovers && (length & 1);
|
||||
static_assert(length + leftover <= 8);
|
||||
if(target) {
|
||||
const auto pixels = output_.pixels();
|
||||
@@ -1030,7 +1030,7 @@ private:
|
||||
}
|
||||
|
||||
if constexpr (is_leftovers) {
|
||||
constexpr int shift_distance = length + leftover;
|
||||
static constexpr int shift_distance = length + leftover;
|
||||
static_assert(!(shift_distance&1));
|
||||
output_.advance_pixels(shift_distance);
|
||||
} else {
|
||||
|
||||
@@ -465,9 +465,9 @@ void Nick::set_output_type(const OutputType type, const bool force_flush) {
|
||||
// MARK: - Sequence points.
|
||||
|
||||
Cycles Nick::next_sequence_point() const {
|
||||
constexpr int load_point = 16; // i.e. 16 cycles after the start of the line, the
|
||||
// interrupt line may change. That is, after the
|
||||
// second byte of the mode line has been read.
|
||||
static constexpr int load_point = 16; // i.e. 16 cycles after the start of the line, the
|
||||
// interrupt line may change. That is, after the
|
||||
// second byte of the mode line has been read.
|
||||
|
||||
// Any mode line may cause a change in the interrupt output, so as a first blush
|
||||
// just always report the time until the end of the mode line.
|
||||
|
||||
@@ -52,8 +52,8 @@ public:
|
||||
void write(const uint8_t value) {
|
||||
switch(address) {
|
||||
default: {
|
||||
constexpr int channel = (address >> 1) & 3;
|
||||
constexpr bool is_count = address & 1;
|
||||
static constexpr int channel = (address >> 1) & 3;
|
||||
static constexpr bool is_count = address & 1;
|
||||
|
||||
next_access_low_ ^= true;
|
||||
if(next_access_low_) {
|
||||
@@ -85,8 +85,8 @@ public:
|
||||
uint8_t read() {
|
||||
switch(address) {
|
||||
default: {
|
||||
constexpr int channel = (address >> 1) & 3;
|
||||
constexpr bool is_count = address & 1;
|
||||
static constexpr int channel = (address >> 1) & 3;
|
||||
static constexpr bool is_count = address & 1;
|
||||
|
||||
next_access_low_ ^= true;
|
||||
if(next_access_low_) {
|
||||
|
||||
@@ -724,13 +724,13 @@ public:
|
||||
|
||||
void run_for(const Cycles duration) final {
|
||||
#ifndef NDEBUG
|
||||
constexpr int SpeedMultiplier = 2;
|
||||
static constexpr int SpeedMultiplier = 2;
|
||||
#else
|
||||
constexpr int SpeedMultiplier = 2;
|
||||
static constexpr int SpeedMultiplier = 2;
|
||||
#endif
|
||||
|
||||
const auto pit_ticks = duration.as<int>() * SpeedMultiplier;
|
||||
constexpr int pit_multiplier = [] {
|
||||
static constexpr int pit_multiplier = [] {
|
||||
switch(pc_model) {
|
||||
// This is implicitly treated as running at 1/3 the PIT clock = around 0.4 MIPS.
|
||||
// i.e. a shade more than 8086 speed, if MIPS were meaningful.
|
||||
|
||||
@@ -67,13 +67,29 @@ template <Timing timing> class Video {
|
||||
// contention began.
|
||||
int delays[8];
|
||||
|
||||
constexpr Timings(int cycles_per_line, int lines_per_frame, int contention_leadin, int contention_duration, int interrupt_offset, const int *delays) noexcept :
|
||||
constexpr Timings(
|
||||
const int cycles_per_line,
|
||||
const int lines_per_frame,
|
||||
const int contention_leadin,
|
||||
const int contention_duration,
|
||||
const int interrupt_offset,
|
||||
const int (&delays)[8])
|
||||
noexcept :
|
||||
half_cycles_per_line(cycles_per_line * 2),
|
||||
lines_per_frame(lines_per_frame),
|
||||
contention_leadin(contention_leadin * 2),
|
||||
contention_duration(contention_duration * 2),
|
||||
interrupt_time((cycles_per_line * lines_per_frame - interrupt_offset - contention_leadin) * 2),
|
||||
delays{ delays[0] * 2, delays[1] * 2, delays[2] * 2, delays[3] * 2, delays[4] * 2, delays[5] * 2, delays[6] * 2, delays[7] * 2}
|
||||
delays{
|
||||
delays[0] * 2,
|
||||
delays[1] * 2,
|
||||
delays[2] * 2,
|
||||
delays[3] * 2,
|
||||
delays[4] * 2,
|
||||
delays[5] * 2,
|
||||
delays[6] * 2,
|
||||
delays[7] * 2
|
||||
}
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -99,14 +115,14 @@ template <Timing timing> class Video {
|
||||
|
||||
public:
|
||||
void run_for(HalfCycles duration) {
|
||||
constexpr auto timings = get_timings();
|
||||
static constexpr auto timings = get_timings();
|
||||
|
||||
constexpr int sync_line = (timings.interrupt_time / timings.half_cycles_per_line) + 1;
|
||||
static constexpr int sync_line = (timings.interrupt_time / timings.half_cycles_per_line) + 1;
|
||||
|
||||
constexpr int sync_position = (timing == Timing::FortyEightK) ? 164 * 2 : 166 * 2;
|
||||
constexpr int sync_length = 17 * 2;
|
||||
constexpr int burst_position = sync_position + 40;
|
||||
constexpr int burst_length = 17;
|
||||
static constexpr int sync_position = (timing == Timing::FortyEightK) ? 164 * 2 : 166 * 2;
|
||||
static constexpr int sync_length = 17 * 2;
|
||||
static constexpr int burst_position = sync_position + 40;
|
||||
static constexpr int burst_length = 17;
|
||||
|
||||
int cycles_remaining = duration.as<int>();
|
||||
while(cycles_remaining) {
|
||||
|
||||
@@ -172,7 +172,7 @@ void print_ram(FILE *file, const std::unordered_map<IntT, uint8_t> &data) {
|
||||
|
||||
template <CPU::MOS6502Esque::Type type> void generate() {
|
||||
BusHandler<type> handler;
|
||||
constexpr bool has_emulation = has(type, CPU::MOS6502Esque::Register::EmulationFlag);
|
||||
static constexpr bool has_emulation = has(type, CPU::MOS6502Esque::Register::EmulationFlag);
|
||||
|
||||
NSString *const tempDir = NSTemporaryDirectory();
|
||||
NSLog(@"Outputting to %@", tempDir);
|
||||
@@ -180,7 +180,7 @@ template <CPU::MOS6502Esque::Type type> void generate() {
|
||||
for(int operation = 0; operation < (has_emulation ? 512 : 256); operation++) {
|
||||
// Make tests repeatable, at least for any given instance of
|
||||
// the runtime.
|
||||
constexpr auto type_offset = int(CPU::MOS6502Esque::Type::TWDC65816) - int(type);
|
||||
static constexpr auto type_offset = int(CPU::MOS6502Esque::Type::TWDC65816) - int(type);
|
||||
srand(65816 + operation + type_offset);
|
||||
|
||||
const bool is_emulated = operation & 256;
|
||||
|
||||
@@ -350,7 +350,7 @@ void populate(InstructionSet::x86::Registers<t_model> ®isters, Flags &flags,
|
||||
flags.set(flags_value);
|
||||
|
||||
// Apply a quick test of flag packing/unpacking.
|
||||
constexpr auto defined_flags = static_cast<uint16_t>(
|
||||
static constexpr auto defined_flags = static_cast<uint16_t>(
|
||||
InstructionSet::x86::FlagValue::Carry |
|
||||
InstructionSet::x86::FlagValue::Parity |
|
||||
InstructionSet::x86::FlagValue::AuxiliaryCarry |
|
||||
|
||||
@@ -20,17 +20,17 @@
|
||||
}
|
||||
|
||||
- (void)testIDMark {
|
||||
constexpr uint8_t IDMark[] = {
|
||||
static constexpr uint8_t IDMark[] = {
|
||||
0xa1, 0xa1, 0xa1, 0xfe, 0x00, 0x00, 0x01, 0x01
|
||||
};
|
||||
constexpr uint16_t crc = 0xfa0c;
|
||||
static constexpr uint16_t crc = 0xfa0c;
|
||||
const uint16_t computedCRC = CRC::CCITT::crc_of(std::begin(IDMark), std::end(IDMark));
|
||||
|
||||
XCTAssert(computedCRC == crc, @"Calculated CRC should have been %04x, was %04x", crc, computedCRC);
|
||||
}
|
||||
|
||||
- (void)testData {
|
||||
constexpr uint8_t sectorData[] = {
|
||||
static constexpr uint8_t sectorData[] = {
|
||||
0xa1, 0xa1, 0xa1, 0xfb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x53, 0x45, 0x44, 0x4f,
|
||||
0x52, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
@@ -49,19 +49,19 @@
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20
|
||||
};
|
||||
constexpr uint16_t crc = 0x4de7;
|
||||
static constexpr uint16_t crc = 0x4de7;
|
||||
uint16_t computedCRC = CRC::CCITT::crc_of(std::begin(sectorData), std::end(sectorData));
|
||||
|
||||
XCTAssert(computedCRC == crc, @"Calculated CRC should have been %04x, was %04x", crc, computedCRC);
|
||||
}
|
||||
|
||||
- (void)testCCITTCheck {
|
||||
constexpr char testString[] = "123456789";
|
||||
static constexpr char testString[] = "123456789";
|
||||
XCTAssertEqual(CRC::CCITT::crc_of(std::begin(testString), std::end(testString) - 1), 0x29b1);
|
||||
}
|
||||
|
||||
- (void)testCRC32Check {
|
||||
constexpr char testString[] = "123456789";
|
||||
static constexpr char testString[] = "123456789";
|
||||
XCTAssertEqual(CRC::CRC32::crc_of(std::begin(testString), std::end(testString) - 1), 0xcbf43926);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace {
|
||||
|
||||
/// Implements the Amiga minterm algorithm in a bit-by-bit form.
|
||||
template <typename IntT> IntT slow_minterm(IntT a, IntT b, IntT c, uint8_t minterm) {
|
||||
constexpr int top_shift = sizeof(IntT) * 8 - 1;
|
||||
static constexpr int top_shift = sizeof(IntT) * 8 - 1;
|
||||
|
||||
IntT result = 0;
|
||||
for(int i = 0; i < 8*sizeof(IntT); i++) {
|
||||
@@ -42,9 +42,9 @@ template <typename IntT> IntT slow_minterm(IntT a, IntT b, IntT c, uint8_t minte
|
||||
- (void)testAll {
|
||||
// These three are selected just to ensure that all combinations of
|
||||
// bit pattern exist in the input.
|
||||
constexpr uint8_t a = 0xaa;
|
||||
constexpr uint8_t b = 0xcc;
|
||||
constexpr uint8_t c = 0xf0;
|
||||
static constexpr uint8_t a = 0xaa;
|
||||
static constexpr uint8_t b = 0xcc;
|
||||
static constexpr uint8_t c = 0xf0;
|
||||
|
||||
for(int minterm = 0; minterm < 256; minterm++) {
|
||||
const uint8_t slow = slow_minterm(a, b, c, minterm);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
}
|
||||
|
||||
- (void)testBitStreamLSBFirst {
|
||||
constexpr uint8_t testData[] = {
|
||||
static constexpr uint8_t testData[] = {
|
||||
0xa3, 0xf4
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
}
|
||||
|
||||
- (void)testBitStreamMSBFirst {
|
||||
constexpr uint8_t testData[] = {
|
||||
static constexpr uint8_t testData[] = {
|
||||
0xa3, 0xf4
|
||||
};
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
}
|
||||
|
||||
- (void)testBitStreamMultibyte {
|
||||
constexpr uint8_t testData[] = {
|
||||
static constexpr uint8_t testData[] = {
|
||||
0xa3, 0xf4, 0x11
|
||||
};
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ private:
|
||||
Tests the progression of Clock Signal's 68000 through the Sinclair QL's ROM against a known-good trace.
|
||||
*/
|
||||
- (void)testStartup {
|
||||
constexpr ROM::Name rom_name = ROM::Name::SinclairQLJS;
|
||||
static constexpr ROM::Name rom_name = ROM::Name::SinclairQLJS;
|
||||
ROM::Request request(rom_name);
|
||||
const auto roms = CSROMFetcher()(request);
|
||||
NSString *const traceLocation = [[NSBundle bundleForClass:[self class]] pathForResource:@"qltrace" ofType:@".txt.gz"];
|
||||
|
||||
@@ -582,7 +582,7 @@ template <typename LHSCollectionT, typename RHSCollectionT>
|
||||
}
|
||||
|
||||
- (void)testLDiiPlusn {
|
||||
constexpr uint8_t offset = 0x10;
|
||||
static constexpr uint8_t offset = 0x10;
|
||||
for(const auto &sequence : std::vector<std::vector<uint8_t>>{
|
||||
// LD r, (ii+n)
|
||||
{0xdd, 0x46, offset}, {0xdd, 0x4e, offset},
|
||||
@@ -663,7 +663,7 @@ template <typename LHSCollectionT, typename RHSCollectionT>
|
||||
}
|
||||
|
||||
- (void)testBITbiin {
|
||||
constexpr uint8_t offset = 0x10;
|
||||
static constexpr uint8_t offset = 0x10;
|
||||
for(const auto &sequence : std::vector<std::vector<uint8_t>>{
|
||||
// BIT b, (ix+d)
|
||||
{0xdd, 0xcb, offset, 0x46}, {0xdd, 0xcb, offset, 0x4e},
|
||||
@@ -748,7 +748,7 @@ template <typename LHSCollectionT, typename RHSCollectionT>
|
||||
}
|
||||
|
||||
- (void)testLDiiPlusnn {
|
||||
constexpr uint8_t offset = 0x10;
|
||||
static constexpr uint8_t offset = 0x10;
|
||||
for(const auto &sequence : std::vector<std::vector<uint8_t>>{
|
||||
// LD (ii+n), n
|
||||
{0xdd, 0x36, offset}, {0xfd, 0x36, offset},
|
||||
@@ -914,7 +914,7 @@ template <typename LHSCollectionT, typename RHSCollectionT>
|
||||
}
|
||||
|
||||
- (void)testINCDECiin {
|
||||
constexpr uint8_t offset = 0x10;
|
||||
static constexpr uint8_t offset = 0x10;
|
||||
for(const auto &sequence : std::vector<std::vector<uint8_t>>{
|
||||
// INC (ii+n)
|
||||
{0xdd, 0x34, offset}, {0xfd, 0x34, offset},
|
||||
@@ -949,7 +949,7 @@ template <typename LHSCollectionT, typename RHSCollectionT>
|
||||
}
|
||||
|
||||
- (void)testSETRESiin {
|
||||
constexpr uint8_t offset = 0x10;
|
||||
static constexpr uint8_t offset = 0x10;
|
||||
for(const auto &sequence : std::vector<std::vector<uint8_t>>{
|
||||
// SET b, (ii+n)
|
||||
{0xdd, 0xcb, offset, 0xc6}, {0xdd, 0xcb, offset, 0xce},
|
||||
@@ -1301,7 +1301,7 @@ template <typename LHSCollectionT, typename RHSCollectionT>
|
||||
CapturingZ80 z80(sequence);
|
||||
|
||||
// Establish a distinct value for DE.
|
||||
constexpr uint16_t de = 0x9876;
|
||||
static constexpr uint16_t de = 0x9876;
|
||||
z80.set_de(de);
|
||||
|
||||
z80.run_for(16);
|
||||
@@ -1331,7 +1331,7 @@ template <typename LHSCollectionT, typename RHSCollectionT>
|
||||
CapturingZ80 z80(sequence);
|
||||
|
||||
// Establish a distinct value for DE.
|
||||
constexpr uint16_t de = 0x9876;
|
||||
static constexpr uint16_t de = 0x9876;
|
||||
z80.set_de(de);
|
||||
|
||||
z80.run_for(21);
|
||||
@@ -1476,7 +1476,7 @@ template <typename LHSCollectionT, typename RHSCollectionT>
|
||||
CapturingZ80 z80(sequence);
|
||||
|
||||
// Establish a distinct value for BC.
|
||||
constexpr uint16_t bc = 0x9876;
|
||||
static constexpr uint16_t bc = 0x9876;
|
||||
z80.set_bc(bc);
|
||||
|
||||
z80.run_for(16);
|
||||
@@ -1505,7 +1505,7 @@ template <typename LHSCollectionT, typename RHSCollectionT>
|
||||
CapturingZ80 z80(sequence);
|
||||
|
||||
// Establish a distinct value for BC.
|
||||
constexpr uint16_t bc = 0x9876;
|
||||
static constexpr uint16_t bc = 0x9876;
|
||||
z80.set_bc(bc);
|
||||
|
||||
z80.run_for(21);
|
||||
|
||||
@@ -241,7 +241,7 @@ public:
|
||||
lights_.clear();
|
||||
|
||||
// Generate a bunch of LEDs for connected drives.
|
||||
constexpr float height = 0.05f;
|
||||
static constexpr float height = 0.05f;
|
||||
const float width = height / aspect_ratio;
|
||||
const float right_x = 1.0f - 2.0f * width;
|
||||
float y = 1.0f - 2.0f * height;
|
||||
|
||||
+8
-8
@@ -17,15 +17,15 @@ using namespace Outputs::CRT;
|
||||
|
||||
void CRT::set_new_timing(int cycles_per_line, int height_of_display, Outputs::Display::ColourSpace colour_space, int colour_cycle_numerator, int colour_cycle_denominator, int vertical_sync_half_lines, bool should_alternate) {
|
||||
|
||||
constexpr int millisecondsHorizontalRetraceTime = 7; // Source: Dictionary of Video and Television Technology, p. 234.
|
||||
constexpr int scanlinesVerticalRetraceTime = 8; // Source: ibid.
|
||||
static constexpr int millisecondsHorizontalRetraceTime = 7; // Source: Dictionary of Video and Television Technology, p. 234.
|
||||
static constexpr int scanlinesVerticalRetraceTime = 8; // Source: ibid.
|
||||
|
||||
// To quote:
|
||||
//
|
||||
// "retrace interval; The interval of time for the return of the blanked scanning beam of
|
||||
// a TV picture tube or camera tube to the starting point of a line or field. It is about
|
||||
// 7 microseconds for horizontal retrace and 500 to 750 microseconds for vertical retrace
|
||||
// in NTSC and PAL TV."
|
||||
// To quote:
|
||||
//
|
||||
// "retrace interval; The interval of time for the return of the blanked scanning beam of
|
||||
// a TV picture tube or camera tube to the starting point of a line or field. It is about
|
||||
// 7 microseconds for horizontal retrace and 500 to 750 microseconds for vertical retrace
|
||||
// in NTSC and PAL TV."
|
||||
|
||||
time_multiplier_ = 63487 / cycles_per_line; // 63475 = 65535 * 31/32, i.e. the same 1/32 error as below is permitted.
|
||||
phase_denominator_ = int64_t(cycles_per_line) * int64_t(colour_cycle_denominator) * int64_t(time_multiplier_);
|
||||
|
||||
@@ -26,7 +26,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
/// Divides memory-accessing instructions by whether they read or write.
|
||||
/// Read-modify-writes are documented with completely distinct bus programs,
|
||||
/// so there's no real ambiguity there.
|
||||
constexpr static AccessType access_type_for_operation(Operation operation) {
|
||||
static constexpr AccessType access_type_for_operation(Operation operation) {
|
||||
switch(operation) {
|
||||
case ADC: case AND: case BIT: case CMP:
|
||||
case CPX: case CPY: case EOR: case ORA:
|
||||
@@ -46,7 +46,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
|
||||
/// Indicates which of the memory-accessing instructions take their cue from the current
|
||||
/// size of the index registers, rather than 'memory'[/accumulator].
|
||||
constexpr static bool operation_is_index_sized(Operation operation) {
|
||||
static constexpr bool operation_is_index_sized(Operation operation) {
|
||||
switch(operation) {
|
||||
case CPX: case CPY:
|
||||
case LDX: case LDY:
|
||||
|
||||
@@ -116,7 +116,7 @@ struct SubrangeDispatcher {
|
||||
#define index(n) \
|
||||
case n: \
|
||||
if constexpr (n <= ClassifierT::max) { \
|
||||
constexpr auto region = ClassifierT::region(n); \
|
||||
static constexpr auto region = ClassifierT::region(n); \
|
||||
if constexpr (n == find_begin(n)) { \
|
||||
if(n >= end) { \
|
||||
return; \
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ namespace Reflection {
|
||||
|
||||
#define ReflectableEnum(Name, ...) \
|
||||
enum class Name { __VA_ARGS__ }; \
|
||||
constexpr static const char *__declaration##Name = #__VA_ARGS__;
|
||||
static constexpr const char *__declaration##Name = #__VA_ARGS__;
|
||||
|
||||
#define EnumDeclaration(Name) #Name, __declaration##Name
|
||||
|
||||
|
||||
@@ -503,7 +503,7 @@ bool Reflection::Struct::deserialise(const uint8_t *bson, const size_t size) {
|
||||
// Validate the object's declared size.
|
||||
const auto end = bson + size;
|
||||
auto read_int = [&bson] (auto &target) {
|
||||
constexpr auto shift = 8 * (sizeof(target) - 1);
|
||||
static constexpr auto shift = 8 * (sizeof(target) - 1);
|
||||
target = 0;
|
||||
for(size_t c = 0; c < sizeof(target); ++c) {
|
||||
target >>= 8;
|
||||
|
||||
@@ -412,7 +412,7 @@ template <typename Type> bool get(const Struct &target, const std::string &name,
|
||||
|
||||
// If the type is a double and stored type is a float, cast upward.
|
||||
if constexpr (std::is_floating_point<Type>::value) {
|
||||
constexpr size_t size = sizeof(Type);
|
||||
static constexpr size_t size = sizeof(Type);
|
||||
const bool target_is_floating_point = TypeInfo::is_floating_point(target_type);
|
||||
const size_t target_size = TypeInfo::size(target_type);
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@ std::unique_ptr<Track> IPF::track_at_position(const Track::Address address) cons
|
||||
/// is required to know all named protection schemes. Which makes IPF unable to handle arbitrary disks (or, indeed, disks
|
||||
/// with multiple protection schemes on a single track).
|
||||
Storage::Time IPF::bit_length(TrackDescription::Density density, int block) const {
|
||||
constexpr unsigned int us = 100'000'000;
|
||||
static constexpr unsigned int us = 100'000'000;
|
||||
static constexpr auto us170 = Storage::Time::simplified(170, us);
|
||||
static constexpr auto us180 = Storage::Time::simplified(180, us);
|
||||
static constexpr auto us189 = Storage::Time::simplified(189, us);
|
||||
|
||||
@@ -33,7 +33,7 @@ JFD::JFD(const std::string &file_name) : file_name_(file_name) {
|
||||
|
||||
// First four bytes: signature.
|
||||
uint8_t signature[4];
|
||||
constexpr uint8_t required_signature[4] = { 'J', 'F', 'D', 'I' };
|
||||
static constexpr uint8_t required_signature[4] = { 'J', 'F', 'D', 'I' };
|
||||
gzread(file_, signature, sizeof(signature));
|
||||
if(!std::equal(std::begin(signature), std::end(signature), std::begin(required_signature))) {
|
||||
throw 1;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace {
|
||||
|
||||
class TrackConstructor {
|
||||
public:
|
||||
constexpr static uint16_t NoFirstOffset = std::numeric_limits<uint16_t>::max();
|
||||
static constexpr uint16_t NoFirstOffset = std::numeric_limits<uint16_t>::max();
|
||||
|
||||
struct Sector {
|
||||
// Records explicitly present in the sector table.
|
||||
|
||||
@@ -24,11 +24,11 @@ constexpr uint32_t chunk(const char *str) {
|
||||
WOZ::WOZ(const std::string &file_name) :
|
||||
file_(file_name) {
|
||||
|
||||
constexpr const char signature1[8] = {
|
||||
static constexpr char signature1[8] = {
|
||||
'W', 'O', 'Z', '1',
|
||||
char(0xff), 0x0a, 0x0d, 0x0a
|
||||
};
|
||||
constexpr const char signature2[8] = {
|
||||
static constexpr char signature2[8] = {
|
||||
'W', 'O', 'Z', '2',
|
||||
char(0xff), 0x0a, 0x0d, 0x0a
|
||||
};
|
||||
|
||||
@@ -51,7 +51,7 @@ private:
|
||||
the track does not exit.
|
||||
*/
|
||||
long file_offset(Track::Address address) const;
|
||||
constexpr static long NoSuchTrack = 0; // This is an offset a track definitely can't lie at.
|
||||
static constexpr long NoSuchTrack = 0; // This is an offset a track definitely can't lie at.
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ bool Drive::get_tachometer() const {
|
||||
// I have made a guess here that the tachometer is a symmetric square wave;
|
||||
// if that is correct then around 60 beats per rotation appears to be correct
|
||||
// to proceed beyond the speed checks I've so far uncovered.
|
||||
constexpr float ticks_per_rotation = 60.0f; // 56 was too low; 64 too high.
|
||||
static constexpr float ticks_per_rotation = 60.0f; // 56 was too low; 64 too high.
|
||||
return int(get_rotation() * 2.0f * ticks_per_rotation) & 1;
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ void Drive::get_next_event(float duration_already_passed) {
|
||||
|
||||
// An interval greater than 15µs => adjust gain up the point where noise starts happening.
|
||||
// Seed that up and leave a 15µs gap until it starts.
|
||||
constexpr float safe_gain_period = 15.0f / 1'000'000.0f;
|
||||
static constexpr float safe_gain_period = 15.0f / 1'000'000.0f;
|
||||
if(interval >= safe_gain_period) {
|
||||
random_interval_ = interval - safe_gain_period;
|
||||
interval = safe_gain_period;
|
||||
|
||||
@@ -142,7 +142,7 @@ Storage::Disk::PCMSegment AppleGCR::AppleII::six_and_two_data(const uint8_t *sou
|
||||
// and combined copies of the bottom two bits of the sector
|
||||
// contents; the 256 bytes afterwards are the remaining
|
||||
// six bits.
|
||||
constexpr uint8_t bit_reverse[] = {0, 2, 1, 3};
|
||||
static constexpr uint8_t bit_reverse[] = {0, 2, 1, 3};
|
||||
for(std::size_t c = 0; c < 84; ++c) {
|
||||
data[3 + c] =
|
||||
uint8_t(
|
||||
|
||||
@@ -204,7 +204,7 @@ std::unique_ptr<Sector> decode_appleii_sector(const std::array<uint_fast8_t, 8>
|
||||
sector->encoding = Sector::Encoding::FiveAndThree;
|
||||
} else {
|
||||
// Undo the 6 and 2 mapping.
|
||||
constexpr uint8_t bit_reverse[] = {0, 2, 1, 3};
|
||||
static constexpr uint8_t bit_reverse[] = {0, 2, 1, 3};
|
||||
const auto unmap = [&](std::size_t byte, std::size_t nibble, int shift) {
|
||||
sector->data[86 + byte] = uint8_t(
|
||||
(sector->data[86 + byte] << 2) | bit_reverse[(sector->data[nibble] >> shift)&3]
|
||||
|
||||
@@ -111,10 +111,10 @@ bool PRG::Serialiser::is_at_end() const {
|
||||
}
|
||||
|
||||
void PRG::Serialiser::get_next_output_token() {
|
||||
constexpr int block_length = 192; // not counting the checksum
|
||||
constexpr int countdown_bytes = 9;
|
||||
constexpr int leadin_length = 20000;
|
||||
constexpr int block_leadin_length = 5000;
|
||||
static constexpr int block_length = 192; // not counting the checksum
|
||||
static constexpr int countdown_bytes = 9;
|
||||
static constexpr int leadin_length = 20000;
|
||||
static constexpr int block_leadin_length = 5000;
|
||||
|
||||
if(file_phase_ == FilePhaseHeaderDataGap || file_phase_ == FilePhaseAtEnd) {
|
||||
output_token_ = Silence;
|
||||
|
||||
@@ -255,7 +255,7 @@ void Parser::process_pulse(const Storage::Tape::Pulse &pulse) {
|
||||
const float medium_ms = is_plus4 ? 480.0f : 262.0f;
|
||||
const float long_ms = is_plus4 ? 960.0f : 342.0f;
|
||||
|
||||
constexpr float to_s = 2.0f / 1'000'000.0f;
|
||||
static constexpr float to_s = 2.0f / 1'000'000.0f;
|
||||
const float overlong_threshold = (long_ms + long_ms - medium_ms) * to_s;
|
||||
const float long_threshold = ((long_ms + medium_ms) * 0.5f) * to_s;
|
||||
const float medium_threshold = ((medium_ms + short_ms) * 0.5f) * to_s;
|
||||
|
||||
@@ -41,9 +41,9 @@ bool Parser::sync_and_get_encoding_speed(Storage::Tape::TapeSerialiser &serialis
|
||||
}
|
||||
|
||||
void Parser::process_pulse(const Storage::Tape::Pulse &pulse) {
|
||||
constexpr float maximum_short_length = 0.000512f;
|
||||
constexpr float maximum_medium_length = 0.000728f;
|
||||
constexpr float maximum_long_length = 0.001456f;
|
||||
static constexpr float maximum_short_length = 0.000512f;
|
||||
static constexpr float maximum_medium_length = 0.000728f;
|
||||
static constexpr float maximum_long_length = 0.001456f;
|
||||
|
||||
const bool wave_is_high = pulse.type == Storage::Tape::Pulse::High;
|
||||
if(!wave_was_high_ && wave_is_high != wave_was_high_) {
|
||||
|
||||
@@ -29,8 +29,8 @@ void Parser::process_pulse(const Storage::Tape::Pulse &pulse) {
|
||||
}
|
||||
|
||||
void Parser::post_pulse() {
|
||||
constexpr float expected_pulse_length = 300.0f / 1000000.0f;
|
||||
constexpr float expected_gap_length = 1300.0f / 1000000.0f;
|
||||
static constexpr float expected_pulse_length = 300.0f / 1000000.0f;
|
||||
static constexpr float expected_gap_length = 1300.0f / 1000000.0f;
|
||||
const auto pulse_time = pulse_time_.get<float>();
|
||||
|
||||
if(pulse_time > expected_gap_length * 1.25f) {
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace TargetPlatform {
|
||||
|
||||
using IntType = uint32_t;
|
||||
|
||||
constexpr IntType bit(int index) {
|
||||
constexpr IntType bit(const int index) {
|
||||
return 1 << index;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user