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 & VM_MSX1;
101  }
102 
106  inline bool isMSX1VDPwithPAL() const {
107  return version & (VM_MSX1 | VM_PAL);
108  }
109 
113  inline bool vdpLacksMirroring() const {
114  return version & VM_NO_MIRRORING;
115  }
116 
120  inline bool vdpHasPatColMirroring() const {
121  return version & VM_PALCOL_MIRRORING;
122  }
123 
127  inline bool isMSX1VDPwithVRAMremapping() const {
128  return version & (VM_MSX1 | VM_VRAM_REMAPPING);
129  }
130 
134  inline bool hasToshibaPalette() const {
135  return version & VM_TOSHIBA_PALETTE;
136  }
137 
141  inline bool hasYJK() const {
142  return version & VM_YJK;
143  }
144 
148  inline DisplayMode getDisplayMode() const {
149  return displayMode;
150  }
151 
154  inline VDPVRAM& getVRAM() {
155  return *vram;
156  }
157 
162  inline const RawFrame* isSuperimposing() const {
163  // Note that bit 0 of r#0 has no effect on an V9938 or higher,
164  // but this bit is masked out. Also note that on an MSX1, if
165  // bit 0 of r#0 is enabled and there is no external video
166  // source, then we lose sync.
167  // Also note that because this property is fixed per frame we
168  // cannot (re)calculate it from register values.
169  return superimposing;
170  }
171 
175  return *spriteChecker;
176  }
177 
181  inline bool getTransparency() const {
182  return (controlRegs[8] & 0x20) == 0;
183  }
184 
188  inline int getForegroundColor() const {
189  return controlRegs[7] >> 4;
190  }
191 
200  inline int getBackgroundColor() const {
201  byte reg7 = controlRegs[7];
202  if (displayMode.getByte() == DisplayMode::GRAPHIC7) {
203  return reg7;
204  } else {
205  return reg7 & 0x0F;
206  }
207  }
208 
212  inline int getBlinkForegroundColor() const {
213  return controlRegs[12] >> 4;
214  }
215 
219  inline int getBlinkBackgroundColor() const {
220  return controlRegs[12] & 0x0F;
221  }
222 
226  inline bool getBlinkState() const {
227  return blinkState;
228  }
229 
235  inline word getPalette(int index) const {
236  return palette[index];
237  }
238 
244  inline bool isDisplayEnabled() const {
245  return isDisplayArea && displayEnabled;
246  }
247 
252  inline bool spritesEnabled() const {
253  return displayEnabled &&
254  (displayMode.getSpriteMode(isMSX1VDP()) != 0) &&
255  ((controlRegs[8] & 0x02) == 0x00);
256  }
257 
261  inline bool spritesEnabledFast() const {
262  assert(displayMode.getSpriteMode(isMSX1VDP()) != 0);
263  return displayEnabled && ((controlRegs[8] & 0x02) == 0x00);
264  }
265 
269  inline byte getVerticalScroll() const {
270  return controlRegs[23];
271  }
272 
278  inline byte getHorizontalScrollLow() const {
279  return controlRegs[27];
280  }
281 
287  inline byte getHorizontalScrollHigh() const {
288  return controlRegs[26];
289  }
290 
296  inline bool isBorderMasked() const {
297  return (controlRegs[25] & 0x02) != 0;
298  }
299 
306  inline bool isMultiPageScrolling() const {
307  return (controlRegs[25] & 0x01) && (controlRegs[2] & 0x20);
308  }
309 
314  inline int getLineZero() const {
315  return displayStart / TICKS_PER_LINE;
316  }
317 
322  inline bool isPalTiming() const {
323  return palTiming;
324  }
325 
333  inline bool isInterlaced() const {
334  return interlaced;
335  }
336 
348  inline bool isEvenOddEnabled() const {
349  return (controlRegs[9] & 4) != 0;
350  }
351 
355  inline bool getEvenOdd() const {
356  return (statusReg2 & 2) != 0;
357  }
358 
369  inline int getEvenOddMask() const {
370  // TODO: Verify which page is displayed on even fields.
371  return (((~controlRegs[9] & 4) << 6) | ((statusReg2 & 2) << 7)) &
372  (!blinkState << 8);
373  }
374 
378  inline int getTicksThisFrame(EmuTime::param time) const {
379  return frameStartTime.getTicksTill_fast(time);
380  }
381 
383  return frameStartTime.getTime();
384  }
385 
388  inline int getSpriteSize() const {
389  return ((controlRegs[1] & 2) << 2) + 8;
390  }
391 
394  inline bool isSpriteMag() const {
395  return controlRegs[1] & 1;
396  }
397 
401  inline bool getCmdBit() const {
402  return (controlRegs[25] & 0x40) != 0;
403  }
404 
407  inline int getTicksPerFrame() const {
408  return palTiming ? TICKS_PER_LINE * 313 : TICKS_PER_LINE * 262;
409  }
410 
420  inline bool isInsideFrame(EmuTime::param time) const {
421  return time >= frameStartTime.getTime() &&
423  }
424 
428  inline int getHorizontalAdjust() const {
429  return horizontalAdjust;
430  }
431 
439  inline int getLeftSprites() const {
440  return 100 + 102 + 56
441  + (horizontalAdjust - 7) * 4
442  + (displayMode.isTextMode() ? 36 : 0);
443  }
444 
450  inline int getLeftBorder() const {
451  return getLeftSprites() + (isBorderMasked() ? 8 * 4 : 0);
452  }
453 
457  inline int getRightBorder() const {
458  return getLeftSprites()
459  + (displayMode.isTextMode() ? 960 : 1024);
460  }
461 
467  inline int getLeftBackground() const {
468  return getLeftSprites() + getHorizontalScrollLow() * 4;
469  }
470 
474  byte getStatusReg0() const { return statusReg0; }
475 
484  void setSpriteStatus(byte value)
485  {
486  statusReg0 = (statusReg0 & 0x80) | (value & 0x7F);
487  }
488 
492  bool getVRMode() const {
493  return (controlRegs[8] & 8) != 0;
494  }
495 
498  void setExternalVideoSource(const RawFrame* externalSource);
499 
503 
514  EmuTime::param time, EmuTime::param limit) const;
515 
517  bool cpuAccessScheduled() const;
518 
519  template<typename Archive>
520  void serialize(Archive& ar, unsigned version);
521 
522 private:
523  void initTables();
524 
525  // VdpVersion bitmasks
526  static const unsigned VM_MSX1 = 1; // set-> MSX1, unset-> MSX2 or MSX2+
527  static const unsigned VM_PAL = 2; // set-> fixed PAL, unset-> fixed NTSC or switchable
528  static const unsigned VM_NO_MIRRORING = 4; // set-> no (screen2) mirroring
529  static const unsigned VM_PALCOL_MIRRORING = 8; // set-> pattern/color-table mirroring
530  static const unsigned VM_VRAM_REMAPPING = 16; // set-> 4k,8/16k VRAM remapping
531  static const unsigned VM_TOSHIBA_PALETTE = 32; // set-> has Toshiba palette
532  static const unsigned VM_YJK = 64; // set-> has YJK (MSX2+)
533 
535  enum VdpVersion {
540  TMS99X8A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING,
541 
543  TMS9929A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING | VM_PAL,
544 
546  TMS9129 = VM_MSX1 | VM_PAL,
547 
549  TMS91X8 = VM_MSX1,
550 
552  T6950PAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING | VM_PAL,
553 
555  T6950NTSC = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING,
556 
558  T7937APAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_PAL,
559 
561  T7937ANTSC = VM_MSX1 | VM_TOSHIBA_PALETTE,
562 
564  V9938 = 0,
565 
567  V9958 = VM_YJK,
568  };
569 
572  enum SyncType {
574  VSYNC,
576  DISPLAY_START,
578  VSCAN,
580  HSCAN,
582  HOR_ADJUST,
584  SET_MODE,
586  SET_BLANK,
588  CPU_VRAM_ACCESS,
589  };
590 
601  static const int LINE_COUNT_RESET_TICKS = 15 * TICKS_PER_LINE;
602 
606  inline int getNumberOfLines() const {
607  return controlRegs[9] & 0x80 ? 212 : 192;
608  }
609 
619  inline bool getHR(int ticksThisFrame) const {
620  // Note: These constants are located inside this function because
621  // GCC 4.0.x won't link if they are in the class scope.
625  static const int HBLANK_LEN_TXT = 404;
629  static const int HBLANK_LEN_GFX = 312;
630  return
631  ( ticksThisFrame + TICKS_PER_LINE - getRightBorder()
632  ) % TICKS_PER_LINE
633  < (displayMode.isTextMode() ? HBLANK_LEN_TXT : HBLANK_LEN_GFX);
634  }
635 
636  // VideoSystemChangeListener interface:
637  virtual void preVideoSystemChange();
638  virtual void postVideoSystemChange();
639 
644  void resetInit();
645 
650  void resetMasks(EmuTime::param time);
651 
655  void frameStart(EmuTime::param time);
656 
664  void scheduleDisplayStart(EmuTime::param time);
665 
671  void scheduleVScan(EmuTime::param time);
672 
678  void scheduleHScan(EmuTime::param time);
679 
682  void vramWrite(byte value, EmuTime::param time);
683 
686  byte vramRead(EmuTime::param time);
687 
689  void scheduleCpuVramAccess(bool isRead, byte write, EmuTime::param time);
690  void executeCpuVramAccess(EmuTime::param time);
691 
694  byte peekStatusReg(byte reg, EmuTime::param time) const;
695  byte readStatusReg(byte reg, EmuTime::param time);
696 
699  void changeRegister(byte reg, byte val, EmuTime::param time);
700 
703  void syncAtNextLine(SyncType type, EmuTime::param time);
704 
707  void createRenderer();
708 
712  void updateNameBase(EmuTime::param time);
713 
717  void updateColorBase(EmuTime::param time);
718 
722  void updatePatternBase(EmuTime::param time);
723 
727  void updateSpriteAttributeBase(EmuTime::param time);
728 
732  void updateSpritePatternBase(EmuTime::param time);
733 
737  void updateDisplayMode(DisplayMode newMode, EmuTime::param time);
738 
745  void setPalette(int index, word grb, EmuTime::param time);
746 
747  // Observer<Setting>
748  virtual void update(const Setting& setting);
749 
750 private:
751  Display& display;
752  EnumSetting<bool>& cmdTiming;
753  EnumSetting<bool>& tooFastAccess;
754 
755  friend class VDPRegDebug;
756  friend class VDPStatusRegDebug;
757  friend class VDPPaletteDebug;
758  friend class VRAMPointerDebug;
759  friend class FrameCountInfo;
760  const std::unique_ptr<VDPRegDebug> vdpRegDebug;
761  const std::unique_ptr<VDPStatusRegDebug> vdpStatusRegDebug;
762  const std::unique_ptr<VDPPaletteDebug> vdpPaletteDebug;
763  const std::unique_ptr<VRAMPointerDebug> vramPointerDebug;
764  const std::unique_ptr<FrameCountInfo> frameCountInfo;
765  const std::unique_ptr<CycleInFrameInfo> cycleInFrameInfo;
766  const std::unique_ptr<LineInFrameInfo> lineInFrameInfo;
767  const std::unique_ptr<CycleInLineInfo> cycleInLineInfo;
768  const std::unique_ptr<MsxYPosInfo> msxYPosInfo;
769  const std::unique_ptr<MsxX256PosInfo> msxX256PosInfo;
770  const std::unique_ptr<MsxX512PosInfo> msxX512PosInfo;
771 
774  std::unique_ptr<Renderer> renderer;
775 
778  std::unique_ptr<VDPCmdEngine> cmdEngine;
779 
782  std::unique_ptr<SpriteChecker> spriteChecker;
783 
786  std::unique_ptr<VDPVRAM> vram;
787 
791  const RawFrame* externalVideo;
792 
798  const RawFrame* superimposing;
799 
802  VDPClock frameStartTime;
803 
806  IRQHelper irqVertical;
807 
810  IRQHelper irqHorizontal;
811 
814  EmuTime displayStartSyncTime;
815 
818  EmuTime vScanSyncTime;
819 
822  EmuTime hScanSyncTime;
823 
826  VdpVersion version;
827 
833  int frameCount;
834 
837  int displayStart;
838 
842  int horizontalScanOffset;
843 
847  int horizontalAdjust;
848 
851  byte controlRegs[32];
852 
857  int controlRegMask;
858 
865  byte controlValueMasks[32];
866 
870  int blinkCount;
871 
875  int vramPointer;
876 
879  word palette[16];
880 
883  bool isDisplayArea;
884 
890  bool palTiming;
891 
895  bool interlaced;
896 
901  byte statusReg0;
902 
908  byte statusReg1;
909 
914  byte statusReg2;
915 
918  bool blinkState;
919 
922  byte dataLatch;
923 
926  bool registerDataStored;
927 
930  bool paletteDataStored;
931 
939  byte cpuVramData;
940 
944  bool cpuVramReqIsRead;
945  bool pendingCpuAccess; // always equal to pendingSyncPoint(CPU_VRAM_ACCESS)
946  unsigned cpuVramReqAddr;
947 
951  bool cpuExtendedVram;
952 
958  DisplayMode displayMode;
959 
964  bool displayEnabled;
965 
969  bool warningPrinted;
970 
972  bool brokenCmdTiming;
973  bool allowTooFastAccess;
974 };
976 
977 } // namespace openmsx
978 
979 #endif
int getBlinkBackgroundColor() const
Gets the current blinking color for blinking text.
Definition: VDP.hh:219
bool isInsideFrame(EmuTime::param time) const
Is the given timestamp inside the current frame? Mainly useful for debugging, because relevant timest...
Definition: VDP.hh:420
int getBlinkForegroundColor() const
Gets the current blinking color for blinking text.
Definition: VDP.hh:212
bool isBorderMasked() const
Gets the current border mask setting.
Definition: VDP.hh:296
bool isEvenOddEnabled() const
Get even/odd page alternation status.
Definition: VDP.hh:348
bool vdpHasPatColMirroring() const
Is this a VDP that has pattern/colortable mirroring?
Definition: VDP.hh:120
void setSpriteStatus(byte value)
Should only be used by SpriteChecker.
Definition: VDP.hh:484
bool spritesEnabled() const
Are sprites enabled?
Definition: VDP.hh:252
int getHorizontalAdjust() const
This is a combination of the (horizontal) set adjust register and the YJK-mode bit.
Definition: VDP.hh:428
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:174
virtual void reset(EmuTime::param time)
This method is called on reset.
Definition: VDP.cc:430
bool isMultiPageScrolling() const
Is multi page scrolling enabled? It is considered enabled if both the multi page scrolling flag is en...
Definition: VDP.hh:306
bool isMSX1VDPwithPAL() const
Is this a MSX1 VDP with PAL?
Definition: VDP.hh:106
bool vdpLacksMirroring() const
Is this a VDP that lacks mirroring?
Definition: VDP.hh:113
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:931
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:148
int getRightBorder() const
Gets the number of VDP clockticks between start of line and the start of the right border...
Definition: VDP.hh:457
int getSpriteMode(bool isMSX1) const
Get the sprite mode of this display mode.
Definition: DisplayMode.hh:176
int getTicksPerFrame() const
Gets the number of VDP clockticks (21MHz) per frame.
Definition: VDP.hh:407
int getLeftSprites() const
Gets the number of VDP clockticks between start of line and the start of the sprite plane...
Definition: VDP.hh:439
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:733
byte getVerticalScroll() const
Gets the current vertical scroll (line displayed at Y=0).
Definition: VDP.hh:269
byte getHorizontalScrollHigh() const
Gets the current horizontal scroll higher bits.
Definition: VDP.hh:287
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:467
const RawFrame * isSuperimposing() const
Are we currently superimposing? In case of superimpose, returns a pointer to the to-be-superimposed f...
Definition: VDP.hh:162
bool hasToshibaPalette() const
Is this a VDP with a Toshiba palette?
Definition: VDP.hh:134
void serialize(Archive &ar, unsigned version)
Definition: VDP.cc:1570
virtual byte peekIO(word port, EmuTime::param time) const
Read a byte from a given IO port.
Definition: VDP.cc:1042
EmuTime::param getFrameStartTime() const
Definition: VDP.hh:382
bool getCmdBit() const
Are commands possible in non Graphic modes? (V9958 only)
Definition: VDP.hh:401
bool getBlinkState() const
Gets the current blink state.
Definition: VDP.hh:226
bool isMSX1VDPwithVRAMremapping() const
Does this MSX1 VDP have VRAM remapping when switching from 4k to 8/16k mode?
Definition: VDP.hh:127
virtual ~VDP()
Definition: VDP.cc:327
int getEvenOddMask() const
Expresses the state of even/odd page interchange in a mask on the line number.
Definition: VDP.hh:369
Clock< TICKS_PER_SECOND > VDPClock
Definition: VDP.hh:73
bool isInterlaced() const
Get interlace status.
Definition: VDP.hh:333
bool isSpriteMag() const
Are sprites magnified?
Definition: VDP.hh:394
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:25
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:188
virtual void executeUntil(EmuTime::param time, int userData)
When the previously registered syncPoint is reached, this method gets called.
Definition: VDP.cc:458
byte getStatusReg0() const
Should only be used by SpriteChecker.
Definition: VDP.hh:474
bool getTransparency() const
Gets the current transparency setting.
Definition: VDP.hh:181
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:1022
bool isDisplayEnabled() const
Is the display enabled? Both the regular border and forced blanking by clearing the display enable bi...
Definition: VDP.hh:244
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:388
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:353
VDP(const DeviceConfig &config)
Definition: VDP.cc:224
bool getEvenOdd() const
Is the even or odd field being displayed?
Definition: VDP.hh:355
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:923
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:378
byte getHorizontalScrollLow() const
Gets the current horizontal scroll lower bits.
Definition: VDP.hh:278
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:918
bool isPalTiming() const
Is PAL timing active? This setting is fixed at start of frame.
Definition: VDP.hh:322
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:141
Manages VRAM contents and synchronises the various users of the VRAM.
Definition: VDPVRAM.hh:383
int getLineZero() const
Get the absolute line number of display line zero.
Definition: VDP.hh:314
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:492
word getPalette(int index) const
Gets a palette entry.
Definition: VDP.hh:235
bool spritesEnabledFast() const
Same as spritesEnabled(), but may only be called in sprite mode 1 or 2.
Definition: VDP.hh:261
void setExternalVideoSource(const RawFrame *externalSource)
Enable superimposing.
Definition: VDP.cc:1453
VDPVRAM & getVRAM()
Get the VRAM object for this VDP.
Definition: VDP.hh:154
virtual void powerUp(EmuTime::param time)
This method is called when MSX is powered up.
Definition: VDP.cc:424
int getLeftBorder() const
Gets the number of VDP clockticks between start of line and the end of the left border.
Definition: VDP.hh:450
int getBackgroundColor() const
Gets the current background color.
Definition: VDP.hh:200