147 return effectiveBaseMask;
162 inline void setMask(
int newBaseMask,
int newIndexMask,
163 EmuTime::param time) {
164 origBaseMask = newBaseMask;
165 newBaseMask &= sizeMask;
167 (newBaseMask == effectiveBaseMask) &&
168 (newIndexMask == indexMask)) {
172 effectiveBaseMask = newBaseMask;
173 indexMask = newIndexMask;
174 baseAddr = effectiveBaseMask & indexMask;
175 combiMask = ~effectiveBaseMask | indexMask;
191 unsigned endIndex = index +
size - 1;
193 if ((areaBits & effectiveBaseMask) != areaBits)
return false;
194 if ((areaBits & ~indexMask) != areaBits)
return false;
208 assert((
mask & ~indexMask) ==
mask);
209 return (
mask & effectiveBaseMask) ==
mask;
220 return &data[effectiveBaseMask & (indexMask | index)];
234 unsigned index,
unsigned size)
const {
235 assert((index & 1) == 0);
236 assert((
size & 1) == 0);
237 unsigned endIndex = index +
size - 1;
239 areaBits = ((areaBits << 16) | (areaBits >> 1)) & 0x1FFFF & sizeMask;
241 assert((areaBits & effectiveBaseMask) == areaBits);
242 assert((areaBits & ~indexMask) == areaBits);
244 unsigned addr = effectiveBaseMask & (indexMask | (index >> 1));
245 const byte* ptr0 = &data[addr | 0x00000];
246 const byte* ptr1 = &data[addr | 0x10000];
253 [[nodiscard]]
inline byte readNP(
unsigned index)
const {
255 return data[effectiveBaseMask & index];
263 index = ((index & 1) << 16) | ((index & 0x1FFFE) >> 1);
264 unsigned addr = effectiveBaseMask & index;
271 return observer != &dummyObserver;
280 observer = newObserver;
286 observer = &dummyObserver;
296 [[nodiscard]]
inline bool isInside(
unsigned address)
const {
297 return (address & combiMask) == unsigned(baseAddr);
305 inline void notify(
unsigned address, EmuTime::param time) {
307 observer->
updateVRAM(address - baseAddr, time);
316 sizeMask = newSizeMask;
318 setMask(origBaseMask, indexMask, time);
322 template<
typename Archive>
323 void serialize(Archive& ar,
unsigned version);
326 [[nodiscard]]
inline bool isEnabled()
const {
327 return baseAddr != -1;
357 int effectiveBaseMask;
401 inline void sync(EmuTime::param time) {
403 cmdEngine->
sync(time);
412 inline void cmdWrite(
unsigned address,
byte value, EmuTime::param time) {
415 assert(time >= vramTime);
421 if (address >= actualSize) [[unlikely]] {
423 assert(address < 0x30000);
429 writeCommon(address, value, time);
437 inline void cpuWrite(
unsigned address,
byte value, EmuTime::param time) {
440 assert(time >= vramTime);
446 if (address >= actualSize) [[unlikely]] {
448 assert(address < 0x30000);
461 cmdEngine->
sync(time);
463 writeCommon(address, value, time);
473 [[nodiscard]]
inline byte cpuRead(
unsigned address, EmuTime::param time) {
476 assert(time >= vramTime);
482 cmdEngine->
sync(time);
489 return data[address];
533 spriteChecker = newSpriteChecker;
539 cmdEngine = newCmdEngine;
547 template<
typename Archive>
548 void serialize(Archive& ar,
unsigned version);
553 inline void writeCommon(
unsigned address,
byte value, EmuTime::param time) {
555 assert(time >= vramTime);
563 if (data[address] == value)
return;
571 data[address] = value;
599 void setSizeMask(EmuTime::param time);
615 class LogicalVRAMDebuggable final :
public SimpleDebuggable {
617 explicit LogicalVRAMDebuggable(
VDP& vdp);
618 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
619 void write(
unsigned address,
byte value, EmuTime::param time)
override;
628 struct PhysicalVRAMDebuggable final : SimpleDebuggable {
629 PhysicalVRAMDebuggable(
VDP& vdp,
unsigned actualSize);
630 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
631 void write(
unsigned address,
byte value, EmuTime::param time)
override;
659 const unsigned actualSize;
Represents a VDP display mode.
void updateVRAM(unsigned, EmuTime::param) override
Informs the observer of a change in VRAM contents.
void updateWindow(bool, EmuTime::param) override
Informs the observer that the entire VRAM window will change.
Abstract base class for Renderers.
byte read(unsigned address) override
void write(unsigned address, byte value) override
VDP command engine by Alex Wulms.
EmuTime stealAccessSlot(EmuTime::param time)
Steal a VRAM access slot from the CmdEngine.
void sync(EmuTime::param time)
Synchronizes the command engine with the VDP.
Manages VRAM contents and synchronizes the various users of the VRAM.
void updateSpritesEnabled(bool enabled, EmuTime::param time)
Used by the VDP to signal sprites enabled changes.
VRAMWindow spriteAttribTable
void clear()
Initialize VRAM content to power-up state.
VDPVRAM(const VDPVRAM &)=delete
void cmdWrite(unsigned address, byte value, EmuTime::param time)
Write a byte from the command engine.
void setRenderer(Renderer *renderer, EmuTime::param time)
void updateVRMode(bool mode, EmuTime::param time)
Change between VR=0 and VR=1 mode.
VRAMWindow bitmapCacheWindow
void updateDisplayEnabled(bool enabled, EmuTime::param time)
Used by the VDP to signal display enabled changes.
void setSpriteChecker(SpriteChecker *newSpriteChecker)
Necessary because of circular dependencies.
void updateDisplayMode(DisplayMode mode, bool cmdBit, EmuTime::param time)
Used by the VDP to signal display mode changes.
VRAMWindow bitmapVisibleWindow
void sync(EmuTime::param time)
Update VRAM state to specified moment in time.
byte cpuRead(unsigned address, EmuTime::param time)
Read a byte from VRAM though the CPU interface.
void serialize(Archive &ar, unsigned version)
unsigned getSize() const
Returns the size of VRAM in bytes.
VRAMWindow spritePatternTable
void cpuWrite(unsigned address, byte value, EmuTime::param time)
Write a byte to VRAM through the CPU interface.
VRAMWindow cmdWriteWindow
void setCmdEngine(VDPCmdEngine *newCmdEngine)
Necessary because of circular dependencies.
void change4k8kMapping(bool mapping8k)
TMS99x8 VRAM can be mapped in two ways.
VDPVRAM & operator=(const VDPVRAM &)=delete
Unified implementation of MSX Video Display Processors (VDPs).
bool isInsideFrame(EmuTime::param time) const
Is the given timestamp inside the current frame? Mainly useful for debugging, because relevant timest...
Interface that can be registered at VRAMWindow, to be called when the contents of the VRAM inside tha...
virtual void updateVRAM(unsigned offset, EmuTime::param time)=0
Informs the observer of a change in VRAM contents.
virtual void updateWindow(bool enabled, EmuTime::param time)=0
Informs the observer that the entire VRAM window will change.
Specifies an address range in the VRAM.
void disable(EmuTime::param time)
Disable this window: no address will be considered inside.
VRAMWindow & operator=(const VRAMWindow &)=delete
bool isContinuous(unsigned index, unsigned size) const
Is the given index range continuous in VRAM (iow there's no mirroring) Only if the range is continuou...
int getMask() const
Gets the mask for this window.
void notify(unsigned address, EmuTime::param time)
Notifies the observer of this window of a VRAM change, if the changes address is inside this window.
byte readNP(unsigned index) const
Reads a byte from VRAM in its current state.
bool hasObserver() const
Is there an observer registered for this window?
bool isInside(unsigned address) const
Test whether an address is inside this window.
void serialize(Archive &ar, unsigned version)
bool isContinuous(unsigned mask) const
Alternative version to check whether a region is continuous in VRAM.
void setSizeMask(unsigned newSizeMask, EmuTime::param time)
Inform VRAMWindow of changed sizeMask.
byte readPlanar(unsigned index) const
Similar to readNP, but now with planar addressing.
const byte * getReadArea(unsigned index, unsigned size) const
Gets a pointer to a contiguous part of the VRAM.
VRAMWindow(const VRAMWindow &)=delete
void setMask(int newBaseMask, int newIndexMask, EmuTime::param time)
Sets the mask and enables this window.
void setObserver(VRAMObserver *newObserver)
Register an observer on this VRAM window.
std::pair< const byte *, const byte * > getReadAreaPlanar(unsigned index, unsigned size) const
Similar to getReadArea(), but now with planar addressing mode.
void resetObserver()
Unregister the observer of this VRAM window.
constexpr auto floodRight(std::unsigned_integral auto x) noexcept
Returns the smallest number of the form 2^n-1 that is greater or equal to the given number.
This file implemented 3 utility functions:
constexpr nibble mask[4][13]
auto transform(InputRange &&range, OutputIter out, UnaryOperation op)
size_t size(std::string_view utf8)