openMSX
VDPCmdEngine.hh
Go to the documentation of this file.
1 #ifndef VDPCMDENGINE_HH
2 #define VDPCMDENGINE_HH
3 
4 #include "VDP.hh"
5 #include "VDPAccessSlots.hh"
6 #include "BooleanSetting.hh"
7 #include "Probe.hh"
8 #include "TclCallback.hh"
9 #include "serialize_meta.hh"
10 #include "openmsx.hh"
11 
12 namespace openmsx {
13 
14 class VDPVRAM;
15 class DisplayMode;
16 class CommandController;
17 
18 
23 {
24 public:
25  VDPCmdEngine(VDP& vdp, CommandController& commandController);
26 
30  void reset(EmuTime::param time);
31 
37  inline void sync(EmuTime::param time) {
38  if (CMD) sync2(time);
39  }
40  void sync2(EmuTime::param time);
41 
46  void stealAccessSlot(EmuTime::param time) {
47  if (CMD && engineTime <= time) {
48  // take the next available slot
49  engineTime = getNextAccessSlot(time, VDPAccessSlots::DELTA_1);
50  assert(engineTime > time);
51  }
52  }
53 
60  [[nodiscard]] inline byte getStatus(EmuTime::param time) {
61  if (time >= statusChangeTime) {
62  sync(time);
63  }
64  return status;
65  }
66 
72  [[nodiscard]] inline byte readColor(EmuTime::param time) {
73  sync(time);
74  return COL;
75  }
76  inline void resetColor() {
77  // Note: Real VDP always resets TR, but for such a short time
78  // that the MSX won't notice it.
79  // TODO: What happens on non-transfer commands?
80  if (!CMD) status &= 0x7F;
81  transfer = true;
82  }
83 
91  [[nodiscard]] inline unsigned getBorderX(EmuTime::param time) {
92  sync(time);
93  return ASX;
94  }
95 
101  void setCmdReg(byte index, byte value, EmuTime::param time);
102 
109  [[nodiscard]] byte peekCmdReg(byte index) const;
110 
116  void updateDisplayMode(DisplayMode mode, bool cmdBit, EmuTime::param time);
117 
120  template<typename Archive>
121  void serialize(Archive& ar, unsigned version);
122 
123 private:
124  void executeCommand(EmuTime::param time);
125 
126  void setStatusChangeTime(EmuTime::param t);
127  void calcFinishTime(unsigned NX, unsigned NY, unsigned ticksPerPixel);
128 
129  void startAbrt(EmuTime::param time);
130  void startPoint(EmuTime::param time);
131  void startPset(EmuTime::param time);
132  void startSrch(EmuTime::param time);
133  void startLine(EmuTime::param time);
134  template<typename Mode> void startLmmv(EmuTime::param time);
135  template<typename Mode> void startLmmm(EmuTime::param time);
136  template<typename Mode> void startLmcm(EmuTime::param time);
137  template<typename Mode> void startLmmc(EmuTime::param time);
138  template<typename Mode> void startHmmv(EmuTime::param time);
139  template<typename Mode> void startHmmm(EmuTime::param time);
140  template<typename Mode> void startYmmm(EmuTime::param time);
141  template<typename Mode> void startHmmc(EmuTime::param time);
142 
143  template<typename Mode> void executePoint(EmuTime::param limit);
144  template<typename Mode, typename LogOp> void executePset(EmuTime::param limit);
145  template<typename Mode> void executeSrch(EmuTime::param limit);
146  template<typename Mode, typename LogOp> void executeLine(EmuTime::param limit);
147  template<typename Mode, typename LogOp> void executeLmmv(EmuTime::param limit);
148  template<typename Mode, typename LogOp> void executeLmmm(EmuTime::param limit);
149  template<typename Mode> void executeLmcm(EmuTime::param limit);
150  template<typename Mode, typename LogOp> void executeLmmc(EmuTime::param limit);
151  template<typename Mode> void executeHmmv(EmuTime::param limit);
152  template<typename Mode> void executeHmmm(EmuTime::param limit);
153  template<typename Mode> void executeYmmm(EmuTime::param limit);
154  template<typename Mode> void executeHmmc(EmuTime::param limit);
155 
156  // Advance to the next access slot at or past the given time.
157  inline EmuTime getNextAccessSlot(EmuTime::param time) {
158  return vdp.getAccessSlot(time, VDPAccessSlots::DELTA_0);
159  }
160  inline void nextAccessSlot(EmuTime::param time) {
161  engineTime = getNextAccessSlot(time);
162  }
163  // Advance to the next access slot that is at least 'delta' cycles past
164  // the current one.
165  inline EmuTime getNextAccessSlot(EmuTime::param time, VDPAccessSlots::Delta delta) {
166  return vdp.getAccessSlot(time, delta);
167  }
168  inline void nextAccessSlot(VDPAccessSlots::Delta delta) {
169  engineTime = getNextAccessSlot(engineTime, delta);
170  }
171  inline VDPAccessSlots::Calculator getSlotCalculator(
172  EmuTime::param limit) const {
173  return vdp.getAccessSlotCalculator(engineTime, limit);
174  }
175 
178  void commandDone(EmuTime::param time);
179 
182  void reportVdpCommand() const;
183 
184 private:
187  VDP& vdp;
188  VDPVRAM& vram;
189 
192  BooleanSetting cmdTraceSetting;
193  TclCallback cmdInProgressCallback;
194 
195  Probe<bool> executingProbe;
196 
200  EmuTime engineTime;
201 
207  EmuTime statusChangeTime;
208 
212  int phase;
213 
219  int scrMode;
220 
223  unsigned SX, SY, DX, DY, NX, NY; // registers that can be set by CPU
224  unsigned ASX, ADX, ANX; // Temporary registers used in the VDP commands
225  // Register ASX can be read (via status register 8/9)
226  byte COL, ARG, CMD;
227 
230  byte tmpSrc;
231  byte tmpDst;
232 
239  byte status;
240 
244  bool transfer;
245 
248  const bool hasExtendedVRAM;
249 };
251 
252 } // namespace openmsx
253 
254 #endif
TclObject t
Represents a VDP display mode.
Definition: DisplayMode.hh:16
VDP command engine by Alex Wulms.
Definition: VDPCmdEngine.hh:23
void updateDisplayMode(DisplayMode mode, bool cmdBit, EmuTime::param time)
Informs the command engine of a VDP display mode change.
void serialize(Archive &ar, unsigned version)
Interface for logical operations.
void reset(EmuTime::param time)
Reinitialize Renderer state.
unsigned getBorderX(EmuTime::param time)
Gets the X coordinate of a border detected by SRCH (intended behaviour, as documented in the V9938 te...
Definition: VDPCmdEngine.hh:91
byte readColor(EmuTime::param time)
Use this method to transfer pixel(s) from VDP to CPU.
Definition: VDPCmdEngine.hh:72
void stealAccessSlot(EmuTime::param time)
Steal a VRAM access slot from the CmdEngine.
Definition: VDPCmdEngine.hh:46
VDPCmdEngine(VDP &vdp, CommandController &commandController)
void sync2(EmuTime::param time)
byte peekCmdReg(byte index) const
Read the content of a command register.
void sync(EmuTime::param time)
Synchronizes the command engine with the VDP.
Definition: VDPCmdEngine.hh:37
void setCmdReg(byte index, byte value, EmuTime::param time)
Writes to a command register.
byte getStatus(EmuTime::param time)
Gets the command engine status (part of S#2).
Definition: VDPCmdEngine.hh:60
Unified implementation of MSX Video Display Processors (VDPs).
Definition: VDP.hh:63
VDPAccessSlots::Calculator getAccessSlotCalculator(EmuTime::param time, EmuTime::param limit) const
Same as getAccessSlot(), but it can be much faster for repeated calls, e.g.
Definition: VDP.cc:872
EmuTime getAccessSlot(EmuTime::param time, VDPAccessSlots::Delta delta) const
Get the earliest access slot that is at least 'delta' cycles in the future.
Definition: VDP.cc:866
This file implemented 3 utility functions:
Definition: Autofire.cc:9
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)