14template<std::
unsigned_
integral Pixel>
17 std::span<const Pixel, 64> palette64_, std::span<const int16_t, 64> palette64_32768_,
18 std::span<const Pixel, 256> palette256_, std::span<const int16_t, 256> palette256_32768_,
19 std::span<const Pixel, 32768> palette32768_)
20 : vdp(vdp_), vram(vdp.getVRAM())
21 , palette64 (palette64_ ), palette64_32768 (palette64_32768_ )
22 , palette256(palette256_), palette256_32768(palette256_32768_)
23 , palette32768(palette32768_)
28template<
bool YJK,
bool PAL,
bool SKIP, std::
unsigned_
integral Pixel,
typename ColorLookup>
29static inline void draw_YJK_YUV_PAL(
31 Pixel* __restrict& out,
unsigned& address,
int firstX = 0)
33 std::array<byte, 4> data;
34 for (
auto& d : data) {
38 int u = (data[2] & 7) + ((data[3] & 3) << 3) - ((data[3] & 4) << 3);
39 int v = (data[0] & 7) + ((data[1] & 3) << 3) - ((data[1] & 4) << 3);
41 for (
auto i :
xrange(SKIP ? firstX : 0, 4)) {
42 if (PAL && (data[i] & 0x08)) {
43 *out++ = color.lookup64(data[i] >> 4);
45 int y = (data[i] & 0xF8) >> 3;
52 *out++ = color.lookup32768((
g << 10) + (r << 5) + b);
57template<std::
unsigned_
integral Pixel,
typename ColorLookup>
58static void rasterBYUV(
60 std::span<Pixel> buf,
unsigned x,
unsigned y)
62 Pixel* __restrict out = buf.data();
63 int nrPixels = narrow<int>(buf.size());
64 unsigned address = (x & ~3) + y * vdp.getImageWidth();
66 draw_YJK_YUV_PAL<false, false, true>(
67 color, vram, out, address, x & 3);
68 nrPixels -= narrow<int>(4 - (x & 3));
70 for (; nrPixels > 0; nrPixels -= 4) {
71 draw_YJK_YUV_PAL<false, false, false>(
72 color, vram, out, address);
77template<std::
unsigned_
integral Pixel,
typename ColorLookup>
78static void rasterBYUVP(
80 std::span<Pixel> buf,
unsigned x,
unsigned y)
84 Pixel* __restrict out = buf.data();
85 int nrPixels = narrow<int>(buf.size());
86 unsigned address = (x & ~3) + y * vdp.getImageWidth();
88 draw_YJK_YUV_PAL<false, true, true>(
89 color, vram, out, address, x & 3);
90 nrPixels -= narrow<int>(4 - (x & 3));
92 for (; nrPixels > 0; nrPixels -= 4) {
93 draw_YJK_YUV_PAL<false, true, false>(
94 color, vram, out, address);
99template<std::
unsigned_
integral Pixel,
typename ColorLookup>
100static void rasterBYJK(
102 std::span<Pixel> buf,
unsigned x,
unsigned y)
104 Pixel* __restrict out = buf.data();
105 int nrPixels = narrow<int>(buf.size());
106 unsigned address = (x & ~3) + y * vdp.getImageWidth();
108 draw_YJK_YUV_PAL<true, false, true>(
109 color, vram, out, address, x & 3);
110 nrPixels -= narrow<int>(4 - (x & 3));
112 for (; nrPixels > 0; nrPixels -= 4) {
113 draw_YJK_YUV_PAL<true, false, false>(
114 color, vram, out, address);
119template<std::
unsigned_
integral Pixel,
typename ColorLookup>
120static void rasterBYJKP(
122 std::span<Pixel> buf,
unsigned x,
unsigned y)
126 Pixel* __restrict out = buf.data();
127 int nrPixels = narrow<int>(buf.size());
128 unsigned address = (x & ~3) + y * vdp.getImageWidth();
130 draw_YJK_YUV_PAL<true, true, true>(
131 color, vram, out, address, x & 3);
132 nrPixels -= narrow<int>(4 - (x & 3));
134 for (; nrPixels > 0; nrPixels -= 4) {
135 draw_YJK_YUV_PAL<true, true, false>(
136 color, vram, out, address);
141template<std::
unsigned_
integral Pixel,
typename ColorLookup>
142static void rasterBD16(
144 std::span<Pixel> buf,
unsigned x,
unsigned y)
146 Pixel* __restrict out = buf.data();
147 int nrPixels = narrow<int>(buf.size());
148 unsigned address = 2 * (x + y * vdp.getImageWidth());
149 if (vdp.isSuperimposing()) {
150 auto transparent = color.lookup256(0);
151 for (; nrPixels > 0; --nrPixels) {
152 byte high = vram.readVRAMBx(address + 1);
156 byte low = vram.readVRAMBx(address + 0);
157 *out = color.lookup32768(low + 256 * high);
163 for (; nrPixels > 0; --nrPixels) {
164 byte low = vram.readVRAMBx(address++);
165 byte high = vram.readVRAMBx(address++);
166 *out++ = color.lookup32768((low + 256 * high) & 0x7FFF);
171template<std::
unsigned_
integral Pixel,
typename ColorLookup>
172static void rasterBD8(
174 std::span<Pixel> buf,
unsigned x,
unsigned y)
176 Pixel* __restrict out = buf.data();
177 int nrPixels = narrow<int>(buf.size());
178 unsigned address = x + y * vdp.getImageWidth();
179 for (; nrPixels > 0; --nrPixels) {
180 *out++ = color.lookup256(vram.readVRAMBx(address++));
184template<std::
unsigned_
integral Pixel,
typename ColorLookup>
185static void rasterBP6(
187 std::span<Pixel> buf,
unsigned x,
unsigned y)
189 Pixel* __restrict out = buf.data();
190 int nrPixels = narrow<int>(buf.size());
191 unsigned address = x + y * vdp.getImageWidth();
192 for (; nrPixels > 0; --nrPixels) {
193 *out++ = color.lookup64(vram.readVRAMBx(address++) & 0x3F);
197template<std::
unsigned_
integral Pixel,
typename ColorLookup>
198static void rasterBP4(
200 std::span<Pixel> buf,
unsigned x,
unsigned y)
202 Pixel* __restrict out = buf.data();
203 int nrPixels = narrow<int>(buf.size());
204 assert(nrPixels > 0);
205 unsigned address = (x + y * vdp.getImageWidth()) / 2;
206 color.set64Offset((vdp.getPaletteOffset() & 0xC) << 2);
208 byte data = vram.readVRAMBx(address++);
209 *out++ = color.lookup64(data & 0x0F);
212 for (; nrPixels > 0; nrPixels -= 2) {
213 byte data = vram.readVRAMBx(address++);
214 *out++ = color.lookup64(data >> 4);
215 *out++ = color.lookup64(data & 0x0F);
219template<std::
unsigned_
integral Pixel,
typename ColorLookup>
220static void rasterBP4HiRes(
222 std::span<Pixel> buf,
unsigned x,
unsigned y)
227 Pixel* __restrict out = buf.data();
228 int nrPixels = narrow<int>(buf.size());
229 unsigned address = (x + y * vdp.getImageWidth()) / 2;
230 color.set64Offset((vdp.getPaletteOffset() & 0x4) << 2);
232 byte data = vram.readVRAMBx(address++);
233 *out++ = color.lookup64(32 | (data & 0x0F));
236 for (; nrPixels > 0; nrPixels -= 2) {
237 byte data = vram.readVRAMBx(address++);
238 *out++ = color.lookup64( 0 | (data >> 4 ));
239 *out++ = color.lookup64(32 | (data & 0x0F));
244template<std::
unsigned_
integral Pixel,
typename ColorLookup>
245static void rasterBP2(
247 std::span<Pixel> buf,
unsigned x,
unsigned y)
249 Pixel* __restrict out = buf.data();
250 int nrPixels = narrow<int>(buf.size());
251 assert(nrPixels > 0);
252 unsigned address = (x + y * vdp.getImageWidth()) / 4;
253 color.set64Offset(vdp.getPaletteOffset() << 2);
255 byte data = vram.readVRAMBx(address++);
256 if ((x & 3) <= 1) *out++ = color.lookup64((data & 0x30) >> 4);
257 if ((x & 3) <= 2) *out++ = color.lookup64((data & 0x0C) >> 2);
258 if (
true) *out++ = color.lookup64((data & 0x03) >> 0);
259 nrPixels -= narrow<int>(4 - (x & 3));
261 for (; nrPixels > 0; nrPixels -= 4) {
262 byte data = vram.readVRAMBx(address++);
263 *out++ = color.lookup64((data & 0xC0) >> 6);
264 *out++ = color.lookup64((data & 0x30) >> 4);
265 *out++ = color.lookup64((data & 0x0C) >> 2);
266 *out++ = color.lookup64((data & 0x03) >> 0);
270template<std::
unsigned_
integral Pixel,
typename ColorLookup>
271static void rasterBP2HiRes(
273 std::span<Pixel> buf,
unsigned x,
unsigned y)
278 Pixel* __restrict out = buf.data();
279 int nrPixels = narrow<int>(buf.size());
280 assert(nrPixels > 0);
281 unsigned address = (x + y * vdp.getImageWidth()) / 4;
282 color.set64Offset((vdp.getPaletteOffset() & 0x7) << 2);
284 byte data = vram.readVRAMBx(address++);
285 if ((x & 3) <= 1) *out++ = color.lookup64(32 | ((data & 0x30) >> 4));
286 if ((x & 3) <= 2) *out++ = color.lookup64( 0 | ((data & 0x0C) >> 2));
287 if (
true) *out++ = color.lookup64(32 | ((data & 0x03) >> 0));
288 nrPixels -= narrow<int>(4 - (x & 3));
290 for (; nrPixels > 0; nrPixels -= 4) {
291 byte data = vram.readVRAMBx(address++);
292 *out++ = color.lookup64( 0 | ((data & 0xC0) >> 6));
293 *out++ = color.lookup64(32 | ((data & 0x30) >> 4));
294 *out++ = color.lookup64( 0 | ((data & 0x0C) >> 2));
295 *out++ = color.lookup64(32 | ((data & 0x03) >> 0));
301template<std::
unsigned_
integral Pixel>
306 std::span<const Pixel, 256> palette256_,
307 std::span<const Pixel, 32768> palette32768_)
308 : palette64Base(palette64_)
309 , palette64(palette64_)
310 , palette256(palette256_)
311 , palette32768(palette32768_)
315 void set64Offset(
size_t offset) { palette64 = palette64Base.subspan(offset); }
321 std::span<const Pixel, 64> palette64Base;
322 std::span<const Pixel> palette64;
323 std::span<const Pixel, 256> palette256;
324 std::span<const Pixel, 32768> palette32768;
332 IndexLookup(std::span<const int16_t, 64> palette64_, std::span<const int16_t, 256> palette256_)
333 : palette64_32768Base(palette64_)
334 , palette64_32768(palette64_)
335 , palette256_32768(palette256_)
339 void set64Offset(
size_t offset) { palette64_32768 = palette64_32768Base.subspan(offset); }
340 [[nodiscard]] int16_t
lookup64 (
size_t idx)
const {
return palette64_32768 [idx]; }
341 [[nodiscard]] int16_t
lookup256 (
size_t idx)
const {
return palette256_32768[idx]; }
342 [[nodiscard]] int16_t
lookup32768(
size_t idx)
const {
return int16_t(idx); }
345 std::span<const int16_t, 64> palette64_32768Base;
346 std::span<const int16_t> palette64_32768;
347 std::span<const int16_t, 256> palette256_32768;
350template<std::
unsigned_
integral Pixel,
typename ColorLookup>
353 std::span<Pixel> out,
unsigned x,
unsigned y)
356 case BYUV:
return rasterBYUV <Pixel>(color, vdp, vram, out, x, y);
357 case BYUVP:
return rasterBYUVP<Pixel>(color, vdp, vram, out, x, y);
358 case BYJK:
return rasterBYJK <Pixel>(color, vdp, vram, out, x, y);
359 case BYJKP:
return rasterBYJKP<Pixel>(color, vdp, vram, out, x, y);
360 case BD16:
return rasterBD16 <Pixel>(color, vdp, vram, out, x, y);
361 case BD8:
return rasterBD8 <Pixel>(color, vdp, vram, out, x, y);
362 case BP6:
return rasterBP6 <Pixel>(color, vdp, vram, out, x, y);
363 case BP4:
return highRes ? rasterBP4HiRes<Pixel>(color, vdp, vram, out, x, y)
364 : rasterBP4 <
Pixel>(color, vdp, vram, out, x, y);
365 case BP2:
return highRes ? rasterBP2HiRes<Pixel>(color, vdp, vram, out, x, y)
366 : rasterBP2 <
Pixel>(color, vdp, vram, out, x, y);
404 unsigned attrAddr,
unsigned patAddr,
405 int displayY,
bool drawCursor)
407 if (!drawCursor)
return;
409 unsigned attrY = vram.
readVRAMBx(attrAddr + 0) +
412 unsigned cursorLine = (displayY - attrY) & 511;
413 if (cursorLine >= 32)
return;
416 if ((attr & 0x10) || ((attr & 0xe0) == 0x00)) {
422 + (vram.
readVRAMBx(patAddr + 4 * cursorLine + 1) << 16)
423 + (vram.
readVRAMBx(patAddr + 4 * cursorLine + 2) << 8)
424 + (vram.
readVRAMBx(patAddr + 4 * cursorLine + 3) << 0);
431 x = vram.
readVRAMBx(attrAddr + 4) + (attr & 3) * 256;
433 doXor = (attr & 0xe0) == 0x20;
436 color = palette64_32768[colorIdx];
437 if (attr & 0x20)
color ^= 0x7fff;
441 return x != unsigned(-1);
443 [[nodiscard]]
bool dot()
const {
444 return (
x == 0) && (
pattern & 0x80000000);
455 unsigned x{unsigned(-1)};
461template<std::
unsigned_
integral Pixel>
463 std::span<Pixel> dst,
unsigned x,
unsigned y,
464 int cursorY,
bool drawCursors)
466 assert(dst.size() <= 1024);
468 CursorInfo cursor0(vdp, vram, palette64_32768, 0x7fe00, 0x7ff00, cursorY, drawCursors);
469 CursorInfo cursor1(vdp, vram, palette64_32768, 0x7fe08, 0x7ff80, cursorY, drawCursors);
473 std::array<uint16_t, 1024> buf;
474 raster(colorMode, highRes,
477 subspan(buf, 0, dst.size()), x, y);
484 for (
auto i :
xrange(dst.size())) {
489 buf[i] = cursor0.
color;
491 }
else if (cursor1.
dot()) {
495 buf[i] = cursor1.
color;
504 for (
auto i :
xrange(dst.size())) {
505 dst[i] = palette32768[buf[i]];
509 raster(colorMode, highRes,
511 vdp, vram, dst, x, y);
519#if HAVE_32BPP || COMPONENT_GL
CursorInfo(V9990 &vdp, V9990VRAM &vram, std::span< const int16_t, 64 > palette64_32768, unsigned attrAddr, unsigned patAddr, int displayY, bool drawCursor)
int16_t lookup64(size_t idx) const
IndexLookup(std::span< const int16_t, 64 > palette64_, std::span< const int16_t, 256 > palette256_)
void set64Offset(size_t offset)
int16_t lookup256(size_t idx) const
int16_t lookup32768(size_t idx) const
Pixel lookup256(size_t idx) const
Pixel lookup64(size_t idx) const
void set64Offset(size_t offset)
Pixel lookup32768(size_t idx) const
PaletteLookup(std::span< const Pixel, 64 > palette64_, std::span< const Pixel, 256 > palette256_, std::span< const Pixel, 32768 > palette32768_)
Utility class to convert VRAM content to host pixels.
V9990BitmapConverter(V9990 &vdp, std::span< const Pixel, 64 > palette64, std::span< const int16_t, 64 > palette64_32768, std::span< const Pixel, 256 > palette256, std::span< const int16_t, 256 > palette256_32768, std::span< const Pixel, 32768 > palette32768)
void convertLine(std::span< Pixel > dst, unsigned x, unsigned y, int cursorY, bool drawCursors)
Convert a line of VRAM into host pixels.
void setColorMode(V9990ColorMode colorMode_, V9990DisplayMode display)
Set a different rendering mode.
byte readVRAMBx(unsigned address)
Implementation of the Yamaha V9990 VDP as used in the GFX9000 cartridge by Sunrise.
bool isInterlaced() const
Get interlace status.
byte getSpritePaletteOffset() const
return sprite palette offset
constexpr vecN< N, T > clamp(const vecN< N, T > &x, const vecN< N, T > &minVal, const vecN< N, T > &maxVal)
This file implemented 3 utility functions:
void swap(openmsx::MemBuffer< T > &l, openmsx::MemBuffer< T > &r) noexcept
constexpr auto subspan(Range &&range, size_t offset, size_t count=std::dynamic_extent)
constexpr auto xrange(T e)