41 void powerUp(EmuTime::param time)
override;
42 void reset(EmuTime::param time)
override;
43 [[nodiscard]]
byte readIO(
word port, EmuTime::param time)
override;
44 [[nodiscard]]
byte peekIO(
word port, EmuTime::param time)
const override;
45 void writeIO(
word port,
byte value, EmuTime::param time)
override;
70 return (regs[SCREEN_MODE_1] & 0x04) != 0;
77 return (status & 0x02) != 0;
86 return isDisplayArea && displayEnabled;
93 return !(regs[CONTROL] & 0x40);
102 return (regs[PALETTE_CONTROL] & 0x0F);
147 return superimposing;
152 externalVideoSource = enable;
178 case P1: x = ticks / 8;
break;
179 case P2: x = ticks / 4;
break;
180 case B0: x = ticks /12;
break;
181 case B1: x = ticks / 8;
break;
182 case B2: x = ticks / 6;
break;
183 case B3: x = ticks / 4;
break;
184 case B4: x = ticks / 3;
break;
185 case B5: x = 1;
break;
186 case B6: x = 1;
break;
187 case B7: x = ticks / 2;
break;
211 return regs[SCREEN_MODE_0] & 0x03;
218 return regs[BACK_DROP_COLOR];
224 return regs[SCROLL_CONTROL_AX0] + 8 * regs[SCROLL_CONTROL_AX1];
230 return regs[SCROLL_CONTROL_AY0] + 256 * scrollAYHigh;
236 return regs[SCROLL_CONTROL_BX0] + 8 * regs[SCROLL_CONTROL_BX1];
242 return regs[SCROLL_CONTROL_BY0] + 256 * scrollBYHigh;
247 [[nodiscard]]
inline unsigned getRollMask(
unsigned maxMask)
const {
248 static std::array<unsigned, 4> rollMasks = {
254 unsigned t = regs[SCROLL_CONTROL_AY1] >> 6;
255 return t ? rollMasks[
t] : maxMask;
261 switch (regs[SCREEN_MODE_0] & 0xC0) {
268 return (256 << ((regs[SCREEN_MODE_0] & 0x0C) >> 2));
276 case P1:
case B1:
return 320;
278 case P2:
case B3:
return 640;
280 case B5:
case B6:
return 1;
281 case B7:
return 1280;
298 return (
int(regs[SPRITE_PATTERN_ADDRESS] & 0x0E) << 14);
300 return (
int(regs[SPRITE_PATTERN_ADDRESS] & 0x0F) << 15);
309 return narrow_cast<byte>(regs[SPRITE_PALETTE_CONTROL] << 2);
323 (((regs[DISPLAY_ADJUST] & 0x0F) ^ 7) - 8) * 8;
340 (((regs[DISPLAY_ADJUST] >> 4) ^ 7) - 8);
347 unsigned t = regs[PRIORITY_CONTROL] & 0x03;
348 return (
t == 0) ? 256 :
t << 6;
351 unsigned t = regs[PRIORITY_CONTROL] & 0x0C;
352 return (
t == 0) ? 256 :
t << 4;
355 template<
typename Archive>
356 void serialize(Archive& ar,
unsigned version);
360 void preVideoSystemChange() noexcept override;
361 void postVideoSystemChange() noexcept override;
369 ~SyncBase() =
default;
372 struct SyncVSync final : SyncBase {
373 explicit SyncVSync(
V9990& v9990) : SyncBase(v9990) {}
374 void executeUntil(EmuTime::param time)
override {
376 v9990.execVSync(time);
380 struct SyncDisplayStart final : SyncBase {
381 explicit SyncDisplayStart(
V9990& v9990) : SyncBase(v9990) {}
382 void executeUntil(EmuTime::param time)
override {
384 v9990.execDisplayStart(time);
388 struct SyncVScan final : SyncBase {
389 explicit SyncVScan(
V9990& v9990) : SyncBase(v9990) {}
390 void executeUntil(EmuTime::param time)
override {
392 v9990.execVScan(time);
396 struct SyncHScan final : SyncBase {
397 explicit SyncHScan(
V9990& v9990) : SyncBase(v9990) {}
398 void executeUntil(EmuTime::param )
override {
404 struct SyncSetMode final : SyncBase {
405 explicit SyncSetMode(
V9990& v9990) : SyncBase(v9990) {}
406 void executeUntil(EmuTime::param time)
override {
408 v9990.execSetMode(time);
412 struct SyncCmdEnd final : SyncBase {
413 explicit SyncCmdEnd(
V9990& v9990) : SyncBase(v9990) {}
414 void executeUntil(EmuTime::param time)
override {
416 v9990.execCheckCmdEnd(time);
420 void execVSync(EmuTime::param time);
421 void execDisplayStart(EmuTime::param time);
422 void execVScan(EmuTime::param time);
424 void execSetMode(EmuTime::param time);
425 void execCheckCmdEnd(EmuTime::param time);
431 enum IRQType :
byte {
461 VRAM_WRITE_ADDRESS_0 = 0,
462 VRAM_WRITE_ADDRESS_1,
463 VRAM_WRITE_ADDRESS_2,
486 SPRITE_PATTERN_ADDRESS,
489 SPRITE_PALETTE_CONTROL,
490 CMD_PARAM_SRC_ADDRESS_0 = 32,
491 CMD_PARAM_SRC_ADDRESS_1,
492 CMD_PARAM_SRC_ADDRESS_2,
493 CMD_PARAM_SRC_ADDRESS_3,
494 CMD_PARAM_DEST_ADDRESS_0,
495 CMD_PARAM_DEST_ADDRESS_1,
496 CMD_PARAM_DEST_ADDRESS_2,
497 CMD_PARAM_DEST_ADDRESS_3,
504 CMD_PARAM_WRITE_MASK_0,
505 CMD_PARAM_WRITE_MASK_1,
506 CMD_PARAM_FONT_COLOR_FC0,
507 CMD_PARAM_FONT_COLOR_FC1,
508 CMD_PARAM_FONT_COLOR_BC0,
509 CMD_PARAM_FONT_COLOR_BC1,
511 CMD_PARAM_BORDER_X_0,
517 struct RegDebug final : SimpleDebuggable {
518 explicit RegDebug(
V9990& v9990);
519 [[nodiscard]]
byte read(
unsigned address)
override;
520 void write(
unsigned address,
byte value, EmuTime::param time)
override;
523 struct PalDebug final : SimpleDebuggable {
524 explicit PalDebug(
V9990& v9990);
525 [[nodiscard]]
byte read(
unsigned address)
override;
526 void write(
unsigned address,
byte value, EmuTime::param time)
override;
533 TclCallback invalidRegisterReadCallback;
534 TclCallback invalidRegisterWriteCallback;
539 unsigned vramReadPtr, vramWritePtr;
548 std::unique_ptr<V9990Renderer> renderer;
552 Clock<V9990DisplayTiming::UC_TICKS_PER_SECOND> frameStartTime;
556 EmuTime hScanSyncTime;
560 const V9990DisplayPeriod* horTiming;
561 const V9990DisplayPeriod* verTiming;
569 std::array<byte, 0x100> palette;
577 byte pendingIRQs = 0;
581 std::array<byte, 0x40> regs = {};
586 bool palTiming{
false};
591 bool interlaced{
false};
595 bool isDisplayArea{
false};
602 bool displayEnabled{
false};
625 bool externalVideoSource{
false};
630 bool superimposing{
false};
634 void setHorizontalTiming();
635 void setVerticalTiming();
643 [[nodiscard]]
inline unsigned getVRAMAddr(RegisterId base)
const;
649 inline void setVRAMAddr(RegisterId base,
unsigned addr);
656 [[nodiscard]]
byte readRegister(
byte reg, EmuTime::param time)
const;
663 void writeRegister(
byte reg,
byte val, EmuTime::param time);
670 void writePaletteRegister(
byte reg,
byte val, EmuTime::param time);
674 void syncAtNextLine(SyncBase& type, EmuTime::param time);
679 void createRenderer(EmuTime::param time);
684 void frameStart(EmuTime::param time);
689 void raiseIRQ(IRQType irqType);
700 void scheduleHscan(EmuTime::param time);
704 void scheduleCmdEnd(EmuTime::param time);
constexpr unsigned getTicksTill_fast(EmuTime::param e) const
Same as above, only faster, Though the time interval may not be too large.
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Scheduler & getScheduler() const
A post processor builds the frame that is displayed from the MSX frame, while applying effects such a...
Every class that wants to get scheduled at some point must inherit from this class.
void setSyncPoint(EmuTime::param timestamp)
virtual byte read(unsigned address, EmuTime::param time)
void write(unsigned address, byte value) override
static constexpr int UC_TICKS_PER_LINE
The number of clock ticks per line is independent of the crystal used or the display mode (NTSC/PAL)
static constexpr auto displayNTSC_MCLK
NTSC display timing, when using MCLK: Normal display mode with borders.
static constexpr auto displayPAL_MCLK
PAL display timing, when using MCLK: Normal display mode with borders.
Implementation of the Yamaha V9990 VDP as used in the GFX9000 cartridge by Sunrise.
void reset(EmuTime::param time) override
This method is called on reset.
unsigned getCursorYOffset() const
In overscan mode the cursor position is still specified with 'normal' (non-overscan) y-coordinates.
void powerUp(EmuTime::param time) override
This method is called when MSX is powered up.
void serialize(Archive &ar, unsigned version)
bool isPalTiming() const
Is PAL timing active? This setting is fixed at start of frame.
int getSpritePatternAddress(V9990DisplayMode m) const
Return the sprite pattern table base address.
bool isSuperimposing() const
Should this frame be superimposed? This is a combination of bit 5 (YSE) in R#8 and the presence of an...
void cmdReady()
Command execution ready.
byte getPaletteOffset() const
Get palette offset.
byte getBackDropColor() const
Return the current back drop color.
int getUCTicksThisFrame(EmuTime::param time) const
Get the number of elapsed UC ticks in this frame.
V9990VRAM & getVRAM()
Obtain a reference to the V9990's VRAM.
bool isInterlaced() const
Get interlace status.
unsigned getLineWidth() const
Return the display width.
bool isEvenOddEnabled() const
Get even/odd page alternation status.
unsigned getScrollBX() const
Returns the X scroll offset for screen B of P1 mode.
V9990DisplayMode getDisplayMode() const
Return the current display mode.
unsigned getImageWidth() const
Return the image width.
unsigned getPriorityControlX() const
bool spritesEnabled() const
Are sprites (cursors) enabled?
unsigned getColorDepth() const
Return the amount of bits per pixels.
void setExternalVideoSource(bool enable)
Is there an external video source available to superimpose on.
GetPaletteResult getPalette(int index) const
byte getSpritePaletteOffset() const
return sprite palette offset
static int UCtoX(int ticks, V9990DisplayMode mode)
Convert UC ticks to V9990 pixel position on a line.
unsigned getPriorityControlY() const
int getBottomBorder() const
unsigned getScrollAX() const
Returns the X scroll offset for screen A of P1 and other modes.
int getLeftBorder() const
Get the number of VDP clock-ticks between the start of the line and the end of the left border.
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.
PostProcessor * getPostProcessor() const
Used by Video9000 to be able to couple the VDP and V9990 output.
bool isDisplayEnabled() const
Is the display enabled? Note this is simpler than the V99x8 version.
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
unsigned getScrollBY() const
Returns the Y scroll offset for screen B of P1 mode.
unsigned getScrollAY() const
Returns the Y scroll offset for screen A of P1 and other modes.
unsigned getRollMask(unsigned maxMask) const
Returns the vertical roll mask.
const V9990DisplayPeriod & getVerticalTiming() const
Get vertical display timings.
V9990ColorMode getColorMode() const
Return the current color mode.
V9990(const DeviceConfig &config)
const V9990DisplayPeriod & getHorizontalTiming() const
Get horizontal display timings.
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
int getRightBorder() const
Get the number of VDP clock-ticks between the start of the line and the end of the right border.
bool isOverScan() const
Returns true iff in overscan mode.
bool getEvenOdd() const
Is the even or odd field being displayed?
This file implemented 3 utility functions:
uint16_t word
16 bit unsigned integer
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)
IntHelper< IRQSource > IRQHelper
#define OUTER(type, member)
A period, either horizontal or vertical, starts with a synchronisation pulse followed by a blank peri...