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 "openmsx.hh"
15
16#include "Observer.hh"
17#include "narrow.hh"
18#include "outer.hh"
19
20#include <memory>
21#include <array>
22
23namespace openmsx {
24
25class PostProcessor;
26class Renderer;
27class VDPCmdEngine;
28class VDPVRAM;
29class MSXCPU;
30class SpriteChecker;
31class Display;
32class RawFrame;
33class Setting;
34namespace VDPAccessSlots {
35 enum Delta : int;
36 class Calculator;
37}
38
64class VDP final : public MSXDevice, private VideoSystemChangeListener
65 , private Observer<Setting>
66{
67public:
70 static constexpr int TICKS_PER_SECOND = 3579545 * 6; // 21.5MHz;
72
75 static constexpr int TICKS_PER_LINE = 1368;
76
77 explicit VDP(const DeviceConfig& config);
78 ~VDP() override;
79
80 void powerUp(EmuTime::param time) override;
81 void reset(EmuTime::param time) override;
82 [[nodiscard]] byte readIO(word port, EmuTime::param time) override;
83 [[nodiscard]] byte peekIO(word port, EmuTime::param time) const override;
84 void writeIO(word port, byte value, EmuTime::param time) override;
85
86 void getExtraDeviceInfo(TclObject& result) const override;
87 [[nodiscard]] std::string_view getVersionString() const;
88
89 [[nodiscard]] byte peekRegister(unsigned address) const;
90 [[nodiscard]] byte peekStatusReg(byte reg, EmuTime::param time) const;
91
94 void changeRegister(byte reg, byte val, EmuTime::param time);
95
96
101 [[nodiscard]] PostProcessor* getPostProcessor() const;
102
107 [[nodiscard]] inline bool isMSX1VDP() const {
108 return (version & VM_MSX1) != 0;
109 }
110
114 [[nodiscard]] inline bool isVDPwithPALonly() const {
115 return (version & VM_PAL) != 0;
116 }
117
121 [[nodiscard]] inline bool vdpLacksMirroring() const {
122 return (version & VM_NO_MIRRORING) != 0;
123 }
124
128 [[nodiscard]] inline bool vdpHasPatColMirroring() const {
129 return (version & VM_PALCOL_MIRRORING) != 0;
130 }
131
135 [[nodiscard]] inline bool isVDPwithVRAMremapping() const {
136 return (version & VM_VRAM_REMAPPING) != 0;
137 }
138
142 [[nodiscard]] inline bool hasYJK() const {
143 return (version & VM_YJK) != 0;
144 }
145
150 [[nodiscard]] std::array<std::array<uint8_t, 3>, 16> getMSX1Palette() const;
151
155 [[nodiscard]] inline DisplayMode getDisplayMode() const {
156 return displayMode;
157 }
158
161 [[nodiscard]] inline VDPVRAM& getVRAM() {
162 return *vram;
163 }
164
169 [[nodiscard]] inline const RawFrame* isSuperimposing() const {
170 // Note that bit 0 of r#0 has no effect on an V9938 or higher,
171 // but this bit is masked out. Also note that on an MSX1, if
172 // bit 0 of r#0 is enabled and there is no external video
173 // source, then we lose sync.
174 // Also note that because this property is fixed per frame we
175 // cannot (re)calculate it from register values.
176 return superimposing;
177 }
178
181 [[nodiscard]] inline SpriteChecker& getSpriteChecker() {
182 return *spriteChecker;
183 }
184
188 [[nodiscard]] inline bool getTransparency() const {
189 return (controlRegs[8] & 0x20) == 0;
190 }
191
194 [[nodiscard]] bool canSpriteColor0Collide() const {
195 // On MSX1 (so far only tested a TMS9129(?)) sprites with
196 // color=0 can always collide with other sprites. Though on
197 // V99x8 (only tested V9958) collisions only occur when color 0
198 // is not transparent. For more details see:
199 // https://github.com/openMSX/openMSX/issues/1198
200 return isMSX1VDP() || !getTransparency();
201 }
202
206 [[nodiscard]] inline int getForegroundColor() const {
207 return controlRegs[7] >> 4;
208 }
209
218 [[nodiscard]] inline byte getBackgroundColor() const {
219 byte reg7 = controlRegs[7];
220 if (displayMode.getByte() == DisplayMode::GRAPHIC7) {
221 return reg7;
222 } else {
223 return reg7 & 0x0F;
224 }
225 }
226
230 [[nodiscard]] inline int getBlinkForegroundColor() const {
231 return controlRegs[12] >> 4;
232 }
233
237 [[nodiscard]] inline int getBlinkBackgroundColor() const {
238 return controlRegs[12] & 0x0F;
239 }
240
244 [[nodiscard]] inline bool getBlinkState() const {
245 return blinkState;
246 }
247
249 [[nodiscard]] int getPatternTableBase() const {
250 return controlRegs[4] << 11;
251 }
253 [[nodiscard]] int getColorTableBase() const {
254 return (controlRegs[10] << 14) | (controlRegs[3] << 6);
255 }
257 [[nodiscard]] int getNameTableBase() const {
258 return controlRegs[2] << 10;
259 }
261 [[nodiscard]] int getSpritePatternTableBase() const {
262 return controlRegs[6] << 11;
263 }
265 [[nodiscard]] int getSpriteAttributeTableBase() const {
266 return (controlRegs[11] << 15) | (controlRegs[5] << 7);
267 }
269 [[nodiscard]] int getVramPointer() const {
270 return vramPointer;
271 }
272
278 [[nodiscard]] inline uint16_t getPalette(unsigned index) const {
279 return palette[index];
280 }
281 [[nodiscard]] inline std::span<const uint16_t, 16> getPalette() const {
282 return palette;
283 }
284
291 void setPalette(unsigned index, word grb, EmuTime::param time);
292
298 [[nodiscard]] inline bool isDisplayEnabled() const {
299 return isDisplayArea && displayEnabled;
300 }
301
306 [[nodiscard]] inline bool spritesEnabled() const {
307 return displayEnabled &&
308 (displayMode.getSpriteMode(isMSX1VDP()) != 0) &&
309 spriteEnabled;
310 }
311
315 [[nodiscard]] inline bool spritesEnabledFast() const {
316 assert(displayMode.getSpriteMode(isMSX1VDP()) != 0);
317 return displayEnabled && spriteEnabled;
318 }
319
323 [[nodiscard]] inline bool spritesEnabledRegister() const {
324 return spriteEnabled;
325 }
326
330 [[nodiscard]] inline byte getVerticalScroll() const {
331 return controlRegs[23];
332 }
333
339 [[nodiscard]] inline byte getHorizontalScrollLow() const {
340 return controlRegs[27];
341 }
342
348 [[nodiscard]] inline byte getHorizontalScrollHigh() const {
349 return controlRegs[26];
350 }
351
357 [[nodiscard]] inline bool isBorderMasked() const {
358 return (controlRegs[25] & 0x02) != 0;
359 }
360
367 [[nodiscard]] inline bool isMultiPageScrolling() const {
368 return (controlRegs[25] & 0x01) && (controlRegs[2] & 0x20);
369 }
370
374 [[nodiscard]] int getDisplayPage() const {
375 return (controlRegs[2] >> 5) & 3;
376 }
377
382 [[nodiscard]] inline int getLineZero() const {
383 return displayStart / TICKS_PER_LINE;
384 }
385
390 [[nodiscard]] inline bool isPalTiming() const {
391 return palTiming;
392 }
393
401 [[nodiscard]] inline bool isInterlaced() const {
402 return interlaced;
403 }
404
415 [[nodiscard]] inline bool isFastBlinkEnabled() const {
416 return (controlRegs[1] & 4) != 0;
417 }
418
430 [[nodiscard]] inline bool isEvenOddEnabled() const {
431 if (isFastBlinkEnabled()) return false;
432 return (controlRegs[9] & 4) != 0;
433 }
434
438 [[nodiscard]] inline bool getEvenOdd() const {
439 return (statusReg2 & 2) != 0;
440 }
441
453 [[nodiscard]] inline unsigned getEvenOddMask() const {
454 // TODO: Verify which page is displayed on even fields.
455 assert(!isFastBlinkEnabled());
456 return (((~controlRegs[9] & 4) << 6) | ((statusReg2 & 2) << 7)) &
457 (!blinkState << 8);
458 }
459
466 [[nodiscard]] inline unsigned getEvenOddMask(int line) const {
467 if (isFastBlinkEnabled()) {
468 // EO and IL not considered in this mode
469 auto p = calculateLineBlinkState(line);
470 return (!p.state) << 8;
471 } else {
472 return getEvenOddMask();
473 }
474 }
475
481 bool state;
482 int count;
483 };
484 [[nodiscard]] BlinkStateCount calculateLineBlinkState(unsigned line) const {
485 assert(isFastBlinkEnabled());
486
487 if (blinkCount == 0) { // not changing
488 return {blinkState, blinkCount};
489 }
490
491 unsigned evenLen = ((controlRegs[13] >> 4) & 0x0F) * 10;
492 unsigned oddLen = ((controlRegs[13] >> 0) & 0x0F) * 10;
493 unsigned totalLen = evenLen + oddLen;
494 assert(totalLen != 0); // because this implies 'blinkCount == 0'
495 line %= totalLen; // reduce double flips
496
497 bool resultState = blinkState; // initial guess, adjusted later
498 if (blinkState) {
499 // We start in the 'even' period -> check first for
500 // even/odd transition, next for odd/even
501 } else {
502 // We start in the 'odd' period -> do the opposite
503 std::swap(evenLen, oddLen);
504 }
505 int newCount = blinkCount - narrow<int>(line);
506 if (newCount <= 0) {
507 // switch even->odd (or odd->even)
508 resultState = !resultState;
509 newCount += narrow<int>(oddLen);
510 if (newCount <= 0) {
511 // switch odd->even (or even->odd)
512 resultState = !resultState;
513 newCount += narrow<int>(evenLen);
514 assert(newCount > 0);
515 }
516 }
517 return {resultState, newCount};
518 }
519
523 [[nodiscard]] inline int getTicksThisFrame(EmuTime::param time) const {
524 return narrow<int>(frameStartTime.getTicksTill_fast(time));
525 }
526
527 [[nodiscard]] inline EmuTime::param getFrameStartTime() const {
528 return frameStartTime.getTime();
529 }
530
533 [[nodiscard]] inline int getSpriteSize() const {
534 return ((controlRegs[1] & 2) << 2) + 8;
535 }
536
539 [[nodiscard]] inline bool isSpriteMag() const {
540 return controlRegs[1] & 1;
541 }
542
546 [[nodiscard]] inline bool getCmdBit() const {
547 return (controlRegs[25] & 0x40) != 0;
548 }
549
552 [[nodiscard]] inline int getLinesPerFrame() const {
553 return palTiming ? 313 : 262;
554 }
555
559 [[nodiscard]] inline int getNumberOfLines() const {
560 return controlRegs[9] & 0x80 ? 212 : 192;
561 }
562
565 [[nodiscard]] inline int getTicksPerFrame() const {
567 }
568
578 [[nodiscard]] inline bool isInsideFrame(EmuTime::param time) const {
579 return time >= frameStartTime.getTime() &&
581 }
582
586 [[nodiscard]] inline int getHorizontalAdjust() const {
587 return horizontalAdjust;
588 }
589
597 [[nodiscard]] inline int getLeftSprites() const {
598 return 100 + 102 + 56
599 + (horizontalAdjust - 7) * 4
600 + (displayMode.isTextMode() ? 36 : 0);
601 }
602
608 [[nodiscard]] inline int getLeftBorder() const {
609 return getLeftSprites() + (isBorderMasked() ? 8 * 4 : 0);
610 }
611
615 [[nodiscard]] inline int getRightBorder() const {
616 return getLeftSprites()
617 + (displayMode.isTextMode() ? 960 : 1024);
618 }
619
625 [[nodiscard]] inline int getLeftBackground() const {
626 return getLeftSprites() + getHorizontalScrollLow() * 4;
627 }
628
632 [[nodiscard]] byte getStatusReg0() const { return statusReg0; }
633
642 void setSpriteStatus(byte value)
643 {
644 statusReg0 = (statusReg0 & 0x80) | (value & 0x7F);
645 }
646
650 [[nodiscard]] bool getVRMode() const {
651 return (controlRegs[8] & 8) != 0;
652 }
653
656 void setExternalVideoSource(const RawFrame* externalSource) {
657 externalVideo = externalSource;
658 }
659
662 [[nodiscard]] bool getBrokenCmdTiming() const {
663 return brokenCmdTiming;
664 }
665
668 [[nodiscard]] EmuTime getAccessSlot(EmuTime::param time, VDPAccessSlots::Delta delta) const;
669
680 EmuTime::param time, EmuTime::param limit) const;
681
699 void scheduleCmdSync(EmuTime t) {
700 if (auto now = getCurrentTime(); t <= now) {
701 // The largest amount of VDP cycles between 'progress'
702 // in command emulation:
703 // - worst case the LMMM takes 120+64 cycles to fully process one pixel
704 // - the largest gap between access slots is 70 cycles
705 // - but if we're unlucky the CPU steals that slot
706 int LARGEST_STALL = 184 + 2 * 70;
707
708 t = now + VDPClock::duration(LARGEST_STALL);
709 }
710 syncCmdDone.setSyncPoint(t);
711 }
712
713 template<typename Archive>
714 void serialize(Archive& ar, unsigned version);
715
716private:
717 void initTables();
718
719 // VdpVersion bitmasks
720 static constexpr unsigned VM_MSX1 = 1; // set-> MSX1, unset-> MSX2 or MSX2+
721 static constexpr unsigned VM_PAL = 2; // set-> fixed PAL, unset-> fixed NTSC or switchable
722 static constexpr unsigned VM_NO_MIRRORING = 4; // set-> no (screen2) mirroring
723 static constexpr unsigned VM_PALCOL_MIRRORING = 8; // set-> pattern/color-table mirroring
724 static constexpr unsigned VM_VRAM_REMAPPING = 16; // set-> 4k,8/16k VRAM remapping
725 static constexpr unsigned VM_TOSHIBA_PALETTE = 32; // set-> has Toshiba palette
726 static constexpr unsigned VM_YJK = 64; // set-> has YJK (MSX2+)
727 static constexpr unsigned VM_YM2220_PALETTE = 128; // set-> has YM2220 palette
728
730 enum VdpVersion {
735 TMS99X8A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING,
736
738 TMS9929A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING | VM_PAL,
739
741 TMS9129 = VM_MSX1 | VM_PAL,
742
744 TMS91X8 = VM_MSX1,
745
747 T6950PAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING | VM_PAL,
748
750 T6950NTSC = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING,
751
753 T7937APAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_PAL,
754
756 T7937ANTSC = VM_MSX1 | VM_TOSHIBA_PALETTE,
757
759 YM2220PAL = VM_MSX1 | VM_YM2220_PALETTE | VM_PALCOL_MIRRORING | VM_PAL,
760
762 YM2220NTSC = VM_MSX1 | VM_YM2220_PALETTE | VM_PALCOL_MIRRORING,
763
765 V9938 = 0,
766
768 V9958 = VM_YJK,
769 };
770
771 struct SyncBase : public Schedulable {
772 explicit SyncBase(VDP& vdp_) : Schedulable(vdp_.getScheduler()) {}
776 protected:
777 ~SyncBase() = default;
778 };
779
780 struct SyncVSync final : public SyncBase {
781 using SyncBase::SyncBase;
782 void executeUntil(EmuTime::param time) override {
783 auto& vdp = OUTER(VDP, syncVSync);
784 vdp.execVSync(time);
785 }
786 } syncVSync;
787
788 struct SyncDisplayStart final : public SyncBase {
789 using SyncBase::SyncBase;
790 void executeUntil(EmuTime::param time) override {
791 auto& vdp = OUTER(VDP, syncDisplayStart);
792 vdp.execDisplayStart(time);
793 }
794 } syncDisplayStart;
795
796 struct SyncVScan final : public SyncBase {
797 using SyncBase::SyncBase;
798 void executeUntil(EmuTime::param time) override {
799 auto& vdp = OUTER(VDP, syncVScan);
800 vdp.execVScan(time);
801 }
802 } syncVScan;
803
804 struct SyncHScan final : public SyncBase {
805 using SyncBase::SyncBase;
806 void executeUntil(EmuTime::param /*time*/) override {
807 auto& vdp = OUTER(VDP, syncHScan);
808 vdp.execHScan();
809 }
810 } syncHScan;
811
812 struct SyncHorAdjust final : public SyncBase {
813 using SyncBase::SyncBase;
814 void executeUntil(EmuTime::param time) override {
815 auto& vdp = OUTER(VDP, syncHorAdjust);
816 vdp.execHorAdjust(time);
817 }
818 } syncHorAdjust;
819
820 struct SyncSetMode final : public SyncBase {
821 using SyncBase::SyncBase;
822 void executeUntil(EmuTime::param time) override {
823 auto& vdp = OUTER(VDP, syncSetMode);
824 vdp.execSetMode(time);
825 }
826 } syncSetMode;
827
828 struct SyncSetBlank final : public SyncBase {
829 using SyncBase::SyncBase;
830 void executeUntil(EmuTime::param time) override {
831 auto& vdp = OUTER(VDP, syncSetBlank);
832 vdp.execSetBlank(time);
833 }
834 } syncSetBlank;
835
836 struct SyncSetSprites final : public SyncBase {
837 using SyncBase::SyncBase;
838 void executeUntil(EmuTime::param time) override {
839 auto& vdp = OUTER(VDP, syncSetSprites);
840 vdp.execSetSprites(time);
841 }
842 } syncSetSprites;
843
844 struct SyncCpuVramAccess final : public SyncBase {
845 using SyncBase::SyncBase;
846 void executeUntil(EmuTime::param time) override {
847 auto& vdp = OUTER(VDP, syncCpuVramAccess);
848 vdp.execCpuVramAccess(time);
849 }
850 } syncCpuVramAccess;
851
852 struct SyncCmdDone final : public SyncBase {
853 using SyncBase::SyncBase;
854 void executeUntil(EmuTime::param time) override {
855 auto& vdp = OUTER(VDP, syncCmdDone);
856 vdp.execSyncCmdDone(time);
857 }
858 } syncCmdDone;
859
860 void execVSync(EmuTime::param time);
861 void execDisplayStart(EmuTime::param time);
862 void execVScan(EmuTime::param time);
863 void execHScan();
864 void execHorAdjust(EmuTime::param time);
865 void execSetMode(EmuTime::param time);
866 void execSetBlank(EmuTime::param time);
867 void execSetSprites(EmuTime::param time);
868 void execCpuVramAccess(EmuTime::param time);
869 void execSyncCmdDone(EmuTime::param time);
870
874 [[nodiscard]] int getVerticalAdjust() const {
875 return (controlRegs[18] >> 4) ^ 0x07;
876 }
877
887 [[nodiscard]] inline bool getHR(int ticksThisFrame) const {
888 // Note: These constants are located inside this function because
889 // GCC 4.0.x won't link if they are in the class scope.
893 static constexpr int HBLANK_LEN_TXT = 404;
897 static constexpr int HBLANK_LEN_GFX = 312;
898 return (ticksThisFrame + TICKS_PER_LINE - getRightBorder()) % TICKS_PER_LINE
899 < (displayMode.isTextMode() ? HBLANK_LEN_TXT : HBLANK_LEN_GFX);
900 }
901
902 // VideoSystemChangeListener interface:
903 void preVideoSystemChange() noexcept override;
904 void postVideoSystemChange() noexcept override;
905
910 void resetInit();
911
916 void resetMasks(EmuTime::param time);
917
921 void frameStart(EmuTime::param time);
922
930 void scheduleDisplayStart(EmuTime::param time);
931
937 void scheduleVScan(EmuTime::param time);
938
944 void scheduleHScan(EmuTime::param time);
945
948 void vramWrite(byte value, EmuTime::param time);
949
952 [[nodiscard]] byte vramRead(EmuTime::param time);
953
955 void scheduleCpuVramAccess(bool isRead, byte write, EmuTime::param time);
956 void executeCpuVramAccess(EmuTime::param time);
957
960 [[nodiscard]] byte readStatusReg(byte reg, EmuTime::param time);
961
964 void syncAtNextLine(SyncBase& type, EmuTime::param time) const;
965
968 void createRenderer();
969
973 void updateNameBase(EmuTime::param time);
974
978 void updateColorBase(EmuTime::param time);
979
983 void updatePatternBase(EmuTime::param time);
984
988 void updateSpriteAttributeBase(EmuTime::param time);
989
993 void updateSpritePatternBase(EmuTime::param time);
994
998 void updateDisplayMode(DisplayMode newMode, bool cmdBit, EmuTime::param time);
999
1000 // Observer<Setting>
1001 void update(const Setting& setting) noexcept override;
1002
1003private:
1004 Display& display;
1005 EnumSetting<bool>& cmdTiming;
1006 EnumSetting<bool>& tooFastAccess;
1007
1008 struct RegDebug final : SimpleDebuggable {
1009 explicit RegDebug(VDP& vdp);
1010 [[nodiscard]] byte read(unsigned address) override;
1011 void write(unsigned address, byte value, EmuTime::param time) override;
1012 } vdpRegDebug;
1013
1014 struct StatusRegDebug final : SimpleDebuggable {
1015 explicit StatusRegDebug(VDP& vdp);
1016 [[nodiscard]] byte read(unsigned address, EmuTime::param time) override;
1017 } vdpStatusRegDebug;
1018
1019 struct PaletteDebug final : SimpleDebuggable {
1020 explicit PaletteDebug(VDP& vdp);
1021 [[nodiscard]] byte read(unsigned address) override;
1022 void write(unsigned address, byte value, EmuTime::param time) override;
1023 } vdpPaletteDebug;
1024
1025 struct VRAMPointerDebug final : SimpleDebuggable {
1026 explicit VRAMPointerDebug(VDP& vdp);
1027 [[nodiscard]] byte read(unsigned address) override;
1028 void write(unsigned address, byte value, EmuTime::param time) override;
1029 } vramPointerDebug;
1030
1031 struct RegisterLatchStatusDebug final : SimpleDebuggable {
1032 explicit RegisterLatchStatusDebug(VDP& vdp);
1033 [[nodiscard]] byte read(unsigned address) override;
1034 } registerLatchStatusDebug;
1035
1036 struct VramAccessStatusDebug final : SimpleDebuggable {
1037 explicit VramAccessStatusDebug(VDP& vdp);
1038 [[nodiscard]] byte read(unsigned address) override;
1039 } vramAccessStatusDebug;
1040
1041 struct PaletteLatchStatusDebug final : SimpleDebuggable {
1042 explicit PaletteLatchStatusDebug(VDP& vdp);
1043 [[nodiscard]] byte read(unsigned address) override;
1044 } paletteLatchStatusDebug;
1045
1046 struct DataLatchDebug final : SimpleDebuggable {
1047 explicit DataLatchDebug(VDP& vdp);
1048 [[nodiscard]] byte read(unsigned address) override;
1049 } dataLatchDebug;
1050
1051 class Info : public InfoTopic {
1052 public:
1053 void execute(std::span<const TclObject> tokens,
1054 TclObject& result) const override;
1055 [[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
1056 [[nodiscard]] virtual int calc(const EmuTime& time) const = 0;
1057 protected:
1058 Info(VDP& vdp_, const std::string& name, std::string helpText_);
1059 ~Info() = default;
1060 VDP& vdp;
1061 const std::string helpText;
1062 };
1063
1064 struct FrameCountInfo final : Info {
1065 explicit FrameCountInfo(VDP& vdp);
1066 [[nodiscard]] int calc(const EmuTime& time) const override;
1067 } frameCountInfo;
1068
1069 struct CycleInFrameInfo final : Info {
1070 explicit CycleInFrameInfo(VDP& vdp);
1071 [[nodiscard]] int calc(const EmuTime& time) const override;
1072 } cycleInFrameInfo;
1073
1074 struct LineInFrameInfo final : Info {
1075 explicit LineInFrameInfo(VDP& vdp);
1076 [[nodiscard]] int calc(const EmuTime& time) const override;
1077 } lineInFrameInfo;
1078
1079 struct CycleInLineInfo final : Info {
1080 explicit CycleInLineInfo(VDP& vdp);
1081 [[nodiscard]] int calc(const EmuTime& time) const override;
1082 } cycleInLineInfo;
1083
1084 struct MsxYPosInfo final : Info {
1085 explicit MsxYPosInfo(VDP& vdp);
1086 [[nodiscard]] int calc(const EmuTime& time) const override;
1087 } msxYPosInfo;
1088
1089 struct MsxX256PosInfo final : Info {
1090 explicit MsxX256PosInfo(VDP& vdp);
1091 [[nodiscard]] int calc(const EmuTime& time) const override;
1092 } msxX256PosInfo;
1093
1094 struct MsxX512PosInfo final : Info {
1095 explicit MsxX512PosInfo(VDP& vdp);
1096 [[nodiscard]] int calc(const EmuTime& time) const override;
1097 } msxX512PosInfo;
1098
1101 std::unique_ptr<Renderer> renderer;
1102
1105 std::unique_ptr<VDPCmdEngine> cmdEngine;
1106
1109 std::unique_ptr<SpriteChecker> spriteChecker;
1110
1113 std::unique_ptr<VDPVRAM> vram;
1114
1118 const RawFrame* externalVideo;
1119
1125 const RawFrame* superimposing;
1126
1129 VDPClock frameStartTime;
1130
1133 OptionalIRQHelper irqVertical;
1134
1137 OptionalIRQHelper irqHorizontal;
1138
1141 EmuTime displayStartSyncTime;
1142
1145 EmuTime vScanSyncTime;
1146
1149 EmuTime hScanSyncTime;
1150
1151 TclCallback tooFastCallback;
1152
1155 VdpVersion version;
1156
1161 int saturationPr;
1162
1167 int saturationPb;
1168
1174 int frameCount;
1175
1178 int displayStart;
1179
1183 int horizontalScanOffset;
1184
1188 int horizontalAdjust;
1189
1192 std::array<byte, 32> controlRegs;
1193
1198 byte controlRegMask;
1199
1206 std::array<byte, 32> controlValueMasks;
1207
1211 int blinkCount;
1212
1216 int vramPointer;
1217
1220 std::array<uint16_t, 16> palette;
1221
1224 bool isDisplayArea;
1225
1231 bool palTiming;
1232
1236 bool interlaced = false;
1237
1242 byte statusReg0;
1243
1249 byte statusReg1;
1250
1255 byte statusReg2;
1256
1259 bool blinkState;
1260
1263 byte dataLatch;
1264
1271 bool writeAccess;
1272
1275 bool registerDataStored;
1276
1279 bool paletteDataStored;
1280
1288 byte cpuVramData;
1289
1293 bool cpuVramReqIsRead;
1294 bool pendingCpuAccess; // always equal to pendingSyncPoint(CPU_VRAM_ACCESS)
1295
1299 bool cpuExtendedVram;
1300
1306 DisplayMode displayMode;
1307
1312 bool displayEnabled;
1313
1319 bool spriteEnabled;
1320
1324 bool warningPrinted = false;
1325
1327 bool brokenCmdTiming;
1328 bool allowTooFastAccess;
1329
1331 MSXCPU& cpu;
1332 const byte fixedVDPIOdelayCycles;
1333};
1335
1336} // namespace openmsx
1337
1338#endif
BaseSetting * setting
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.
constexpr bool isTextMode() const
Is the current mode a text mode? Text1 and Text2 are text modes.
constexpr byte getByte() const
Get the display mode as a byte: YAE YJK M5..M1 combined.
constexpr int getSpriteMode(bool isMSX1) const
Get the sprite mode of this display mode.
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition MSXDevice.hh:36
EmuTime::param getCurrentTime() const
Definition MSXDevice.cc:125
Generic Gang-of-Four Observer class, templatized edition.
Definition Observer.hh:10
A post processor builds the frame that is displayed from the MSX frame, while applying effects such a...
A video frame as output by the VDP scanline conversion unit, before any postprocessing filters are ap...
Definition RawFrame.hh:17
void setSyncPoint(EmuTime::param timestamp)
bool pendingSyncPoint() const
Scheduler & getScheduler() const
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:397
Unified implementation of MSX Video Display Processors (VDPs).
Definition VDP.hh:66
int getHorizontalAdjust() const
This is a combination of the (horizontal) set adjust register and the YJK-mode bit.
Definition VDP.hh:586
bool getEvenOdd() const
Is the even or odd field being displayed?
Definition VDP.hh:438
int getLinesPerFrame() const
Gets the number of lines per frame.
Definition VDP.hh:552
int getNumberOfLines() const
Gets the number of display lines per screen.
Definition VDP.hh:559
unsigned getEvenOddMask() const
Expresses the state of even/odd page interchange in a mask on the line number.
Definition VDP.hh:453
bool spritesEnabled() const
Are sprites enabled?
Definition VDP.hh:306
int getSpriteSize() const
Gets the sprite size in pixels (8/16).
Definition VDP.hh:533
int getLeftBackground() const
Gets the number of VDP clock ticks between start of line and the time when the background pixel with ...
Definition VDP.hh:625
SpriteChecker & getSpriteChecker()
Get the sprite checker for this VDP.
Definition VDP.hh:181
bool getBrokenCmdTiming() const
Value of the cmdTiming setting, true means commands have infinite speed.
Definition VDP.hh:662
int getNameTableBase() const
Get address of name table (only for debugger)
Definition VDP.hh:257
bool isEvenOddEnabled() const
Get even/odd page alternation status.
Definition VDP.hh:430
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:651
void changeRegister(byte reg, byte val, EmuTime::param time)
VDP control register has changed, work out the consequences.
Definition VDP.cc:1017
void scheduleCmdSync(EmuTime t)
Only used when there are commandExecuting-probe listeners.
Definition VDP.hh:699
byte peekRegister(unsigned address) const
Definition VDP.cc:757
bool spritesEnabledRegister() const
Still faster variant (just looks at the sprite-enabled-bit).
Definition VDP.hh:323
BlinkStateCount calculateLineBlinkState(unsigned line) const
Definition VDP.hh:484
static constexpr int TICKS_PER_SECOND
Number of VDP clock ticks per second.
Definition VDP.hh:70
VDPVRAM & getVRAM()
Get the VRAM object for this VDP.
Definition VDP.hh:161
bool isFastBlinkEnabled() const
Get 'fast-blink' status.
Definition VDP.hh:415
std::array< std::array< uint8_t, 3 >, 16 > getMSX1Palette() const
Get the (fixed) palette for this MSX1 VDP.
Definition VDP.cc:1553
PostProcessor * getPostProcessor() const
Used by Video9000 to be able to couple the VDP and V9990 output.
Definition VDP.cc:241
int getSpritePatternTableBase() const
Get address of pattern table (only for debugger)
Definition VDP.hh:261
bool isVDPwithPALonly() const
Is this a VDP only capable of PAL?
Definition VDP.hh:114
const RawFrame * isSuperimposing() const
Are we currently superimposing? In case of superimpose, returns a pointer to the to-be-superimposed f...
Definition VDP.hh:169
int getVramPointer() const
Get vram pointer (14-bit) (only for debugger)
Definition VDP.hh:269
void getExtraDeviceInfo(TclObject &result) const override
Definition VDP.cc:752
bool getCmdBit() const
Are commands possible in non Graphic modes? (V9958 only)
Definition VDP.hh:546
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:902
void reset(EmuTime::param time) override
This method is called on reset.
Definition VDP.cc:319
void setPalette(unsigned index, word grb, EmuTime::param time)
Sets a palette entry.
Definition VDP.cc:768
bool isBorderMasked() const
Gets the current border mask setting.
Definition VDP.hh:357
byte getStatusReg0() const
Should only be used by SpriteChecker.
Definition VDP.hh:632
bool spritesEnabledFast() const
Same as spritesEnabled(), but may only be called in sprite mode 1 or 2.
Definition VDP.hh:315
int getForegroundColor() const
Gets the current foreground color.
Definition VDP.hh:206
static constexpr int TICKS_PER_LINE
Number of VDP clock ticks per line.
Definition VDP.hh:75
int getBlinkBackgroundColor() const
Gets the current blinking color for blinking text.
Definition VDP.hh:237
int getTicksPerFrame() const
Gets the number of VDP clock ticks (21MHz) per frame.
Definition VDP.hh:565
bool isInsideFrame(EmuTime::param time) const
Is the given timestamp inside the current frame? Mainly useful for debugging, because relevant timest...
Definition VDP.hh:578
void serialize(Archive &ar, unsigned version)
Definition VDP.cc:1917
unsigned getEvenOddMask(int line) const
Similar to the above getEvenOddMask() method, but can also be called when 'isFastBlinkEnabled() == tr...
Definition VDP.hh:466
void setSpriteStatus(byte value)
Should only be used by SpriteChecker.
Definition VDP.hh:642
Clock< TICKS_PER_SECOND > VDPClock
Definition VDP.hh:71
uint16_t getPalette(unsigned index) const
Gets a palette entry.
Definition VDP.hh:278
byte getHorizontalScrollHigh() const
Gets the current horizontal scroll higher bits.
Definition VDP.hh:348
int getRightBorder() const
Gets the number of VDP clock ticks between start of line and the start of the right border.
Definition VDP.hh:615
DisplayMode getDisplayMode() const
Get the display mode the VDP is in.
Definition VDP.hh:155
int getPatternTableBase() const
Get address of pattern table (only for debugger)
Definition VDP.hh:249
int getDisplayPage() const
Only used by debugger.
Definition VDP.hh:374
~VDP() override
Definition VDP.cc:215
bool getBlinkState() const
Gets the current blink state.
Definition VDP.hh:244
int getColorTableBase() const
Get address of color table (only for debugger)
Definition VDP.hh:253
int getLineZero() const
Get the absolute line number of display line zero.
Definition VDP.hh:382
int getBlinkForegroundColor() const
Gets the current blinking color for blinking text.
Definition VDP.hh:230
void setExternalVideoSource(const RawFrame *externalSource)
Enable superimposing.
Definition VDP.hh:656
bool isMSX1VDP() const
Is this an MSX1 VDP?
Definition VDP.hh:107
byte getBackgroundColor() const
Gets the current background color.
Definition VDP.hh:218
byte getVerticalScroll() const
Gets the current vertical scroll (line displayed at Y=0).
Definition VDP.hh:330
bool isVDPwithVRAMremapping() const
Does this VDP have VRAM remapping when switching from 4k to 8/16k mode?
Definition VDP.hh:135
bool hasYJK() const
Does this VDP support YJK display?
Definition VDP.hh:142
EmuTime::param getFrameStartTime() const
Definition VDP.hh:527
bool canSpriteColor0Collide() const
Can a sprite which has color=0 collide with some other sprite?
Definition VDP.hh:194
bool isMultiPageScrolling() const
Is multi page scrolling enabled? It is considered enabled if both the multi page scrolling flag is en...
Definition VDP.hh:367
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition VDP.cc:1011
int getLeftBorder() const
Gets the number of VDP clock ticks between start of line and the end of the left border.
Definition VDP.hh:608
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:896
bool isSpriteMag() const
Are sprites magnified?
Definition VDP.hh:539
bool vdpHasPatColMirroring() const
Is this a VDP that has pattern/color table mirroring?
Definition VDP.hh:128
bool isPalTiming() const
Is PAL timing active? This setting is fixed at start of frame.
Definition VDP.hh:390
bool isInterlaced() const
Get interlace status.
Definition VDP.hh:401
bool getTransparency() const
Gets the current transparency setting.
Definition VDP.hh:188
int getSpriteAttributeTableBase() const
Get address of color table (only for debugger)
Definition VDP.hh:265
bool getVRMode() const
Returns current VR mode.
Definition VDP.hh:650
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:991
std::string_view getVersionString() const
Definition VDP.cc:741
bool isDisplayEnabled() const
Is the display enabled? Both the regular border and forced blanking by clearing the display enable bi...
Definition VDP.hh:298
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:523
bool vdpLacksMirroring() const
Is this a VDP that lacks mirroring?
Definition VDP.hh:121
byte getHorizontalScrollLow() const
Gets the current horizontal scroll lower bits.
Definition VDP.hh:339
byte peekStatusReg(byte reg, EmuTime::param time) const
Definition VDP.cc:909
void powerUp(EmuTime::param time) override
This method is called when MSX is powered up.
Definition VDP.cc:313
int getLeftSprites() const
Gets the number of VDP clock ticks between start of line and the start of the sprite plane.
Definition VDP.hh:597
std::span< const uint16_t, 16 > getPalette() const
Definition VDP.hh:281
This file implemented 3 utility functions:
Definition Autofire.cc:11
IntHelper< OptionalIRQ > OptionalIRQHelper
Definition IRQHelper.hh:123
AmdFlash::SectorInfo Info
Definition RomManbow2.cc:18
uint16_t word
16 bit unsigned integer
Definition openmsx.hh:29
#define OUTER(type, member)
Definition outer.hh:42
#define SERIALIZE_CLASS_VERSION(CLASS, VERSION)
Calculates what 'blinkState' and 'blinkCount' would be at a specific line.
Definition VDP.hh:480