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
7#include "BooleanSetting.hh"
8#include "Probe.hh"
9#include "TclCallback.hh"
10#include "openmsx.hh"
11#include "serialize_meta.hh"
12
13namespace openmsx {
14
15class VDPVRAM;
16class DisplayMode;
17class CommandController;
18
19
24{
25public:
26 // bits in ARG register
27 static constexpr byte MXD = 0x20;
28 static constexpr byte MXS = 0x10;
29 static constexpr byte DIY = 0x08;
30 static constexpr byte DIX = 0x04;
31 static constexpr byte EQ = 0x02;
32 static constexpr byte MAJ = 0x01;
33
34public:
35 VDPCmdEngine(VDP& vdp, CommandController& commandController);
36
40 void reset(EmuTime::param time);
41
47 inline void sync(EmuTime::param time) {
48 if (CMD) sync2(time);
49 }
50 void sync2(EmuTime::param time);
51
56 void stealAccessSlot(EmuTime::param time) {
57 if (CMD && engineTime <= time) {
58 // take the next available slot
59 engineTime = getNextAccessSlot(time, VDPAccessSlots::Delta::D1);
60 assert(engineTime > time);
61 }
62 }
63
70 [[nodiscard]] inline byte getStatus(EmuTime::param time) {
71 if (time >= statusChangeTime) {
72 sync(time);
73 }
74 return status;
75 }
76
82 [[nodiscard]] inline byte readColor(EmuTime::param time) {
83 sync(time);
84 return COL;
85 }
86 inline void resetColor() {
87 // Note: Real VDP always resets TR, but for such a short time
88 // that the MSX won't notice it.
89 // TODO: What happens on non-transfer commands?
90 if (!CMD) status &= 0x7F;
91 transfer = true;
92 }
93
101 [[nodiscard]] inline unsigned getBorderX(EmuTime::param time) {
102 sync(time);
103 return ASX;
104 }
105
111 void setCmdReg(byte index, byte value, EmuTime::param time);
112
119 [[nodiscard]] byte peekCmdReg(byte index) const;
120
126 void updateDisplayMode(DisplayMode mode, bool cmdBit, EmuTime::param time);
127
128 // For debugging only
129 bool commandInProgress(EmuTime::param time) {
130 sync(time);
131 return status & 1;
132 }
136 auto getLastCommand() const {
137 return std::tuple{
138 lastSX, lastSY, lastDX, lastDY, lastNX, lastNY,
139 lastCOL, lastARG, lastCMD};
140 }
145 return (status & 1) ? std::tuple{int(ASX), int(SY), int(ADX), int(DY)}
146 : std::tuple{-1, -1, -1, -1};
147 }
148
151 template<typename Archive>
152 void serialize(Archive& ar, unsigned version);
153
154private:
155 void executeCommand(EmuTime::param time);
156
157 void setStatusChangeTime(EmuTime::param t);
158 void calcFinishTime(unsigned NX, unsigned NY, unsigned ticksPerPixel);
159
160 void startAbrt(EmuTime::param time);
161 void startPoint(EmuTime::param time);
162 void startPset(EmuTime::param time);
163 void startSrch(EmuTime::param time);
164 void startLine(EmuTime::param time);
165 template<typename Mode> void startLmmv(EmuTime::param time);
166 template<typename Mode> void startLmmm(EmuTime::param time);
167 template<typename Mode> void startLmcm(EmuTime::param time);
168 template<typename Mode> void startLmmc(EmuTime::param time);
169 template<typename Mode> void startHmmv(EmuTime::param time);
170 template<typename Mode> void startHmmm(EmuTime::param time);
171 template<typename Mode> void startYmmm(EmuTime::param time);
172 template<typename Mode> void startHmmc(EmuTime::param time);
173
174 template<typename Mode> void executePoint(EmuTime::param limit);
175 template<typename Mode, typename LogOp> void executePset(EmuTime::param limit);
176 template<typename Mode> void executeSrch(EmuTime::param limit);
177 template<typename Mode, typename LogOp> void executeLine(EmuTime::param limit);
178 template<typename Mode, typename LogOp> void executeLmmv(EmuTime::param limit);
179 template<typename Mode, typename LogOp> void executeLmmm(EmuTime::param limit);
180 template<typename Mode> void executeLmcm(EmuTime::param limit);
181 template<typename Mode, typename LogOp> void executeLmmc(EmuTime::param limit);
182 template<typename Mode> void executeHmmv(EmuTime::param limit);
183 template<typename Mode> void executeHmmm(EmuTime::param limit);
184 template<typename Mode> void executeYmmm(EmuTime::param limit);
185 template<typename Mode> void executeHmmc(EmuTime::param limit);
186
187 // Advance to the next access slot at or past the given time.
188 inline EmuTime getNextAccessSlot(EmuTime::param time) const {
190 }
191 inline void nextAccessSlot(EmuTime::param time) {
192 engineTime = getNextAccessSlot(time);
193 }
194 // Advance to the next access slot that is at least 'delta' cycles past
195 // the current one.
196 inline EmuTime getNextAccessSlot(EmuTime::param time, VDPAccessSlots::Delta delta) const {
197 return vdp.getAccessSlot(time, delta);
198 }
199 inline void nextAccessSlot(VDPAccessSlots::Delta delta) {
200 engineTime = getNextAccessSlot(engineTime, delta);
201 }
202 inline VDPAccessSlots::Calculator getSlotCalculator(
203 EmuTime::param limit) const {
204 return vdp.getAccessSlotCalculator(engineTime, limit);
205 }
206
209 void commandDone(EmuTime::param time);
210
213 void reportVdpCommand() const;
214
215private:
218 VDP& vdp;
219 VDPVRAM& vram;
220
223 BooleanSetting cmdTraceSetting;
224 TclCallback cmdInProgressCallback;
225
226 Probe<bool> executingProbe;
227
231 EmuTime engineTime{EmuTime::zero()};
232
238 EmuTime statusChangeTime{EmuTime::infinity()};
239
243 int phase{0};
244
250 int scrMode{-1};
251
254 unsigned SX{0}, SY{0}, DX{0}, DY{0}, NX{0}, NY{0}; // registers that can be set by CPU
255 unsigned ASX{0}, ADX{0}, ANX{0}; // Temporary registers used in the VDP commands
256 // Register ASX can be read (via status register 8/9)
257 byte COL{0}, ARG{0}, CMD{0};
258
264 int lastSX{0}, lastSY{0}, lastDX{0}, lastDY{0}, lastNX{0}, lastNY{0};
265 byte lastCOL{0}, lastARG{0}, lastCMD{0};
266
269 byte tmpSrc{0};
270 byte tmpDst{0};
271
278 byte status{0};
279
283 bool transfer{false};
284
287 const bool hasExtendedVRAM;
288};
290
291} // namespace openmsx
292
293#endif
TclObject t
Represents a VDP display mode.
VDP command engine by Alex Wulms.
auto getLastCommand() const
Get the register-values for the last executed (or still in progress) command.
static constexpr byte MXD
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.
bool commandInProgress(EmuTime::param time)
static constexpr byte MAJ
static constexpr byte DIX
static constexpr byte DIY
static constexpr byte MXS
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...
byte readColor(EmuTime::param time)
Use this method to transfer pixel(s) from VDP to CPU.
void stealAccessSlot(EmuTime::param time)
Steal a VRAM access slot from the CmdEngine.
void sync2(EmuTime::param time)
auto getInprogressPosition() const
Get the (source and destination) X/Y coordinates of the currently executing command.
static constexpr byte EQ
byte peekCmdReg(byte index) const
Read the content of a command register.
void sync(EmuTime::param time)
Synchronizes the command engine with the VDP.
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).
Unified implementation of MSX Video Display Processors (VDPs).
Definition VDP.hh:67
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:896
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:890
This file implemented 3 utility functions:
Definition Autofire.cc:11
#define SERIALIZE_CLASS_VERSION(CLASS, VERSION)