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 "DisplayMode.hh"
6 #include "Observer.hh"
7 #include "serialize_meta.hh"
8 #include "openmsx.hh"
9 #include "noncopyable.hh"
10 #include "likely.hh"
11 #include <memory>
12 
13 namespace openmsx {
14 
15 class VDPVRAM;
16 class CommandController;
17 class RenderSettings;
18 class Setting;
19 class BooleanSetting;
20 class TclCallback;
21 
22 
25 class VDPCmd {
26 public:
27  virtual ~VDPCmd() {}
28 
31  virtual void start(EmuTime::param time, VDPCmdEngine& engine) = 0;
32 
35  virtual void execute(EmuTime::param limit, VDPCmdEngine& engine) = 0;
36 };
37 
38 
42 class VDPCmdEngine : private Observer<Setting>, private noncopyable
43 {
44 public:
45  VDPCmdEngine(VDP& vdp, RenderSettings& renderSettings_,
46  CommandController& commandController);
47  virtual ~VDPCmdEngine();
48 
52  void reset(EmuTime::param time);
53 
59  inline void sync(EmuTime::param time) {
60  if (!currentCommand) return;
61  currentCommand->execute(time, *this);
62  if (currentCommand && unlikely(vdp.cpuAccessScheduled())) {
63  // If there's a CPU access scheduled, then the next
64  // slot will be used by the CPU. So we take a later
65  // slot.
66  nextAccessSlot(1); // skip one slot
67  assert(this->time > time);
68  }
69  }
70 
77  inline byte getStatus(EmuTime::param time) {
78  if (time >= statusChangeTime) {
79  sync(time);
80  }
81  return status;
82  }
83 
89  inline byte readColor(EmuTime::param time) {
90  sync(time);
91  return COL;
92  }
93  inline void resetColor() {
94  // Note: Real VDP always resets TR, but for such a short time
95  // that the MSX won't notice it.
96  // TODO: What happens on non-transfer commands?
97  if (!currentCommand) status &= 0x7F;
98  transfer = true;
99  }
100 
108  inline unsigned getBorderX(EmuTime::param time) {
109  sync(time);
110  return ASX;
111  }
112 
118  void setCmdReg(byte index, byte value, EmuTime::param time);
119 
126  byte peekCmdReg(byte index);
127 
133 
136  template<typename Archive>
137  void serialize(Archive& ar, unsigned version);
138 
139 private:
140  template <template <typename Mode> class Command>
141  void createHEngines(unsigned cmd);
142  void deleteHEngines(unsigned cmd);
143 
144  template <template <typename Mode, typename LogOp> class Command>
145  void createLEngines(unsigned cmd, VDPCmd* dummy);
146  void deleteLEngines(unsigned cmd);
147 
148  virtual void update(const Setting& setting);
149 
150  void executeCommand(EmuTime::param time);
151 
152  inline void nextAccessSlot(int delta) {
153  time = vdp.getAccessSlot(time, delta);
154  }
155  inline AccessSlotCalculator getSlotCalculator() const {
156  return vdp.getAccessSlotCalculator(time);
157  }
158  inline void nextAccessSlot(AccessSlotCalculator& calculator, int delta) {
159 #ifdef DEBUG
160  EmuTime old = time;
161  nextAccessSlot(delta);
162  EmuTime verify = time;
163  time = old;
164 #endif
165  time += calculator.getNext(delta);
166 #ifdef DEBUG
167  assert(time == verify);
168 #endif
169  }
170 
173  void commandDone(EmuTime::param time);
174 
177  void reportVdpCommand();
178 
179 
182  VDP& vdp;
183  VDPVRAM& vram;
184 
185  RenderSettings& renderSettings;
186 
189  const std::unique_ptr<BooleanSetting> cmdTraceSetting;
190  const std::unique_ptr<TclCallback> cmdInProgressCallback;
191 
192  VDPCmd* commands[256][4];
193  VDPCmd* currentCommand;
194 
203  EmuTime time;
204 
210  EmuTime statusChangeTime;
211 
215  int phase;
216 
221  int scrMode;
222 
225  unsigned SX, SY, DX, DY, NX, NY; // registers that can be set by CPU
226  unsigned ASX, ADX, ANX; // Temporary registers used in the VDP commands
227  // Register ASX can be read (via status register 8/9)
228  byte COL, ARG, CMD;
229 
232  byte tmpSrc;
233  byte tmpDst;
234 
241  byte status;
242 
246  bool transfer;
247 
250  const bool hasExtendedVRAM;
251 
254  //bool brokenTiming; // not used anymore ATM
255  // // TODO remove completely or try to restore?
256 
257  friend struct AbortCmd;
258  friend struct PointBaseCmd;
259  friend struct PsetBaseCmd;
260  friend struct SrchBaseCmd;
261  friend struct LineBaseCmd;
262  friend class BlockCmd;
263  template<typename> friend struct PointCmd;
264  template<typename> friend struct SrchCmd;
265  template<typename> friend struct LmcmCmd;
266  template<typename> friend struct HmmvCmd;
267  template<typename> friend struct HmmmCmd;
268  template<typename> friend struct YmmmCmd;
269  template<typename> friend struct HmmcCmd;
270  template<typename> friend struct LmmvBaseCmd;
271  template<typename> friend struct LmmmBaseCmd;
272  template<typename> friend struct LmmcBaseCmd;
273  template<typename, typename> friend struct PsetCmd;
274  template<typename, typename> friend struct LineCmd;
275  template<typename, typename> friend struct LmmvCmd;
276  template<typename, typename> friend struct LmmmCmd;
277  template<typename, typename> friend struct LmmcCmd;
278 };
280 
281 } // namespace openmsx
282 
283 #endif