mirror of
https://github.com/Pecusx/libretro-atari800.git
synced 2026-05-21 14:49:36 +02:00
initial commit
This commit is contained in:
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* pal_blending.c - blitting functions that emulate PAL delay line accurately
|
||||
*
|
||||
* Copyright (C) 2013 Tomasz Krasuski
|
||||
* Copyright (C) 2013 Atari800 development team (see DOC/CREDITS)
|
||||
*
|
||||
* This file is part of the Atari800 emulator project which emulates
|
||||
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
||||
|
||||
* Atari800 is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* Atari800 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with Atari800; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "pal_blending.h"
|
||||
|
||||
#include "artifact.h"
|
||||
#include "atari.h"
|
||||
#include "colours.h"
|
||||
#include "colours_pal.h"
|
||||
#include "platform.h"
|
||||
#include "screen.h"
|
||||
|
||||
#if SUPPORTS_CHANGE_VIDEOMODE
|
||||
#include "videomode.h"
|
||||
#endif /* SUPPORTS_CHANGE_VIDEOMODE */
|
||||
|
||||
static union {
|
||||
UWORD bpp16[2][256]; /* 16-bit palette */
|
||||
ULONG bpp32[2][256]; /* 32-bit palette */
|
||||
} palette;
|
||||
|
||||
static ULONG shift_mask;
|
||||
|
||||
void PAL_BLENDING_UpdateLookup(void)
|
||||
{
|
||||
if (ARTIFACT_mode == ARTIFACT_PAL_BLEND) {
|
||||
double yuv_table[256*5];
|
||||
int even_pal[256];
|
||||
int odd_pal[256];
|
||||
int i;
|
||||
double *ptr = yuv_table;
|
||||
PLATFORM_pixel_format_t format;
|
||||
|
||||
COLOURS_PAL_GetYUV(yuv_table);
|
||||
|
||||
for (i = 0; i < 256; ++i) {
|
||||
double y = *ptr++;
|
||||
double even_u = *ptr++;
|
||||
double odd_u = *ptr++;
|
||||
double even_v = *ptr++;
|
||||
double odd_v = *ptr++;
|
||||
double r, g, b;
|
||||
Colours_YUV2RGB(y, even_u, even_v, &r, &g, &b);
|
||||
if (!COLOURS_PAL_external.loaded || COLOURS_PAL_external.adjust) {
|
||||
r = Colours_Gamma2Linear(r, COLOURS_PAL_setup.gamma);
|
||||
g = Colours_Gamma2Linear(g, COLOURS_PAL_setup.gamma);
|
||||
b = Colours_Gamma2Linear(b, COLOURS_PAL_setup.gamma);
|
||||
r = Colours_Linear2sRGB(r);
|
||||
g = Colours_Linear2sRGB(g);
|
||||
b = Colours_Linear2sRGB(b);
|
||||
}
|
||||
Colours_SetRGB(i, (int) (r * 255), (int) (g * 255), (int) (b * 255), even_pal);
|
||||
Colours_YUV2RGB(y, odd_u, odd_v, &r, &g, &b);
|
||||
if (!COLOURS_PAL_external.loaded || COLOURS_PAL_external.adjust) {
|
||||
r = Colours_Gamma2Linear(r, COLOURS_PAL_setup.gamma);
|
||||
g = Colours_Gamma2Linear(g, COLOURS_PAL_setup.gamma);
|
||||
b = Colours_Gamma2Linear(b, COLOURS_PAL_setup.gamma);
|
||||
r = Colours_Linear2sRGB(r);
|
||||
g = Colours_Linear2sRGB(g);
|
||||
b = Colours_Linear2sRGB(b);
|
||||
}
|
||||
Colours_SetRGB(i, (int) (r * 255), (int) (g * 255), (int) (b * 255), odd_pal);
|
||||
}
|
||||
PLATFORM_GetPixelFormat(&format);
|
||||
shift_mask = (format.rmask & ~(format.rmask << 1)) | (format.gmask & ~(format.gmask << 1)) | (format.bmask & ~(format.bmask << 1));
|
||||
switch (format.bpp) {
|
||||
case 16:
|
||||
PLATFORM_MapRGB(palette.bpp16[0], even_pal, 256);
|
||||
PLATFORM_MapRGB(palette.bpp16[1], odd_pal, 256);
|
||||
shift_mask |= shift_mask << 16;
|
||||
break;
|
||||
case 32:
|
||||
PLATFORM_MapRGB(palette.bpp32[0], even_pal, 256);
|
||||
PLATFORM_MapRGB(palette.bpp32[1], odd_pal, 256);
|
||||
}
|
||||
shift_mask = ~shift_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void PAL_BLENDING_Blit16(ULONG *dest, UBYTE *src, int pitch, int width, int height, int start_odd)
|
||||
{
|
||||
register ULONG quad, quad_prev;
|
||||
register UBYTE c;
|
||||
register int pos;
|
||||
UBYTE *src_prev = src;
|
||||
int odd_prev = start_odd ^ 1;
|
||||
int width_32;
|
||||
if (width & 0x01)
|
||||
width_32 = width + 1;
|
||||
else
|
||||
width_32 = width;
|
||||
while (height > 0) {
|
||||
pos = width_32;
|
||||
do {
|
||||
pos--;
|
||||
c = src[pos];
|
||||
/* Make QUAD_PREV have the same Y component as the current line's pixel. */
|
||||
quad_prev = palette.bpp16[odd_prev][(src_prev[pos] & 0xf0) | (c & 0x0f)] << 16;
|
||||
quad = palette.bpp16[start_odd][c] << 16;
|
||||
pos--;
|
||||
c = src[pos];
|
||||
quad_prev |= palette.bpp16[odd_prev][(src_prev[pos] & 0xf0) | (c & 0x0f)];
|
||||
quad |= palette.bpp16[start_odd][c];
|
||||
/* Since QUAD_PREV and QUAD have the same Y component, computing
|
||||
averages of even U/V and odd U/V is equal to computing averages
|
||||
of even and odd RGB components. */
|
||||
/* dest[pos >> 1] = ((quad+quad_prev) & shift_mask)/2; */
|
||||
dest[pos >> 1] = (quad & quad_prev) + (((quad ^ quad_prev) & shift_mask) >> 1);
|
||||
} while (pos > 0);
|
||||
src_prev = src;
|
||||
src += Screen_WIDTH;
|
||||
dest += pitch;
|
||||
height--;
|
||||
start_odd ^= 1;
|
||||
odd_prev ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void PAL_BLENDING_Blit32(ULONG *dest, UBYTE *src, int pitch, int width, int height, int start_odd)
|
||||
{
|
||||
register ULONG quad, quad_prev;
|
||||
register UBYTE c;
|
||||
register int pos;
|
||||
UBYTE *src_prev = src;
|
||||
int odd_prev = start_odd ^ 1;
|
||||
while (height > 0) {
|
||||
pos = width;
|
||||
do {
|
||||
pos--;
|
||||
c = src[pos];
|
||||
/* Make QUAD_PREV have the same Y component as the current line's pixel. */
|
||||
quad_prev = palette.bpp32[odd_prev][(src_prev[pos] & 0xf0) | (c & 0x0f)];
|
||||
quad = palette.bpp32[start_odd][c];
|
||||
/* Since QUAD_PREV and QUAD have the same Y component, computing
|
||||
averages of even U/V and odd U/V is equal to computing averages
|
||||
of even and odd RGB components. */
|
||||
/* dest[pos] = ((quad+quad_prev) & shift_mask)/2; */
|
||||
dest[pos] = (quad & quad_prev) + (((quad ^ quad_prev) & shift_mask) >> 1);
|
||||
} while (pos > 0);
|
||||
src_prev = src;
|
||||
src += Screen_WIDTH;
|
||||
dest += pitch;
|
||||
height--;
|
||||
start_odd ^= 1;
|
||||
odd_prev ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void PAL_BLENDING_BlitScaled16(ULONG *dest, UBYTE *src, int pitch, int width, int height, int dest_width, int dest_height, int start_odd)
|
||||
{
|
||||
register ULONG quad, quad_prev;
|
||||
register int x;
|
||||
int y = 0x10000;
|
||||
int w1 = dest_width / 2 - 1;
|
||||
int w = width << 16;
|
||||
int h = height << 16;
|
||||
int pos;
|
||||
register int dx = w / dest_width;
|
||||
int dy = h / dest_height;
|
||||
int init_x = (width << 16) - 0x4000;
|
||||
UBYTE *src_prev = src;
|
||||
int odd_prev = start_odd ^ 1;
|
||||
|
||||
UBYTE c;
|
||||
|
||||
while (dest_height > 0) {
|
||||
x = init_x;
|
||||
pos = w1;
|
||||
while (pos >= 0) {
|
||||
c = src[x >> 16];
|
||||
/* Make QUAD_PREV have the same Y component as the current line's pixel. */
|
||||
quad_prev = palette.bpp16[odd_prev][(src_prev[x >> 16] & 0xf0) | (c & 0x0f)] << 16;
|
||||
quad = palette.bpp16[start_odd][c] << 16;
|
||||
x -= dx;
|
||||
c = src[x >> 16];
|
||||
quad_prev |= palette.bpp16[odd_prev][(src_prev[x >> 16] & 0xf0) | (c & 0x0f)];
|
||||
quad |= palette.bpp16[start_odd][c];
|
||||
x -= dx;
|
||||
/* Since QUAD_PREV and QUAD have the same Y component, computing
|
||||
averages of even U/V and odd U/V is equal to computing averages
|
||||
of even and odd RGB components. */
|
||||
/* dest[pos] = ((quad+quad_prev) & shift_mask)/2; */
|
||||
dest[pos] = (quad & quad_prev) + (((quad ^ quad_prev) & shift_mask) >> 1);
|
||||
pos--;
|
||||
}
|
||||
dest += pitch;
|
||||
y -= dy;
|
||||
--dest_height;
|
||||
if (y < 0) {
|
||||
y += 0x10000;
|
||||
src_prev = src;
|
||||
src += Screen_WIDTH;
|
||||
start_odd ^= 1;
|
||||
odd_prev ^= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PAL_BLENDING_BlitScaled32(ULONG *dest, UBYTE *src, int pitch, int width, int height, int dest_width, int dest_height, int start_odd)
|
||||
{
|
||||
register ULONG quad, quad_prev;
|
||||
register int x;
|
||||
int y = 0x10000;
|
||||
int w1 = dest_width - 1;
|
||||
int w = width << 16;
|
||||
int h = height << 16;
|
||||
int pos;
|
||||
register int dx = w / dest_width;
|
||||
int dy = h / dest_height;
|
||||
int init_x = w - 0x4000;
|
||||
UBYTE *src_prev = src;
|
||||
int odd_prev = start_odd ^ 1;
|
||||
|
||||
UBYTE c;
|
||||
|
||||
while (dest_height > 0) {
|
||||
x = init_x;
|
||||
pos = w1;
|
||||
while (pos >= 0) {
|
||||
c = src[x >> 16];
|
||||
/* Make QUAD_PREV have the same Y component as the current line's pixel. */
|
||||
quad_prev = palette.bpp32[odd_prev][(src_prev[x >> 16] & 0xf0) | (c & 0x0f)];
|
||||
quad = palette.bpp32[start_odd][c];
|
||||
x -= dx;
|
||||
/* Since QUAD_PREV and QUAD have the same Y component, computing
|
||||
averages of even U/V and odd U/V is equal to computing averages
|
||||
of even and odd RGB components. */
|
||||
/* dest[pos] = ((quad+quad_prev) & shift_mask)/2; */
|
||||
dest[pos] = (quad & quad_prev) + (((quad ^ quad_prev) & shift_mask) >> 1);
|
||||
pos--;
|
||||
}
|
||||
dest += pitch;
|
||||
y -= dy;
|
||||
--dest_height;
|
||||
if (y < 0) {
|
||||
y += 0x10000;
|
||||
src_prev = src;
|
||||
src += Screen_WIDTH;
|
||||
start_odd ^= 1;
|
||||
odd_prev ^= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user