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 
19 /** VDP command engine by Alex Wulms.
20  * Implements command execution unit of V9938/58.
21  */
23 {
24 public:
25  VDPCmdEngine(VDP& vdp, CommandController& commandController);
26 
27  /** Reinitialise Renderer state.
28  * @param time The moment in time the reset occurs.
29  */
30  void reset(EmuTime::param time);
31 
32  /** Synchronises the command engine with the VDP.
33  * Ideally this would be a private method, but the current
34  * design doesn't allow that.
35  * @param time The moment in emulated time to sync to.
36  */
37  inline void sync(EmuTime::param time) {
38  if (CMD) sync2(time);
39  }
40  void sync2(EmuTime::param time);
41 
42  /** Steal a VRAM access slot from the CmdEngine.
43  * Used when the CPU reads/writes VRAM.
44  * @param time The moment in time the CPU read/write is performed.
45  */
46  void stealAccessSlot(EmuTime::param time) {
47  if (!CMD) return;
48  engineTime = time;
49  nextAccessSlot(VDPAccessSlots::DELTA_1); // skip one slot
50  assert(engineTime > time);
51  }
52 
53  /** Gets the command engine status (part of S#2).
54  * Bit 7 (TR) is set when the command engine is ready for
55  * a pixel transfer.
56  * Bit 4 (BD) is set when the boundary color is detected.
57  * Bit 0 (CE) is set when a command is in progress.
58  */
59  inline byte getStatus(EmuTime::param time) {
60  if (time >= statusChangeTime) {
61  sync(time);
62  }
63  return status;
64  }
65 
66  /** Use this method to transfer pixel(s) from VDP to CPU.
67  * This method implements V9938 S#7.
68  * @param time The moment in emulated time this read occurs.
69  * @return Color value of the pixel.
70  */
71  inline byte readColor(EmuTime::param time) {
72  sync(time);
73  return COL;
74  }
75  inline void resetColor() {
76  // Note: Real VDP always resets TR, but for such a short time
77  // that the MSX won't notice it.
78  // TODO: What happens on non-transfer commands?
79  if (!CMD) status &= 0x7F;
80  transfer = true;
81  }
82 
83  /** Gets the X coordinate of a border detected by SRCH (intended behaviour,
84  * as documented in the V9938 technical data book). However, real VDP
85  * simply returns the current value of the ASX 'temporary source X' counter,
86  * regardless of the command that is being executed or was executed most
87  * recently
88  * @param time The moment in emulated time this get occurs.
89  */
90  inline unsigned getBorderX(EmuTime::param time) {
91  sync(time);
92  return ASX;
93  }
94 
95  /** Writes to a command register.
96  * @param index The register [0..14] to write to.
97  * @param value The new value for the specified register.
98  * @param time The moment in emulated time this write occurs.
99  */
100  void setCmdReg(byte index, byte value, EmuTime::param time);
101 
102  /** Read the content of a command register. This method is meant to
103  * be used by the debugger, there is no strict guarantee that the
104  * returned value is the correct value at _exactly_ this moment in
105  * time (IOW this method does not sync the complete CmdEngine)
106  * @param index The register [0..14] to read from.
107  */
108  byte peekCmdReg(byte index);
109 
110  /** Informs the command engine of a VDP display mode change.
111  * @param mode The new display mode.
112  * @param cmdBit Are VDP commands allowed in non-bitmap mode.
113  * @param time The moment in emulated time this change occurs.
114  */
115  void updateDisplayMode(DisplayMode mode, bool cmdBit, EmuTime::param time);
116 
117  /** Interface for logical operations.
118  */
119  template<typename Archive>
120  void serialize(Archive& ar, unsigned version);
121 
122 private:
123  void executeCommand(EmuTime::param time);
124 
125  void setStatusChangeTime(EmuTime::param t);
126  void calcFinishTime(unsigned NX, unsigned NY, unsigned ticksPerPixel);
127 
128  void startAbrt(EmuTime::param time);
129  void startPoint(EmuTime::param time);
130  void startPset(EmuTime::param time);
131  void startSrch(EmuTime::param time);
132  void startLine(EmuTime::param time);
133  template<typename Mode> void startLmmv(EmuTime::param time);
134  template<typename Mode> void startLmmm(EmuTime::param time);
135  template<typename Mode> void startLmcm(EmuTime::param time);
136  template<typename Mode> void startLmmc(EmuTime::param time);
137  template<typename Mode> void startHmmv(EmuTime::param time);
138  template<typename Mode> void startHmmm(EmuTime::param time);
139  template<typename Mode> void startYmmm(EmuTime::param time);
140  template<typename Mode> void startHmmc(EmuTime::param time);
141 
142  template<typename Mode> void executePoint(EmuTime::param limit);
143  template<typename Mode, typename LogOp> void executePset(EmuTime::param limit);
144  template<typename Mode> void executeSrch(EmuTime::param limit);
145  template<typename Mode, typename LogOp> void executeLine(EmuTime::param limit);
146  template<typename Mode, typename LogOp> void executeLmmv(EmuTime::param limit);
147  template<typename Mode, typename LogOp> void executeLmmm(EmuTime::param limit);
148  template<typename Mode> void executeLmcm(EmuTime::param limit);
149  template<typename Mode, typename LogOp> void executeLmmc(EmuTime::param limit);
150  template<typename Mode> void executeHmmv(EmuTime::param limit);
151  template<typename Mode> void executeHmmm(EmuTime::param limit);
152  template<typename Mode> void executeYmmm(EmuTime::param limit);
153  template<typename Mode> void executeHmmc(EmuTime::param limit);
154 
155  // Advance to the next access slot at or past the given time.
156  inline void nextAccessSlot(EmuTime::param time) {
157  engineTime = vdp.getAccessSlot(time, VDPAccessSlots::DELTA_0);
158  }
159  // Advance to the next access slot that is at least 'delta' cycles past
160  // the current one.
161  inline void nextAccessSlot(VDPAccessSlots::Delta delta) {
162  engineTime = vdp.getAccessSlot(engineTime, delta);
163  }
164  inline VDPAccessSlots::Calculator getSlotCalculator(
165  EmuTime::param limit) const {
166  return vdp.getAccessSlotCalculator(engineTime, limit);
167  }
168 
169  /** Finshed executing graphical operation.
170  */
171  void commandDone(EmuTime::param time);
172 
173  /** Report the VDP command specified in the registers.
174  */
175  void reportVdpCommand();
176 
177 
178  /** The VDP this command engine is part of.
179  */
180  VDP& vdp;
181  VDPVRAM& vram;
182 
183  /** Only call reportVdpCommand() when this setting is turned on
184  */
185  BooleanSetting cmdTraceSetting;
186  TclCallback cmdInProgressCallback;
187 
188  Probe<bool> executingProbe;
189 
190  /** Time at which the next vram access slot is available.
191  * Only valid when a command is executing.
192  */
193  EmuTime engineTime;
194 
195  /** Lower bound for the time when the status register will change, IOW
196  * the status register will not change before this time.
197  * Can also be EmuTime::zero -> status can change any moment
198  * or EmuTime::infinity -> this command doesn't change the status
199  */
200  EmuTime statusChangeTime;
201 
202  /** Some commands execute multiple VRAM accesses per pixel
203  * (e.g. LMMM does two reads and a write). This variable keeps
204  * track of where in the (sub)command we are. */
205  int phase;
206 
207  /** Current screen mode.
208  * 0 -> SCREEN5, 1 -> SCREEN6, 2 -> SCREEN7, 3 -> SCREEN8,
209  * 4 -> Non-BitMap mode (like SCREEN8 but non-planar addressing)
210  * -1 -> other.
211  */
212  int scrMode;
213 
214  /** VDP command registers.
215  */
216  unsigned SX, SY, DX, DY, NX, NY; // registers that can be set by CPU
217  unsigned ASX, ADX, ANX; // Temporary registers used in the VDP commands
218  // Register ASX can be read (via status register 8/9)
219  byte COL, ARG, CMD;
220 
221  /** When a command needs multiple VRAM accesses per pixel, the result
222  * of intermediate reads is stored in these variables. */
223  byte tmpSrc;
224  byte tmpDst;
225 
226  /** The command engine status (part of S#2).
227  * Bit 7 (TR) is set when the command engine is ready for
228  * a pixel transfer.
229  * Bit 4 (BD) is set when the boundary color is detected.
230  * Bit 0 (CE) is set when a command is in progress.
231  */
232  byte status;
233 
234  /** Used in LMCM LMMC HMMC cmds, true when CPU has read or written
235  * next byte.
236  */
237  bool transfer;
238 
239  /** Flag that indicated whether extended VRAM is available
240  */
241  const bool hasExtendedVRAM;
242 };
244 
245 } // namespace openmsx
246 
247 #endif
void sync2(EmuTime::param time)
bool getEnum() const noexcept
Definition: EnumSetting.hh:96
void stealAccessSlot(EmuTime::param time)
Steal a VRAM access slot from the CmdEngine.
Definition: VDPCmdEngine.hh:46
VDP command engine by Alex Wulms.
Definition: VDPCmdEngine.hh:22
Represents a VDP display mode.
Definition: DisplayMode.hh:14
void serialize(Archive &ar, unsigned version)
Interface for logical operations.
byte getStatus(EmuTime::param time)
Gets the command engine status (part of S#2).
Definition: VDPCmdEngine.hh:59
VDPCmdEngine(VDP &vdp, CommandController &commandController)
void sync(EmuTime::param time)
Synchronises the command engine with the VDP.
Definition: VDPCmdEngine.hh:37
byte peekCmdReg(byte index)
Read the content of a command register.
void reset(EmuTime::param time)
Reinitialise Renderer state.
byte readColor(EmuTime::param time)
Use this method to transfer pixel(s) from VDP to CPU.
Definition: VDPCmdEngine.hh:71
VDP-VRAM access slot calculator, meant to be used in the inner loops of the VDPCmdEngine commands...
void updateDisplayMode(DisplayMode mode, bool cmdBit, EmuTime::param time)
Informs the command engine of a VDP display mode change.
void setCmdReg(byte index, byte value, EmuTime::param time)
Writes to a command register.
std::array< std::array< uint8_t, 3 >, 16 > getMSX1Palette() const
Get the (fixed) palette for this MSX1 VDP.
Definition: VDP.cc:1482
Manages VRAM contents and synchronises the various users of the VRAM.
Definition: VDPVRAM.hh:384
#define SERIALIZE_CLASS_VERSION(CLASS, VERSION)
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:90