openMSX
PixelRenderer.cc
Go to the documentation of this file.
1 /*
2 TODO:
3 - Implement blinking (of page mask) in bitmap modes.
4 */
5 
6 #include "PixelRenderer.hh"
7 #include "Rasterizer.hh"
8 #include "PostProcessor.hh"
9 #include "Display.hh"
10 #include "VideoSystem.hh"
11 #include "RenderSettings.hh"
12 #include "VideoSourceSetting.hh"
13 #include "IntegerSetting.hh"
14 #include "VDP.hh"
15 #include "VDPVRAM.hh"
16 #include "SpriteChecker.hh"
17 #include "EventDistributor.hh"
18 #include "FinishFrameEvent.hh"
19 #include "RealTime.hh"
20 #include "MSXMotherBoard.hh"
21 #include "Reactor.hh"
22 #include "Timer.hh"
23 #include "unreachable.hh"
24 #include <algorithm>
25 #include <cassert>
26 
27 namespace openmsx {
28 
29 void PixelRenderer::draw(
30  int startX, int startY, int endX, int endY, DrawType drawType, bool atEnd)
31 {
32  if (drawType == DRAW_BORDER) {
33  rasterizer->drawBorder(startX, startY, endX, endY);
34  } else {
35  assert(drawType == DRAW_DISPLAY);
36 
37  // Calculate display coordinates.
38  int zero = vdp.getLineZero();
39  int displayX = (startX - vdp.getLeftSprites()) / 2;
40  int displayY = startY - zero;
41  if (!vdp.getDisplayMode().isTextMode()) {
42  displayY += vdp.getVerticalScroll();
43  } else {
44  // this is not what the real VDP does, but it is good
45  // enough for "Boring scroll" demo part of "Relax"
46  displayY = (displayY & 7) | (textModeCounter * 8);
47  if (atEnd && (drawType == DRAW_DISPLAY)) {
48  int low = std::max(0, (startY - zero)) / 8;
49  int high = std::max(0, (endY - zero)) / 8;
50  textModeCounter += (high - low);
51  }
52  }
53 
54  displayY &= 255; // Page wrap.
55  int displayWidth = (endX - (startX & ~1)) / 2;
56  int displayHeight = endY - startY;
57 
58  assert(0 <= displayX);
59  assert(displayX + displayWidth <= 512);
60 
61  rasterizer->drawDisplay(
62  startX, startY,
63  displayX - vdp.getHorizontalScrollLow() * 2, displayY,
64  displayWidth, displayHeight
65  );
66  if (vdp.spritesEnabled() && !renderSettings.getDisableSprites()) {
67  rasterizer->drawSprites(
68  startX, startY,
69  displayX / 2, displayY,
70  (displayWidth + 1) / 2, displayHeight);
71  }
72  }
73 }
74 
75 void PixelRenderer::subdivide(
76  int startX, int startY, int endX, int endY, int clipL, int clipR,
77  DrawType drawType )
78 {
79  // Partial first line.
80  if (startX > clipL) {
81  bool atEnd = (startY != endY) || (endX >= clipR);
82  if (startX < clipR) {
83  draw(startX, startY, (atEnd ? clipR : endX),
84  startY + 1, drawType, atEnd);
85  }
86  if (startY == endY) return;
87  startY++;
88  }
89  // Partial last line.
90  bool drawLast = false;
91  if (endX >= clipR) {
92  endY++;
93  } else if (endX > clipL) {
94  drawLast = true;
95  }
96  // Full middle lines.
97  if (startY < endY) {
98  draw(clipL, startY, clipR, endY, drawType, true);
99  }
100  // Actually draw last line if necessary.
101  // The point of keeping top-to-bottom draw order is that it increases
102  // the locality of memory references, which generally improves cache
103  // hit rates.
104  if (drawLast) draw(clipL, endY, endX, endY + 1, drawType, false);
105 }
106 
108  : vdp(vdp_), vram(vdp.getVRAM())
109  , eventDistributor(vdp.getReactor().getEventDistributor())
110  , realTime(vdp.getMotherBoard().getRealTime())
111  , renderSettings(display.getRenderSettings())
112  , videoSourceSetting(vdp.getMotherBoard().getVideoSource())
113  , spriteChecker(vdp.getSpriteChecker())
114  , rasterizer(display.getVideoSystem().createRasterizer(vdp))
115 {
116  // In case of loadstate we can't yet query any state from the VDP
117  // (because that object is not yet fully deserialized). But
118  // VDP::serialize() will call Renderer::reInit() again when it is
119  // safe to query.
120  reInit();
121 
122  finishFrameDuration = 0;
123  frameSkipCounter = 999; // force drawing of frame
124  prevRenderFrame = false;
125 
126  renderSettings.getMaxFrameSkipSetting().attach(*this);
127  renderSettings.getMinFrameSkipSetting().attach(*this);
128 }
129 
131 {
132  renderSettings.getMinFrameSkipSetting().detach(*this);
133  renderSettings.getMaxFrameSkipSetting().detach(*this);
134 }
135 
137 {
138  return rasterizer->getPostProcessor();
139 }
140 
142 {
143  // Don't draw before frameStart() is called.
144  // This for example can happen after a loadstate or after switching
145  // renderer in the middle of a frame.
146  renderFrame = false;
147 
148  rasterizer->reset();
149  displayEnabled = vdp.isDisplayEnabled();
150 }
151 
152 void PixelRenderer::updateDisplayEnabled(bool enabled, EmuTime::param time)
153 {
154  sync(time, true);
155  displayEnabled = enabled;
156 }
157 
158 void PixelRenderer::frameStart(EmuTime::param time)
159 {
160  if (!rasterizer->isActive()) {
161  frameSkipCounter = 999;
162  renderFrame = false;
163  prevRenderFrame = false;
164  return;
165  }
166  prevRenderFrame = renderFrame;
167  if (vdp.isInterlaced() && renderSettings.getDeinterlace() &&
168  vdp.getEvenOdd() && vdp.isEvenOddEnabled()) {
169  // deinterlaced odd frame, do same as even frame
170  } else {
171  if (frameSkipCounter < renderSettings.getMinFrameSkip()) {
172  ++frameSkipCounter;
173  renderFrame = false;
174  } else if (frameSkipCounter >= renderSettings.getMaxFrameSkip()) {
175  frameSkipCounter = 0;
176  renderFrame = true;
177  } else {
178  ++frameSkipCounter;
179  if (rasterizer->isRecording()) {
180  renderFrame = true;
181  } else {
182  renderFrame = realTime.timeLeft(
183  unsigned(finishFrameDuration), time);
184  }
185  if (renderFrame) {
186  frameSkipCounter = 0;
187  }
188  }
189  }
190  if (!renderFrame) return;
191 
192  rasterizer->frameStart(time);
193 
194  accuracy = renderSettings.getAccuracy();
195 
196  nextX = 0;
197  nextY = 0;
198  // This is not what the real VDP does, but it is good enough
199  // for the "Boring scroll" demo part of ANMA's "Relax" demo.
200  textModeCounter = 0;
201 }
202 
203 void PixelRenderer::frameEnd(EmuTime::param time)
204 {
205  bool skipEvent = !renderFrame;
206  if (renderFrame) {
207  // Render changes from this last frame.
208  sync(time, true);
209 
210  // Let underlying graphics system finish rendering this frame.
211  auto time1 = Timer::getTime();
212  rasterizer->frameEnd();
213  auto time2 = Timer::getTime();
214  auto current = time2 - time1;
215  const float ALPHA = 0.2f;
216  finishFrameDuration = finishFrameDuration * (1 - ALPHA) +
217  current * ALPHA;
218 
219  if (vdp.isInterlaced() && vdp.isEvenOddEnabled() &&
220  renderSettings.getDeinterlace() &&
221  !prevRenderFrame) {
222  // dont send event in deinterlace mode when
223  // previous frame was not rendered
224  skipEvent = true;
225  }
226  }
227  if (vdp.getMotherBoard().isActive() &&
228  !vdp.getMotherBoard().isFastForwarding()) {
229  eventDistributor.distributeEvent(
230  std::make_shared<FinishFrameEvent>(
231  rasterizer->getPostProcessor()->getVideoSource(),
232  videoSourceSetting.getSource(),
233  skipEvent));
234  }
235 }
236 
238  byte scroll, EmuTime::param time)
239 {
240  if (displayEnabled) sync(time);
241  rasterizer->setHorizontalScrollLow(scroll);
242 }
243 
245  byte /*scroll*/, EmuTime::param time)
246 {
247  if (displayEnabled) sync(time);
248 }
249 
251  bool masked, EmuTime::param time)
252 {
253  if (displayEnabled) sync(time);
254  rasterizer->setBorderMask(masked);
255 }
256 
258  bool /*multiPage*/, EmuTime::param time)
259 {
260  if (displayEnabled) sync(time);
261 }
262 
264  bool enabled, EmuTime::param time)
265 {
266  if (displayEnabled) sync(time);
267  rasterizer->setTransparency(enabled);
268 }
269 
271  const RawFrame* videoSource, EmuTime::param time)
272 {
273  if (displayEnabled) sync(time);
274  rasterizer->setSuperimposeVideoFrame(videoSource);
275 }
276 
278  int /*color*/, EmuTime::param time)
279 {
280  if (displayEnabled) sync(time);
281 }
282 
284  int color, EmuTime::param time)
285 {
286  sync(time);
287  rasterizer->setBackgroundColor(color);
288 }
289 
291  int /*color*/, EmuTime::param time)
292 {
293  if (displayEnabled) sync(time);
294 }
295 
297  int /*color*/, EmuTime::param time)
298 {
299  if (displayEnabled) sync(time);
300 }
301 
303  bool /*enabled*/, EmuTime::param /*time*/)
304 {
305  // TODO: When the sync call is enabled, the screen flashes on
306  // every call to this method.
307  // I don't know why exactly, but it's probably related to
308  // being called at frame start.
309  //sync(time);
310 }
311 
313  int index, int grb, EmuTime::param time)
314 {
315  if (displayEnabled) {
316  sync(time);
317  } else {
318  // Only sync if border color changed.
319  DisplayMode mode = vdp.getDisplayMode();
320  if (mode.getBase() == DisplayMode::GRAPHIC5) {
321  int bgColor = vdp.getBackgroundColor();
322  if (index == (bgColor & 3) || (index == (bgColor >> 2))) {
323  sync(time);
324  }
325  } else if (mode.getByte() != DisplayMode::GRAPHIC7) {
326  if (index == vdp.getBackgroundColor()) {
327  sync(time);
328  }
329  }
330  }
331  rasterizer->setPalette(index, grb);
332 }
333 
335  int /*scroll*/, EmuTime::param time)
336 {
337  if (displayEnabled) sync(time);
338 }
339 
341  int adjust, EmuTime::param time)
342 {
343  if (displayEnabled) sync(time);
344  rasterizer->setHorizontalAdjust(adjust);
345 }
346 
348  DisplayMode mode, EmuTime::param time)
349 {
350  // Sync if in display area or if border drawing process changes.
351  DisplayMode oldMode = vdp.getDisplayMode();
352  if (displayEnabled
353  || oldMode.getByte() == DisplayMode::GRAPHIC5
354  || oldMode.getByte() == DisplayMode::GRAPHIC7
355  || mode.getByte() == DisplayMode::GRAPHIC5
356  || mode.getByte() == DisplayMode::GRAPHIC7) {
357  sync(time, true);
358  }
359  rasterizer->setDisplayMode(mode);
360 }
361 
363  int /*addr*/, EmuTime::param time)
364 {
365  if (displayEnabled) sync(time);
366 }
367 
369  int /*addr*/, EmuTime::param time)
370 {
371  if (displayEnabled) sync(time);
372 }
373 
375  int /*addr*/, EmuTime::param time)
376 {
377  if (displayEnabled) sync(time);
378 }
379 
381  bool /*enabled*/, EmuTime::param time
382 ) {
383  if (displayEnabled) sync(time);
384 }
385 
386 static inline bool overlap(
387  int displayY0, // start of display region, inclusive
388  int displayY1, // end of display region, exclusive
389  int vramLine0, // start of VRAM region, inclusive
390  int vramLine1 // end of VRAM region, exclusive
391  // Note: Display region can wrap around: 256 -> 0.
392  // VRAM region cannot wrap around.
393 ) {
394  if (displayY0 <= displayY1) {
395  if (vramLine1 > displayY0) {
396  if (vramLine0 <= displayY1) return true;
397  }
398  } else {
399  if (vramLine1 > displayY0) return true;
400  if (vramLine0 <= displayY1) return true;
401  }
402  return false;
403 }
404 
405 inline bool PixelRenderer::checkSync(int offset, EmuTime::param time)
406 {
407  // TODO: Because range is entire VRAM, offset == address.
408 
409  // If display is disabled, VRAM changes will not affect the
410  // renderer output, therefore sync is not necessary.
411  // TODO: Have bitmapVisibleWindow disabled in this case.
412  if (!displayEnabled) return false;
413  //if (frameSkipCounter != 0) return false; // TODO
414  if (accuracy == RenderSettings::ACC_SCREEN) return false;
415 
416  // Calculate what display lines are scanned between current
417  // renderer time and update-to time.
418  // Note: displayY1 is inclusive.
419  int deltaY = vdp.getVerticalScroll() - vdp.getLineZero();
420  int limitY = vdp.getTicksThisFrame(time) / VDP::TICKS_PER_LINE;
421  int displayY0 = (nextY + deltaY) & 255;
422  int displayY1 = (limitY + deltaY) & 255;
423 
424  switch(vdp.getDisplayMode().getBase()) {
427  if (vram.colorTable.isInside(offset)) {
428  int vramQuarter = (offset & 0x1800) >> 11;
429  int mask = (vram.colorTable.getMask() & 0x1800) >> 11;
430  for (int i = 0; i < 4; i++) {
431  if ( (i & mask) == vramQuarter
432  && overlap(displayY0, displayY1, i * 64, (i + 1) * 64) ) {
433  /*fprintf(stderr,
434  "color table: %05X %04X - quarter %d\n",
435  offset, offset & 0x1FFF, i
436  );*/
437  return true;
438  }
439  }
440  }
441  if (vram.patternTable.isInside(offset)) {
442  int vramQuarter = (offset & 0x1800) >> 11;
443  int mask = (vram.patternTable.getMask() & 0x1800) >> 11;
444  for (int i = 0; i < 4; i++) {
445  if ( (i & mask) == vramQuarter
446  && overlap(displayY0, displayY1, i * 64, (i + 1) * 64) ) {
447  /*fprintf(stderr,
448  "pattern table: %05X %04X - quarter %d\n",
449  offset, offset & 0x1FFF, i
450  );*/
451  return true;
452  }
453  }
454  }
455  if (vram.nameTable.isInside(offset)) {
456  int vramLine = ((offset & 0x3FF) / 32) * 8;
457  if (overlap(displayY0, displayY1, vramLine, vramLine + 8)) {
458  /*fprintf(stderr,
459  "name table: %05X %03X - line %d\n",
460  offset, offset & 0x3FF, vramLine
461  );*/
462  return true;
463  }
464  }
465  return false;
467  case DisplayMode::GRAPHIC5: {
468  if (vdp.isFastBlinkEnabled()) {
469  // TODO could be improved
470  return true;
471  }
472  // Is the address inside the visual page(s)?
473  // TODO: Also look at which lines are touched inside pages.
474  int visiblePage = vram.nameTable.getMask()
475  & (0x10000 | (vdp.getEvenOddMask() << 7));
476  if (vdp.isMultiPageScrolling()) {
477  return (offset & 0x18000) == visiblePage
478  || (offset & 0x18000) == (visiblePage & 0x10000);
479  } else {
480  return (offset & 0x18000) == visiblePage;
481  }
482  }
485  return true; // TODO: Implement better detection.
486  default:
487  // Range unknown; assume full range.
488  return vram.nameTable.isInside(offset)
489  || vram.colorTable.isInside(offset)
490  || vram.patternTable.isInside(offset);
491  }
492 }
493 
494 void PixelRenderer::updateVRAM(unsigned offset, EmuTime::param time)
495 {
496  // Note: No need to sync if display is disabled, because then the
497  // output does not depend on VRAM (only on background color).
498  if (renderFrame && displayEnabled && checkSync(offset, time)) {
499  //fprintf(stderr, "vram sync @ line %d\n",
500  // vdp.getTicksThisFrame(time) / VDP::TICKS_PER_LINE);
501  renderUntil(time);
502  }
503 }
504 
505 void PixelRenderer::updateWindow(bool /*enabled*/, EmuTime::param /*time*/)
506 {
507  // The bitmapVisibleWindow has moved to a different area.
508  // This update is redundant: Renderer will be notified in another way
509  // as well (updateDisplayEnabled or updateNameBase, for example).
510  // TODO: Can this be used as the main update method instead?
511 }
512 
513 void PixelRenderer::sync(EmuTime::param time, bool force)
514 {
515  if (!renderFrame) return;
516 
517  // Synchronisation is done in two phases:
518  // 1. update VRAM
519  // 2. update other subsystems
520  // Note that as part of step 1, type 2 updates can be triggered.
521  // Executing step 2 takes care of the subsystem changes that occur
522  // after the last VRAM update.
523  // This scheme makes sure type 2 routines such as renderUntil and
524  // checkUntil are not re-entered, which was causing major pain in
525  // the past.
526  // TODO: I wonder if it's possible to enforce this synchronisation
527  // scheme at a higher level. Probably. But how...
528  //if ((frameSkipCounter == 0) && TODO
529  if (accuracy != RenderSettings::ACC_SCREEN || force) {
530  vram.sync(time);
531  renderUntil(time);
532  }
533 }
534 
535 void PixelRenderer::renderUntil(EmuTime::param time)
536 {
537  // Translate from time to pixel position.
538  int limitTicks = vdp.getTicksThisFrame(time);
539  assert(limitTicks <= vdp.getTicksPerFrame());
540  int limitX, limitY;
541  switch (accuracy) {
543  limitX = limitTicks % VDP::TICKS_PER_LINE;
544  limitY = limitTicks / VDP::TICKS_PER_LINE;
545  break;
546  }
549  // Note: I'm not sure the rounding point is optimal.
550  // It used to be based on the left margin, but that doesn't work
551  // because the margin can change which leads to a line being
552  // rendered even though the time doesn't advance.
553  limitX = 0;
554  limitY =
555  (limitTicks + VDP::TICKS_PER_LINE - 400) / VDP::TICKS_PER_LINE;
556  break;
557  }
558  default:
559  UNREACHABLE;
560  limitX = limitY = 0; // avoid warning
561  }
562 
563  // Stop here if there is nothing to render.
564  // This ensures that no pixels are rendered in a series of updates that
565  // happen at exactly the same time; the VDP subsystem states may be
566  // inconsistent until all updates are performed.
567  // Also it is a small performance optimisation.
568  if (limitX == nextX && limitY == nextY) return;
569 
570  if (displayEnabled) {
571  if (vdp.spritesEnabled()) {
572  // Update sprite checking, so that rasterizer can call getSprites.
573  spriteChecker.checkUntil(time);
574  }
575 
576  // Calculate start and end of borders in ticks since start of line.
577  // The 0..7 extra horizontal scroll low pixels should be drawn in
578  // border color. These will be drawn together with the border,
579  // but sprites above these pixels are clipped at the actual border
580  // rather than the end of the border colored area.
581  // TODO: Move these calculations and getDisplayLeft() to VDP.
582  int borderL = vdp.getLeftBorder();
583  int displayL =
584  vdp.isBorderMasked() ? borderL : vdp.getLeftBackground();
585  int borderR = vdp.getRightBorder();
586 
587  // It's important that right border is drawn last (after left
588  // border and display area). See comment in SDLRasterizer::drawBorder().
589  // Left border.
590  subdivide(nextX, nextY, limitX, limitY,
591  0, displayL, DRAW_BORDER);
592  // Display area.
593  subdivide(nextX, nextY, limitX, limitY,
594  displayL, borderR, DRAW_DISPLAY);
595  // Right border.
596  subdivide(nextX, nextY, limitX, limitY,
597  borderR, VDP::TICKS_PER_LINE, DRAW_BORDER);
598  } else {
599  subdivide(nextX, nextY, limitX, limitY,
600  0, VDP::TICKS_PER_LINE, DRAW_BORDER);
601  }
602 
603  nextX = limitX;
604  nextY = limitY;
605 }
606 
607 void PixelRenderer::update(const Setting& setting)
608 {
609  if (&setting == &renderSettings.getMinFrameSkipSetting() ||
610  &setting == &renderSettings.getMaxFrameSkipSetting()) {
611  // Force drawing of frame.
612  frameSkipCounter = 999;
613  } else {
614  UNREACHABLE;
615  }
616 }
617 
618 } // namespace openmsx
openmsx::adjust
constexpr AdjustTables adjust
Definition: Y8950.cc:204
VideoSystem.hh
openmsx::PixelRenderer::frameStart
void frameStart(EmuTime::param time) override
Signals the start of a new frame.
Definition: PixelRenderer.cc:158
IntegerSetting.hh
openmsx::Subject::detach
void detach(Observer< T > &observer)
Definition: Subject.hh:56
Timer.hh
Display.hh
openmsx::VDP
Unified implementation of MSX Video Display Processors (VDPs).
Definition: VDP.hh:61
openmsx::RenderSettings::ACC_LINE
Definition: RenderSettings.hh:32
openmsx::PixelRenderer::reInit
void reInit() override
Reinitialise Renderer state.
Definition: PixelRenderer.cc:141
openmsx::PixelRenderer::updateBorderMask
void updateBorderMask(bool masked, EmuTime::param time) override
Informs the renderer of a horizontal scroll change: the border mask has been enabled/disabled.
Definition: PixelRenderer.cc:250
openmsx::VDP::getHorizontalScrollLow
byte getHorizontalScrollLow() const
Gets the current horizontal scroll lower bits.
Definition: VDP.hh:289
openmsx::RenderSettings::getMaxFrameSkipSetting
IntegerSetting & getMaxFrameSkipSetting()
The current max frameskip.
Definition: RenderSettings.hh:59
openmsx::VDP::isInterlaced
bool isInterlaced() const
Get interlace status.
Definition: VDP.hh:344
openmsx::SpriteChecker::checkUntil
void checkUntil(EmuTime::param time)
Update sprite checking until specified line.
Definition: SpriteChecker.hh:169
openmsx::VDP::getEvenOdd
bool getEvenOdd() const
Is the even or odd field being displayed?
Definition: VDP.hh:381
VDP.hh
openmsx::VDP::isBorderMasked
bool isBorderMasked() const
Gets the current border mask setting.
Definition: VDP.hh:307
openmsx::PixelRenderer::getPostProcessor
PostProcessor * getPostProcessor() const override
See VDP::getPostProcessor.
Definition: PixelRenderer.cc:136
VideoSourceSetting.hh
openmsx::VDP::getBackgroundColor
int getBackgroundColor() const
Gets the current background color.
Definition: VDP.hh:204
openmsx::PixelRenderer::~PixelRenderer
~PixelRenderer() override
Definition: PixelRenderer.cc:130
openmsx::Timer::getTime
uint64_t getTime()
Get current (real) time in us.
Definition: Timer.cc:7
openmsx::VRAMWindow::isInside
bool isInside(unsigned address) const
Test whether an address is inside this window.
Definition: VDPVRAM.hh:296
openmsx::VDP::getTicksPerFrame
int getTicksPerFrame() const
Gets the number of VDP clockticks (21MHz) per frame.
Definition: VDP.hh:497
openmsx::PixelRenderer::updateVerticalScroll
void updateVerticalScroll(int scroll, EmuTime::param time) override
Informs the renderer of a vertical scroll change.
Definition: PixelRenderer.cc:334
openmsx::Subject::attach
void attach(Observer< T > &observer)
Definition: Subject.hh:50
openmsx::VDP::spritesEnabled
bool spritesEnabled() const
Are sprites enabled?
Definition: VDP.hh:256
openmsx::RenderSettings::getDisableSprites
bool getDisableSprites() const
Disable sprite rendering?
Definition: RenderSettings.hh:131
openmsx::DisplayMode::getBase
constexpr byte getBase() const
Get the base dispay mode as an integer: M5..M1 combined.
Definition: DisplayMode.hh:114
openmsx::PixelRenderer::updatePatternBase
void updatePatternBase(int addr, EmuTime::param time) override
Informs the renderer of a pattern table base address change.
Definition: PixelRenderer.cc:368
openmsx::DisplayMode::GRAPHIC7
Definition: DisplayMode.hh:37
openmsx::VDP::getDisplayMode
DisplayMode getDisplayMode() const
Get the display mode the VDP is in.
Definition: VDP.hh:141
openmsx::PixelRenderer::updateWindow
void updateWindow(bool enabled, EmuTime::param time) override
Informs the observer that the entire VRAM window will change.
Definition: PixelRenderer.cc:505
openmsx::DisplayMode
Represents a VDP display mode.
Definition: DisplayMode.hh:14
openmsx::DisplayMode::GRAPHIC5
Definition: DisplayMode.hh:35
openmsx::MSXMotherBoard::isFastForwarding
bool isFastForwarding() const
Definition: MSXMotherBoard.hh:96
openmsx::PixelRenderer::updateBackgroundColor
void updateBackgroundColor(int color, EmuTime::param time) override
Informs the renderer of a VDP background color change.
Definition: PixelRenderer.cc:283
openmsx::RenderSettings::getDeinterlace
bool getDeinterlace() const
Deinterlacing [on, off].
Definition: RenderSettings.hh:53
openmsx::PixelRenderer::updateMultiPage
void updateMultiPage(bool multiPage, EmuTime::param time) override
Informs the renderer of a horizontal scroll change: the multi page setting has changed.
Definition: PixelRenderer.cc:257
openmsx::PixelRenderer::updateSuperimposing
void updateSuperimposing(const RawFrame *videoSource, EmuTime::param time) override
Informs the renderer of a VDP superimposing change.
Definition: PixelRenderer.cc:270
RealTime.hh
openmsx::VDPVRAM::colorTable
VRAMWindow colorTable
Definition: VDPVRAM.hh:667
openmsx::PixelRenderer::updateHorizontalScrollLow
void updateHorizontalScrollLow(byte scroll, EmuTime::param time) override
Informs the renderer of a horizontal scroll change: the lower scroll value has changed.
Definition: PixelRenderer.cc:237
Reactor.hh
openmsx::PixelRenderer::frameEnd
void frameEnd(EmuTime::param time) override
Signals the end of a frame.
Definition: PixelRenderer.cc:203
openmsx::PixelRenderer::PixelRenderer
PixelRenderer(VDP &vdp, Display &display)
Definition: PixelRenderer.cc:107
SpriteChecker.hh
UNREACHABLE
#define UNREACHABLE
Definition: unreachable.hh:38
openmsx::VDP::isDisplayEnabled
bool isDisplayEnabled() const
Is the display enabled? Both the regular border and forced blanking by clearing the display enable bi...
Definition: VDP.hh:248
openmsx::PixelRenderer::updatePalette
void updatePalette(int index, int grb, EmuTime::param time) override
Informs the renderer of a VDP palette change.
Definition: PixelRenderer.cc:312
openmsx::VDP::isFastBlinkEnabled
bool isFastBlinkEnabled() const
Get 'fast-blink' status.
Definition: VDP.hh:358
openmsx::RenderSettings::getMinFrameSkipSetting
IntegerSetting & getMinFrameSkipSetting()
The current min frameskip.
Definition: RenderSettings.hh:63
openmsx::VDP::getLineZero
int getLineZero() const
Get the absolute line number of display line zero.
Definition: VDP.hh:325
EventDistributor.hh
PostProcessor.hh
openmsx::RenderSettings::getAccuracy
Accuracy getAccuracy() const
Accuracy [screen, line, pixel].
Definition: RenderSettings.hh:50
openmsx::MSXDevice::getMotherBoard
MSXMotherBoard & getMotherBoard() const
Get the mother board this device belongs to.
Definition: MSXDevice.cc:74
openmsx::PixelRenderer::updateNameBase
void updateNameBase(int addr, EmuTime::param time) override
Informs the renderer of a name table base address change.
Definition: PixelRenderer.cc:362
openmsx::VideoSourceSetting::getSource
int getSource() noexcept
Definition: VideoSourceSetting.cc:35
openmsx::PostProcessor
Abstract base class for post processors.
Definition: PostProcessor.hh:29
openmsx::PixelRenderer::updateColorBase
void updateColorBase(int addr, EmuTime::param time) override
Informs the renderer of a color table base address change.
Definition: PixelRenderer.cc:374
openmsx::VDPVRAM::sync
void sync(EmuTime::param time)
Update VRAM state to specified moment in time.
Definition: VDPVRAM.hh:400
openmsx::RawFrame
A video frame as output by the VDP scanline conversion unit, before any postprocessing filters are ap...
Definition: RawFrame.hh:25
RenderSettings.hh
FinishFrameEvent.hh
openmsx::PixelRenderer::updateTransparency
void updateTransparency(bool enabled, EmuTime::param time) override
Informs the renderer of a VDP transparency enable/disable change.
Definition: PixelRenderer.cc:263
openmsx::DisplayMode::isTextMode
constexpr bool isTextMode() const
Is the current mode a text mode? Text1 and Text2 are text modes.
Definition: DisplayMode.hh:129
openmsx::PixelRenderer::updateSpritesEnabled
void updateSpritesEnabled(bool enabled, EmuTime::param time) override
Informs the renderer of a VDP sprites enabled change.
Definition: PixelRenderer.cc:380
Rasterizer.hh
openmsx::VDP::isMultiPageScrolling
bool isMultiPageScrolling() const
Is multi page scrolling enabled? It is considered enabled if both the multi page scrolling flag is en...
Definition: VDP.hh:317
openmsx::DisplayMode::GRAPHIC4
Definition: DisplayMode.hh:34
openmsx::VDP::getRightBorder
int getRightBorder() const
Gets the number of VDP clockticks between start of line and the start of the right border.
Definition: VDP.hh:547
openmsx::VDP::getLeftSprites
int getLeftSprites() const
Gets the number of VDP clockticks between start of line and the start of the sprite plane.
Definition: VDP.hh:529
openmsx::VDP::getTicksThisFrame
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.
Definition: VDP.hh:462
openmsx::VDPVRAM::nameTable
VRAMWindow nameTable
Definition: VDPVRAM.hh:666
openmsx::PixelRenderer::updateBlinkForegroundColor
void updateBlinkForegroundColor(int color, EmuTime::param time) override
Informs the renderer of a VDP blink foreground color change.
Definition: PixelRenderer.cc:290
openmsx::VDP::getLeftBackground
int getLeftBackground() const
Gets the number of VDP clockticks between start of line and the time when the background pixel with X...
Definition: VDP.hh:557
openmsx::VDP::isEvenOddEnabled
bool isEvenOddEnabled() const
Get even/odd page alternation status.
Definition: VDP.hh:373
openmsx::RenderSettings::getMinFrameSkip
int getMinFrameSkip() const
Definition: RenderSettings.hh:64
openmsx::RenderSettings::ACC_SCREEN
Definition: RenderSettings.hh:32
openmsx::PixelRenderer::updateHorizontalScrollHigh
void updateHorizontalScrollHigh(byte scroll, EmuTime::param time) override
Informs the renderer of a horizontal scroll change: the higher scroll value has changed.
Definition: PixelRenderer.cc:244
openmsx::Display
Represents the output window/screen of openMSX.
Definition: Display.hh:31
openmsx::MSXMotherBoard::isActive
bool isActive() const
Definition: MSXMotherBoard.hh:95
openmsx::RenderSettings::getMaxFrameSkip
int getMaxFrameSkip() const
Definition: RenderSettings.hh:60
openmsx::DisplayMode::GRAPHIC2
Definition: DisplayMode.hh:29
openmsx::PixelRenderer::updateDisplayMode
void updateDisplayMode(DisplayMode mode, EmuTime::param time) override
Informs the renderer of a VDP display mode change.
Definition: PixelRenderer.cc:347
openmsx::VDP::getVerticalScroll
byte getVerticalScroll() const
Gets the current vertical scroll (line displayed at Y=0).
Definition: VDP.hh:280
VDPVRAM.hh
openmsx::mask
constexpr nibble mask[4][13]
Definition: RP5C01.cc:33
openmsx::PixelRenderer::updateForegroundColor
void updateForegroundColor(int color, EmuTime::param time) override
Informs the renderer of a VDP foreground color change.
Definition: PixelRenderer.cc:277
gl::max
vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:292
openmsx::VDP::getEvenOddMask
int getEvenOddMask() const
Expresses the state of even/odd page interchange in a mask on the line number.
Definition: VDP.hh:396
openmsx::DisplayMode::GRAPHIC3
Definition: DisplayMode.hh:32
openmsx::DisplayMode::GRAPHIC6
Definition: DisplayMode.hh:36
PixelRenderer.hh
openmsx::VRAMWindow::getMask
int getMask() const
Gets the mask for this window.
Definition: VDPVRAM.hh:146
openmsx::PixelRenderer::updateBlinkBackgroundColor
void updateBlinkBackgroundColor(int color, EmuTime::param time) override
Informs the renderer of a VDP blink background color change.
Definition: PixelRenderer.cc:296
openmsx::VDPVRAM::patternTable
VRAMWindow patternTable
Definition: VDPVRAM.hh:668
unreachable.hh
openmsx::RealTime::timeLeft
bool timeLeft(uint64_t us, EmuTime::param time)
Check that there is enough real time left before we reach as certain point in emulated time.
Definition: RealTime.cc:67
openmsx::PixelRenderer::updateHorizontalAdjust
void updateHorizontalAdjust(int adjust, EmuTime::param time) override
Informs the renderer of a horizontal adjust change.
Definition: PixelRenderer.cc:340
openmsx::VDP::getLeftBorder
int getLeftBorder() const
Gets the number of VDP clockticks between start of line and the end of the left border.
Definition: VDP.hh:540
openmsx::DisplayMode::getByte
constexpr byte getByte() const
Get the dispay mode as a byte: YAE YJK M5..M1 combined.
Definition: DisplayMode.hh:100
openmsx::PixelRenderer::updateBlinkState
void updateBlinkState(bool enabled, EmuTime::param time) override
Informs the renderer of a VDP blinking state change.
Definition: PixelRenderer.cc:302
openmsx::VDP::TICKS_PER_LINE
static constexpr int TICKS_PER_LINE
Number of VDP clock ticks per line.
Definition: VDP.hh:72
openmsx::PixelRenderer::updateDisplayEnabled
void updateDisplayEnabled(bool enabled, EmuTime::param time) override
Informs the renderer of a VDP display enabled change.
Definition: PixelRenderer.cc:152
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
MSXMotherBoard.hh
openmsx::PixelRenderer::updateVRAM
void updateVRAM(unsigned offset, EmuTime::param time) override
Informs the observer of a change in VRAM contents.
Definition: PixelRenderer.cc:494
openmsx::EventDistributor::distributeEvent
void distributeEvent(const EventPtr &event)
Schedule the given event for delivery.
Definition: EventDistributor.cc:44
openmsx::RenderSettings::ACC_PIXEL
Definition: RenderSettings.hh:32