14template<std::
unsigned_
integral Pixel>
16 std::span<const Pixel, 16 * 2> palette16_,
17 std::span<const Pixel, 256> palette256_,
18 std::span<const Pixel, 32768> palette32768_)
19 : palette16(palette16_)
20 , palette256(palette256_)
21 , palette32768(palette32768_)
25template<std::
unsigned_
integral Pixel>
29 unsigned bits =
sizeof(
Pixel) * 8;
30 for (
auto i :
xrange(16)) {
31 DPixel p0 = palette16[i];
32 for (
auto j :
xrange(16)) {
33 DPixel p1 = palette16[j];
36 dPalette[16 * i + j] = dp;
41template<std::
unsigned_
integral Pixel>
44 switch (mode.getByte()) {
47 renderGraphic4(subspan<256>(buf), vramPtr);
51 renderGraphic5(subspan<512>(buf), vramPtr);
69 renderBogus(subspan<256>(buf));
74template<std::
unsigned_
integral Pixel>
76 std::span<Pixel> buf, std::span<const byte, 128> vramPtr0, std::span<const byte, 128> vramPtr1)
78 switch (mode.getByte()) {
81 renderGraphic6(subspan<512>(buf), vramPtr0, vramPtr1);
85 renderGraphic7(subspan<256>(buf), vramPtr0, vramPtr1);
89 renderYJK(subspan<256>(buf), vramPtr0, vramPtr1);
93 renderYAE(subspan<256>(buf), vramPtr0, vramPtr1);
106 renderBogus(subspan<256>(buf));
111template<std::
unsigned_
integral Pixel>
113 std::span<Pixel, 256> buf,
114 std::span<const byte, 128> vramPtr0)
125 if (!dPaletteValid) [[unlikely]] {
129 Pixel* __restrict pixelPtr = buf.data();
130 if ((
sizeof(
Pixel) == 2) && ((uintptr_t(pixelPtr) & 1) == 1)) {
135 const auto* in =
reinterpret_cast<const unsigned*
>(vramPtr0.data());
136 unsigned data = in[0];
138 pixelPtr[0] = palette16[(data >> 28) & 0x0F];
141 pixelPtr[0] = palette16[(data >> 0) & 0x0F];
146 auto out =
reinterpret_cast<DPixel*
>(pixelPtr);
147 for (
auto i :
xrange(256 / 8)) {
150 out[4 * i + 0] = dPalette[(data >> 24) & 0xFF];
151 out[4 * i + 1] = dPalette[(data >> 16) & 0xFF];
152 out[4 * i + 2] = dPalette[(data >> 8) & 0xFF];
153 if (i == (256-8) / 8) {
155 pixelPtr[254] = palette16[(data >> 0) & 0x0F];
160 unsigned prevData = data;
162 out[4 * i + 3] = dPalette[(prevData & 0xF0) | ((data >> 28) & 0x0F)];
166 out[4 * i + 0] = dPalette[(data >> 0) & 0xFF];
167 out[4 * i + 1] = dPalette[(data >> 8) & 0xFF];
168 out[4 * i + 2] = dPalette[(data >> 16) & 0xFF];
169 if (i != (256-8) / 8) {
171 pixelPtr[254] = palette16[(data >> 24) & 0x0F];
176 unsigned prevData = data;
178 out[4 * i + 3] = dPalette[((prevData >> 24) & 0x0F) | ((data & 0x0F)<<4)];
186 auto* out =
reinterpret_cast<DPixel*
>(pixelPtr);
187 const auto* in =
reinterpret_cast<const unsigned*
>(vramPtr0.data());
188 for (
auto i :
xrange(256 / 8)) {
190 unsigned data = in[i];
192 out[4 * i + 0] = dPalette[(data >> 24) & 0xFF];
193 out[4 * i + 1] = dPalette[(data >> 16) & 0xFF];
194 out[4 * i + 2] = dPalette[(data >> 8) & 0xFF];
195 out[4 * i + 3] = dPalette[(data >> 0) & 0xFF];
197 out[4 * i + 0] = dPalette[(data >> 0) & 0xFF];
198 out[4 * i + 1] = dPalette[(data >> 8) & 0xFF];
199 out[4 * i + 2] = dPalette[(data >> 16) & 0xFF];
200 out[4 * i + 3] = dPalette[(data >> 24) & 0xFF];
205template<std::
unsigned_
integral Pixel>
206void BitmapConverter<Pixel>::renderGraphic5(
207 std::span<Pixel, 512> buf,
208 std::span<const byte, 128> vramPtr0)
210 Pixel* __restrict pixelPtr = buf.data();
211 for (
auto i :
xrange(128)) {
212 unsigned data = vramPtr0[i];
213 pixelPtr[4 * i + 0] = palette16[ 0 + (data >> 6) ];
214 pixelPtr[4 * i + 1] = palette16[16 + ((data >> 4) & 3)];
215 pixelPtr[4 * i + 2] = palette16[ 0 + ((data >> 2) & 3)];
216 pixelPtr[4 * i + 3] = palette16[16 + ((data >> 0) & 3)];
220template<std::
unsigned_
integral Pixel>
221void BitmapConverter<Pixel>::renderGraphic6(
222 std::span<Pixel, 512> buf,
223 std::span<const byte, 128> vramPtr0,
224 std::span<const byte, 128> vramPtr1)
226 Pixel* __restrict pixelPtr = buf.data();
235 if (!dPaletteValid) [[unlikely]] {
238 auto* out =
reinterpret_cast<DPixel*
>(pixelPtr);
239 const auto* in0 =
reinterpret_cast<const unsigned*
>(vramPtr0.data());
240 const auto* in1 =
reinterpret_cast<const unsigned*
>(vramPtr1.data());
241 for (
auto i :
xrange(512 / 16)) {
243 unsigned data0 = in0[i];
244 unsigned data1 = in1[i];
246 out[8 * i + 0] = dPalette[(data0 >> 24) & 0xFF];
247 out[8 * i + 1] = dPalette[(data1 >> 24) & 0xFF];
248 out[8 * i + 2] = dPalette[(data0 >> 16) & 0xFF];
249 out[8 * i + 3] = dPalette[(data1 >> 16) & 0xFF];
250 out[8 * i + 4] = dPalette[(data0 >> 8) & 0xFF];
251 out[8 * i + 5] = dPalette[(data1 >> 8) & 0xFF];
252 out[8 * i + 6] = dPalette[(data0 >> 0) & 0xFF];
253 out[8 * i + 7] = dPalette[(data1 >> 0) & 0xFF];
255 out[8 * i + 0] = dPalette[(data0 >> 0) & 0xFF];
256 out[8 * i + 1] = dPalette[(data1 >> 0) & 0xFF];
257 out[8 * i + 2] = dPalette[(data0 >> 8) & 0xFF];
258 out[8 * i + 3] = dPalette[(data1 >> 8) & 0xFF];
259 out[8 * i + 4] = dPalette[(data0 >> 16) & 0xFF];
260 out[8 * i + 5] = dPalette[(data1 >> 16) & 0xFF];
261 out[8 * i + 6] = dPalette[(data0 >> 24) & 0xFF];
262 out[8 * i + 7] = dPalette[(data1 >> 24) & 0xFF];
267template<std::
unsigned_
integral Pixel>
268void BitmapConverter<Pixel>::renderGraphic7(
269 std::span<Pixel, 256> buf,
270 std::span<const byte, 128> vramPtr0,
271 std::span<const byte, 128> vramPtr1)
273 Pixel* __restrict pixelPtr = buf.data();
274 for (
auto i :
xrange(128)) {
275 pixelPtr[2 * i + 0] = palette256[vramPtr0[i]];
276 pixelPtr[2 * i + 1] = palette256[vramPtr1[i]];
280static constexpr std::tuple<int, int, int> yjk2rgb(
int y,
int j,
int k)
289 int b =
std::clamp((5 * y - 2 * j - k + 2) / 4, 0, 31);
293template<std::
unsigned_
integral Pixel>
294void BitmapConverter<Pixel>::renderYJK(
295 std::span<Pixel, 256> buf,
296 std::span<const byte, 128> vramPtr0,
297 std::span<const byte, 128> vramPtr1)
299 Pixel* __restrict pixelPtr = buf.data();
300 for (
auto i :
xrange(64)) {
301 std::array<unsigned, 4> p = {
307 int j = narrow<int>((p[2] & 7) + ((p[3] & 3) << 3)) - narrow<int>((p[3] & 4) << 3);
308 int k = narrow<int>((p[0] & 7) + ((p[1] & 3) << 3)) - narrow<int>((p[1] & 4) << 3);
310 for (
auto n :
xrange(4)) {
311 int y = narrow<int>(p[n] >> 3);
312 auto [r,
g, b] = yjk2rgb(y, j, k);
313 int col = (r << 10) + (
g << 5) + b;
314 pixelPtr[4 * i + n] = palette32768[col];
319template<std::
unsigned_
integral Pixel>
320void BitmapConverter<Pixel>::renderYAE(
321 std::span<Pixel, 256> buf,
322 std::span<const byte, 128> vramPtr0,
323 std::span<const byte, 128> vramPtr1)
325 Pixel* __restrict pixelPtr = buf.data();
326 for (
auto i :
xrange(64)) {
327 std::array<unsigned, 4> p = {
333 int j = narrow<int>((p[2] & 7) + ((p[3] & 3) << 3)) - narrow<int>((p[3] & 4) << 3);
334 int k = narrow<int>((p[0] & 7) + ((p[1] & 3) << 3)) - narrow<int>((p[1] & 4) << 3);
336 for (
auto n :
xrange(4)) {
340 pix = palette16[p[n] >> 4];
343 int y = narrow<int>(p[n] >> 3);
344 auto [r,
g, b] = yjk2rgb(y, j, k);
345 pix = palette32768[(r << 10) + (
g << 5) + b];
347 pixelPtr[4 * i + n] = pix;
352template<std::
unsigned_
integral Pixel>
353void BitmapConverter<Pixel>::renderBogus(std::span<Pixel, 256> buf)
364template class BitmapConverter<uint16_t>;
366#if HAVE_32BPP || COMPONENT_GL
367template class BitmapConverter<uint32_t>;
Utility class for converting VRAM contents to host pixels.
void convertLine(std::span< Pixel > buf, std::span< const byte, 128 > vramPtr)
Convert a line of V9938 VRAM to 256 or 512 host pixels.
void convertLinePlanar(std::span< Pixel > buf, std::span< const byte, 128 > vramPtr0, std::span< const byte, 128 > vramPtr1)
Convert a line of V9938 VRAM to 256 or 512 host pixels.
BitmapConverter(std::span< const Pixel, 16 *2 > palette16, std::span< const Pixel, 256 > palette256, std::span< const Pixel, 32768 > palette32768)
Create a new bitmap scanline converter.
static constexpr byte YAE
Encoding of YAE flag.
static constexpr byte YJK
Encoding of YJK flag.
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:
constexpr void fill(ForwardRange &&range, const T &value)
constexpr auto xrange(T e)