30 template<
typename>
class EnumSetting;
31 namespace VDPAccessSlots {
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;
94 return (version & VM_MSX1) != 0;
101 return (version & VM_PAL) != 0;
108 return (version & VM_NO_MIRRORING) != 0;
115 return (version & VM_PALCOL_MIRRORING) != 0;
122 return (version & VM_VRAM_REMAPPING) != 0;
128 [[nodiscard]]
inline bool hasYJK()
const {
129 return (version & VM_YJK) != 0;
136 [[nodiscard]] std::array<std::array<uint8_t, 3>, 16>
getMSX1Palette()
const;
162 return superimposing;
168 return *spriteChecker;
175 return (controlRegs[8] & 0x20) == 0;
193 return controlRegs[7] >> 4;
205 byte reg7 = controlRegs[7];
217 return controlRegs[12] >> 4;
224 return controlRegs[12] & 0x0F;
240 return palette[index];
249 return isDisplayArea && displayEnabled;
257 return displayEnabled &&
267 return displayEnabled && spriteEnabled;
274 return spriteEnabled;
281 return controlRegs[23];
290 return controlRegs[27];
299 return controlRegs[26];
308 return (controlRegs[25] & 0x02) != 0;
318 return (controlRegs[25] & 0x01) && (controlRegs[2] & 0x20);
359 return (controlRegs[1] & 4) != 0;
375 return (controlRegs[9] & 4) != 0;
382 return (statusReg2 & 2) != 0;
399 return (((~controlRegs[9] & 4) << 6) | ((statusReg2 & 2) << 7)) &
413 return (!p.first) << 8;
426 if (blinkCount == 0) {
427 return {blinkState, blinkCount};
430 unsigned evenLen = ((controlRegs[13] >> 4) & 0x0F) * 10;
431 unsigned oddLen = ((controlRegs[13] >> 0) & 0x0F) * 10;
432 unsigned totalLen = evenLen + oddLen;
433 assert(totalLen != 0);
436 bool resultState = blinkState;
442 std::swap(evenLen, oddLen);
444 int newCount = blinkCount - line;
447 resultState = !resultState;
451 resultState = !resultState;
453 assert(newCount > 0);
456 return {resultState, newCount};
467 return frameStartTime.
getTime();
473 return ((controlRegs[1] & 2) << 2) + 8;
479 return controlRegs[1] & 1;
486 return (controlRegs[25] & 0x40) != 0;
492 return palTiming ? 313 : 262;
511 return time >= frameStartTime.
getTime() &&
519 return horizontalAdjust;
530 return 100 + 102 + 56
531 + (horizontalAdjust - 7) * 4
576 statusReg0 = (statusReg0 & 0x80) | (value & 0x7F);
583 return (controlRegs[8] & 8) != 0;
589 externalVideo = externalSource;
595 return brokenCmdTiming;
612 EmuTime::param time, EmuTime::param limit)
const;
639 int LARGEST_STALL = 184 + 2 * 70;
643 syncCmdDone.setSyncPoint(
t);
646 template<
typename Archive>
647 void serialize(Archive& ar,
unsigned version);
653 static constexpr
unsigned VM_MSX1 = 1;
654 static constexpr
unsigned VM_PAL = 2;
655 static constexpr
unsigned VM_NO_MIRRORING = 4;
656 static constexpr
unsigned VM_PALCOL_MIRRORING = 8;
657 static constexpr
unsigned VM_VRAM_REMAPPING = 16;
658 static constexpr
unsigned VM_TOSHIBA_PALETTE = 32;
659 static constexpr
unsigned VM_YJK = 64;
660 static constexpr
unsigned VM_YM2220_PALETTE = 128;
668 TMS99X8A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING,
671 TMS9929A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING | VM_PAL,
674 TMS9129 = VM_MSX1 | VM_PAL,
680 T6950PAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING | VM_PAL,
683 T6950NTSC = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING,
686 T7937APAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_PAL,
689 T7937ANTSC = VM_MSX1 | VM_TOSHIBA_PALETTE,
692 YM2220PAL = VM_MSX1 | VM_YM2220_PALETTE | VM_PALCOL_MIRRORING | VM_PAL,
695 YM2220NTSC = VM_MSX1 | VM_YM2220_PALETTE | VM_PALCOL_MIRRORING,
710 ~SyncBase() =
default;
713 struct SyncVSync final :
public SyncBase {
714 explicit SyncVSync(
VDP& vdp) : SyncBase(vdp) {}
715 void executeUntil(EmuTime::param time)
override {
721 struct SyncDisplayStart final :
public SyncBase {
722 explicit SyncDisplayStart(
VDP& vdp) : SyncBase(vdp) {}
723 void executeUntil(EmuTime::param time)
override {
724 auto& vdp =
OUTER(
VDP, syncDisplayStart);
725 vdp.execDisplayStart(time);
729 struct SyncVScan final :
public SyncBase {
730 explicit SyncVScan(
VDP& vdp) : SyncBase(vdp) {}
731 void executeUntil(EmuTime::param time)
override {
737 struct SyncHScan final :
public SyncBase {
738 explicit SyncHScan(
VDP& vdp) : SyncBase(vdp) {}
739 void executeUntil(EmuTime::param )
override {
745 struct SyncHorAdjust final :
public SyncBase {
746 explicit SyncHorAdjust(
VDP& vdp) : SyncBase(vdp) {}
747 void executeUntil(EmuTime::param time)
override {
748 auto& vdp =
OUTER(
VDP, syncHorAdjust);
749 vdp.execHorAdjust(time);
753 struct SyncSetMode final :
public SyncBase {
754 explicit SyncSetMode(
VDP& vdp) : SyncBase(vdp) {}
755 void executeUntil(EmuTime::param time)
override {
756 auto& vdp =
OUTER(
VDP, syncSetMode);
757 vdp.execSetMode(time);
761 struct SyncSetBlank final :
public SyncBase {
762 explicit SyncSetBlank(
VDP& vdp) : SyncBase(vdp) {}
763 void executeUntil(EmuTime::param time)
override {
764 auto& vdp =
OUTER(
VDP, syncSetBlank);
765 vdp.execSetBlank(time);
769 struct SyncSetSprites final :
public SyncBase {
770 explicit SyncSetSprites(
VDP& vdp) : SyncBase(vdp) {}
771 void executeUntil(EmuTime::param time)
override {
772 auto& vdp =
OUTER(
VDP, syncSetSprites);
773 vdp.execSetSprites(time);
777 struct SyncCpuVramAccess final :
public SyncBase {
778 explicit SyncCpuVramAccess(
VDP& vdp) : SyncBase(vdp) {}
779 void executeUntil(EmuTime::param time)
override {
780 auto& vdp =
OUTER(
VDP, syncCpuVramAccess);
781 vdp.execCpuVramAccess(time);
785 struct SyncCmdDone final :
public SyncBase {
786 explicit SyncCmdDone(
VDP& vdp) : SyncBase(vdp) {}
787 void executeUntil(EmuTime::param time)
override {
788 auto& vdp =
OUTER(
VDP, syncCmdDone);
789 vdp.execSyncCmdDone(time);
793 void execVSync(EmuTime::param time);
794 void execDisplayStart(EmuTime::param time);
795 void execVScan(EmuTime::param time);
797 void execHorAdjust(EmuTime::param time);
798 void execSetMode(EmuTime::param time);
799 void execSetBlank(EmuTime::param time);
800 void execSetSprites(EmuTime::param time);
801 void execCpuVramAccess(EmuTime::param time);
802 void execSyncCmdDone(EmuTime::param time);
807 [[nodiscard]]
inline int getNumberOfLines()
const {
808 return controlRegs[9] & 0x80 ? 212 : 192;
814 [[nodiscard]]
int getVerticalAdjust()
const {
815 return (controlRegs[18] >> 4) ^ 0x07;
827 [[nodiscard]]
inline bool getHR(
int ticksThisFrame)
const {
833 static constexpr
int HBLANK_LEN_TXT = 404;
837 static constexpr
int HBLANK_LEN_GFX = 312;
839 < (displayMode.
isTextMode() ? HBLANK_LEN_TXT : HBLANK_LEN_GFX);
843 void preVideoSystemChange() noexcept override;
844 void postVideoSystemChange() noexcept override;
856 void resetMasks(EmuTime::param time);
861 void frameStart(EmuTime::param time);
870 void scheduleDisplayStart(EmuTime::param time);
877 void scheduleVScan(EmuTime::param time);
884 void scheduleHScan(EmuTime::param time);
888 void vramWrite(
byte value, EmuTime::param time);
892 [[nodiscard]]
byte vramRead(EmuTime::param time);
895 void scheduleCpuVramAccess(
bool isRead,
byte write, EmuTime::param time);
896 void executeCpuVramAccess(EmuTime::param time);
900 [[nodiscard]]
byte peekStatusReg(
byte reg, EmuTime::param time) const;
901 [[nodiscard]]
byte readStatusReg(
byte reg, EmuTime::param time);
905 void changeRegister(
byte reg,
byte val, EmuTime::param time);
909 void syncAtNextLine(SyncBase& type, EmuTime::param time);
913 void createRenderer();
918 void updateNameBase(EmuTime::param time);
923 void updateColorBase(EmuTime::param time);
928 void updatePatternBase(EmuTime::param time);
933 void updateSpriteAttributeBase(EmuTime::param time);
938 void updateSpritePatternBase(EmuTime::param time);
943 void updateDisplayMode(DisplayMode newMode,
bool cmdBit, EmuTime::param time);
951 void setPalette(
int index,
word grb, EmuTime::param time);
954 void update(const Setting& setting) noexcept override;
958 EnumSetting<
bool>& cmdTiming;
959 EnumSetting<
bool>& tooFastAccess;
961 struct RegDebug final : SimpleDebuggable {
962 explicit RegDebug(
VDP& vdp);
963 [[nodiscard]]
byte read(
unsigned address)
override;
964 void write(
unsigned address,
byte value, EmuTime::param time)
override;
967 struct StatusRegDebug final : SimpleDebuggable {
968 explicit StatusRegDebug(
VDP& vdp);
969 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
972 struct PaletteDebug final : SimpleDebuggable {
973 explicit PaletteDebug(
VDP& vdp);
974 [[nodiscard]]
byte read(
unsigned address)
override;
975 void write(
unsigned address,
byte value, EmuTime::param time)
override;
978 struct VRAMPointerDebug final : SimpleDebuggable {
979 explicit VRAMPointerDebug(
VDP& vdp);
980 [[nodiscard]]
byte read(
unsigned address)
override;
981 void write(
unsigned address,
byte value, EmuTime::param time)
override;
984 class Info :
public InfoTopic {
987 TclObject& result)
const override;
988 [[nodiscard]] std::string help(
const std::vector<std::string>& tokens)
const override;
989 [[nodiscard]]
virtual int calc(
const EmuTime& time)
const = 0;
991 Info(
VDP& vdp_,
const std::string& name, std::string helpText_);
994 const std::string helpText;
997 struct FrameCountInfo final :
Info {
998 explicit FrameCountInfo(
VDP& vdp);
999 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1002 struct CycleInFrameInfo final :
Info {
1003 explicit CycleInFrameInfo(
VDP& vdp);
1004 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1007 struct LineInFrameInfo final :
Info {
1008 explicit LineInFrameInfo(
VDP& vdp);
1009 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1012 struct CycleInLineInfo final :
Info {
1013 explicit CycleInLineInfo(
VDP& vdp);
1014 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1017 struct MsxYPosInfo final :
Info {
1018 explicit MsxYPosInfo(
VDP& vdp);
1019 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1022 struct MsxX256PosInfo final :
Info {
1023 explicit MsxX256PosInfo(
VDP& vdp);
1024 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1027 struct MsxX512PosInfo final :
Info {
1028 explicit MsxX512PosInfo(
VDP& vdp);
1029 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1034 std::unique_ptr<Renderer> renderer;
1038 std::unique_ptr<VDPCmdEngine> cmdEngine;
1042 std::unique_ptr<SpriteChecker> spriteChecker;
1046 std::unique_ptr<VDPVRAM> vram;
1051 const RawFrame* externalVideo;
1058 const RawFrame* superimposing;
1074 EmuTime displayStartSyncTime;
1078 EmuTime vScanSyncTime;
1082 EmuTime hScanSyncTime;
1084 TclCallback tooFastCallback;
1116 int horizontalScanOffset;
1121 int horizontalAdjust;
1125 byte controlRegs[32];
1139 byte controlValueMasks[32];
1200 bool registerDataStored;
1204 bool paletteDataStored;
1218 bool cpuVramReqIsRead;
1219 bool pendingCpuAccess;
1224 bool cpuExtendedVram;
1231 DisplayMode displayMode;
1237 bool displayEnabled;
1249 bool warningPrinted;
1252 bool brokenCmdTiming;
1253 bool allowTooFastAccess;
1257 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 dispay 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?
word getPalette(int index) const
Gets a palette entry.
int getLinesPerFrame() const
Gets the number of lines per frame.
int getEvenOddMask(int line) const
Similar to the above getEvenOddMask() method, but can also be called when 'isFastBlinkEnabled() == tr...
int getEvenOddMask() const
Expresses the state of even/odd page interchange in a mask on the line number.
VDPVRAM & getVRAM()
Get the VRAM object for this VDP.
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 clockticks between start of line and the time when the background pixel with X...
int getBackgroundColor() const
Gets the current background color.
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).
static constexpr int TICKS_PER_SECOND
Number of VDP clock ticks per second.
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?
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.
std::pair< bool, int > calculateLineBlinkState(unsigned line) const
Calculates what 'blinkState' and 'blinkCount' would be at a specific line.
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.
int getTicksPerFrame() const
Gets the number of VDP clockticks (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)
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 clockticks 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 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 clockticks 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/colortable 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...
const RawFrame * isSuperimposing() const
Are we currently superimposing? In case of superimpose, returns a pointer to the to-be-superimposed f...
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?
SpriteChecker & getSpriteChecker()
Get the sprite checker for this VDP.
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 clockticks 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)
#define OUTER(type, member)