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
12namespace openmsx {
13
14class VDPVRAM;
15class DisplayMode;
16class CommandController;
17
18
23{
24public:
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
123private:
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
184private:
187 VDP& vdp;
188 VDPVRAM& vram;
189
192 BooleanSetting cmdTraceSetting;
193 TclCallback cmdInProgressCallback;
194
195 Probe<bool> executingProbe;
196
200 EmuTime engineTime{EmuTime::zero()};
201
207 EmuTime statusChangeTime{EmuTime::infinity()};
208
212 int phase{0};
213
219 int scrMode{-1};
220
223 unsigned SX{0}, SY{0}, DX{0}, DY{0}, NX{0}, NY{0}; // registers that can be set by CPU
224 unsigned ASX{0}, ADX{0}, ANX{0}; // Temporary registers used in the VDP commands
225 // Register ASX can be read (via status register 8/9)
226 byte COL{0}, ARG{0}, CMD{0};
227
230 byte tmpSrc{0};
231 byte tmpDst{0};
232
239 byte status{0};
240
244 bool transfer{false};
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:64
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:898
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:892
This file implemented 3 utility functions:
Definition: Autofire.cc:9
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)