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 || version == T6950PAL || version == T6950NTSC || version == TMS91X8 || version == TMS9129 || version == T7937APAL || version == T7937ANTSC;
101  }
102 
107  inline bool isMSX1VDPwithPAL() const {
108  return version == TMS9929A || version == TMS9129 || version == T6950PAL || version == T7937APAL;
109  }
110 
115  inline bool vdpLacksMirroring() const {
116  return version == T6950PAL || version == T6950NTSC;
117  }
118 
123  inline bool vdpHasPatColMirroring() const {
124  return version == TMS9929A || version == TMS99X8A;
125  }
126 
131  inline bool isMSX1VDPwithVRAMremapping() const {
132  return version == TMS9929A || version == TMS99X8A;
133  }
134 
139  inline bool hasToshibaPalette() const {
140  return version == T6950PAL || version == T6950NTSC || version == T7937APAL || version == T7937ANTSC;
141  }
142 
146  inline bool hasYJK() const {
147  return version == V9958;
148  }
149 
153  inline DisplayMode getDisplayMode() const {
154  return displayMode;
155  }
156 
159  inline VDPVRAM& getVRAM() {
160  return *vram;
161  }
162 
167  inline const RawFrame* isSuperimposing() const {
168  // Note that bit 0 of r#0 has no effect on an V9938 or higher,
169  // but this bit is masked out. Also note that on an MSX1, if
170  // bit 0 of r#0 is enabled and there is no external video
171  // source, then we lose sync.
172  // Also note that because this property is fixed per frame we
173  // cannot (re)calculate it from register values.
174  return superimposing;
175  }
176 
180  return *spriteChecker;
181  }
182 
186  inline bool getTransparency() const {
187  return (controlRegs[8] & 0x20) == 0;
188  }
189 
193  inline int getForegroundColor() const {
194  return controlRegs[7] >> 4;
195  }
196 
205  inline int getBackgroundColor() const {
206  byte reg7 = controlRegs[7];
207  if (displayMode.getByte() == DisplayMode::GRAPHIC7) {
208  return reg7;
209  } else {
210  return reg7 & 0x0F;
211  }
212  }
213 
217  inline int getBlinkForegroundColor() const {
218  return controlRegs[12] >> 4;
219  }
220 
224  inline int getBlinkBackgroundColor() const {
225  return controlRegs[12] & 0x0F;
226  }
227 
231  inline bool getBlinkState() const {
232  return blinkState;
233  }
234 
240  inline word getPalette(int index) const {
241  return palette[index];
242  }
243 
249  inline bool isDisplayEnabled() const {
250  return isDisplayArea && displayEnabled;
251  }
252 
257  inline bool spritesEnabled() const {
258  return displayEnabled && !displayMode.isTextMode() &&
259  ((controlRegs[8] & 0x02) == 0x00);
260  }
261 
265  inline bool spritesEnabledFast() const {
266  assert(!displayMode.isTextMode());
267  return displayEnabled && ((controlRegs[8] & 0x02) == 0x00);
268  }
269 
273  inline byte getVerticalScroll() const {
274  return controlRegs[23];
275  }
276 
282  inline byte getHorizontalScrollLow() const {
283  return controlRegs[27];
284  }
285 
291  inline byte getHorizontalScrollHigh() const {
292  return controlRegs[26];
293  }
294 
300  inline bool isBorderMasked() const {
301  return (controlRegs[25] & 0x02) != 0;
302  }
303 
310  inline bool isMultiPageScrolling() const {
311  return (controlRegs[25] & 0x01) && (controlRegs[2] & 0x20);
312  }
313 
318  inline int getLineZero() const {
319  return displayStart / TICKS_PER_LINE;
320  }
321 
326  inline bool isPalTiming() const {
327  return palTiming;
328  }
329 
337  inline bool isInterlaced() const {
338  return interlaced;
339  }
340 
352  inline bool isEvenOddEnabled() const {
353  return (controlRegs[9] & 4) != 0;
354  }
355 
359  inline bool getEvenOdd() const {
360  return (statusReg2 & 2) != 0;
361  }
362 
373  inline int getEvenOddMask() const {
374  // TODO: Verify which page is displayed on even fields.
375  return (((~controlRegs[9] & 4) << 6) | ((statusReg2 & 2) << 7)) &
376  (!blinkState << 8);
377  }
378 
382  inline int getTicksThisFrame(EmuTime::param time) const {
383  return frameStartTime.getTicksTill_fast(time);
384  }
385 
387  return frameStartTime.getTime();
388  }
389 
392  inline int getSpriteSize() const {
393  return ((controlRegs[1] & 2) << 2) + 8;
394  }
395 
398  inline bool isSpriteMag() const {
399  return controlRegs[1] & 1;
400  }
401 
405  inline bool getCmdBit() const {
406  return (controlRegs[25] & 0x40) != 0;
407  }
408 
411  inline int getTicksPerFrame() const {
412  return palTiming ? TICKS_PER_LINE * 313 : TICKS_PER_LINE * 262;
413  }
414 
424  inline bool isInsideFrame(EmuTime::param time) const {
425  return time >= frameStartTime.getTime() &&
427  }
428 
436  inline int getLeftSprites() const {
437  return 100 + 102 + 56
438  + (horizontalAdjust - 7) * 4
439  + (displayMode.isTextMode() ? 36 : 0);
440  }
441 
447  inline int getLeftBorder() const {
448  return getLeftSprites() + (isBorderMasked() ? 8 * 4 : 0);
449  }
450 
454  inline int getRightBorder() const {
455  return getLeftSprites()
456  + (displayMode.isTextMode() ? 960 : 1024);
457  }
458 
464  inline int getLeftBackground() const {
465  return getLeftSprites() + getHorizontalScrollLow() * 4;
466  }
467 
471  byte getStatusReg0() const { return statusReg0; }
472 
481  void setSpriteStatus(byte value)
482  {
483  statusReg0 = (statusReg0 & 0x80) | (value & 0x7F);
484  }
485 
489  bool getVRMode() const {
490  return (controlRegs[8] & 8) != 0;
491  }
492 
495  void setExternalVideoSource(const RawFrame* externalSource);
496 
500 
511  EmuTime::param time, EmuTime::param limit) const;
512 
514  bool cpuAccessScheduled() const;
515 
516  template<typename Archive>
517  void serialize(Archive& ar, unsigned version);
518 
519 private:
520  void initTables();
521 
524  enum VdpVersion {
530  TMS99X8A,
531  T6950PAL, // Toshiba clone (hardwired as PAL)
532  T6950NTSC, // Toshiba clone (hardwired as NTSC)
533  T7937APAL, // VDP in Toshiba T7937A engine (hardwired as PAL)
534  T7937ANTSC, // VDP in Toshiba T7937A engine (hardwired as NTSC)
535  TMS91X8, // newer variant NTSC
538  TMS9929A,
539  TMS9129, // newer variant PAL
542  V9938,
545  V9958
546  };
547 
550  enum SyncType {
552  VSYNC,
554  DISPLAY_START,
556  VSCAN,
558  HSCAN,
560  HOR_ADJUST,
562  SET_MODE,
564  SET_BLANK,
566  CPU_VRAM_ACCESS,
567  };
568 
579  static const int LINE_COUNT_RESET_TICKS = 15 * TICKS_PER_LINE;
580 
584  inline int getNumberOfLines() const {
585  return controlRegs[9] & 0x80 ? 212 : 192;
586  }
587 
597  inline bool getHR(int ticksThisFrame) const {
598  // Note: These constants are located inside this function because
599  // GCC 4.0.x won't link if they are in the class scope.
603  static const int HBLANK_LEN_TXT = 404;
607  static const int HBLANK_LEN_GFX = 312;
608  return
609  ( ticksThisFrame + TICKS_PER_LINE - getRightBorder()
610  ) % TICKS_PER_LINE
611  < (displayMode.isTextMode() ? HBLANK_LEN_TXT : HBLANK_LEN_GFX);
612  }
613 
614  // VideoSystemChangeListener interface:
615  virtual void preVideoSystemChange();
616  virtual void postVideoSystemChange();
617 
622  void resetInit();
623 
628  void resetMasks(EmuTime::param time);
629 
633  void frameStart(EmuTime::param time);
634 
642  void scheduleDisplayStart(EmuTime::param time);
643 
649  void scheduleVScan(EmuTime::param time);
650 
656  void scheduleHScan(EmuTime::param time);
657 
660  void vramWrite(byte value, EmuTime::param time);
661 
664  byte vramRead(EmuTime::param time);
665 
667  void scheduleCpuVramAccess(bool isRead, byte write, EmuTime::param time);
668  void executeCpuVramAccess(EmuTime::param time);
669 
672  byte peekStatusReg(byte reg, EmuTime::param time) const;
673  byte readStatusReg(byte reg, EmuTime::param time);
674 
677  void changeRegister(byte reg, byte val, EmuTime::param time);
678 
681  void syncAtNextLine(SyncType type, EmuTime::param time);
682 
685  void createRenderer();
686 
690  void updateNameBase(EmuTime::param time);
691 
695  void updateColorBase(EmuTime::param time);
696 
700  void updatePatternBase(EmuTime::param time);
701 
705  void updateSpriteAttributeBase(EmuTime::param time);
706 
710  void updateSpritePatternBase(EmuTime::param time);
711 
715  void updateDisplayMode(DisplayMode newMode, EmuTime::param time);
716 
723  void setPalette(int index, word grb, EmuTime::param time);
724 
725  // Observer<Setting>
726  virtual void update(const Setting& setting);
727 
728 private:
729  Display& display;
730  EnumSetting<bool>& cmdTiming;
731  EnumSetting<bool>& tooFastAccess;
732 
733  friend class VDPRegDebug;
734  friend class VDPStatusRegDebug;
735  friend class VDPPaletteDebug;
736  friend class VRAMPointerDebug;
737  friend class FrameCountInfo;
738  const std::unique_ptr<VDPRegDebug> vdpRegDebug;
739  const std::unique_ptr<VDPStatusRegDebug> vdpStatusRegDebug;
740  const std::unique_ptr<VDPPaletteDebug> vdpPaletteDebug;
741  const std::unique_ptr<VRAMPointerDebug> vramPointerDebug;
742  const std::unique_ptr<FrameCountInfo> frameCountInfo;
743  const std::unique_ptr<CycleInFrameInfo> cycleInFrameInfo;
744  const std::unique_ptr<LineInFrameInfo> lineInFrameInfo;
745  const std::unique_ptr<CycleInLineInfo> cycleInLineInfo;
746  const std::unique_ptr<MsxYPosInfo> msxYPosInfo;
747  const std::unique_ptr<MsxX256PosInfo> msxX256PosInfo;
748  const std::unique_ptr<MsxX512PosInfo> msxX512PosInfo;
749 
752  std::unique_ptr<Renderer> renderer;
753 
756  std::unique_ptr<VDPCmdEngine> cmdEngine;
757 
760  std::unique_ptr<SpriteChecker> spriteChecker;
761 
764  std::unique_ptr<VDPVRAM> vram;
765 
769  const RawFrame* externalVideo;
770 
776  const RawFrame* superimposing;
777 
780  VDPClock frameStartTime;
781 
784  IRQHelper irqVertical;
785 
788  IRQHelper irqHorizontal;
789 
792  EmuTime displayStartSyncTime;
793 
796  EmuTime vScanSyncTime;
797 
800  EmuTime hScanSyncTime;
801 
804  VdpVersion version;
805 
811  int frameCount;
812 
815  int displayStart;
816 
820  int horizontalScanOffset;
821 
825  int horizontalAdjust;
826 
829  byte controlRegs[32];
830 
835  int controlRegMask;
836 
843  byte controlValueMasks[32];
844 
848  int blinkCount;
849 
853  int vramPointer;
854 
857  word palette[16];
858 
861  bool isDisplayArea;
862 
868  bool palTiming;
869 
873  bool interlaced;
874 
879  byte statusReg0;
880 
886  byte statusReg1;
887 
892  byte statusReg2;
893 
896  bool blinkState;
897 
900  byte dataLatch;
901 
904  bool registerDataStored;
905 
908  bool paletteDataStored;
909 
917  byte cpuVramData;
918 
922  bool cpuVramReqIsRead;
923  unsigned cpuVramReqAddr;
924 
928  bool cpuExtendedVram;
929 
935  DisplayMode displayMode;
936 
941  bool displayEnabled;
942 
946  bool warningPrinted;
947 
949  bool allowTooFastAccess;
950 };
952 
953 } // namespace openmsx
954 
955 #endif
int getBlinkBackgroundColor() const
Gets the current blinking color for blinking text.
Definition: VDP.hh:224
bool isInsideFrame(EmuTime::param time) const
Is the given timestamp inside the current frame? Mainly useful for debugging, because relevant timest...
Definition: VDP.hh:424
int getBlinkForegroundColor() const
Gets the current blinking color for blinking text.
Definition: VDP.hh:217
bool isBorderMasked() const
Gets the current border mask setting.
Definition: VDP.hh:300
bool isEvenOddEnabled() const
Get even/odd page alternation status.
Definition: VDP.hh:352
bool vdpHasPatColMirroring() const
Is this a VDP that has pattern/colortable mirroring?
Definition: VDP.hh:123
void setSpriteStatus(byte value)
Should only be used by SpriteChecker.
Definition: VDP.hh:481
bool spritesEnabled() const
Are sprites enabled?
Definition: VDP.hh:257
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:179
virtual void reset(EmuTime::param time)
This method is called on reset.
Definition: VDP.cc:428
bool isMultiPageScrolling() const
Is multi page scrolling enabled? It is considered enabled if both the multi page scrolling flag is en...
Definition: VDP.hh:310
bool isMSX1VDPwithPAL() const
Is this a MSX1 VDP with PAL?
Definition: VDP.hh:107
bool vdpLacksMirroring() const
Is this a VDP that lacks mirroring?
Definition: VDP.hh:115
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:926
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:153
int getRightBorder() const
Gets the number of VDP clockticks between start of line and the start of the right border...
Definition: VDP.hh:454
int getTicksPerFrame() const
Gets the number of VDP clockticks (21MHz) per frame.
Definition: VDP.hh:411
int getLeftSprites() const
Gets the number of VDP clockticks between start of line and the start of the sprite plane...
Definition: VDP.hh:436
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:729
byte getVerticalScroll() const
Gets the current vertical scroll (line displayed at Y=0).
Definition: VDP.hh:273
byte getHorizontalScrollHigh() const
Gets the current horizontal scroll higher bits.
Definition: VDP.hh:291
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:464
const RawFrame * isSuperimposing() const
Are we currently superimposing? In case of superimpose, returns a pointer to the to-be-superimposed f...
Definition: VDP.hh:167
bool hasToshibaPalette() const
Is this a VDP with a Toshiba palette?
Definition: VDP.hh:139
void serialize(Archive &ar, unsigned version)
Definition: VDP.cc:1562
virtual byte peekIO(word port, EmuTime::param time) const
Read a byte from a given IO port.
Definition: VDP.cc:1038
EmuTime::param getFrameStartTime() const
Definition: VDP.hh:386
bool getCmdBit() const
Are commands possible in non Graphic modes? (V9958 only)
Definition: VDP.hh:405
bool getBlinkState() const
Gets the current blink state.
Definition: VDP.hh:231
bool isMSX1VDPwithVRAMremapping() const
Does this MSX1 VDP have VRAM remapping when switching from 4k to 8/16k mode?
Definition: VDP.hh:131
virtual ~VDP()
Definition: VDP.cc:326
int getEvenOddMask() const
Expresses the state of even/odd page interchange in a mask on the line number.
Definition: VDP.hh:373
Clock< TICKS_PER_SECOND > VDPClock
Definition: VDP.hh:73
bool isInterlaced() const
Get interlace status.
Definition: VDP.hh:337
bool isSpriteMag() const
Are sprites magnified?
Definition: VDP.hh:398
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:193
virtual void executeUntil(EmuTime::param time, int userData)
When the previously registered syncPoint is reached, this method gets called.
Definition: VDP.cc:455
byte getStatusReg0() const
Should only be used by SpriteChecker.
Definition: VDP.hh:471
bool getTransparency() const
Gets the current transparency setting.
Definition: VDP.hh:186
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:1018
bool isDisplayEnabled() const
Is the display enabled? Both the regular border and forced blanking by clearing the display enable bi...
Definition: VDP.hh:249
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:392
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:351
VDP(const DeviceConfig &config)
Definition: VDP.cc:224
bool getEvenOdd() const
Is the even or odd field being displayed?
Definition: VDP.hh:359
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:917
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:382
byte getHorizontalScrollLow() const
Gets the current horizontal scroll lower bits.
Definition: VDP.hh:282
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:912
bool isPalTiming() const
Is PAL timing active? This setting is fixed at start of frame.
Definition: VDP.hh:326
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:146
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:318
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:489
word getPalette(int index) const
Gets a palette entry.
Definition: VDP.hh:240
bool spritesEnabledFast() const
Same as spritesEnabled(), but may only be called in sprite mode 1 or 2.
Definition: VDP.hh:265
void setExternalVideoSource(const RawFrame *externalSource)
Enable superimposing.
Definition: VDP.cc:1448
VDPVRAM & getVRAM()
Get the VRAM object for this VDP.
Definition: VDP.hh:159
virtual void powerUp(EmuTime::param time)
This method is called when MSX is powered up.
Definition: VDP.cc:422
int getLeftBorder() const
Gets the number of VDP clockticks between start of line and the end of the left border.
Definition: VDP.hh:447
int getBackgroundColor() const
Gets the current background color.
Definition: VDP.hh:205