// $Id: VDPCmdEngine.hh 5969 2006-12-29 14:53:25Z m9710797 $ #ifndef VDPCMDENGINE_HH #define VDPCMDENGINE_HH #include "VDP.hh" #include "DisplayMode.hh" #include "Observer.hh" #include "openmsx.hh" #include "noncopyable.hh" #include "likely.hh" #include namespace openmsx { class VDPVRAM; class CommandController; class RenderSettings; class BooleanSetting; /** VDP command engine by Alex Wulms. * Implements command execution unit of V9938/58. */ class VDPCmdEngine : private Observer, private noncopyable { public: VDPCmdEngine(VDP& vdp, RenderSettings& renderSettings_, CommandController& commandController); virtual ~VDPCmdEngine(); /** Reinitialise Renderer state. * @param time The moment in time the reset occurs. */ void reset(const EmuTime& time); /** Synchronises the command engine with the VDP. * Ideally this would be a private method, but the current * design doesn't allow that. * @param time The moment in emulated time to sync to. */ inline void sync(const EmuTime& time) { if (currentCommand) currentCommand->execute(time); } /** Gets the command engine status (part of S#2). * Bit 7 (TR) is set when the command engine is ready for * a pixel transfer. * Bit 4 (BD) is set when the boundary colour is detected. * Bit 0 (CE) is set when a command is in progress. */ inline byte getStatus(const EmuTime& time) { if (time >= statusChangeTime) { sync(time); } return status; } /** Use this method to transfer pixel(s) from VDP to CPU. * This method implements V9938 S#7. * @param time The moment in emulated time this read occurs. * @return Colour value of the pixel. */ inline byte readColour(const EmuTime& time) { sync(time); return COL; } inline void resetColour() { // Note: Real VDP always resets TR, but for such a short time // that the MSX won't notice it. // TODO: What happens on non-transfer commands? if (!currentCommand) status &= 0x7F; transfer = true; } /** Gets the X coordinate of a border detected by SRCH (intended behaviour, * as documented in the V9938 technical data book). However, real VDP * simply returns the current value of the ASX 'temporary source X' counter, * regardless of the command that is being executed or was executed most * recently * @param time The moment in emulated time this get occurs. */ inline unsigned getBorderX(const EmuTime& time) { sync(time); return ASX; } /** Writes to a command register. * @param index The register [0..14] to write to. * @param value The new value for the specified register. * @param time The moment in emulated time this write occurs. */ void setCmdReg(byte index, byte value, const EmuTime& time); /** Read the content of a command register. This method is meant to * be used by the debugger, there is no strict guarantee that the * returned value is the correct value at _exactly_ this moment in * time (IOW this method does not sync the complete CmdEngine) * @param index The register [0..14] to read from. */ byte peekCmdReg(byte index); /** Informs the command engine of a VDP display mode change. * @param mode The new display mode. * @param time The moment in emulated time this change occurs. */ void updateDisplayMode(DisplayMode mode, const EmuTime& time); /** Interface for logical operations. */ class LogOp { public: /** Write a pixel using a logical operation. * @param time Time at which the write occurs. * @param vram Pointer to VRAM class. * @param addr Address of pixel in VRAM. * @param colour Colour of pixel to be written, * shifted if necessary to correspond to the right VRAM position. * @param mask Read mask: bit positions that are 1 are read from * VRAM before the write is performed. */ virtual void pset(const EmuTime& time, VDPVRAM& vram, unsigned addr, byte colour, byte mask) = 0; virtual ~LogOp() {} }; private: /** Represents V9938 Graphic 4 mode (SCREEN5). */ class Graphic4Mode { public: static const byte COLOUR_MASK = 0x0F; static const byte PIXELS_PER_BYTE = 2; static const byte PIXELS_PER_BYTE_SHIFT = 1; static const unsigned PIXELS_PER_LINE = 256; static inline unsigned addressOf(unsigned x, unsigned y, bool extVRAM); static inline byte point(VDPVRAM& vram, unsigned x, unsigned y, bool extVRAM); static inline void pset(const EmuTime& time, VDPVRAM& vram, unsigned x, unsigned y, bool extVRAM, byte colour, LogOp& op); }; /** Represents V9938 Graphic 5 mode (SCREEN6). */ class Graphic5Mode { public: static const byte COLOUR_MASK = 0x03; static const byte PIXELS_PER_BYTE = 4; static const byte PIXELS_PER_BYTE_SHIFT = 2; static const unsigned PIXELS_PER_LINE = 512; static inline unsigned addressOf(unsigned x, unsigned y, bool extVRAM); static inline byte point(VDPVRAM& vram, unsigned x, unsigned y, bool extVRAM); static inline void pset(const EmuTime& time, VDPVRAM& vram, unsigned x, unsigned y, bool extVRAM, byte colour, LogOp& op); }; /** Represents V9938 Graphic 6 mode (SCREEN7). */ class Graphic6Mode { public: static const byte COLOUR_MASK = 0x0F; static const byte PIXELS_PER_BYTE = 2; static const byte PIXELS_PER_BYTE_SHIFT = 1; static const unsigned PIXELS_PER_LINE = 512; static inline unsigned addressOf(unsigned x, unsigned y, bool extVRAM); static inline byte point(VDPVRAM& vram, unsigned x, unsigned y, bool extVRAM); static inline void pset(const EmuTime& time, VDPVRAM& vram, unsigned x, unsigned y, bool extVRAM, byte colour, LogOp& op); }; /** Represents V9938 Graphic 7 mode (SCREEN8). */ class Graphic7Mode { public: static const byte COLOUR_MASK = 0xFF; static const byte PIXELS_PER_BYTE = 1; static const byte PIXELS_PER_BYTE_SHIFT = 0; static const unsigned PIXELS_PER_LINE = 256; static inline unsigned addressOf(unsigned x, unsigned y, bool extVRAM); static inline byte point(VDPVRAM& vram, unsigned x, unsigned y, bool extVRAM); static inline void pset(const EmuTime& time, VDPVRAM& vram, unsigned x, unsigned y, bool extVRAM, byte colour, LogOp& op); }; /** This is an abstract base class the VDP commands */ class VDPCmd { public: VDPCmd(VDPCmdEngine& engine, VDPVRAM& vram); virtual ~VDPCmd(); /** Prepare execution of cmd */ virtual void start(const EmuTime& time) = 0; /** Perform a given V9938 graphical operation. */ virtual void execute(const EmuTime& time) = 0; protected: VDPCmdEngine& engine; VDPVRAM& vram; }; template