35namespace VDPAccessSlots {
36 enum class Delta : int;
81 void powerUp(EmuTime::param time)
override;
82 void reset(EmuTime::param time)
override;
83 [[nodiscard]]
byte readIO(
word port, EmuTime::param time)
override;
84 [[nodiscard]]
byte peekIO(
word port, EmuTime::param time)
const override;
85 void writeIO(
word port,
byte value, EmuTime::param time)
override;
91 [[nodiscard]]
byte peekStatusReg(
byte reg, EmuTime::param time)
const;
109 return (version & VM_MSX1) != 0;
116 return (version & VM_PAL) != 0;
123 return (version & VM_NO_MIRRORING) != 0;
130 return (version & VM_PALCOL_MIRRORING) != 0;
137 return (version & VM_VRAM_REMAPPING) != 0;
143 [[nodiscard]]
inline bool hasYJK()
const {
144 return (version & VM_YJK) != 0;
151 [[nodiscard]] std::array<std::array<uint8_t, 3>, 16>
getMSX1Palette()
const;
177 return superimposing;
183 return *spriteChecker;
190 return (controlRegs[8] & 0x20) == 0;
208 return controlRegs[7] >> 4;
220 byte reg7 = controlRegs[7];
232 return controlRegs[12] >> 4;
239 return controlRegs[12] & 0x0F;
251 return controlRegs[4] << 11;
255 return (controlRegs[10] << 14) | (controlRegs[3] << 6);
259 return controlRegs[2] << 10;
263 return controlRegs[6] << 11;
267 return (controlRegs[11] << 15) | (controlRegs[5] << 7);
279 [[nodiscard]]
inline uint16_t
getPalette(
unsigned index)
const {
280 return palette[index];
282 [[nodiscard]]
inline std::span<const uint16_t, 16>
getPalette()
const {
300 return isDisplayArea && displayEnabled;
308 return displayEnabled &&
318 return displayEnabled && spriteEnabled;
325 return spriteEnabled;
332 return controlRegs[23];
341 return controlRegs[27];
350 return controlRegs[26];
359 return (controlRegs[25] & 0x02) != 0;
369 return (controlRegs[25] & 0x01) && (controlRegs[2] & 0x20);
376 return (controlRegs[2] >> 5) & 3;
417 return (controlRegs[1] & 4) != 0;
433 return (controlRegs[9] & 4) != 0;
440 return (statusReg2 & 2) != 0;
457 return (((~controlRegs[9] & 4) << 6) | ((statusReg2 & 2) << 7)) &
471 return (!p.state) << 8;
488 if (blinkCount == 0) {
489 return {blinkState, blinkCount};
492 unsigned evenLen = ((controlRegs[13] >> 4) & 0x0F) * 10;
493 unsigned oddLen = ((controlRegs[13] >> 0) & 0x0F) * 10;
494 unsigned totalLen = evenLen + oddLen;
495 assert(totalLen != 0);
498 bool resultState = blinkState;
504 std::swap(evenLen, oddLen);
506 int newCount = blinkCount - narrow<int>(line);
509 resultState = !resultState;
510 newCount += narrow<int>(oddLen);
513 resultState = !resultState;
514 newCount += narrow<int>(evenLen);
515 assert(newCount > 0);
518 return {resultState, newCount};
529 return frameStartTime.
getTime();
535 return ((controlRegs[1] & 2) << 2) + 8;
541 return controlRegs[1] & 1;
548 return (controlRegs[25] & 0x40) != 0;
554 return palTiming ? 313 : 262;
561 return controlRegs[9] & 0x80 ? 212 : 192;
580 return time >= frameStartTime.
getTime() &&
588 return horizontalAdjust;
599 return 100 + 102 + 56
600 + (horizontalAdjust - 7) * 4
645 statusReg0 = (statusReg0 & 0x80) | (value & 0x7F);
652 return (controlRegs[8] & 8) != 0;
658 externalVideo = externalSource;
664 return brokenCmdTiming;
681 EmuTime::param time, EmuTime::param limit)
const;
707 int LARGEST_STALL = 184 + 2 * 70;
711 syncCmdDone.setSyncPoint(
t);
738 template<
typename Archive>
739 void serialize(Archive& ar,
unsigned version);
745 static constexpr unsigned VM_MSX1 = 1;
746 static constexpr unsigned VM_PAL = 2;
747 static constexpr unsigned VM_NO_MIRRORING = 4;
748 static constexpr unsigned VM_PALCOL_MIRRORING = 8;
749 static constexpr unsigned VM_VRAM_REMAPPING = 16;
750 static constexpr unsigned VM_TOSHIBA_PALETTE = 32;
751 static constexpr unsigned VM_YJK = 64;
752 static constexpr unsigned VM_YM2220_PALETTE = 128;
760 TMS99X8A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING,
763 TMS9929A = VM_MSX1 | VM_PALCOL_MIRRORING | VM_VRAM_REMAPPING | VM_PAL,
766 TMS9129 = VM_MSX1 | VM_PAL,
772 T6950PAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING | VM_PAL,
775 T6950NTSC = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_NO_MIRRORING,
778 T7937APAL = VM_MSX1 | VM_TOSHIBA_PALETTE | VM_PAL,
781 T7937ANTSC = VM_MSX1 | VM_TOSHIBA_PALETTE,
784 YM2220PAL = VM_MSX1 | VM_YM2220_PALETTE | VM_PALCOL_MIRRORING | VM_PAL,
787 YM2220NTSC = VM_MSX1 | VM_YM2220_PALETTE | VM_PALCOL_MIRRORING,
796 struct SyncBase :
public Schedulable {
797 explicit SyncBase(
const VDP& vdp_) : Schedulable(vdp_.
getScheduler()) {}
802 ~SyncBase() =
default;
805 struct SyncVSync final :
public SyncBase {
806 using SyncBase::SyncBase;
807 void executeUntil(EmuTime::param time)
override {
808 auto& vdp =
OUTER(VDP, syncVSync);
813 struct SyncDisplayStart final :
public SyncBase {
814 using SyncBase::SyncBase;
815 void executeUntil(EmuTime::param time)
override {
816 auto& vdp =
OUTER(VDP, syncDisplayStart);
817 vdp.execDisplayStart(time);
821 struct SyncVScan final :
public SyncBase {
822 using SyncBase::SyncBase;
823 void executeUntil(EmuTime::param time)
override {
824 auto& vdp =
OUTER(VDP, syncVScan);
829 struct SyncHScan final :
public SyncBase {
830 using SyncBase::SyncBase;
831 void executeUntil(EmuTime::param )
override {
832 auto& vdp =
OUTER(VDP, syncHScan);
837 struct SyncHorAdjust final :
public SyncBase {
838 using SyncBase::SyncBase;
839 void executeUntil(EmuTime::param time)
override {
840 auto& vdp =
OUTER(VDP, syncHorAdjust);
841 vdp.execHorAdjust(time);
845 struct SyncSetMode final :
public SyncBase {
846 using SyncBase::SyncBase;
847 void executeUntil(EmuTime::param time)
override {
848 auto& vdp =
OUTER(VDP, syncSetMode);
849 vdp.execSetMode(time);
853 struct SyncSetBlank final :
public SyncBase {
854 using SyncBase::SyncBase;
855 void executeUntil(EmuTime::param time)
override {
856 auto& vdp =
OUTER(VDP, syncSetBlank);
857 vdp.execSetBlank(time);
861 struct SyncSetSprites final :
public SyncBase {
862 using SyncBase::SyncBase;
863 void executeUntil(EmuTime::param time)
override {
864 auto& vdp =
OUTER(VDP, syncSetSprites);
865 vdp.execSetSprites(time);
869 struct SyncCpuVramAccess final :
public SyncBase {
870 using SyncBase::SyncBase;
871 void executeUntil(EmuTime::param time)
override {
872 auto& vdp =
OUTER(VDP, syncCpuVramAccess);
873 vdp.execCpuVramAccess(time);
877 struct SyncCmdDone final :
public SyncBase {
878 using SyncBase::SyncBase;
879 void executeUntil(EmuTime::param time)
override {
880 auto& vdp =
OUTER(VDP, syncCmdDone);
881 vdp.execSyncCmdDone(time);
885 void execVSync(EmuTime::param time);
886 void execDisplayStart(EmuTime::param time);
887 void execVScan(EmuTime::param time);
889 void execHorAdjust(EmuTime::param time);
890 void execSetMode(EmuTime::param time);
891 void execSetBlank(EmuTime::param time);
892 void execSetSprites(EmuTime::param time);
893 void execCpuVramAccess(EmuTime::param time);
894 void execSyncCmdDone(EmuTime::param time);
899 [[nodiscard]]
int getVerticalAdjust()
const {
900 return (controlRegs[18] >> 4) ^ 0x07;
912 [[nodiscard]]
inline bool getHR(
int ticksThisFrame)
const {
918 static constexpr int HBLANK_LEN_TXT = 404;
922 static constexpr int HBLANK_LEN_GFX = 312;
924 < (displayMode.
isTextMode() ? HBLANK_LEN_TXT : HBLANK_LEN_GFX);
928 void preVideoSystemChange() noexcept override;
929 void postVideoSystemChange() noexcept override;
941 void resetMasks(EmuTime::param time);
946 void frameStart(EmuTime::param time);
955 void scheduleDisplayStart(EmuTime::param time);
962 void scheduleVScan(EmuTime::param time);
969 void scheduleHScan(EmuTime::param time);
973 void vramWrite(
byte value, EmuTime::param time);
977 [[nodiscard]]
byte vramRead(EmuTime::param time);
980 void scheduleCpuVramAccess(
bool isRead,
byte write, EmuTime::param time);
981 void executeCpuVramAccess(EmuTime::param time);
985 [[nodiscard]]
byte readStatusReg(
byte reg, EmuTime::param time);
989 void syncAtNextLine(SyncBase& type, EmuTime::param time) const;
993 void createRenderer();
998 void updateNameBase(EmuTime::param time);
1003 void updateColorBase(EmuTime::param time);
1008 void updatePatternBase(EmuTime::param time);
1013 void updateSpriteAttributeBase(EmuTime::param time);
1018 void updateSpritePatternBase(EmuTime::param time);
1023 void updateDisplayMode(DisplayMode newMode,
bool cmdBit, EmuTime::param time);
1026 void update(const Setting&
setting) noexcept override;
1030 EnumSetting<
bool>& cmdTiming;
1031 EnumSetting<
bool>& tooFastAccess;
1033 struct RegDebug final : SimpleDebuggable {
1034 explicit RegDebug(
const VDP& vdp);
1035 [[nodiscard]]
byte read(
unsigned address)
override;
1036 void write(
unsigned address,
byte value, EmuTime::param time)
override;
1039 struct StatusRegDebug final : SimpleDebuggable {
1040 explicit StatusRegDebug(
const VDP& vdp);
1041 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
1042 } vdpStatusRegDebug;
1044 struct PaletteDebug final : SimpleDebuggable {
1045 explicit PaletteDebug(
const VDP& vdp);
1046 [[nodiscard]]
byte read(
unsigned address)
override;
1047 void write(
unsigned address,
byte value, EmuTime::param time)
override;
1050 struct VRAMPointerDebug final : SimpleDebuggable {
1051 explicit VRAMPointerDebug(
const VDP& vdp);
1052 [[nodiscard]]
byte read(
unsigned address)
override;
1053 void write(
unsigned address,
byte value, EmuTime::param time)
override;
1056 struct RegisterLatchStatusDebug final : SimpleDebuggable {
1057 explicit RegisterLatchStatusDebug(
const VDP& vdp);
1058 [[nodiscard]]
byte read(
unsigned address)
override;
1059 } registerLatchStatusDebug;
1061 struct VramAccessStatusDebug final : SimpleDebuggable {
1062 explicit VramAccessStatusDebug(
const VDP& vdp);
1063 [[nodiscard]]
byte read(
unsigned address)
override;
1064 } vramAccessStatusDebug;
1066 struct PaletteLatchStatusDebug final : SimpleDebuggable {
1067 explicit PaletteLatchStatusDebug(
const VDP& vdp);
1068 [[nodiscard]]
byte read(
unsigned address)
override;
1069 } paletteLatchStatusDebug;
1071 struct DataLatchDebug final : SimpleDebuggable {
1072 explicit DataLatchDebug(
const VDP& vdp);
1073 [[nodiscard]]
byte read(
unsigned address)
override;
1076 class Info :
public InfoTopic {
1078 void execute(std::span<const TclObject> tokens,
1079 TclObject& result)
const override;
1080 [[nodiscard]] std::string help(std::span<const TclObject> tokens)
const override;
1081 [[nodiscard]]
virtual int calc(
const EmuTime& time)
const = 0;
1083 Info(VDP& vdp_,
const std::string& name, std::string helpText_);
1086 const std::string helpText;
1089 struct FrameCountInfo final : Info {
1090 explicit FrameCountInfo(VDP& vdp);
1091 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1094 struct CycleInFrameInfo final : Info {
1095 explicit CycleInFrameInfo(VDP& vdp);
1096 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1099 struct LineInFrameInfo final : Info {
1100 explicit LineInFrameInfo(VDP& vdp);
1101 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1104 struct CycleInLineInfo final : Info {
1105 explicit CycleInLineInfo(VDP& vdp);
1106 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1109 struct MsxYPosInfo final : Info {
1110 explicit MsxYPosInfo(VDP& vdp);
1111 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1114 struct MsxX256PosInfo final : Info {
1115 explicit MsxX256PosInfo(VDP& vdp);
1116 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1119 struct MsxX512PosInfo final : Info {
1120 explicit MsxX512PosInfo(VDP& vdp);
1121 [[nodiscard]]
int calc(
const EmuTime& time)
const override;
1126 std::unique_ptr<Renderer> renderer;
1130 std::unique_ptr<VDPCmdEngine> cmdEngine;
1134 std::unique_ptr<SpriteChecker> spriteChecker;
1138 std::unique_ptr<VDPVRAM> vram;
1143 const RawFrame* externalVideo;
1150 const RawFrame* superimposing;
1166 EmuTime displayStartSyncTime;
1170 EmuTime vScanSyncTime;
1174 EmuTime hScanSyncTime;
1176 TclCallback tooFastCallback;
1177 TclCallback dotClockDirectionCallback;
1209 int horizontalScanOffset;
1214 int horizontalAdjust;
1218 std::array<byte, 32> controlRegs;
1224 byte controlRegMask;
1232 std::array<byte, 32> controlValueMasks;
1246 std::array<uint16_t, 16> palette;
1262 bool interlaced =
false;
1301 bool registerDataStored;
1305 bool paletteDataStored;
1319 bool cpuVramReqIsRead;
1320 bool pendingCpuAccess;
1325 bool cpuExtendedVram;
1332 DisplayMode displayMode;
1338 bool displayEnabled;
1350 bool warningPrinted =
false;
1353 bool brokenCmdTiming;
1354 bool allowTooFastAccess;
1358 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.
static constexpr uint8_t GRAPHIC7
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.
EmuTime::param getCurrentTime() const
Generic Gang-of-Four Observer class, templatized edition.
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...
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.
VDP command engine by Alex Wulms.
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.
int getNumberOfLines() const
Gets the number of display lines per screen.
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.
VDPCmdEngine & getCmdEngine()
int getNameTableBase() const
Get address of name table (only for debugger)
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 changeRegister(byte reg, byte val, EmuTime::param time)
VDP control register has changed, work out the consequences.
void scheduleCmdSync(EmuTime t)
Only used when there are commandExecuting-probe listeners.
byte peekRegister(unsigned address) const
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.
int getSpritePatternTableBase() const
Get address of pattern table (only for debugger)
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...
int getVramPointer() const
Get vram pointer (14-bit) (only for debugger)
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.
void setPalette(unsigned index, word grb, EmuTime::param time)
Sets a palette entry.
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.
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
gl::ivec2 getMSXPos(EmuTime::param time) const
Returns the position of the raster beam expressed in 'narrow' MSX screen coordinates (like 'screen 7'...
uint16_t getPalette(unsigned index) const
Gets a palette entry.
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.
int getPatternTableBase() const
Get address of pattern table (only for debugger)
int getDisplayPage() const
Only used by debugger.
bool getBlinkState() const
Gets the current blink state.
int getColorTableBase() const
Get address of color table (only for debugger)
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.
int getSpriteAttributeTableBase() const
Get address of color table (only for debugger)
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.
std::string_view getVersionString() const
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.
byte peekStatusReg(byte reg, EmuTime::param time) const
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.
std::span< const uint16_t, 16 > getPalette() const
This file implemented 3 utility functions:
IntHelper< OptionalIRQ > OptionalIRQHelper
uint16_t word
16 bit unsigned integer
#define OUTER(type, member)
Calculates what 'blinkState' and 'blinkCount' would be at a specific line.