| e8555c89 Andy McCall |
1 |
#ifndef VDPACCESSSLOTS_HH |
| 2 |
#define VDPACCESSSLOTS_HH |
| 3 |
|
| 4 |
#include "VDP.hh" |
| 5 |
|
| 6 |
#include "narrow.hh" |
| 7 |
|
| 8 |
#include <cassert> |
| 9 |
#include <cstdint> |
| 10 |
#include <span> |
| 11 |
#include <utility> |
| 12 |
|
| 13 |
namespace openmsx::VDPAccessSlots { |
| 14 |
|
| 15 |
inline constexpr int TICKS = VDP::TICKS_PER_LINE; |
| 16 |
|
| 17 |
|
| 18 |
enum class Delta : int { |
| 19 |
D0 = 0 * TICKS, |
| 20 |
D1 = 1 * TICKS, |
| 21 |
CPU_16 = 2 * TICKS, |
| 22 |
CPU_28 = 3 * TICKS, |
| 23 |
|
| 24 |
|
| 25 |
|
| 26 |
CPU_16_ANY = 4 * TICKS, |
| 27 |
CMD_24 = 5 * TICKS, |
| 28 |
CMD_32 = 6 * TICKS, |
| 29 |
CMD_36 = 7 * TICKS, |
| 30 |
CMD_46 = 8 * TICKS, |
| 31 |
CMD_60 = 9 * TICKS, |
| 32 |
CMD_72 = 10 * TICKS, |
| 33 |
CMD_84 = 11 * TICKS, |
| 34 |
CMD_88 = 12 * TICKS, |
| 35 |
CMD_36_68 = 13 * TICKS, |
| 36 |
CMD_46_58 = 13 * TICKS, |
| 37 |
CMD_84_36 = 14 * TICKS, |
| 38 |
CMD_60_68 = 15 * TICKS, |
| 39 |
CMD_72_58 = 16 * TICKS, |
| 40 |
|
| 41 |
|
| 42 |
|
| 43 |
|
| 44 |
|
| 45 |
|
| 46 |
CMD_START_63 = 17 * TICKS, |
| 47 |
CMD_START_64 = 18 * TICKS, |
| 48 |
CMD_START_76 = 19 * TICKS, |
| 49 |
CMD_START_88 = 12 * TICKS, |
| 50 |
CMD_START_100 = 20 * TICKS, |
| 51 |
CMD_START_112 = 21 * TICKS, |
| 52 |
}; |
| 53 |
static constexpr int NUM_DELTAS = 22; |
| 54 |
|
| 55 |
static constexpr int FIRST_CPU_DELTA = 2; |
| 56 |
static constexpr int LAST_CPU_DELTA = 5; |
| 57 |
|
| 58 |
static constexpr int CPU_ANY_DELTA = 4; |
| 59 |
|
| 60 |
|
| 61 |
|
| 62 |
static constexpr int FIRST_CMD_DELTA = 5; |
| 63 |
static constexpr int LAST_CMD_DELTA = NUM_DELTAS; |
| 64 |
|
| 65 |
|
| 66 |
|
| 67 |
|
| 68 |
|
| 69 |
|
| 70 |
class Calculator |
| 71 |
{ |
| 72 |
public: |
| 73 |
|
| 74 |
Calculator(EmuTime frame, EmuTime time, |
| 75 |
EmuTime limit_, std::span<const uint8_t, NUM_DELTAS * TICKS> tab_) |
| 76 |
: ref(frame), tab(tab_) |
| 77 |
{ |
| 78 |
assert(frame <= time); |
| 79 |
assert(frame <= limit_); |
| 80 |
|
| 81 |
|
| 82 |
ticks = narrow<int>(ref.getTicksTill(time)); |
| 83 |
limit = narrow<int>(ref.getTicksTill(limit_)); |
| 84 |
int lines = ticks / TICKS; |
| 85 |
ticks -= lines * TICKS; |
| 86 |
limit -= lines * TICKS; |
| 87 |
ref += lines * TICKS; |
| 88 |
assert(0 <= ticks); assert(ticks < TICKS); |
| 89 |
} |
| 90 |
|
| 91 |
|
| 92 |
[[nodiscard]] bool limitReached() const { |
| 93 |
return ticks >= limit; |
| 94 |
} |
| 95 |
|
| 96 |
|
| 97 |
|
| 98 |
|
| 99 |
[[nodiscard]] EmuTime getTime() const { |
| 100 |
return ref.getFastAdd(ticks); |
| 101 |
} |
| 102 |
|
| 103 |
|
| 104 |
|
| 105 |
void next(Delta delta) { |
| 106 |
ticks += tab[std::to_underlying(delta) + ticks]; |
| 107 |
if (ticks >= TICKS) [[unlikely]] { |
| 108 |
ticks -= TICKS; |
| 109 |
limit -= TICKS; |
| 110 |
ref += TICKS; |
| 111 |
} |
| 112 |
} |
| 113 |
|
| 114 |
private: |
| 115 |
int ticks; |
| 116 |
int limit; |
| 117 |
VDP::VDPClock ref; |
| 118 |
std::span<const uint8_t, NUM_DELTAS * TICKS> tab; |
| 119 |
}; |
| 120 |
|
| 121 |
|
| 122 |
|
| 123 |
|
| 124 |
[[nodiscard]] EmuTime getAccessSlot(EmuTime frame, EmuTime time, Delta delta, |
| 125 |
const VDP& vdp); |
| 126 |
|
| 127 |
|
| 128 |
|
| 129 |
[[nodiscard]] Calculator getCalculator( |
| 130 |
EmuTime frame, EmuTime time, EmuTime limit, |
| 131 |
const VDP& vdp); |
| 132 |
|
| 133 |
|
| 134 |
inline constexpr int MAX_PADDING_SPAN = 8; |
| 135 |
|
| 136 |
|
| 137 |
|
| 138 |
|
| 139 |
|
| 140 |
[[nodiscard]] int paddingCycles(int tick, int n, const VDP& vdp); |
| 141 |
|
| 142 |
|
| 143 |
|
| 144 |
|
| 145 |
[[nodiscard]] bool isLateCpuSlot(int slotTick, const VDP& vdp); |
| 146 |
|
| 147 |
} |
| 148 |
|
| 149 |
#endif |