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 "likely.hh"
6 #include <cassert>
7 #include <cstdint>
8 
9 namespace openmsx {
10 namespace VDPAccessSlots {
11 
12 static const int TICKS = VDP::TICKS_PER_LINE;
13 
14 enum Delta : int {
15  DELTA_0 = 0 * TICKS,
16  DELTA_1 = 1 * TICKS,
17  DELTA_16 = 2 * TICKS,
18  DELTA_24 = 3 * TICKS,
19  DELTA_28 = 4 * TICKS,
20  DELTA_32 = 5 * TICKS,
21  DELTA_40 = 6 * TICKS,
22  DELTA_48 = 7 * TICKS,
23  DELTA_64 = 8 * TICKS,
24  DELTA_72 = 9 * TICKS,
25  DELTA_88 = 10 * TICKS,
26  DELTA_104 = 11 * TICKS,
27  DELTA_120 = 12 * TICKS,
28  DELTA_128 = 13 * TICKS,
29  DELTA_136 = 14 * TICKS,
30  NUM_DELTAS = 15,
31 };
32 
39 {
40 public:
42  Calculator(EmuTime::param frame, EmuTime::param time,
43  EmuTime::param limit_, const uint8_t* tab_)
44  : ref(frame), tab(tab_)
45  {
46  assert(frame <= time);
47  assert(frame <= limit_);
48  // not required that time <= limit
49 
50  ticks = ref.getTicksTill_fast(time);
51  limit = 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  inline bool limitReached() const {
61  return ticks >= limit;
62  }
63 
67  inline EmuTime getTime() const {
68  return ref.getFastAdd(ticks);
69  }
70 
73  inline void next(Delta delta) {
74  ticks += tab[delta + ticks];
75  if (unlikely(ticks >= TICKS)) {
76  ticks -= TICKS;
77  limit -= TICKS;
78  ref += TICKS;
79  }
80  }
81 
82 private:
83  int ticks;
84  int limit;
85  VDP::VDPClock ref;
86  const uint8_t* const tab;
87 };
88 
92 EmuTime getAccessSlot(EmuTime::param frame, EmuTime::param time, Delta delta,
93  const VDP& vdp);
94 
98  EmuTime::param frame, EmuTime::param time, EmuTime::param limit,
99  const VDP& vdp);
100 
101 } // namespace VDPAccessSlots
102 } // namespace openmsx
103 
104 #endif
Calculator getCalculator(EmuTime::param frame, EmuTime::param time, EmuTime::param limit, const VDP &vdp)
When many calls to getAccessSlot() are needed, it&#39;s more efficient to instead use this function...
static const int TICKS_PER_LINE
Number of VDP clock ticks per line.
Definition: VDP.hh:72
#define unlikely(x)
Definition: likely.hh:15
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 &#39;delta&#39; cycles later than &#39;time&#39;...
void next(Delta delta)
Advance time to the earliest access slot that is at least &#39;delta&#39; ticks later than the current time...
Calculator(EmuTime::param frame, EmuTime::param time, EmuTime::param limit_, const uint8_t *tab_)
This shouldn&#39;t be called directly, instead use getCalculator().
EmuTime getTime() const
Get the current time.
EmuTime getFastAdd(unsigned n) const
Like operator+() but faster, though the step can&#39;t be too big (max a little over 1 second)...
Definition: Clock.hh:93
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
VDP-VRAM access slot calculator, meant to be used in the inner loops of the VDPCmdEngine commands...
Unified implementation of MSX Video Display Processors (VDPs).
Definition: VDP.hh:61
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
bool limitReached() const
Has &#39;time&#39; advanced to or past &#39;limit&#39;?