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 VDPCmdEngine(VDP& vdp, CommandController& commandController);
27
31 void reset(EmuTime::param time);
32
38 inline void sync(EmuTime::param time) {
39 if (CMD) sync2(time);
40 }
41 void sync2(EmuTime::param time);
42
47 void stealAccessSlot(EmuTime::param time) {
48 if (CMD && engineTime <= time) {
49 // take the next available slot
50 engineTime = getNextAccessSlot(time, VDPAccessSlots::DELTA_1);
51 assert(engineTime > time);
52 }
53 }
54
61 [[nodiscard]] inline byte getStatus(EmuTime::param time) {
62 if (time >= statusChangeTime) {
63 sync(time);
64 }
65 return status;
66 }
67
73 [[nodiscard]] inline byte readColor(EmuTime::param time) {
74 sync(time);
75 return COL;
76 }
77 inline void resetColor() {
78 // Note: Real VDP always resets TR, but for such a short time
79 // that the MSX won't notice it.
80 // TODO: What happens on non-transfer commands?
81 if (!CMD) status &= 0x7F;
82 transfer = true;
83 }
84
92 [[nodiscard]] inline unsigned getBorderX(EmuTime::param time) {
93 sync(time);
94 return ASX;
95 }
96
102 void setCmdReg(byte index, byte value, EmuTime::param time);
103
110 [[nodiscard]] byte peekCmdReg(byte index) const;
111
117 void updateDisplayMode(DisplayMode mode, bool cmdBit, EmuTime::param time);
118
121 template<typename Archive>
122 void serialize(Archive& ar, unsigned version);
123
124private:
125 void executeCommand(EmuTime::param time);
126
127 void setStatusChangeTime(EmuTime::param t);
128 void calcFinishTime(unsigned NX, unsigned NY, unsigned ticksPerPixel);
129
130 void startAbrt(EmuTime::param time);
131 void startPoint(EmuTime::param time);
132 void startPset(EmuTime::param time);
133 void startSrch(EmuTime::param time);
134 void startLine(EmuTime::param time);
135 template<typename Mode> void startLmmv(EmuTime::param time);
136 template<typename Mode> void startLmmm(EmuTime::param time);
137 template<typename Mode> void startLmcm(EmuTime::param time);
138 template<typename Mode> void startLmmc(EmuTime::param time);
139 template<typename Mode> void startHmmv(EmuTime::param time);
140 template<typename Mode> void startHmmm(EmuTime::param time);
141 template<typename Mode> void startYmmm(EmuTime::param time);
142 template<typename Mode> void startHmmc(EmuTime::param time);
143
144 template<typename Mode> void executePoint(EmuTime::param limit);
145 template<typename Mode, typename LogOp> void executePset(EmuTime::param limit);
146 template<typename Mode> void executeSrch(EmuTime::param limit);
147 template<typename Mode, typename LogOp> void executeLine(EmuTime::param limit);
148 template<typename Mode, typename LogOp> void executeLmmv(EmuTime::param limit);
149 template<typename Mode, typename LogOp> void executeLmmm(EmuTime::param limit);
150 template<typename Mode> void executeLmcm(EmuTime::param limit);
151 template<typename Mode, typename LogOp> void executeLmmc(EmuTime::param limit);
152 template<typename Mode> void executeHmmv(EmuTime::param limit);
153 template<typename Mode> void executeHmmm(EmuTime::param limit);
154 template<typename Mode> void executeYmmm(EmuTime::param limit);
155 template<typename Mode> void executeHmmc(EmuTime::param limit);
156
157 // Advance to the next access slot at or past the given time.
158 inline EmuTime getNextAccessSlot(EmuTime::param time) const {
159 return vdp.getAccessSlot(time, VDPAccessSlots::DELTA_0);
160 }
161 inline void nextAccessSlot(EmuTime::param time) {
162 engineTime = getNextAccessSlot(time);
163 }
164 // Advance to the next access slot that is at least 'delta' cycles past
165 // the current one.
166 inline EmuTime getNextAccessSlot(EmuTime::param time, VDPAccessSlots::Delta delta) const {
167 return vdp.getAccessSlot(time, delta);
168 }
169 inline void nextAccessSlot(VDPAccessSlots::Delta delta) {
170 engineTime = getNextAccessSlot(engineTime, delta);
171 }
172 inline VDPAccessSlots::Calculator getSlotCalculator(
173 EmuTime::param limit) const {
174 return vdp.getAccessSlotCalculator(engineTime, limit);
175 }
176
179 void commandDone(EmuTime::param time);
180
183 void reportVdpCommand() const;
184
185private:
188 VDP& vdp;
189 VDPVRAM& vram;
190
193 BooleanSetting cmdTraceSetting;
194 TclCallback cmdInProgressCallback;
195
196 Probe<bool> executingProbe;
197
201 EmuTime engineTime{EmuTime::zero()};
202
208 EmuTime statusChangeTime{EmuTime::infinity()};
209
213 int phase{0};
214
220 int scrMode{-1};
221
224 unsigned SX{0}, SY{0}, DX{0}, DY{0}, NX{0}, NY{0}; // registers that can be set by CPU
225 unsigned ASX{0}, ADX{0}, ANX{0}; // Temporary registers used in the VDP commands
226 // Register ASX can be read (via status register 8/9)
227 byte COL{0}, ARG{0}, CMD{0};
228
231 byte tmpSrc{0};
232 byte tmpDst{0};
233
240 byte status{0};
241
245 bool transfer{false};
246
249 const bool hasExtendedVRAM;
250};
252
253} // namespace openmsx
254
255#endif
TclObject t
Represents a VDP display mode.
VDP command engine by Alex Wulms.
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...
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)
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:66
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:902
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:896
This file implemented 3 utility functions:
Definition Autofire.cc:11
#define SERIALIZE_CLASS_VERSION(CLASS, VERSION)