32namespace VDPAccessSlots {
78 void powerUp(EmuTime::param time)
override;
79 void reset(EmuTime::param time)
override;
80 [[nodiscard]]
byte readIO(
word port, EmuTime::param time)
override;
81 [[nodiscard]]
byte peekIO(
word port, EmuTime::param time)
const override;
82 void writeIO(
word port,
byte value, EmuTime::param time)
override;
97 return (version & VM_MSX1) != 0;
104 return (version & VM_PAL) != 0;
111 return (version & VM_NO_MIRRORING) != 0;
118 return (version & VM_PALCOL_MIRRORING) != 0;
125 return (version & VM_VRAM_REMAPPING) != 0;
131 [[nodiscard]]
inline bool hasYJK()
const {
132 return (version & VM_YJK) != 0;
139 [[nodiscard]] std::array<std::array<uint8_t, 3>, 16>
getMSX1Palette()
const;
165 return superimposing;
171 return *spriteChecker;
178 return (controlRegs[8] & 0x20) == 0;
196 return controlRegs[7] >> 4;
208 byte reg7 = controlRegs[7];
220 return controlRegs[12] >> 4;
227 return controlRegs[12] & 0x0F;
243 return palette[index];
252 return isDisplayArea && displayEnabled;
260 return displayEnabled &&
270 return displayEnabled && spriteEnabled;
277 return spriteEnabled;
284 return controlRegs[23];
293 return controlRegs[27];
302 return controlRegs[26];
311 return (controlRegs[25] & 0x02) != 0;
321 return (controlRegs[25] & 0x01) && (controlRegs[2] & 0x20);
362 return (controlRegs[1] & 4) != 0;
378 return (controlRegs[9] & 4) != 0;
385 return (statusReg2 & 2) != 0;
402 return (((~controlRegs[9] & 4) << 6) | ((statusReg2 & 2) << 7)) &
416 return (!p.state) << 8;
433 if (blinkCount == 0) {
434 return {blinkState, blinkCount};
437 unsigned evenLen = ((controlRegs[13] >> 4) & 0x0F) * 10;
438 unsigned oddLen = ((controlRegs[13] >> 0) & 0x0F) * 10;
439 unsigned totalLen = evenLen + oddLen;
440 assert(totalLen != 0);
443 bool resultState = blinkState;
451 int newCount = blinkCount - narrow<int>(line);
454 resultState = !resultState;
455 newCount += narrow<int>(oddLen);
458 resultState = !resultState;
459 newCount += narrow<int>(evenLen);
460 assert(newCount > 0);
463 return {resultState, newCount};
474 return frameStartTime.
getTime();
480 return ((controlRegs[1] & 2) << 2) + 8;
486 return controlRegs[1] & 1;
493 return (controlRegs[25] & 0x40) != 0;
499 return palTiming ? 313 : 262;
518 return time >= frameStartTime.
getTime() &&
526 return horizontalAdjust;
537 return 100 + 102 + 56
538 + (horizontalAdjust - 7) * 4
583 statusReg0 = (statusReg0 & 0x80) | (value & 0x7F);
590 return (controlRegs[8] & 8) != 0;
596 externalVideo = externalSource;
602 return brokenCmdTiming;
619 EmuTime::param time, EmuTime::param limit)
const;
646 int LARGEST_STALL = 184 + 2 * 70;
650 syncCmdDone.setSyncPoint(
t);
653 template<
typename Archive>
654 void serialize(Archive& ar,
unsigned version);
660 static constexpr unsigned VM_MSX1 = 1;
661 static constexpr unsigned VM_PAL = 2;
662 static constexpr unsigned VM_NO_MIRRORING = 4;
663 static constexpr unsigned VM_PALCOL_MIRRORING = 8;
664 static constexpr unsigned VM_VRAM_REMAPPING = 16;
665 static constexpr unsigned VM_TOSHIBA_PALETTE = 32;
666 static constexpr unsigned VM_YJK = 64;
667 static constexpr unsigned VM_YM2220_PALETTE = 128;
675 TMS99X8A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING,
678 TMS9929A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING | VM_PAL,
681 TMS9129 = VM_MSX1 | VM_PAL,
687 T6950PAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING | VM_PAL,
690 T6950NTSC = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING,
693 T7937APAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_PAL,
696 T7937ANTSC = VM_MSX1 | VM_TOSHIBA_PALETTE,
699 YM2220PAL = VM_MSX1 | VM_YM2220_PALETTE | VM_PALCOL_MIRRORING | VM_PAL,
702 YM2220NTSC = VM_MSX1 | VM_YM2220_PALETTE | VM_PALCOL_MIRRORING,
717 ~SyncBase() =
default;
720 struct SyncVSync final :
public SyncBase {
721 explicit SyncVSync(
VDP& vdp) : SyncBase(vdp) {}
722 void executeUntil(EmuTime::param time)
override {
728 struct SyncDisplayStart final :
public SyncBase {
729 explicit SyncDisplayStart(
VDP& vdp) : SyncBase(vdp) {}
730 void executeUntil(EmuTime::param time)
override {
731 auto& vdp =
OUTER(
VDP, syncDisplayStart);
732 vdp.execDisplayStart(time);
736 struct SyncVScan final :
public SyncBase {
737 explicit SyncVScan(
VDP& vdp) : SyncBase(vdp) {}
738 void executeUntil(EmuTime::param time)
override {
744 struct SyncHScan final :
public SyncBase {
745 explicit SyncHScan(
VDP& vdp) : SyncBase(vdp) {}
746 void executeUntil(EmuTime::param )
override {
752 struct SyncHorAdjust final :
public SyncBase {
753 explicit SyncHorAdjust(
VDP& vdp) : SyncBase(vdp) {}
754 void executeUntil(EmuTime::param time)
override {
755 auto& vdp =
OUTER(
VDP, syncHorAdjust);
756 vdp.execHorAdjust(time);
760 struct SyncSetMode final :
public SyncBase {
761 explicit SyncSetMode(
VDP& vdp) : SyncBase(vdp) {}
762 void executeUntil(EmuTime::param time)
override {
763 auto& vdp =
OUTER(
VDP, syncSetMode);
764 vdp.execSetMode(time);
768 struct SyncSetBlank final :
public SyncBase {
769 explicit SyncSetBlank(
VDP& vdp) : SyncBase(vdp) {}
770 void executeUntil(EmuTime::param time)
override {
771 auto& vdp =
OUTER(
VDP, syncSetBlank);
772 vdp.execSetBlank(time);
776 struct SyncSetSprites final :
public SyncBase {
777 explicit SyncSetSprites(
VDP& vdp) : SyncBase(vdp) {}
778 void executeUntil(EmuTime::param time)
override {
779 auto& vdp =
OUTER(
VDP, syncSetSprites);
780 vdp.execSetSprites(time);
784 struct SyncCpuVramAccess final :
public SyncBase {
785 explicit SyncCpuVramAccess(
VDP& vdp) : SyncBase(vdp) {}
786 void executeUntil(EmuTime::param time)
override {
787 auto& vdp =
OUTER(
VDP, syncCpuVramAccess);
788 vdp.execCpuVramAccess(time);
792 struct SyncCmdDone final :
public SyncBase {
793 explicit SyncCmdDone(
VDP& vdp) : SyncBase(vdp) {}
794 void executeUntil(EmuTime::param time)
override {
795 auto& vdp =
OUTER(
VDP, syncCmdDone);
796 vdp.execSyncCmdDone(time);
800 void execVSync(EmuTime::param time);
801 void execDisplayStart(EmuTime::param time);
802 void execVScan(EmuTime::param time);
804 void execHorAdjust(EmuTime::param time);
805 void execSetMode(EmuTime::param time);
806 void execSetBlank(EmuTime::param time);
807 void execSetSprites(EmuTime::param time);
808 void execCpuVramAccess(EmuTime::param time);
809 void execSyncCmdDone(EmuTime::param time);
814 [[nodiscard]]
inline int getNumberOfLines()
const {
815 return controlRegs[9] & 0x80 ? 212 : 192;
821 [[nodiscard]]
int getVerticalAdjust()
const {
822 return (controlRegs[18] >> 4) ^ 0x07;
834 [[nodiscard]]
inline bool getHR(
int ticksThisFrame)
const {
840 static constexpr int HBLANK_LEN_TXT = 404;
844 static constexpr int HBLANK_LEN_GFX = 312;
846 < (displayMode.
isTextMode() ? HBLANK_LEN_TXT : HBLANK_LEN_GFX);
850 void preVideoSystemChange() noexcept override;
851 void postVideoSystemChange() noexcept override;
863 void resetMasks(EmuTime::param time);
868 void frameStart(EmuTime::param time);
877 void scheduleDisplayStart(EmuTime::param time);
884 void scheduleVScan(EmuTime::param time);
891 void scheduleHScan(EmuTime::param time);
895 void vramWrite(
byte value, EmuTime::param time);
899 [[nodiscard]]
byte vramRead(EmuTime::param time);
902 void scheduleCpuVramAccess(
bool isRead,
byte write, EmuTime::param time);
903 void executeCpuVramAccess(EmuTime::param time);
907 [[nodiscard]]
byte peekStatusReg(
byte reg, EmuTime::param time) const;
908 [[nodiscard]]
byte readStatusReg(
byte reg, EmuTime::param time);
912 void changeRegister(
byte reg,
byte val, EmuTime::param time);
916 void syncAtNextLine(SyncBase& type, EmuTime::param time);
920 void createRenderer();
925 void updateNameBase(EmuTime::param time);
930 void updateColorBase(EmuTime::param time);
935 void updatePatternBase(EmuTime::param time);
940 void updateSpriteAttributeBase(EmuTime::param time);
945 void updateSpritePatternBase(EmuTime::param time);
950 void updateDisplayMode(DisplayMode newMode,
bool cmdBit, EmuTime::param time);
958 void setPalette(
unsigned index,
word grb, EmuTime::param time);
961 void update(const Setting&
setting) noexcept override;
965 EnumSetting<
bool>& cmdTiming;
966 EnumSetting<
bool>& tooFastAccess;
968 struct RegDebug final : SimpleDebuggable {
969 explicit RegDebug(
VDP& vdp);
970 [[nodiscard]]
byte read(
unsigned address)
override;
971 void write(
unsigned address,
byte value, EmuTime::param time)
override;
974 struct StatusRegDebug final : SimpleDebuggable {
975 explicit StatusRegDebug(
VDP& vdp);
976 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
979 struct PaletteDebug final : SimpleDebuggable {
980 explicit PaletteDebug(
VDP& vdp);
981 [[nodiscard]]
byte read(
unsigned address)
override;
982 void write(
unsigned address,
byte value, EmuTime::param time)
override;
985 struct VRAMPointerDebug final : SimpleDebuggable {
986 explicit VRAMPointerDebug(
VDP& vdp);
987 [[nodiscard]]
byte read(
unsigned address)
override;
988 void write(
unsigned address,
byte value, EmuTime::param time)
override;
991 struct RegisterLatchStatusDebug final : SimpleDebuggable {
992 explicit RegisterLatchStatusDebug(
VDP& vdp);
993 [[nodiscard]]
byte read(
unsigned address)
override;
994 } registerLatchStatusDebug;
996 struct VramAccessStatusDebug final : SimpleDebuggable {
997 explicit VramAccessStatusDebug(
VDP& vdp);
998 [[nodiscard]]
byte read(
unsigned address)
override;
999 } vramAccessStatusDebug;
1001 struct PaletteLatchStatusDebug final : SimpleDebuggable {
1002 explicit PaletteLatchStatusDebug(
VDP& vdp);
1003 [[nodiscard]]
byte read(
unsigned address)
override;
1004 } paletteLatchStatusDebug;
1006 struct DataLatchDebug final : SimpleDebuggable {
1007 explicit DataLatchDebug(
VDP& vdp);
1008 [[nodiscard]]
byte read(
unsigned address)
override;
1011 class Info :
public InfoTopic {
1013 void execute(std::span<const TclObject> tokens,
1014 TclObject& result)
const override;
1015 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
1016 [[nodiscard]]
virtual int calc(
const EmuTime& time)
const = 0;
1018 Info(
VDP& vdp_,
const std::string& name, std::string helpText_);
1021 const std::string helpText;
1024 struct FrameCountInfo final :
Info {
1025 explicit FrameCountInfo(
VDP& vdp);
1026 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1029 struct CycleInFrameInfo final :
Info {
1030 explicit CycleInFrameInfo(
VDP& vdp);
1031 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1034 struct LineInFrameInfo final :
Info {
1035 explicit LineInFrameInfo(
VDP& vdp);
1036 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1039 struct CycleInLineInfo final :
Info {
1040 explicit CycleInLineInfo(
VDP& vdp);
1041 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1044 struct MsxYPosInfo final :
Info {
1045 explicit MsxYPosInfo(
VDP& vdp);
1046 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1049 struct MsxX256PosInfo final :
Info {
1050 explicit MsxX256PosInfo(
VDP& vdp);
1051 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1054 struct MsxX512PosInfo final :
Info {
1055 explicit MsxX512PosInfo(
VDP& vdp);
1056 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1061 std::unique_ptr<Renderer> renderer;
1065 std::unique_ptr<VDPCmdEngine> cmdEngine;
1069 std::unique_ptr<SpriteChecker> spriteChecker;
1073 std::unique_ptr<VDPVRAM> vram;
1078 const RawFrame* externalVideo;
1085 const RawFrame* superimposing;
1101 EmuTime displayStartSyncTime;
1105 EmuTime vScanSyncTime;
1109 EmuTime hScanSyncTime;
1111 TclCallback tooFastCallback;
1143 int horizontalScanOffset;
1148 int horizontalAdjust;
1152 std::array<byte, 32> controlRegs;
1158 byte controlRegMask;
1166 std::array<byte, 32> controlValueMasks;
1180 std::array<uint16_t, 16> palette;
1196 bool interlaced =
false;
1235 bool registerDataStored;
1239 bool paletteDataStored;
1253 bool cpuVramReqIsRead;
1254 bool pendingCpuAccess;
1259 bool cpuExtendedVram;
1266 DisplayMode displayMode;
1272 bool displayEnabled;
1284 bool warningPrinted =
false;
1287 bool brokenCmdTiming;
1288 bool allowTooFastAccess;
1292 const byte fixedVDPIOdelayCycles;
static constexpr EmuDuration duration(unsigned ticks)
Calculates the duration of the given number of ticks at this clock's frequency.
constexpr unsigned getTicksTill_fast(EmuTime::param e) const
Same as above, only faster, Though the time interval may not be too large.
constexpr EmuTime::param getTime() const
Gets the time at which the last clock tick occurred.
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.
Scheduler & getScheduler() const
EmuTime::param getCurrentTime() const
Generic Gang-of-Four Observer class, templatized edition.
Abstract base class for post processors.
A video frame as output by the VDP scanline conversion unit, before any postprocessing filters are ap...
void setSyncPoint(EmuTime::param timestamp)
bool pendingSyncPoint() 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.
Unified implementation of MSX Video Display Processors (VDPs).
int getHorizontalAdjust() const
This is a combination of the (horizontal) set adjust register and the YJK-mode bit.
bool getEvenOdd() const
Is the even or odd field being displayed?
int getLinesPerFrame() const
Gets the number of lines per frame.
unsigned getEvenOddMask() const
Expresses the state of even/odd page interchange in a mask on the line number.
bool spritesEnabled() const
Are sprites enabled?
int getSpriteSize() const
Gets the sprite size in pixels (8/16).
int getLeftBackground() const
Gets the number of VDP clock ticks between start of line and the time when the background pixel with ...
SpriteChecker & getSpriteChecker()
Get the sprite checker for this VDP.
bool getBrokenCmdTiming() const
Value of the cmdTiming setting, true means commands have infinite speed.
bool isEvenOddEnabled() const
Get even/odd page alternation status.
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.
void scheduleCmdSync(EmuTime t)
Only used when there are commandExecuting-probe listeners.
bool spritesEnabledRegister() const
Still faster variant (just looks at the sprite-enabled-bit).
BlinkStateCount calculateLineBlinkState(unsigned line) const
static constexpr int TICKS_PER_SECOND
Number of VDP clock ticks per second.
VDPVRAM & getVRAM()
Get the VRAM object for this VDP.
bool isFastBlinkEnabled() const
Get 'fast-blink' status.
std::array< std::array< uint8_t, 3 >, 16 > getMSX1Palette() const
Get the (fixed) palette for this MSX1 VDP.
PostProcessor * getPostProcessor() const
Used by Video9000 to be able to couple the VDP and V9990 output.
bool isVDPwithPALonly() const
Is this a VDP only capable of PAL?
const RawFrame * isSuperimposing() const
Are we currently superimposing? In case of superimpose, returns a pointer to the to-be-superimposed f...
void getExtraDeviceInfo(TclObject &result) const override
bool getCmdBit() const
Are commands possible in non Graphic modes? (V9958 only)
VDPAccessSlots::Calculator getAccessSlotCalculator(EmuTime::param time, EmuTime::param limit) const
Same as getAccessSlot(), but it can be much faster for repeated calls, e.g.
void reset(EmuTime::param time) override
This method is called on reset.
bool isBorderMasked() const
Gets the current border mask setting.
byte getStatusReg0() const
Should only be used by SpriteChecker.
bool spritesEnabledFast() const
Same as spritesEnabled(), but may only be called in sprite mode 1 or 2.
int getForegroundColor() const
Gets the current foreground color.
static constexpr int TICKS_PER_LINE
Number of VDP clock ticks per line.
int getBlinkBackgroundColor() const
Gets the current blinking color for blinking text.
word getPalette(unsigned index) const
Gets a palette entry.
int getTicksPerFrame() const
Gets the number of VDP clock ticks (21MHz) per frame.
bool isInsideFrame(EmuTime::param time) const
Is the given timestamp inside the current frame? Mainly useful for debugging, because relevant timest...
void serialize(Archive &ar, unsigned version)
unsigned getEvenOddMask(int line) const
Similar to the above getEvenOddMask() method, but can also be called when 'isFastBlinkEnabled() == tr...
void setSpriteStatus(byte value)
Should only be used by SpriteChecker.
Clock< TICKS_PER_SECOND > VDPClock
byte getHorizontalScrollHigh() const
Gets the current horizontal scroll higher bits.
int getRightBorder() const
Gets the number of VDP clock ticks between start of line and the start of the right border.
DisplayMode getDisplayMode() const
Get the display mode the VDP is in.
bool getBlinkState() const
Gets the current blink state.
int getLineZero() const
Get the absolute line number of display line zero.
int getBlinkForegroundColor() const
Gets the current blinking color for blinking text.
void setExternalVideoSource(const RawFrame *externalSource)
Enable superimposing.
bool isMSX1VDP() const
Is this an MSX1 VDP?
byte getBackgroundColor() const
Gets the current background color.
byte getVerticalScroll() const
Gets the current vertical scroll (line displayed at Y=0).
bool isVDPwithVRAMremapping() const
Does this VDP have VRAM remapping when switching from 4k to 8/16k mode?
bool hasYJK() const
Does this VDP support YJK display?
EmuTime::param getFrameStartTime() const
bool canSpriteColor0Collide() const
Can a sprite which has color=0 collide with some other sprite?
bool isMultiPageScrolling() const
Is multi page scrolling enabled? It is considered enabled if both the multi page scrolling flag is en...
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
int getLeftBorder() const
Gets the number of VDP clock ticks between start of line and the end of the left border.
EmuTime getAccessSlot(EmuTime::param time, VDPAccessSlots::Delta delta) const
Get the earliest access slot that is at least 'delta' cycles in the future.
bool isSpriteMag() const
Are sprites magnified?
bool vdpHasPatColMirroring() const
Is this a VDP that has pattern/color table mirroring?
bool isPalTiming() const
Is PAL timing active? This setting is fixed at start of frame.
bool isInterlaced() const
Get interlace status.
bool getTransparency() const
Gets the current transparency setting.
bool getVRMode() const
Returns current VR mode.
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
bool isDisplayEnabled() const
Is the display enabled? Both the regular border and forced blanking by clearing the display enable bi...
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.
bool vdpLacksMirroring() const
Is this a VDP that lacks mirroring?
byte getHorizontalScrollLow() const
Gets the current horizontal scroll lower bits.
VDP(const DeviceConfig &config)
void powerUp(EmuTime::param time) override
This method is called when MSX is powered up.
int getLeftSprites() const
Gets the number of VDP clock ticks between start of line and the start of the sprite plane.
This file implemented 3 utility functions:
IntHelper< OptionalIRQ > OptionalIRQHelper
AmdFlash::SectorInfo Info
uint16_t word
16 bit unsigned integer
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)
void swap(openmsx::MemBuffer< T > &l, openmsx::MemBuffer< T > &r) noexcept
#define OUTER(type, member)
Calculates what 'blinkState' and 'blinkCount' would be at a specific line.