15 std::span<const Pixel, 64> palette64_, std::span<const int16_t, 64> palette64_32768_,
16 std::span<const Pixel, 256> palette256_, std::span<const int16_t, 256> palette256_32768_,
17 std::span<const Pixel, 32768> palette32768_)
18 : vdp(vdp_), vram(vdp.getVRAM())
19 , palette64 (palette64_ ), palette64_32768 (palette64_32768_ )
20 , palette256(palette256_), palette256_32768(palette256_32768_)
21 , palette32768(palette32768_)
26template<
bool YJK,
bool PAL,
bool SKIP, std::
unsigned_
integral Pixel,
typename ColorLookup>
27static inline void draw_YJK_YUV_PAL(
29 Pixel* __restrict& out,
unsigned& address,
int firstX = 0)
31 std::array<byte, 4> data;
32 for (
auto& d : data) {
36 int u = (data[2] & 7) + ((data[3] & 3) << 3) - ((data[3] & 4) << 3);
37 int v = (data[0] & 7) + ((data[1] & 3) << 3) - ((data[1] & 4) << 3);
39 for (
auto i :
xrange(SKIP ? firstX : 0, 4)) {
40 if (PAL && (data[i] & 0x08)) {
41 *out++ = color.lookup64(data[i] >> 4);
43 int y = (data[i] & 0xF8) >> 3;
50 *out++ = color.lookup32768((
g << 10) + (r << 5) + b);
55template<std::
unsigned_
integral Pixel,
typename ColorLookup>
56static void rasterBYUV(
58 std::span<Pixel> buf,
unsigned x,
unsigned y)
60 Pixel* __restrict out = buf.data();
61 int nrPixels = narrow<int>(buf.size());
62 unsigned address = (x & ~3) + y * vdp.getImageWidth();
64 draw_YJK_YUV_PAL<false, false, true>(
65 color, vram, out, address, x & 3);
66 nrPixels -= narrow<int>(4 - (x & 3));
68 for (; nrPixels > 0; nrPixels -= 4) {
69 draw_YJK_YUV_PAL<false, false, false>(
70 color, vram, out, address);
75template<std::
unsigned_
integral Pixel,
typename ColorLookup>
76static void rasterBYUVP(
78 std::span<Pixel> buf,
unsigned x,
unsigned y)
82 Pixel* __restrict out = buf.data();
83 int nrPixels = narrow<int>(buf.size());
84 unsigned address = (x & ~3) + y * vdp.getImageWidth();
86 draw_YJK_YUV_PAL<false, true, true>(
87 color, vram, out, address, x & 3);
88 nrPixels -= narrow<int>(4 - (x & 3));
90 for (; nrPixels > 0; nrPixels -= 4) {
91 draw_YJK_YUV_PAL<false, true, false>(
92 color, vram, out, address);
97template<std::
unsigned_
integral Pixel,
typename ColorLookup>
98static void rasterBYJK(
100 std::span<Pixel> buf,
unsigned x,
unsigned y)
102 Pixel* __restrict out = buf.data();
103 int nrPixels = narrow<int>(buf.size());
104 unsigned address = (x & ~3) + y * vdp.getImageWidth();
106 draw_YJK_YUV_PAL<true, false, true>(
107 color, vram, out, address, x & 3);
108 nrPixels -= narrow<int>(4 - (x & 3));
110 for (; nrPixels > 0; nrPixels -= 4) {
111 draw_YJK_YUV_PAL<true, false, false>(
112 color, vram, out, address);
117template<std::
unsigned_
integral Pixel,
typename ColorLookup>
118static void rasterBYJKP(
120 std::span<Pixel> buf,
unsigned x,
unsigned y)
124 Pixel* __restrict out = buf.data();
125 int nrPixels = narrow<int>(buf.size());
126 unsigned address = (x & ~3) + y * vdp.getImageWidth();
128 draw_YJK_YUV_PAL<true, true, true>(
129 color, vram, out, address, x & 3);
130 nrPixels -= narrow<int>(4 - (x & 3));
132 for (; nrPixels > 0; nrPixels -= 4) {
133 draw_YJK_YUV_PAL<true, true, false>(
134 color, vram, out, address);
139template<std::
unsigned_
integral Pixel,
typename ColorLookup>
140static void rasterBD16(
142 std::span<Pixel> buf,
unsigned x,
unsigned y)
144 Pixel* __restrict out = buf.data();
145 int nrPixels = narrow<int>(buf.size());
146 unsigned address = 2 * (x + y * vdp.getImageWidth());
147 if (vdp.isSuperimposing()) {
148 auto transparent = color.lookup256(0);
149 for (; nrPixels > 0; --nrPixels) {
150 byte high = vram.readVRAMBx(address + 1);
154 byte low = vram.readVRAMBx(address + 0);
155 *out = color.lookup32768(low + 256 * high);
161 for (; nrPixels > 0; --nrPixels) {
162 byte low = vram.readVRAMBx(address++);
163 byte high = vram.readVRAMBx(address++);
164 *out++ = color.lookup32768((low + 256 * high) & 0x7FFF);
169template<std::
unsigned_
integral Pixel,
typename ColorLookup>
170static void rasterBD8(
172 std::span<Pixel> buf,
unsigned x,
unsigned y)
174 Pixel* __restrict out = buf.data();
175 int nrPixels = narrow<int>(buf.size());
176 unsigned address = x + y * vdp.getImageWidth();
177 for (; nrPixels > 0; --nrPixels) {
178 *out++ = color.lookup256(vram.readVRAMBx(address++));
182template<std::
unsigned_
integral Pixel,
typename ColorLookup>
183static void rasterBP6(
185 std::span<Pixel> buf,
unsigned x,
unsigned y)
187 Pixel* __restrict out = buf.data();
188 int nrPixels = narrow<int>(buf.size());
189 unsigned address = x + y * vdp.getImageWidth();
190 for (; nrPixels > 0; --nrPixels) {
191 *out++ = color.lookup64(vram.readVRAMBx(address++) & 0x3F);
195template<std::
unsigned_
integral Pixel,
typename ColorLookup>
196static void rasterBP4(
198 std::span<Pixel> buf,
unsigned x,
unsigned y)
200 Pixel* __restrict out = buf.data();
201 int nrPixels = narrow<int>(buf.size());
202 assert(nrPixels > 0);
203 unsigned address = (x + y * vdp.getImageWidth()) / 2;
204 color.set64Offset((vdp.getPaletteOffset() & 0xC) << 2);
206 byte data = vram.readVRAMBx(address++);
207 *out++ = color.lookup64(data & 0x0F);
210 for (; nrPixels > 0; nrPixels -= 2) {
211 byte data = vram.readVRAMBx(address++);
212 *out++ = color.lookup64(data >> 4);
213 *out++ = color.lookup64(data & 0x0F);
217template<std::
unsigned_
integral Pixel,
typename ColorLookup>
218static void rasterBP4HiRes(
220 std::span<Pixel> buf,
unsigned x,
unsigned y)
225 Pixel* __restrict out = buf.data();
226 int nrPixels = narrow<int>(buf.size());
227 unsigned address = (x + y * vdp.getImageWidth()) / 2;
228 color.set64Offset((vdp.getPaletteOffset() & 0x4) << 2);
230 byte data = vram.readVRAMBx(address++);
231 *out++ = color.lookup64(32 | (data & 0x0F));
234 for (; nrPixels > 0; nrPixels -= 2) {
235 byte data = vram.readVRAMBx(address++);
236 *out++ = color.lookup64( 0 | (data >> 4 ));
237 *out++ = color.lookup64(32 | (data & 0x0F));
242template<std::
unsigned_
integral Pixel,
typename ColorLookup>
243static void rasterBP2(
245 std::span<Pixel> buf,
unsigned x,
unsigned y)
247 Pixel* __restrict out = buf.data();
248 int nrPixels = narrow<int>(buf.size());
249 assert(nrPixels > 0);
250 unsigned address = (x + y * vdp.getImageWidth()) / 4;
251 color.set64Offset(vdp.getPaletteOffset() << 2);
253 byte data = vram.readVRAMBx(address++);
254 if ((x & 3) <= 1) *out++ = color.lookup64((data & 0x30) >> 4);
255 if ((x & 3) <= 2) *out++ = color.lookup64((data & 0x0C) >> 2);
256 if (
true) *out++ = color.lookup64((data & 0x03) >> 0);
257 nrPixels -= narrow<int>(4 - (x & 3));
259 for (; nrPixels > 0; nrPixels -= 4) {
260 byte data = vram.readVRAMBx(address++);
261 *out++ = color.lookup64((data & 0xC0) >> 6);
262 *out++ = color.lookup64((data & 0x30) >> 4);
263 *out++ = color.lookup64((data & 0x0C) >> 2);
264 *out++ = color.lookup64((data & 0x03) >> 0);
268template<std::
unsigned_
integral Pixel,
typename ColorLookup>
269static void rasterBP2HiRes(
271 std::span<Pixel> buf,
unsigned x,
unsigned y)
276 Pixel* __restrict out = buf.data();
277 int nrPixels = narrow<int>(buf.size());
278 assert(nrPixels > 0);
279 unsigned address = (x + y * vdp.getImageWidth()) / 4;
280 color.set64Offset((vdp.getPaletteOffset() & 0x7) << 2);
282 byte data = vram.readVRAMBx(address++);
283 if ((x & 3) <= 1) *out++ = color.lookup64(32 | ((data & 0x30) >> 4));
284 if ((x & 3) <= 2) *out++ = color.lookup64( 0 | ((data & 0x0C) >> 2));
285 if (
true) *out++ = color.lookup64(32 | ((data & 0x03) >> 0));
286 nrPixels -= narrow<int>(4 - (x & 3));
288 for (; nrPixels > 0; nrPixels -= 4) {
289 byte data = vram.readVRAMBx(address++);
290 *out++ = color.lookup64( 0 | ((data & 0xC0) >> 6));
291 *out++ = color.lookup64(32 | ((data & 0x30) >> 4));
292 *out++ = color.lookup64( 0 | ((data & 0x0C) >> 2));
293 *out++ = color.lookup64(32 | ((data & 0x03) >> 0));
299template<std::
unsigned_
integral Pixel>
304 std::span<const Pixel, 256> palette256_,
305 std::span<const Pixel, 32768> palette32768_)
306 : palette64Base(palette64_)
307 , palette64(palette64_)
308 , palette256(palette256_)
309 , palette32768(palette32768_)
313 void set64Offset(
size_t offset) { palette64 = palette64Base.subspan(offset); }
319 std::span<const Pixel, 64> palette64Base;
320 std::span<const Pixel> palette64;
321 std::span<const Pixel, 256> palette256;
322 std::span<const Pixel, 32768> palette32768;
330 IndexLookup(std::span<const int16_t, 64> palette64_, std::span<const int16_t, 256> palette256_)
331 : palette64_32768Base(palette64_)
332 , palette64_32768(palette64_)
333 , palette256_32768(palette256_)
337 void set64Offset(
size_t offset) { palette64_32768 = palette64_32768Base.subspan(offset); }
338 [[nodiscard]] int16_t
lookup64 (
size_t idx)
const {
return palette64_32768 [idx]; }
339 [[nodiscard]] int16_t
lookup256 (
size_t idx)
const {
return palette256_32768[idx]; }
340 [[nodiscard]] int16_t
lookup32768(
size_t idx)
const {
return int16_t(idx); }
343 std::span<const int16_t, 64> palette64_32768Base;
344 std::span<const int16_t> palette64_32768;
345 std::span<const int16_t, 256> palette256_32768;
348template<std::
unsigned_
integral Pixel,
typename ColorLookup>
351 std::span<Pixel> out,
unsigned x,
unsigned y)
354 case BYUV:
return rasterBYUV <Pixel>(color, vdp, vram, out, x, y);
355 case BYUVP:
return rasterBYUVP<Pixel>(color, vdp, vram, out, x, y);
356 case BYJK:
return rasterBYJK <Pixel>(color, vdp, vram, out, x, y);
357 case BYJKP:
return rasterBYJKP<Pixel>(color, vdp, vram, out, x, y);
358 case BD16:
return rasterBD16 <Pixel>(color, vdp, vram, out, x, y);
359 case BD8:
return rasterBD8 <Pixel>(color, vdp, vram, out, x, y);
360 case BP6:
return rasterBP6 <Pixel>(color, vdp, vram, out, x, y);
361 case BP4:
return highRes ? rasterBP4HiRes<Pixel>(color, vdp, vram, out, x, y)
362 : rasterBP4 <
Pixel>(color, vdp, vram, out, x, y);
363 case BP2:
return highRes ? rasterBP2HiRes<Pixel>(color, vdp, vram, out, x, y)
364 : rasterBP2 <
Pixel>(color, vdp, vram, out, x, y);
402 unsigned attrAddr,
unsigned patAddr,
403 int displayY,
bool drawCursor)
405 if (!drawCursor)
return;
407 unsigned attrY = vram.
readVRAMBx(attrAddr + 0) +
410 unsigned cursorLine = (displayY - attrY) & 511;
411 if (cursorLine >= 32)
return;
414 if ((attr & 0x10) || ((attr & 0xe0) == 0x00)) {
420 + (vram.
readVRAMBx(patAddr + 4 * cursorLine + 1) << 16)
421 + (vram.
readVRAMBx(patAddr + 4 * cursorLine + 2) << 8)
422 + (vram.
readVRAMBx(patAddr + 4 * cursorLine + 3) << 0);
429 x = vram.
readVRAMBx(attrAddr + 4) + (attr & 3) * 256;
431 doXor = (attr & 0xe0) == 0x20;
434 color = palette64_32768[colorIdx];
435 if (attr & 0x20)
color ^= 0x7fff;
439 return x != unsigned(-1);
441 [[nodiscard]]
bool dot()
const {
442 return (
x == 0) && (
pattern & 0x80000000);
453 unsigned x{unsigned(-1)};
460 std::span<Pixel> dst,
unsigned x,
unsigned y,
461 int cursorY,
bool drawCursors)
463 assert(dst.size() <= 1024);
465 CursorInfo cursor0(vdp, vram, palette64_32768, 0x7fe00, 0x7ff00, cursorY, drawCursors);
466 CursorInfo cursor1(vdp, vram, palette64_32768, 0x7fe08, 0x7ff80, cursorY, drawCursors);
470 std::array<uint16_t, 1024> buf;
471 raster(colorMode, highRes,
474 subspan(buf, 0, dst.size()), x, y);
481 for (
auto i :
xrange(dst.size())) {
486 buf[i] = cursor0.
color;
488 }
else if (cursor1.
dot()) {
492 buf[i] = cursor1.
color;
501 for (
auto i :
xrange(dst.size())) {
502 dst[i] = palette32768[buf[i]];
506 raster(colorMode, highRes,
508 vdp, vram, dst, x, y);
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_)
void convertLine(std::span< Pixel > dst, unsigned x, unsigned y, int cursorY, bool drawCursors)
Convert a line of VRAM into 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 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:
CharacterConverter::Pixel Pixel
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)