openMSX
VDP.hh
Go to the documentation of this file.
1 #ifndef VDP_HH
2 #define VDP_HH
3 
4 #include "MSXDevice.hh"
5 #include "Schedulable.hh"
7 #include "IRQHelper.hh"
8 #include "Clock.hh"
9 #include "DisplayMode.hh"
10 #include "Observer.hh"
11 #include "openmsx.hh"
12 #include <memory>
13 
14 namespace openmsx {
15 
16 class PostProcessor;
17 class Renderer;
18 class VDPCmdEngine;
19 class VDPVRAM;
20 class SpriteChecker;
21 class VDPRegDebug;
22 class VDPStatusRegDebug;
23 class VDPPaletteDebug;
24 class VRAMPointerDebug;
25 class FrameCountInfo;
26 class CycleInFrameInfo;
27 class LineInFrameInfo;
28 class CycleInLineInfo;
29 class MsxYPosInfo;
30 class MsxX256PosInfo;
31 class MsxX512PosInfo;
32 class Display;
33 class RawFrame;
34 class Setting;
35 template<typename> class EnumSetting;
36 namespace VDPAccessSlots {
37  enum Delta : int;
38  class Calculator;
39 }
40 
66 class VDP : public MSXDevice, public Schedulable,
67  private VideoSystemChangeListener, Observer<Setting>
68 {
69 public:
72  static const int TICKS_PER_SECOND = 3579545 * 6; // 21.5MHz;
74 
77  static const int TICKS_PER_LINE = 1368;
78 
79  explicit VDP(const DeviceConfig& config);
80  virtual ~VDP();
81 
82  virtual void powerUp(EmuTime::param time);
83  virtual void reset(EmuTime::param time);
84  virtual byte readIO(word port, EmuTime::param time);
85  virtual byte peekIO(word port, EmuTime::param time) const;
86  virtual void writeIO(word port, byte value, EmuTime::param time);
87  virtual void executeUntil(EmuTime::param time, int userData);
88 
94 
99  inline bool isMSX1VDP() const {
100  return version == TMS99X8A || version == TMS9929A;
101  }
102 
106  inline bool hasYJK() const {
107  return version == V9958;
108  }
109 
113  inline DisplayMode getDisplayMode() const {
114  return displayMode;
115  }
116 
119  inline VDPVRAM& getVRAM() {
120  return *vram;
121  }
122 
127  inline const RawFrame* isSuperimposing() const {
128  // Note that bit 0 of r#0 has no effect on an V9938 or higher,
129  // but this bit is masked out. Also note that on an MSX1, if
130  // bit 0 of r#0 is enabled and there is no external video
131  // source, then we lose sync.
132  // Also note that because this property is fixed per frame we
133  // cannot (re)calculate it from register values.
134  return superimposing;
135  }
136 
140  return *spriteChecker;
141  }
142 
146  inline bool getTransparency() const {
147  return (controlRegs[8] & 0x20) == 0;
148  }
149 
153  inline int getForegroundColor() const {
154  return controlRegs[7] >> 4;
155  }
156 
165  inline int getBackgroundColor() const {
166  byte reg7 = controlRegs[7];
167  if (displayMode.getByte() == DisplayMode::GRAPHIC7) {
168  return reg7;
169  } else {
170  return reg7 & 0x0F;
171  }
172  }
173 
177  inline int getBlinkForegroundColor() const {
178  return controlRegs[12] >> 4;
179  }
180 
184  inline int getBlinkBackgroundColor() const {
185  return controlRegs[12] & 0x0F;
186  }
187 
191  inline bool getBlinkState() const {
192  return blinkState;
193  }
194 
200  inline word getPalette(int index) const {
201  return palette[index];
202  }
203 
209  inline bool isDisplayEnabled() const {
210  return isDisplayArea && displayEnabled;
211  }
212 
217  inline bool spritesEnabled() const {
218  return displayEnabled && !displayMode.isTextMode() &&
219  ((controlRegs[8] & 0x02) == 0x00);
220  }
221 
225  inline bool spritesEnabledFast() const {
226  assert(!displayMode.isTextMode());
227  return displayEnabled && ((controlRegs[8] & 0x02) == 0x00);
228  }
229 
233  inline byte getVerticalScroll() const {
234  return controlRegs[23];
235  }
236 
242  inline byte getHorizontalScrollLow() const {
243  return controlRegs[27];
244  }
245 
251  inline byte getHorizontalScrollHigh() const {
252  return controlRegs[26];
253  }
254 
260  inline bool isBorderMasked() const {
261  return (controlRegs[25] & 0x02) != 0;
262  }
263 
270  inline bool isMultiPageScrolling() const {
271  return (controlRegs[25] & 0x01) && (controlRegs[2] & 0x20);
272  }
273 
278  inline int getLineZero() const {
279  return displayStart / TICKS_PER_LINE;
280  }
281 
286  inline bool isPalTiming() const {
287  return palTiming;
288  }
289 
297  inline bool isInterlaced() const {
298  return interlaced;
299  }
300 
312  inline bool isEvenOddEnabled() const {
313  return (controlRegs[9] & 4) != 0;
314  }
315 
319  inline bool getEvenOdd() const {
320  return (statusReg2 & 2) != 0;
321  }
322 
333  inline int getEvenOddMask() const {
334  // TODO: Verify which page is displayed on even fields.
335  return (((~controlRegs[9] & 4) << 6) | ((statusReg2 & 2) << 7)) &
336  (!blinkState << 8);
337  }
338 
342  inline int getTicksThisFrame(EmuTime::param time) const {
343  return frameStartTime.getTicksTill_fast(time);
344  }
345 
347  return frameStartTime.getTime();
348  }
349 
352  inline int getSpriteSize() const {
353  return ((controlRegs[1] & 2) << 2) + 8;
354  }
355 
358  inline bool isSpriteMag() const {
359  return controlRegs[1] & 1;
360  }
361 
365  inline bool getCmdBit() const {
366  return (controlRegs[25] & 0x40) != 0;
367  }
368 
371  inline int getTicksPerFrame() const {
372  return palTiming ? TICKS_PER_LINE * 313 : TICKS_PER_LINE * 262;
373  }
374 
384  inline bool isInsideFrame(EmuTime::param time) const {
385  return time >= frameStartTime.getTime() &&
387  }
388 
396  inline int getLeftSprites() const {
397  return 100 + 102 + 56
398  + (horizontalAdjust - 7) * 4
399  + (displayMode.isTextMode() ? 36 : 0);
400  }
401 
407  inline int getLeftBorder() const {
408  return getLeftSprites() + (isBorderMasked() ? 8 * 4 : 0);
409  }
410 
414  inline int getRightBorder() const {
415  return getLeftSprites()
416  + (displayMode.isTextMode() ? 960 : 1024);
417  }
418 
424  inline int getLeftBackground() const {
425  return getLeftSprites() + getHorizontalScrollLow() * 4;
426  }
427 
431  byte getStatusReg0() const { return statusReg0; }
432 
441  void setSpriteStatus(byte value)
442  {
443  statusReg0 = (statusReg0 & 0x80) | (value & 0x7F);
444  }
445 
449  bool getVRMode() const {
450  return (controlRegs[8] & 8) != 0;
451  }
452 
455  void setExternalVideoSource(const RawFrame* externalSource);
456 
460 
471  EmuTime::param time, EmuTime::param limit) const;
472 
474  bool cpuAccessScheduled() const;
475 
476  template<typename Archive>
477  void serialize(Archive& ar, unsigned version);
478 
479 private:
480  void initTables();
481 
484  enum VdpVersion {
490  TMS99X8A,
493  TMS9929A,
496  V9938,
499  V9958
500  };
501 
504  enum SyncType {
506  VSYNC,
508  DISPLAY_START,
510  VSCAN,
512  HSCAN,
514  HOR_ADJUST,
516  SET_MODE,
518  SET_BLANK,
520  CPU_VRAM_ACCESS,
521  };
522 
533  static const int LINE_COUNT_RESET_TICKS = 15 * TICKS_PER_LINE;
534 
538  inline int getNumberOfLines() const {
539  return controlRegs[9] & 0x80 ? 212 : 192;
540  }
541 
551  inline bool getHR(int ticksThisFrame) const {
552  // Note: These constants are located inside this function because
553  // GCC 4.0.x won't link if they are in the class scope.
557  static const int HBLANK_LEN_TXT = 404;
561  static const int HBLANK_LEN_GFX = 312;
562  return
563  ( ticksThisFrame + TICKS_PER_LINE - getRightBorder()
564  ) % TICKS_PER_LINE
565  < (displayMode.isTextMode() ? HBLANK_LEN_TXT : HBLANK_LEN_GFX);
566  }
567 
568  // VideoSystemChangeListener interface:
569  virtual void preVideoSystemChange();
570  virtual void postVideoSystemChange();
571 
576  void resetInit();
577 
582  void resetMasks(EmuTime::param time);
583 
587  void frameStart(EmuTime::param time);
588 
596  void scheduleDisplayStart(EmuTime::param time);
597 
603  void scheduleVScan(EmuTime::param time);
604 
610  void scheduleHScan(EmuTime::param time);
611 
614  void vramWrite(byte value, EmuTime::param time);
615 
618  byte vramRead(EmuTime::param time);
619 
621  void scheduleCpuVramAccess(bool isRead, byte write, EmuTime::param time);
622  void executeCpuVramAccess(EmuTime::param time);
623 
626  byte peekStatusReg(byte reg, EmuTime::param time) const;
627  byte readStatusReg(byte reg, EmuTime::param time);
628 
631  void changeRegister(byte reg, byte val, EmuTime::param time);
632 
635  void syncAtNextLine(SyncType type, EmuTime::param time);
636 
639  void createRenderer();
640 
644  void updateNameBase(EmuTime::param time);
645 
649  void updateColorBase(EmuTime::param time);
650 
654  void updatePatternBase(EmuTime::param time);
655 
659  void updateSpriteAttributeBase(EmuTime::param time);
660 
664  void updateSpritePatternBase(EmuTime::param time);
665 
669  void updateDisplayMode(DisplayMode newMode, EmuTime::param time);
670 
677  void setPalette(int index, word grb, EmuTime::param time);
678 
679  // Observer<Setting>
680  virtual void update(const Setting& setting);
681 
682 private:
683  Display& display;
684  EnumSetting<bool>& cmdTiming;
685  EnumSetting<bool>& tooFastAccess;
686 
687  friend class VDPRegDebug;
688  friend class VDPStatusRegDebug;
689  friend class VDPPaletteDebug;
690  friend class VRAMPointerDebug;
691  friend class FrameCountInfo;
692  const std::unique_ptr<VDPRegDebug> vdpRegDebug;
693  const std::unique_ptr<VDPStatusRegDebug> vdpStatusRegDebug;
694  const std::unique_ptr<VDPPaletteDebug> vdpPaletteDebug;
695  const std::unique_ptr<VRAMPointerDebug> vramPointerDebug;
696  const std::unique_ptr<FrameCountInfo> frameCountInfo;
697  const std::unique_ptr<CycleInFrameInfo> cycleInFrameInfo;
698  const std::unique_ptr<LineInFrameInfo> lineInFrameInfo;
699  const std::unique_ptr<CycleInLineInfo> cycleInLineInfo;
700  const std::unique_ptr<MsxYPosInfo> msxYPosInfo;
701  const std::unique_ptr<MsxX256PosInfo> msxX256PosInfo;
702  const std::unique_ptr<MsxX512PosInfo> msxX512PosInfo;
703 
706  std::unique_ptr<Renderer> renderer;
707 
710  std::unique_ptr<VDPCmdEngine> cmdEngine;
711 
714  std::unique_ptr<SpriteChecker> spriteChecker;
715 
718  std::unique_ptr<VDPVRAM> vram;
719 
723  const RawFrame* externalVideo;
724 
730  const RawFrame* superimposing;
731 
734  VDPClock frameStartTime;
735 
738  IRQHelper irqVertical;
739 
742  IRQHelper irqHorizontal;
743 
746  EmuTime displayStartSyncTime;
747 
750  EmuTime vScanSyncTime;
751 
754  EmuTime hScanSyncTime;
755 
758  VdpVersion version;
759 
765  int frameCount;
766 
769  int displayStart;
770 
774  int horizontalScanOffset;
775 
779  int horizontalAdjust;
780 
783  byte controlRegs[32];
784 
789  int controlRegMask;
790 
797  byte controlValueMasks[32];
798 
802  int blinkCount;
803 
807  int vramPointer;
808 
811  word palette[16];
812 
815  bool isDisplayArea;
816 
822  bool palTiming;
823 
827  bool interlaced;
828 
833  byte statusReg0;
834 
840  byte statusReg1;
841 
846  byte statusReg2;
847 
850  bool blinkState;
851 
854  byte dataLatch;
855 
858  bool registerDataStored;
859 
862  bool paletteDataStored;
863 
871  byte cpuVramData;
872 
876  bool cpuVramReqIsRead;
877  unsigned cpuVramReqAddr;
878 
882  bool cpuExtendedVram;
883 
889  DisplayMode displayMode;
890 
895  bool displayEnabled;
896 
900  bool warningPrinted;
901 
903  bool allowTooFastAccess;
904 };
906 
907 } // namespace openmsx
908 
909 #endif
int getBlinkBackgroundColor() const
Gets the current blinking color for blinking text.
Definition: VDP.hh:184
bool isInsideFrame(EmuTime::param time) const
Is the given timestamp inside the current frame? Mainly useful for debugging, because relevant timest...
Definition: VDP.hh:384
int getBlinkForegroundColor() const
Gets the current blinking color for blinking text.
Definition: VDP.hh:177
bool isBorderMasked() const
Gets the current border mask setting.
Definition: VDP.hh:260
bool isEvenOddEnabled() const
Get even/odd page alternation status.
Definition: VDP.hh:312
void setSpriteStatus(byte value)
Should only be used by SpriteChecker.
Definition: VDP.hh:441
bool spritesEnabled() const
Are sprites enabled?
Definition: VDP.hh:217
static const int TICKS_PER_LINE
Number of VDP clock ticks per line.
Definition: VDP.hh:77
SpriteChecker & getSpriteChecker()
Get the sprite checker for this VDP.
Definition: VDP.hh:139
virtual void reset(EmuTime::param time)
This method is called on reset.
Definition: VDP.cc:418
bool isMultiPageScrolling() const
Is multi page scrolling enabled? It is considered enabled if both the multi page scrolling flag is en...
Definition: VDP.hh:270
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:916
unsigned char byte
8 bit unsigned integer
Definition: openmsx.hh:33
DisplayMode getDisplayMode() const
Get the display mode the VDP is in.
Definition: VDP.hh:113
int getRightBorder() const
Gets the number of VDP clockticks between start of line and the start of the right border...
Definition: VDP.hh:414
int getTicksPerFrame() const
Gets the number of VDP clockticks (21MHz) per frame.
Definition: VDP.hh:371
int getLeftSprites() const
Gets the number of VDP clockticks between start of line and the start of the sprite plane...
Definition: VDP.hh:396
Represents a VDP display mode.
Definition: DisplayMode.hh:14
virtual void writeIO(word port, byte value, EmuTime::param time)
Write a byte to a given IO port at a certain time to this device.
Definition: VDP.cc:719
byte getVerticalScroll() const
Gets the current vertical scroll (line displayed at Y=0).
Definition: VDP.hh:233
byte getHorizontalScrollHigh() const
Gets the current horizontal scroll higher bits.
Definition: VDP.hh:251
int getLeftBackground() const
Gets the number of VDP clockticks between start of line and the time when the background pixel with X...
Definition: VDP.hh:424
const RawFrame * isSuperimposing() const
Are we currently superimposing? In case of superimpose, returns a pointer to the to-be-superimposed f...
Definition: VDP.hh:127
void serialize(Archive &ar, unsigned version)
Definition: VDP.cc:1536
virtual byte peekIO(word port, EmuTime::param time) const
Read a byte from a given IO port.
Definition: VDP.cc:1026
EmuTime::param getFrameStartTime() const
Definition: VDP.hh:346
bool getCmdBit() const
Are commands possible in non Graphic modes? (V9958 only)
Definition: VDP.hh:365
bool getBlinkState() const
Gets the current blink state.
Definition: VDP.hh:191
virtual ~VDP()
Definition: VDP.cc:316
int getEvenOddMask() const
Expresses the state of even/odd page interchange in a mask on the line number.
Definition: VDP.hh:333
Clock< TICKS_PER_SECOND > VDPClock
Definition: VDP.hh:73
bool isInterlaced() const
Get interlace status.
Definition: VDP.hh:297
bool isSpriteMag() const
Are sprites magnified?
Definition: VDP.hh:358
Every class that wants to get scheduled at some point must inherit from this class.
Definition: Schedulable.hh:16
A video frame as output by the VDP scanline conversion unit, before any postprocessing filters are ap...
Definition: RawFrame.hh:13
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)
bool isTextMode() const
Is the current mode a text mode? Text1 and Text2 are text modes.
Definition: DisplayMode.hh:138
int getForegroundColor() const
Gets the current foreground color.
Definition: VDP.hh:153
virtual void executeUntil(EmuTime::param time, int userData)
When the previously registered syncPoint is reached, this method gets called.
Definition: VDP.cc:445
byte getStatusReg0() const
Should only be used by SpriteChecker.
Definition: VDP.hh:431
bool getTransparency() const
Gets the current transparency setting.
Definition: VDP.hh:146
virtual byte readIO(word port, EmuTime::param time)
Read a byte from an IO port at a certain time from this device.
Definition: VDP.cc:1008
bool isDisplayEnabled() const
Is the display enabled? Both the regular border and forced blanking by clearing the display enable bi...
Definition: VDP.hh:209
bool isMSX1VDP() const
Is this an MSX1 VDP?
Definition: VDP.hh:99
int getSpriteSize() const
Gets the sprite size in pixels (8/16).
Definition: VDP.hh:352
const EmuTime & param
Definition: EmuTime.hh:20
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX...
Definition: MSXDevice.hh:32
unsigned short word
16 bit unsigned integer
Definition: openmsx.hh:38
PostProcessor * getPostProcessor() const
Used by Video9000 to be able to couple the VDP and V9990 output.
Definition: VDP.cc:341
VDP(const DeviceConfig &config)
Definition: VDP.cc:224
bool getEvenOdd() const
Is the even or odd field being displayed?
Definition: VDP.hh:319
byte getByte() const
Get the dispay mode as a byte: YAE YJK M5..M1 combined.
Definition: DisplayMode.hh:109
VDP-VRAM access slot calculator, meant to be used in the inner loops of the VDPCmdEngine commands...
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:907
Unified implementation of MSX Video Display Processors (VDPs).
Definition: VDP.hh:66
Abstract base class for post processors.
int getTicksThisFrame(EmuTime::param time) const
Gets the number of VDP clock ticks (21MHz) elapsed between a given time and the start of this frame...
Definition: VDP.hh:342
byte getHorizontalScrollLow() const
Gets the current horizontal scroll lower bits.
Definition: VDP.hh:242
EmuTime::param getTime() const
Gets the time at which the last clock tick occurred.
Definition: Clock.hh:46
bool cpuAccessScheduled() const
Is there a CPU-VRAM access scheduled.
Definition: VDP.cc:902
bool isPalTiming() const
Is PAL timing active? This setting is fixed at start of frame.
Definition: VDP.hh:286
static const int TICKS_PER_SECOND
Number of VDP clock ticks per second.
Definition: VDP.hh:72
bool hasYJK() const
Does this VDP support YJK display?
Definition: VDP.hh:106
Manages VRAM contents and synchronises the various users of the VRAM.
Definition: VDPVRAM.hh:362
int getLineZero() const
Get the absolute line number of display line zero.
Definition: VDP.hh:278
unsigned getTicksTill_fast(EmuTime::param e) const
Same as above, only faster, Though the time interval may not be too large.
Definition: Clock.hh:70
Generic Gang-of-Four Observer class, templatized edition.
Definition: Observer.hh:9
bool getVRMode() const
Returns current VR mode.
Definition: VDP.hh:449
word getPalette(int index) const
Gets a palette entry.
Definition: VDP.hh:200
bool spritesEnabledFast() const
Same as spritesEnabled(), but may only be called in sprite mode 1 or 2.
Definition: VDP.hh:225
void setExternalVideoSource(const RawFrame *externalSource)
Enable superimposing.
Definition: VDP.cc:1422
VDPVRAM & getVRAM()
Get the VRAM object for this VDP.
Definition: VDP.hh:119
virtual void powerUp(EmuTime::param time)
This method is called when MSX is powered up.
Definition: VDP.cc:412
int getLeftBorder() const
Gets the number of VDP clockticks between start of line and the end of the left border.
Definition: VDP.hh:407
int getBackgroundColor() const
Gets the current background color.
Definition: VDP.hh:165