openMSX
VDPAccessSlots.hh
Go to the documentation of this file.
1#ifndef VDPACCESSSLOTS_HH
2#define VDPACCESSSLOTS_HH
3
4#include "VDP.hh"
5#include "narrow.hh"
6#include <cassert>
7#include <cstdint>
8#include <span>
9
11
12inline constexpr int TICKS = VDP::TICKS_PER_LINE;
13
14enum class Delta : int {
15 D0 = 0 * TICKS,
16 D1 = 1 * TICKS,
17 D16 = 2 * TICKS,
18 D24 = 3 * TICKS,
19 D28 = 4 * TICKS,
20 D32 = 5 * TICKS,
21 D40 = 6 * TICKS,
22 D48 = 7 * TICKS,
23 D64 = 8 * TICKS,
24 D72 = 9 * TICKS,
25 D88 = 10 * TICKS,
26 D104 = 11 * TICKS,
27 D120 = 12 * TICKS,
28 D128 = 13 * TICKS,
29 D136 = 14 * TICKS,
30};
31static constexpr int NUM_DELTAS = 15;
32
39{
40public:
42 Calculator(EmuTime::param frame, EmuTime::param time,
43 EmuTime::param limit_, std::span<const uint8_t, NUM_DELTAS * TICKS> tab_)
44 : ref(frame), tab(tab_)
45 {
46 assert(frame <= time);
47 assert(frame <= limit_);
48 // not required that time <= limit
49
50 ticks = narrow<int>(ref.getTicksTill_fast(time));
51 limit = narrow<int>(ref.getTicksTill_fast(limit_));
52 int lines = ticks / TICKS;
53 ticks -= lines * TICKS;
54 limit -= lines * TICKS; // might be negative
55 ref += lines * TICKS;
56 assert(0 <= ticks); assert(ticks < TICKS);
57 }
58
60 [[nodiscard]] inline bool limitReached() const {
61 return ticks >= limit;
62 }
63
67 [[nodiscard]] inline EmuTime getTime() const {
68 return ref.getFastAdd(ticks);
69 }
70
73 inline void next(Delta delta) {
74 ticks += tab[to_underlying(delta) + ticks];
75 if (ticks >= TICKS) [[unlikely]] {
76 ticks -= TICKS;
77 limit -= TICKS;
78 ref += TICKS;
79 }
80 }
81
82private:
83 int ticks;
84 int limit;
85 VDP::VDPClock ref;
86 std::span<const uint8_t, NUM_DELTAS * TICKS> tab;
87};
88
92[[nodiscard]] EmuTime getAccessSlot(EmuTime::param frame, EmuTime::param time, Delta delta,
93 const VDP& vdp);
94
97[[nodiscard]] Calculator getCalculator(
98 EmuTime::param frame, EmuTime::param time, EmuTime::param limit,
99 const VDP& vdp);
100
101} // namespace openmsx::VDPAccessSlots
102
103#endif
constexpr EmuTime getFastAdd(unsigned n) const
Like operator+() but faster, though the step can't be too big (max a little over 1 second).
Definition Clock.hh:93
constexpr unsigned getTicksTill_fast(EmuTime::param e) const
Same as above, only faster, Though the time interval may not be too large.
Definition Clock.hh:70
VDP-VRAM access slot calculator, meant to be used in the inner loops of the VDPCmdEngine commands.
Calculator(EmuTime::param frame, EmuTime::param time, EmuTime::param limit_, std::span< const uint8_t, NUM_DELTAS *TICKS > tab_)
This shouldn't be called directly, instead use getCalculator().
void next(Delta delta)
Advance time to the earliest access slot that is at least 'delta' ticks later than the current time.
bool limitReached() const
Has 'time' advanced to or past 'limit'?
EmuTime getTime() const
Get the current time.
Unified implementation of MSX Video Display Processors (VDPs).
Definition VDP.hh:66
static constexpr int TICKS_PER_LINE
Number of VDP clock ticks per line.
Definition VDP.hh:75
EmuTime getAccessSlot(EmuTime::param frame_, EmuTime::param time, Delta delta, const VDP &vdp)
Return the time of the next available access slot that is at least 'delta' cycles later than 'time'.
Calculator getCalculator(EmuTime::param frame, EmuTime::param time, EmuTime::param limit, const VDP &vdp)
When many calls to getAccessSlot() are needed, it's more efficient to instead use this function.
constexpr auto to_underlying(E e) noexcept
Definition stl.hh:465