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 "SimpleDebuggable.hh"
8#include "TclCallback.hh"
9#include "InfoTopic.hh"
10#include "IRQHelper.hh"
11#include "Clock.hh"
12#include "DisplayMode.hh"
13#include "EnumSetting.hh"
14#include "Observer.hh"
15#include "openmsx.hh"
16#include "outer.hh"
17#include <memory>
18#include <array>
19
20namespace openmsx {
21
22class PostProcessor;
23class Renderer;
24class VDPCmdEngine;
25class VDPVRAM;
26class MSXCPU;
27class SpriteChecker;
28class Display;
29class RawFrame;
30class Setting;
31namespace VDPAccessSlots {
32 enum Delta : int;
33 class Calculator;
34}
35
61class VDP final : public MSXDevice, private VideoSystemChangeListener
62 , private Observer<Setting>
63{
64public:
67 static constexpr int TICKS_PER_SECOND = 3579545 * 6; // 21.5MHz;
69
72 static constexpr int TICKS_PER_LINE = 1368;
73
74 explicit VDP(const DeviceConfig& config);
75 ~VDP() override;
76
77 void powerUp(EmuTime::param time) override;
78 void reset(EmuTime::param time) override;
79 [[nodiscard]] byte readIO(word port, EmuTime::param time) override;
80 [[nodiscard]] byte peekIO(word port, EmuTime::param time) const override;
81 void writeIO(word port, byte value, EmuTime::param time) override;
82
87 [[nodiscard]] PostProcessor* getPostProcessor() const;
88
93 [[nodiscard]] inline bool isMSX1VDP() const {
94 return (version & VM_MSX1) != 0;
95 }
96
100 [[nodiscard]] inline bool isVDPwithPALonly() const {
101 return (version & VM_PAL) != 0;
102 }
103
107 [[nodiscard]] inline bool vdpLacksMirroring() const {
108 return (version & VM_NO_MIRRORING) != 0;
109 }
110
114 [[nodiscard]] inline bool vdpHasPatColMirroring() const {
115 return (version & VM_PALCOL_MIRRORING) != 0;
116 }
117
121 [[nodiscard]] inline bool isVDPwithVRAMremapping() const {
122 return (version & VM_VRAM_REMAPPING) != 0;
123 }
124
128 [[nodiscard]] inline bool hasYJK() const {
129 return (version & VM_YJK) != 0;
130 }
131
136 [[nodiscard]] std::array<std::array<uint8_t, 3>, 16> getMSX1Palette() const;
137
141 [[nodiscard]] inline DisplayMode getDisplayMode() const {
142 return displayMode;
143 }
144
147 [[nodiscard]] inline VDPVRAM& getVRAM() {
148 return *vram;
149 }
150
155 [[nodiscard]] inline const RawFrame* isSuperimposing() const {
156 // Note that bit 0 of r#0 has no effect on an V9938 or higher,
157 // but this bit is masked out. Also note that on an MSX1, if
158 // bit 0 of r#0 is enabled and there is no external video
159 // source, then we lose sync.
160 // Also note that because this property is fixed per frame we
161 // cannot (re)calculate it from register values.
162 return superimposing;
163 }
164
167 [[nodiscard]] inline SpriteChecker& getSpriteChecker() {
168 return *spriteChecker;
169 }
170
174 [[nodiscard]] inline bool getTransparency() const {
175 return (controlRegs[8] & 0x20) == 0;
176 }
177
180 [[nodiscard]] bool canSpriteColor0Collide() const {
181 // On MSX1 (so far only tested a TMS9129(?)) sprites with
182 // color=0 can always collide with other sprites. Though on
183 // V99x8 (only tested V9958) collisions only occur when color 0
184 // is not transparent. For more details see:
185 // https://github.com/openMSX/openMSX/issues/1198
186 return isMSX1VDP() || !getTransparency();
187 }
188
192 [[nodiscard]] inline int getForegroundColor() const {
193 return controlRegs[7] >> 4;
194 }
195
204 [[nodiscard]] inline int getBackgroundColor() const {
205 byte reg7 = controlRegs[7];
206 if (displayMode.getByte() == DisplayMode::GRAPHIC7) {
207 return reg7;
208 } else {
209 return reg7 & 0x0F;
210 }
211 }
212
216 [[nodiscard]] inline int getBlinkForegroundColor() const {
217 return controlRegs[12] >> 4;
218 }
219
223 [[nodiscard]] inline int getBlinkBackgroundColor() const {
224 return controlRegs[12] & 0x0F;
225 }
226
230 [[nodiscard]] inline bool getBlinkState() const {
231 return blinkState;
232 }
233
239 [[nodiscard]] inline word getPalette(int index) const {
240 return palette[index];
241 }
242
248 [[nodiscard]] inline bool isDisplayEnabled() const {
249 return isDisplayArea && displayEnabled;
250 }
251
256 [[nodiscard]] inline bool spritesEnabled() const {
257 return displayEnabled &&
258 (displayMode.getSpriteMode(isMSX1VDP()) != 0) &&
259 spriteEnabled;
260 }
261
265 [[nodiscard]] inline bool spritesEnabledFast() const {
266 assert(displayMode.getSpriteMode(isMSX1VDP()) != 0);
267 return displayEnabled && spriteEnabled;
268 }
269
273 [[nodiscard]] inline bool spritesEnabledRegister() const {
274 return spriteEnabled;
275 }
276
280 [[nodiscard]] inline byte getVerticalScroll() const {
281 return controlRegs[23];
282 }
283
289 [[nodiscard]] inline byte getHorizontalScrollLow() const {
290 return controlRegs[27];
291 }
292
298 [[nodiscard]] inline byte getHorizontalScrollHigh() const {
299 return controlRegs[26];
300 }
301
307 [[nodiscard]] inline bool isBorderMasked() const {
308 return (controlRegs[25] & 0x02) != 0;
309 }
310
317 [[nodiscard]] inline bool isMultiPageScrolling() const {
318 return (controlRegs[25] & 0x01) && (controlRegs[2] & 0x20);
319 }
320
325 [[nodiscard]] inline int getLineZero() const {
326 return displayStart / TICKS_PER_LINE;
327 }
328
333 [[nodiscard]] inline bool isPalTiming() const {
334 return palTiming;
335 }
336
344 [[nodiscard]] inline bool isInterlaced() const {
345 return interlaced;
346 }
347
358 [[nodiscard]] inline bool isFastBlinkEnabled() const {
359 return (controlRegs[1] & 4) != 0;
360 }
361
373 [[nodiscard]] inline bool isEvenOddEnabled() const {
374 if (isFastBlinkEnabled()) return false;
375 return (controlRegs[9] & 4) != 0;
376 }
377
381 [[nodiscard]] inline bool getEvenOdd() const {
382 return (statusReg2 & 2) != 0;
383 }
384
396 [[nodiscard]] inline int getEvenOddMask() const {
397 // TODO: Verify which page is displayed on even fields.
398 assert(!isFastBlinkEnabled());
399 return (((~controlRegs[9] & 4) << 6) | ((statusReg2 & 2) << 7)) &
400 (!blinkState << 8);
401 }
402
409 [[nodiscard]] inline int getEvenOddMask(int line) const {
410 if (isFastBlinkEnabled()) {
411 // EO and IL not considered in this mode
412 auto p = calculateLineBlinkState(line);
413 return (!p.state) << 8;
414 } else {
415 return getEvenOddMask();
416 }
417 }
418
424 bool state;
425 int count;
426 };
427 [[nodiscard]] BlinkStateCount calculateLineBlinkState(unsigned line) const {
428 assert(isFastBlinkEnabled());
429
430 if (blinkCount == 0) { // not changing
431 return {blinkState, blinkCount};
432 }
433
434 unsigned evenLen = ((controlRegs[13] >> 4) & 0x0F) * 10;
435 unsigned oddLen = ((controlRegs[13] >> 0) & 0x0F) * 10;
436 unsigned totalLen = evenLen + oddLen;
437 assert(totalLen != 0); // because this implies 'blinkCount == 0'
438 line %= totalLen; // reduce double flips
439
440 bool resultState = blinkState; // initial guess, adjusted later
441 if (blinkState) {
442 // We start in the 'even' period -> check first for
443 // even/odd transition, next for odd/even
444 } else {
445 // We start in the 'odd' period -> do the opposite
446 std::swap(evenLen, oddLen);
447 }
448 int newCount = blinkCount - line;
449 if (newCount <= 0) {
450 // switch even->odd (or odd->even)
451 resultState = !resultState;
452 newCount += oddLen;
453 if (newCount <= 0) {
454 // switch odd->even (or even->odd)
455 resultState = !resultState;
456 newCount += evenLen;
457 assert(newCount > 0);
458 }
459 }
460 return {resultState, newCount};
461 }
462
466 [[nodiscard]] inline int getTicksThisFrame(EmuTime::param time) const {
467 return frameStartTime.getTicksTill_fast(time);
468 }
469
470 [[nodiscard]] inline EmuTime::param getFrameStartTime() const {
471 return frameStartTime.getTime();
472 }
473
476 [[nodiscard]] inline int getSpriteSize() const {
477 return ((controlRegs[1] & 2) << 2) + 8;
478 }
479
482 [[nodiscard]] inline bool isSpriteMag() const {
483 return controlRegs[1] & 1;
484 }
485
489 [[nodiscard]] inline bool getCmdBit() const {
490 return (controlRegs[25] & 0x40) != 0;
491 }
492
495 [[nodiscard]] inline int getLinesPerFrame() const {
496 return palTiming ? 313 : 262;
497 }
498
501 [[nodiscard]] inline int getTicksPerFrame() const {
503 }
504
514 [[nodiscard]] inline bool isInsideFrame(EmuTime::param time) const {
515 return time >= frameStartTime.getTime() &&
517 }
518
522 [[nodiscard]] inline int getHorizontalAdjust() const {
523 return horizontalAdjust;
524 }
525
533 [[nodiscard]] inline int getLeftSprites() const {
534 return 100 + 102 + 56
535 + (horizontalAdjust - 7) * 4
536 + (displayMode.isTextMode() ? 36 : 0);
537 }
538
544 [[nodiscard]] inline int getLeftBorder() const {
545 return getLeftSprites() + (isBorderMasked() ? 8 * 4 : 0);
546 }
547
551 [[nodiscard]] inline int getRightBorder() const {
552 return getLeftSprites()
553 + (displayMode.isTextMode() ? 960 : 1024);
554 }
555
561 [[nodiscard]] inline int getLeftBackground() const {
562 return getLeftSprites() + getHorizontalScrollLow() * 4;
563 }
564
568 [[nodiscard]] byte getStatusReg0() const { return statusReg0; }
569
578 void setSpriteStatus(byte value)
579 {
580 statusReg0 = (statusReg0 & 0x80) | (value & 0x7F);
581 }
582
586 [[nodiscard]] bool getVRMode() const {
587 return (controlRegs[8] & 8) != 0;
588 }
589
592 void setExternalVideoSource(const RawFrame* externalSource) {
593 externalVideo = externalSource;
594 }
595
598 [[nodiscard]] bool getBrokenCmdTiming() const {
599 return brokenCmdTiming;
600 }
601
604 [[nodiscard]] EmuTime getAccessSlot(EmuTime::param time, VDPAccessSlots::Delta delta) const;
605
616 EmuTime::param time, EmuTime::param limit) const;
617
635 void scheduleCmdSync(EmuTime t) {
636 auto now = getCurrentTime();
637 if (t <= now) {
638 // The largest amount of VDP cycles between 'progress'
639 // in command emulation:
640 // - worst case the LMMM takes 120+64 cycles to fully process one pixel
641 // - the largest gap between access slots is 70 cycles
642 // - but if we're unlucky the CPU steals that slot
643 int LARGEST_STALL = 184 + 2 * 70;
644
645 t = now + VDPClock::duration(LARGEST_STALL);
646 }
647 syncCmdDone.setSyncPoint(t);
648 }
649
650 template<typename Archive>
651 void serialize(Archive& ar, unsigned version);
652
653private:
654 void initTables();
655
656 // VdpVersion bitmasks
657 static constexpr unsigned VM_MSX1 = 1; // set-> MSX1, unset-> MSX2 or MSX2+
658 static constexpr unsigned VM_PAL = 2; // set-> fixed PAL, unset-> fixed NTSC or switchable
659 static constexpr unsigned VM_NO_MIRRORING = 4; // set-> no (screen2) mirroring
660 static constexpr unsigned VM_PALCOL_MIRRORING = 8; // set-> pattern/color-table mirroring
661 static constexpr unsigned VM_VRAM_REMAPPING = 16; // set-> 4k,8/16k VRAM remapping
662 static constexpr unsigned VM_TOSHIBA_PALETTE = 32; // set-> has Toshiba palette
663 static constexpr unsigned VM_YJK = 64; // set-> has YJK (MSX2+)
664 static constexpr unsigned VM_YM2220_PALETTE = 128; // set-> has YM2220 palette
665
667 enum VdpVersion {
672 TMS99X8A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING,
673
675 TMS9929A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING | VM_PAL,
676
678 TMS9129 = VM_MSX1 | VM_PAL,
679
681 TMS91X8 = VM_MSX1,
682
684 T6950PAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING | VM_PAL,
685
687 T6950NTSC = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING,
688
690 T7937APAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_PAL,
691
693 T7937ANTSC = VM_MSX1 | VM_TOSHIBA_PALETTE,
694
696 YM2220PAL = VM_MSX1 | VM_YM2220_PALETTE | VM_PALCOL_MIRRORING | VM_PAL,
697
699 YM2220NTSC = VM_MSX1 | VM_YM2220_PALETTE | VM_PALCOL_MIRRORING,
700
702 V9938 = 0,
703
705 V9958 = VM_YJK,
706 };
707
708 struct SyncBase : public Schedulable {
709 explicit SyncBase(VDP& vdp_) : Schedulable(vdp_.getScheduler()) {}
713 protected:
714 ~SyncBase() = default;
715 };
716
717 struct SyncVSync final : public SyncBase {
718 explicit SyncVSync(VDP& vdp) : SyncBase(vdp) {}
719 void executeUntil(EmuTime::param time) override {
720 auto& vdp = OUTER(VDP, syncVSync);
721 vdp.execVSync(time);
722 }
723 } syncVSync;
724
725 struct SyncDisplayStart final : public SyncBase {
726 explicit SyncDisplayStart(VDP& vdp) : SyncBase(vdp) {}
727 void executeUntil(EmuTime::param time) override {
728 auto& vdp = OUTER(VDP, syncDisplayStart);
729 vdp.execDisplayStart(time);
730 }
731 } syncDisplayStart;
732
733 struct SyncVScan final : public SyncBase {
734 explicit SyncVScan(VDP& vdp) : SyncBase(vdp) {}
735 void executeUntil(EmuTime::param time) override {
736 auto& vdp = OUTER(VDP, syncVScan);
737 vdp.execVScan(time);
738 }
739 } syncVScan;
740
741 struct SyncHScan final : public SyncBase {
742 explicit SyncHScan(VDP& vdp) : SyncBase(vdp) {}
743 void executeUntil(EmuTime::param /*time*/) override {
744 auto& vdp = OUTER(VDP, syncHScan);
745 vdp.execHScan();
746 }
747 } syncHScan;
748
749 struct SyncHorAdjust final : public SyncBase {
750 explicit SyncHorAdjust(VDP& vdp) : SyncBase(vdp) {}
751 void executeUntil(EmuTime::param time) override {
752 auto& vdp = OUTER(VDP, syncHorAdjust);
753 vdp.execHorAdjust(time);
754 }
755 } syncHorAdjust;
756
757 struct SyncSetMode final : public SyncBase {
758 explicit SyncSetMode(VDP& vdp) : SyncBase(vdp) {}
759 void executeUntil(EmuTime::param time) override {
760 auto& vdp = OUTER(VDP, syncSetMode);
761 vdp.execSetMode(time);
762 }
763 } syncSetMode;
764
765 struct SyncSetBlank final : public SyncBase {
766 explicit SyncSetBlank(VDP& vdp) : SyncBase(vdp) {}
767 void executeUntil(EmuTime::param time) override {
768 auto& vdp = OUTER(VDP, syncSetBlank);
769 vdp.execSetBlank(time);
770 }
771 } syncSetBlank;
772
773 struct SyncSetSprites final : public SyncBase {
774 explicit SyncSetSprites(VDP& vdp) : SyncBase(vdp) {}
775 void executeUntil(EmuTime::param time) override {
776 auto& vdp = OUTER(VDP, syncSetSprites);
777 vdp.execSetSprites(time);
778 }
779 } syncSetSprites;
780
781 struct SyncCpuVramAccess final : public SyncBase {
782 explicit SyncCpuVramAccess(VDP& vdp) : SyncBase(vdp) {}
783 void executeUntil(EmuTime::param time) override {
784 auto& vdp = OUTER(VDP, syncCpuVramAccess);
785 vdp.execCpuVramAccess(time);
786 }
787 } syncCpuVramAccess;
788
789 struct SyncCmdDone final : public SyncBase {
790 explicit SyncCmdDone(VDP& vdp) : SyncBase(vdp) {}
791 void executeUntil(EmuTime::param time) override {
792 auto& vdp = OUTER(VDP, syncCmdDone);
793 vdp.execSyncCmdDone(time);
794 }
795 } syncCmdDone;
796
797 void execVSync(EmuTime::param time);
798 void execDisplayStart(EmuTime::param time);
799 void execVScan(EmuTime::param time);
800 void execHScan();
801 void execHorAdjust(EmuTime::param time);
802 void execSetMode(EmuTime::param time);
803 void execSetBlank(EmuTime::param time);
804 void execSetSprites(EmuTime::param time);
805 void execCpuVramAccess(EmuTime::param time);
806 void execSyncCmdDone(EmuTime::param time);
807
811 [[nodiscard]] inline int getNumberOfLines() const {
812 return controlRegs[9] & 0x80 ? 212 : 192;
813 }
814
818 [[nodiscard]] int getVerticalAdjust() const {
819 return (controlRegs[18] >> 4) ^ 0x07;
820 }
821
831 [[nodiscard]] inline bool getHR(int ticksThisFrame) const {
832 // Note: These constants are located inside this function because
833 // GCC 4.0.x won't link if they are in the class scope.
837 static constexpr int HBLANK_LEN_TXT = 404;
841 static constexpr int HBLANK_LEN_GFX = 312;
842 return (ticksThisFrame + TICKS_PER_LINE - getRightBorder()) % TICKS_PER_LINE
843 < (displayMode.isTextMode() ? HBLANK_LEN_TXT : HBLANK_LEN_GFX);
844 }
845
846 // VideoSystemChangeListener interface:
847 void preVideoSystemChange() noexcept override;
848 void postVideoSystemChange() noexcept override;
849
854 void resetInit();
855
860 void resetMasks(EmuTime::param time);
861
865 void frameStart(EmuTime::param time);
866
874 void scheduleDisplayStart(EmuTime::param time);
875
881 void scheduleVScan(EmuTime::param time);
882
888 void scheduleHScan(EmuTime::param time);
889
892 void vramWrite(byte value, EmuTime::param time);
893
896 [[nodiscard]] byte vramRead(EmuTime::param time);
897
899 void scheduleCpuVramAccess(bool isRead, byte write, EmuTime::param time);
900 void executeCpuVramAccess(EmuTime::param time);
901
904 [[nodiscard]] byte peekStatusReg(byte reg, EmuTime::param time) const;
905 [[nodiscard]] byte readStatusReg(byte reg, EmuTime::param time);
906
909 void changeRegister(byte reg, byte val, EmuTime::param time);
910
913 void syncAtNextLine(SyncBase& type, EmuTime::param time);
914
917 void createRenderer();
918
922 void updateNameBase(EmuTime::param time);
923
927 void updateColorBase(EmuTime::param time);
928
932 void updatePatternBase(EmuTime::param time);
933
937 void updateSpriteAttributeBase(EmuTime::param time);
938
942 void updateSpritePatternBase(EmuTime::param time);
943
947 void updateDisplayMode(DisplayMode newMode, bool cmdBit, EmuTime::param time);
948
955 void setPalette(int index, word grb, EmuTime::param time);
956
957 // Observer<Setting>
958 void update(const Setting& setting) noexcept override;
959
960private:
961 Display& display;
962 EnumSetting<bool>& cmdTiming;
963 EnumSetting<bool>& tooFastAccess;
964
965 struct RegDebug final : SimpleDebuggable {
966 explicit RegDebug(VDP& vdp);
967 [[nodiscard]] byte read(unsigned address) override;
968 void write(unsigned address, byte value, EmuTime::param time) override;
969 } vdpRegDebug;
970
971 struct StatusRegDebug final : SimpleDebuggable {
972 explicit StatusRegDebug(VDP& vdp);
973 [[nodiscard]] byte read(unsigned address, EmuTime::param time) override;
974 } vdpStatusRegDebug;
975
976 struct PaletteDebug final : SimpleDebuggable {
977 explicit PaletteDebug(VDP& vdp);
978 [[nodiscard]] byte read(unsigned address) override;
979 void write(unsigned address, byte value, EmuTime::param time) override;
980 } vdpPaletteDebug;
981
982 struct VRAMPointerDebug final : SimpleDebuggable {
983 explicit VRAMPointerDebug(VDP& vdp);
984 [[nodiscard]] byte read(unsigned address) override;
985 void write(unsigned address, byte value, EmuTime::param time) override;
986 } vramPointerDebug;
987
988 class Info : public InfoTopic {
989 public:
990 void execute(std::span<const TclObject> tokens,
991 TclObject& result) const override;
992 [[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
993 [[nodiscard]] virtual int calc(const EmuTime& time) const = 0;
994 protected:
995 Info(VDP& vdp_, const std::string& name, std::string helpText_);
996 ~Info() = default;
997 VDP& vdp;
998 const std::string helpText;
999 };
1000
1001 struct FrameCountInfo final : Info {
1002 explicit FrameCountInfo(VDP& vdp);
1003 [[nodiscard]] int calc(const EmuTime& time) const override;
1004 } frameCountInfo;
1005
1006 struct CycleInFrameInfo final : Info {
1007 explicit CycleInFrameInfo(VDP& vdp);
1008 [[nodiscard]] int calc(const EmuTime& time) const override;
1009 } cycleInFrameInfo;
1010
1011 struct LineInFrameInfo final : Info {
1012 explicit LineInFrameInfo(VDP& vdp);
1013 [[nodiscard]] int calc(const EmuTime& time) const override;
1014 } lineInFrameInfo;
1015
1016 struct CycleInLineInfo final : Info {
1017 explicit CycleInLineInfo(VDP& vdp);
1018 [[nodiscard]] int calc(const EmuTime& time) const override;
1019 } cycleInLineInfo;
1020
1021 struct MsxYPosInfo final : Info {
1022 explicit MsxYPosInfo(VDP& vdp);
1023 [[nodiscard]] int calc(const EmuTime& time) const override;
1024 } msxYPosInfo;
1025
1026 struct MsxX256PosInfo final : Info {
1027 explicit MsxX256PosInfo(VDP& vdp);
1028 [[nodiscard]] int calc(const EmuTime& time) const override;
1029 } msxX256PosInfo;
1030
1031 struct MsxX512PosInfo final : Info {
1032 explicit MsxX512PosInfo(VDP& vdp);
1033 [[nodiscard]] int calc(const EmuTime& time) const override;
1034 } msxX512PosInfo;
1035
1038 std::unique_ptr<Renderer> renderer;
1039
1042 std::unique_ptr<VDPCmdEngine> cmdEngine;
1043
1046 std::unique_ptr<SpriteChecker> spriteChecker;
1047
1050 std::unique_ptr<VDPVRAM> vram;
1051
1055 const RawFrame* externalVideo;
1056
1062 const RawFrame* superimposing;
1063
1066 VDPClock frameStartTime;
1067
1070 OptionalIRQHelper irqVertical;
1071
1074 OptionalIRQHelper irqHorizontal;
1075
1078 EmuTime displayStartSyncTime;
1079
1082 EmuTime vScanSyncTime;
1083
1086 EmuTime hScanSyncTime;
1087
1088 TclCallback tooFastCallback;
1089
1092 VdpVersion version;
1093
1098 int saturationPr;
1099
1104 int saturationPb;
1105
1111 int frameCount;
1112
1115 int displayStart;
1116
1120 int horizontalScanOffset;
1121
1125 int horizontalAdjust;
1126
1129 byte controlRegs[32];
1130
1135 int controlRegMask;
1136
1143 byte controlValueMasks[32];
1144
1148 int blinkCount;
1149
1153 int vramPointer;
1154
1157 word palette[16];
1158
1161 bool isDisplayArea;
1162
1168 bool palTiming;
1169
1173 bool interlaced;
1174
1179 byte statusReg0;
1180
1186 byte statusReg1;
1187
1192 byte statusReg2;
1193
1196 bool blinkState;
1197
1200 byte dataLatch;
1201
1204 bool registerDataStored;
1205
1208 bool paletteDataStored;
1209
1217 byte cpuVramData;
1218
1222 bool cpuVramReqIsRead;
1223 bool pendingCpuAccess; // always equal to pendingSyncPoint(CPU_VRAM_ACCESS)
1224
1228 bool cpuExtendedVram;
1229
1235 DisplayMode displayMode;
1236
1241 bool displayEnabled;
1242
1248 bool spriteEnabled;
1249
1253 bool warningPrinted;
1254
1256 bool brokenCmdTiming;
1257 bool allowTooFastAccess;
1258
1260 MSXCPU& cpu;
1261 const byte fixedVDPIOdelayCycles;
1262};
1264
1265} // namespace openmsx
1266
1267#endif
BaseSetting * setting
Definition: Interpreter.cc:27
TclObject t
static constexpr EmuDuration duration(unsigned ticks)
Calculates the duration of the given number of ticks at this clock's frequency.
Definition: Clock.hh:35
constexpr 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
constexpr EmuTime::param getTime() const
Gets the time at which the last clock tick occurred.
Definition: Clock.hh:46
Represents a VDP display mode.
Definition: DisplayMode.hh:16
constexpr bool isTextMode() const
Is the current mode a text mode? Text1 and Text2 are text modes.
Definition: DisplayMode.hh:122
constexpr byte getByte() const
Get the display mode as a byte: YAE YJK M5..M1 combined.
Definition: DisplayMode.hh:93
constexpr int getSpriteMode(bool isMSX1) const
Get the sprite mode of this display mode.
Definition: DisplayMode.hh:158
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:33
Scheduler & getScheduler() const
Definition: MSXDevice.cc:138
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:126
Generic Gang-of-Four Observer class, templatized edition.
Definition: Observer.hh:10
Abstract base class for post processors.
A video frame as output by the VDP scanline conversion unit, before any postprocessing filters are ap...
Definition: RawFrame.hh:15
void setSyncPoint(EmuTime::param timestamp)
Definition: Schedulable.cc:23
bool pendingSyncPoint() const
Definition: Schedulable.cc:38
virtual byte read(unsigned address, EmuTime::param time)
byte read(unsigned address) override
void write(unsigned address, byte value) override
VDP-VRAM access slot calculator, meant to be used in the inner loops of the VDPCmdEngine commands.
Manages VRAM contents and synchronizes the various users of the VRAM.
Definition: VDPVRAM.hh:386
Unified implementation of MSX Video Display Processors (VDPs).
Definition: VDP.hh:63
int getHorizontalAdjust() const
This is a combination of the (horizontal) set adjust register and the YJK-mode bit.
Definition: VDP.hh:522
bool getEvenOdd() const
Is the even or odd field being displayed?
Definition: VDP.hh:381
word getPalette(int index) const
Gets a palette entry.
Definition: VDP.hh:239
int getLinesPerFrame() const
Gets the number of lines per frame.
Definition: VDP.hh:495
int getEvenOddMask(int line) const
Similar to the above getEvenOddMask() method, but can also be called when 'isFastBlinkEnabled() == tr...
Definition: VDP.hh:409
int getEvenOddMask() const
Expresses the state of even/odd page interchange in a mask on the line number.
Definition: VDP.hh:396
bool spritesEnabled() const
Are sprites enabled?
Definition: VDP.hh:256
int getSpriteSize() const
Gets the sprite size in pixels (8/16).
Definition: VDP.hh:476
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:561
SpriteChecker & getSpriteChecker()
Get the sprite checker for this VDP.
Definition: VDP.hh:167
int getBackgroundColor() const
Gets the current background color.
Definition: VDP.hh:204
bool getBrokenCmdTiming() const
Value of the cmdTiming setting, true means commands have infinite speed.
Definition: VDP.hh:598
bool isEvenOddEnabled() const
Get even/odd page alternation status.
Definition: VDP.hh:373
void writeIO(word port, byte value, EmuTime::param time) override
Write a byte to a given IO port at a certain time to this device.
Definition: VDP.cc:649
void scheduleCmdSync(EmuTime t)
Only used when there are commandExecuting-probe listeners.
Definition: VDP.hh:635
bool spritesEnabledRegister() const
Still faster variant (just looks at the sprite-enabled-bit).
Definition: VDP.hh:273
BlinkStateCount calculateLineBlinkState(unsigned line) const
Definition: VDP.hh:427
static constexpr int TICKS_PER_SECOND
Number of VDP clock ticks per second.
Definition: VDP.hh:67
VDPVRAM & getVRAM()
Get the VRAM object for this VDP.
Definition: VDP.hh:147
bool isFastBlinkEnabled() const
Get 'fast-blink' status.
Definition: VDP.hh:358
std::array< std::array< uint8_t, 3 >, 16 > getMSX1Palette() const
Get the (fixed) palette for this MSX1 VDP.
Definition: VDP.cc:1523
PostProcessor * getPostProcessor() const
Used by Video9000 to be able to couple the VDP and V9990 output.
Definition: VDP.cc:240
bool isVDPwithPALonly() const
Is this a VDP only capable of PAL?
Definition: VDP.hh:100
const RawFrame * isSuperimposing() const
Are we currently superimposing? In case of superimpose, returns a pointer to the to-be-superimposed f...
Definition: VDP.hh:155
bool getCmdBit() const
Are commands possible in non Graphic modes? (V9958 only)
Definition: VDP.hh:489
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:872
void reset(EmuTime::param time) override
This method is called on reset.
Definition: VDP.cc:317
bool isBorderMasked() const
Gets the current border mask setting.
Definition: VDP.hh:307
byte getStatusReg0() const
Should only be used by SpriteChecker.
Definition: VDP.hh:568
bool spritesEnabledFast() const
Same as spritesEnabled(), but may only be called in sprite mode 1 or 2.
Definition: VDP.hh:265
int getForegroundColor() const
Gets the current foreground color.
Definition: VDP.hh:192
static constexpr int TICKS_PER_LINE
Number of VDP clock ticks per line.
Definition: VDP.hh:72
int getBlinkBackgroundColor() const
Gets the current blinking color for blinking text.
Definition: VDP.hh:223
int getTicksPerFrame() const
Gets the number of VDP clockticks (21MHz) per frame.
Definition: VDP.hh:501
bool isInsideFrame(EmuTime::param time) const
Is the given timestamp inside the current frame? Mainly useful for debugging, because relevant timest...
Definition: VDP.hh:514
void serialize(Archive &ar, unsigned version)
Definition: VDP.cc:1835
void setSpriteStatus(byte value)
Should only be used by SpriteChecker.
Definition: VDP.hh:578
Clock< TICKS_PER_SECOND > VDPClock
Definition: VDP.hh:68
byte getHorizontalScrollHigh() const
Gets the current horizontal scroll higher bits.
Definition: VDP.hh:298
int getRightBorder() const
Gets the number of VDP clockticks between start of line and the start of the right border.
Definition: VDP.hh:551
DisplayMode getDisplayMode() const
Get the display mode the VDP is in.
Definition: VDP.hh:141
~VDP() override
Definition: VDP.cc:214
bool getBlinkState() const
Gets the current blink state.
Definition: VDP.hh:230
int getLineZero() const
Get the absolute line number of display line zero.
Definition: VDP.hh:325
int getBlinkForegroundColor() const
Gets the current blinking color for blinking text.
Definition: VDP.hh:216
void setExternalVideoSource(const RawFrame *externalSource)
Enable superimposing.
Definition: VDP.hh:592
bool isMSX1VDP() const
Is this an MSX1 VDP?
Definition: VDP.hh:93
byte getVerticalScroll() const
Gets the current vertical scroll (line displayed at Y=0).
Definition: VDP.hh:280
bool isVDPwithVRAMremapping() const
Does this VDP have VRAM remapping when switching from 4k to 8/16k mode?
Definition: VDP.hh:121
bool hasYJK() const
Does this VDP support YJK display?
Definition: VDP.hh:128
EmuTime::param getFrameStartTime() const
Definition: VDP.hh:470
bool canSpriteColor0Collide() const
Can a sprite which has color=0 collide with some other sprite?
Definition: VDP.hh:180
bool isMultiPageScrolling() const
Is multi page scrolling enabled? It is considered enabled if both the multi page scrolling flag is en...
Definition: VDP.hh:317
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: VDP.cc:981
int getLeftBorder() const
Gets the number of VDP clockticks between start of line and the end of the left border.
Definition: VDP.hh:544
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:866
bool isSpriteMag() const
Are sprites magnified?
Definition: VDP.hh:482
bool vdpHasPatColMirroring() const
Is this a VDP that has pattern/colortable mirroring?
Definition: VDP.hh:114
bool isPalTiming() const
Is PAL timing active? This setting is fixed at start of frame.
Definition: VDP.hh:333
bool isInterlaced() const
Get interlace status.
Definition: VDP.hh:344
bool getTransparency() const
Gets the current transparency setting.
Definition: VDP.hh:174
bool getVRMode() const
Returns current VR mode.
Definition: VDP.hh:586
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: VDP.cc:961
bool isDisplayEnabled() const
Is the display enabled? Both the regular border and forced blanking by clearing the display enable bi...
Definition: VDP.hh:248
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:466
bool vdpLacksMirroring() const
Is this a VDP that lacks mirroring?
Definition: VDP.hh:107
byte getHorizontalScrollLow() const
Gets the current horizontal scroll lower bits.
Definition: VDP.hh:289
VDP(const DeviceConfig &config)
Definition: VDP.cc:61
void powerUp(EmuTime::param time) override
This method is called when MSX is powered up.
Definition: VDP.cc:311
int getLeftSprites() const
Gets the number of VDP clockticks between start of line and the start of the sprite plane.
Definition: VDP.hh:533
This file implemented 3 utility functions:
Definition: Autofire.cc:9
IntHelper< OptionalIRQ > OptionalIRQHelper
Definition: IRQHelper.hh:123
AmdFlash::SectorInfo Info
Definition: RomManbow2.cc:17
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)
void swap(openmsx::MemBuffer< T > &l, openmsx::MemBuffer< T > &r) noexcept
Definition: MemBuffer.hh:202
#define OUTER(type, member)
Definition: outer.hh:41
Calculates what 'blinkState' and 'blinkCount' would be at a specific line.
Definition: VDP.hh:423