27 static const int TICKS_LEFT_BORDER = 100 + 102;
33 static const int TICKS_VISIBLE_MIDDLE =
36 template <
class Pixel>
37 inline int SDLRasterizer<Pixel>::translateX(
int absoluteX,
bool narrow)
39 int maxX = narrow ? 640 : 320;
46 const int ROUND_MASK = narrow ? ~1 : ~3;
48 ((absoluteX & ROUND_MASK) - (TICKS_VISIBLE_MIDDLE & ROUND_MASK))
51 return std::max(screenX, 0);
54 template <
class Pixel>
55 inline void SDLRasterizer<Pixel>::renderBitmapLine(
Pixel* buf,
unsigned vramLine)
57 if (vdp.getDisplayMode().isPlanar()) {
60 vram.bitmapCacheWindow.getReadAreaPlanar(
61 vramLine * 256, 256, vramPtr0, vramPtr1);
62 bitmapConverter->convertLinePlanar(buf, vramPtr0, vramPtr1);
65 vram.bitmapCacheWindow.getReadArea(vramLine * 128, 128);
66 bitmapConverter->convertLine(buf, vramPtr);
70 template <
class Pixel>
73 std::unique_ptr<PostProcessor> postProcessor_)
74 : vdp(vdp_), vram(vdp.getVRAM())
76 , postProcessor(std::move(postProcessor_))
78 , renderSettings(display.getRenderSettings())
82 palFg, PALETTE256, V9958_COLORS))
84 vdp.getSpriteChecker()))
91 for (
int i = 0; i < 16; ++i) {
92 palFg[i] = palFg[i + 16] = palBg[i] =
93 V9938_COLORS[0][0][0];
103 template <
class Pixel>
106 renderSettings.getColorMatrix().detach(*
this);
107 renderSettings.getGamma() .detach(*
this);
108 renderSettings.getBrightness() .detach(*
this);
109 renderSettings.getContrast() .detach(*
this);
112 template <
class Pixel>
115 return postProcessor.get();
118 template <
class Pixel>
121 return postProcessor->needRender() &&
122 vdp.getMotherBoard().isActive() &&
123 !vdp.getMotherBoard().isFastForwarding();
126 template <
class Pixel>
130 setDisplayMode(vdp.getDisplayMode());
131 spriteConverter->setTransparency(vdp.getTransparency());
136 template <
class Pixel>
139 if (!vdp.isMSX1VDP()) {
141 for (
int i = 0; i < 16; i++) {
142 setPalette(i, vdp.getPalette(i));
147 template<
class Pixel>
150 postProcessor->setSuperimposeVideoFrame(videoSource);
151 precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
152 videoSource, vdp.getBackgroundColor());
155 template <
class Pixel>
158 workFrame = postProcessor->rotateFrames(std::move(workFrame),
169 lineRenderTop = vdp.isPalTiming() ? 59 - 14 : 32 - 14;
172 template <
class Pixel>
178 template <
class Pixel>
182 bitmapConverter->setDisplayMode(mode);
184 characterConverter->setDisplayMode(mode);
186 precalcColorIndex0(mode, vdp.getTransparency(),
187 vdp.isSuperimposing(), vdp.getBackgroundColor());
188 spriteConverter->setDisplayMode(mode);
190 ? palGraphic7Sprites : palBg);
193 template <
class Pixel>
197 Pixel newColor = V9938_COLORS[(grb >> 4) & 7][grb >> 8][grb & 7];
198 palFg[index ] = newColor;
199 palFg[index + 16] = newColor;
200 palBg[index ] = newColor;
201 bitmapConverter->palette16Changed();
203 precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
204 vdp.isSuperimposing(), vdp.getBackgroundColor());
207 template <
class Pixel>
210 precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
211 vdp.isSuperimposing(), index);
214 template <
class Pixel>
217 spriteConverter->setTransparency(enabled);
218 precalcColorIndex0(vdp.getDisplayMode(), enabled,
219 vdp.isSuperimposing(), vdp.getBackgroundColor());
222 template <
class Pixel>
225 if (vdp.isMSX1VDP()) {
227 for (
int i = 0; i < 16; i++) {
229 double dr = rgb[0] / 255.0;
230 double dg = rgb[1] / 255.0;
231 double db = rgb[2] / 255.0;
232 renderSettings.transformRGB(dr, dg, db);
233 palFg[i] = palFg[i + 16] = palBg[i] =
234 screen.mapKeyedRGB<
Pixel>(dr, dg, db);
239 if (renderSettings.isColorMatrixIdentity()) {
243 for (
int i = 0; i < 32; i++) {
245 int(255 * renderSettings.transformComponent(i / 31.0));
247 for (
int rgb = 0; rgb < (1 << 15); rgb++) {
248 V9958_COLORS[rgb] = screen.mapKeyedRGB<
Pixel>(
249 intensity[(rgb >> 10) ],
250 intensity[(rgb >> 5) & 31],
251 intensity[ rgb & 31]);
254 for (
int r5 = 0; r5 < 32; r5++) {
255 for (
int g5 = 0; g5 < 32; g5++) {
256 for (
int b5 = 0; b5 < 32; b5++) {
257 double dr = r5 / 31.0;
258 double dg = g5 / 31.0;
259 double db = b5 / 31.0;
260 renderSettings.transformRGB(dr, dg, db);
261 V9958_COLORS[(r5<<10) + (g5<<5) + b5] =
262 screen.mapKeyedRGB<
Pixel>(dr, dg, db);
270 for (
int r3 = 0; r3 < 8; r3++) {
271 int r5 = (r3 << 2) | (r3 >> 1);
272 for (
int g3 = 0; g3 < 8; g3++) {
273 int g5 = (g3 << 2) | (g3 >> 1);
274 for (
int b3 = 0; b3 < 8; b3++) {
275 int b5 = (b3 << 2) | (b3 >> 1);
276 V9938_COLORS[r3][g3][b3] =
277 V9958_COLORS[(r5<<10) + (g5<<5) + b5];
283 if (renderSettings.isColorMatrixIdentity()) {
285 for (
int i = 0; i < 8; i++) {
287 int(255 * renderSettings.transformComponent(i / 7.0));
289 for (
int r3 = 0; r3 < 8; r3++) {
290 for (
int g3 = 0; g3 < 8; g3++) {
291 for (
int b3 = 0; b3 < 8; b3++) {
292 V9938_COLORS[r3][g3][b3] =
293 screen.mapKeyedRGB<
Pixel>(
294 intensity[r3], intensity[g3], intensity[b3]
300 for (
int r3 = 0; r3 < 8; r3++) {
301 for (
int g3 = 0; g3 < 8; g3++) {
302 for (
int b3 = 0; b3 < 8; b3++) {
303 double dr = r3 / 7.0;
304 double dg = g3 / 7.0;
305 double db = b3 / 7.0;
306 renderSettings.transformRGB(dr, dg, db);
307 V9938_COLORS[r3][g3][b3] =
308 screen.mapKeyedRGB<
Pixel>(dr, dg, db);
315 for (
int i = 0; i < 256; i++) {
316 PALETTE256[i] = V9938_COLORS
319 [(i & 0x03) == 3 ? 7 : (i & 0x03) * 2];
322 for (
int i = 0; i < 16; i++) {
324 palGraphic7Sprites[i] =
325 V9938_COLORS[(grb >> 4) & 7][grb >> 8][grb & 7];
330 template <
class Pixel>
331 void SDLRasterizer<Pixel>::precalcColorIndex0(DisplayMode mode,
332 bool transparency,
const RawFrame* superimposing,
byte bgcolorIndex)
336 transparency =
false;
339 int tpIndex = transparency ? bgcolorIndex : 0;
341 Pixel c = (superimposing && (bgcolorIndex == 0))
342 ? screen.getKeyColor<
Pixel>()
347 bitmapConverter->palette16Changed();
351 if ((palFg[ 0] != palBg[tpIndex >> 2]) ||
352 (palFg[16] != palBg[tpIndex & 3])) {
353 palFg[ 0] = palBg[tpIndex >> 2];
354 palFg[16] = palBg[tpIndex & 3];
355 bitmapConverter->palette16Changed();
360 template <
class Pixel>
362 int fromX,
int fromY,
int limitX,
int limitY)
366 int bgColor = vdp.getBackgroundColor();
367 Pixel border0, border1;
371 border0 = palBg[(bgColor & 0x0C) >> 2];
372 border1 = palBg[(bgColor & 0x03) >> 0];
374 border0 = border1 = PALETTE256[bgColor];
376 if (!bgColor && vdp.isSuperimposing()) {
377 border0 = border1 = screen.getKeyColor<
Pixel>();
379 border0 = border1 = palBg[bgColor];
383 int startY = std::max(fromY - lineRenderTop, 0);
384 int endY = std::min(limitY - lineRenderTop, 240);
386 (border0 == border1)) {
388 for (
int y = startY; y < endY; y++) {
389 workFrame->setBlank(y, border0);
393 unsigned x = translateX(fromX, (lineWidth == 512));
394 unsigned num = translateX(limitX, (lineWidth == 512)) - x;
395 unsigned width = (lineWidth == 512) ? 640 : 320;
397 for (
int y = startY; y < endY; ++y) {
398 memset(workFrame->getLinePtrDirect<
Pixel>(y) + x,
399 num, border0, border1);
400 workFrame->setLineWidth(y, width);
405 template <
class Pixel>
408 int displayX,
int displayY,
409 int displayWidth,
int displayHeight)
413 if (lineWidth == 256) {
414 int endX = displayX + displayWidth;
416 displayWidth = endX / 2 - displayX;
420 int screenLimitY = std::min(
421 fromY + displayHeight - lineRenderTop,
423 int screenY = fromY - lineRenderTop;
426 fromY = lineRenderTop;
429 displayHeight = screenLimitY - screenY;
430 if (displayHeight <= 0)
return;
433 translateX(vdp.getLeftBackground(), lineWidth == 512);
439 : 8 * (lineWidth / 256) * (vdp.getHorizontalScrollHigh() & 0x1F);
446 int pageBorder = displayX + displayWidth;
447 int scrollPage1, scrollPage2;
448 if (vdp.isMultiPageScrolling()) {
449 scrollPage1 = vdp.getHorizontalScrollHigh() >> 5;
450 scrollPage2 = scrollPage1 ^ 1;
457 int pageSplit = lineWidth - hScroll;
458 if (pageSplit < pageBorder) {
459 pageBorder = pageSplit;
464 int pageMaskOdd = (mode.
isPlanar() ? 0x000 : 0x200) |
465 vdp.getEvenOddMask();
466 int pageMaskEven = vdp.isMultiPageScrolling()
467 ? (pageMaskOdd & ~0x100)
470 for (
int y = screenY; y < screenLimitY; y++) {
471 const int vramLine[2] = {
472 (vram.nameTable.getMask() >> 7) & (pageMaskEven | displayY),
473 (vram.nameTable.getMask() >> 7) & (pageMaskOdd | displayY)
478 Pixel* dst = workFrame->getLinePtrDirect<
Pixel>(y)
479 + leftBackground + displayX;
480 int firstPageWidth = pageBorder - displayX;
481 if (firstPageWidth > 0) {
482 if ((displayX + hScroll) == 0) {
483 renderBitmapLine(dst, vramLine[scrollPage1]);
485 lineInBuf = vramLine[scrollPage1];
486 renderBitmapLine(buf, vramLine[scrollPage1]);
487 const Pixel* src = buf + displayX + hScroll;
493 if (firstPageWidth < displayWidth) {
494 if (lineInBuf != vramLine[scrollPage2]) {
495 renderBitmapLine(buf, vramLine[scrollPage2]);
497 unsigned x = displayX < pageBorder
498 ? 0 : displayX + hScroll - lineWidth;
500 dst + firstPageWidth,
502 displayWidth - firstPageWidth);
504 workFrame->setLineWidth(y, (lineWidth == 512) ? 640 : 320);
506 displayY = (displayY + 1) & 255;
510 for (
int y = screenY; y < screenLimitY; y++) {
511 assert(!vdp.isMSX1VDP() || displayY < 192);
513 Pixel* dst = workFrame->getLinePtrDirect<
Pixel>(y)
514 + leftBackground + displayX;
516 characterConverter->convertLine(dst, displayY);
519 characterConverter->convertLine(buf, displayY);
520 const Pixel* src = buf + displayX;
524 workFrame->setLineWidth(y, (lineWidth == 512) ? 640 : 320);
525 displayY = (displayY + 1) & 255;
530 template <
class Pixel>
533 int displayX,
int displayY,
534 int displayWidth,
int displayHeight)
538 int screenLimitY = std::min(
539 fromY + displayHeight - lineRenderTop,
541 int screenY = fromY - lineRenderTop;
544 fromY = lineRenderTop;
547 displayHeight = screenLimitY - screenY;
548 if (displayHeight <= 0)
return;
553 int spriteMode = vdp.getDisplayMode().getSpriteMode();
554 int displayLimitX = displayX + displayWidth;
555 int limitY = fromY + displayHeight;
556 int screenX = translateX(
557 vdp.getLeftSprites(),
558 vdp.getDisplayMode().getLineWidth() == 512);
559 if (spriteMode == 1) {
560 for (
int y = fromY; y < limitY; y++, screenY++) {
561 Pixel* pixelPtr = workFrame->getLinePtrDirect<
Pixel>(screenY) + screenX;
562 spriteConverter->drawMode1(y, displayX, displayLimitX, pixelPtr);
565 byte mode = vdp.getDisplayMode().getByte();
567 for (
int y = fromY; y < limitY; y++, screenY++) {
568 Pixel* pixelPtr = workFrame->getLinePtrDirect<
Pixel>(screenY) + screenX;
569 spriteConverter->template drawMode2<DisplayMode::GRAPHIC5>(
570 y, displayX, displayLimitX, pixelPtr);
573 for (
int y = fromY; y < limitY; y++, screenY++) {
574 Pixel* pixelPtr = workFrame->getLinePtrDirect<
Pixel>(screenY) + screenX;
575 spriteConverter->template drawMode2<DisplayMode::GRAPHIC6>(
576 y, displayX, displayLimitX, pixelPtr);
579 for (
int y = fromY; y < limitY; y++, screenY++) {
580 Pixel* pixelPtr = workFrame->getLinePtrDirect<
Pixel>(screenY) + screenX;
581 spriteConverter->template drawMode2<DisplayMode::GRAPHIC4>(
582 y, displayX, displayLimitX, pixelPtr);
588 template <
class Pixel>
591 return postProcessor->isRecording();
594 template <
class Pixel>
597 if ((&setting == &renderSettings.getGamma()) ||
598 (&setting == &renderSettings.getBrightness()) ||
599 (&setting == &renderSettings.getContrast()) ||
600 (&setting == &renderSettings.getColorMatrix())) {
609 template class SDLRasterizer<word>;
611 #if HAVE_32BPP || COMPONENT_GL
612 template class SDLRasterizer<unsigned>;