mirror of
https://github.com/FunKey-Project/picodrive-irixxxx.git
synced 2026-05-05 04:13:36 +02:00
Merged all new changes from irixxxx (September 10th)
This commit is contained in:
@@ -338,18 +338,6 @@ static int custom_read(menu_entry *me, const char *var, const char *val)
|
||||
return 1;
|
||||
|
||||
/* PSP */
|
||||
case MA_OPT3_SCALE:
|
||||
if (strcasecmp(var, "Scale factor") != 0) return 0;
|
||||
currentConfig.scale = atof(val);
|
||||
return 1;
|
||||
case MA_OPT3_HSCALE32:
|
||||
if (strcasecmp(var, "Hor. scale (for low res. games)") != 0) return 0;
|
||||
currentConfig.hscale32 = atof(val);
|
||||
return 1;
|
||||
case MA_OPT3_HSCALE40:
|
||||
if (strcasecmp(var, "Hor. scale (for hi res. games)") != 0) return 0;
|
||||
currentConfig.hscale40 = atof(val);
|
||||
return 1;
|
||||
case MA_OPT3_VSYNC:
|
||||
// XXX: use enum
|
||||
if (strcasecmp(var, "Wait for vsync") != 0) return 0;
|
||||
|
||||
@@ -1504,7 +1504,7 @@ void emu_cmn_forced_frame(int no_scale, int do_emu, void *buf)
|
||||
memset32((short *)g_screen_ptr + g_screen_ppitch * y, 0,
|
||||
g_screen_width * 2 / 4);
|
||||
|
||||
PicoIn.opt &= ~POPT_ALT_RENDERER;
|
||||
PicoIn.opt &= ~(POPT_ALT_RENDERER|POPT_EN_SOFTSCALE);
|
||||
PicoIn.opt |= POPT_ACC_SPRITES;
|
||||
if (!no_scale && currentConfig.scaling)
|
||||
PicoIn.opt |= POPT_EN_SOFTSCALE;
|
||||
|
||||
@@ -37,8 +37,26 @@ extern int g_screen_ppitch; // pitch in pixels
|
||||
|
||||
enum {
|
||||
EOPT_SCALE_NONE = 0,
|
||||
EOPT_SCALE_SW,
|
||||
// linux, GP2X:
|
||||
EOPT_SCALE_SW = 1,
|
||||
EOPT_SCALE_HW,
|
||||
// PSP horiz:
|
||||
EOPT_SCALE_43 = 1, // DAR 4:3 (12:9)
|
||||
EOPT_SCALE_WIDE, // DAR 14:9
|
||||
EOPT_SCALE_FULL, // DAR 16:9
|
||||
// PSP vert:
|
||||
EOPT_VSCALE_PAL = 1, // always 240 lines
|
||||
EOPT_VSCALE_FULL, // zoomed to full height
|
||||
};
|
||||
|
||||
enum {
|
||||
EOPT_FILTER_NONE = 0,
|
||||
// PSP texture filtering
|
||||
EOPT_FILTER_BILINEAR = 1,
|
||||
// software scalers
|
||||
EOPT_FILTER_SMOOTHER = 1,
|
||||
EOPT_FILTER_BILINEAR1,
|
||||
EOPT_FILTER_BILINEAR2,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -63,16 +81,14 @@ typedef struct _currentConfig_t {
|
||||
int CPUclock;
|
||||
int volume;
|
||||
int gamma;
|
||||
int scaling; // gp2x: EOPT_SCALE_*; psp: bilinear filtering
|
||||
int scaling; // EOPT_SCALE_*
|
||||
int vscaling;
|
||||
int rotation; // for UIQ
|
||||
float scale; // psp: screen scale
|
||||
float hscale32, hscale40; // psp: horizontal scale
|
||||
int gamma2; // psp: black level
|
||||
int turbo_rate;
|
||||
int renderer;
|
||||
int renderer32x;
|
||||
int filter; // pandora
|
||||
int filter; // EOPT_FILTER_* video filter
|
||||
int analog_deadzone;
|
||||
int msh2_khz;
|
||||
int ssh2_khz;
|
||||
@@ -196,6 +212,7 @@ void plat_update_volume(int has_changed, int is_up);
|
||||
/* should be in libpicofe/plat.h */
|
||||
void plat_video_clear_status(void);
|
||||
void plat_video_clear_buffers(void);
|
||||
void plat_video_set_size(int w, int h);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
@@ -125,13 +125,7 @@ typedef enum
|
||||
MA_OPT2_MAX_FRAMESKIP,
|
||||
MA_OPT2_PWM_IRQ_OPT,
|
||||
MA_OPT2_DONE,
|
||||
MA_OPT3_SCALE, /* psp (all OPT3) */
|
||||
MA_OPT3_HSCALE32,
|
||||
MA_OPT3_HSCALE40,
|
||||
MA_OPT3_GAMMAA,
|
||||
MA_OPT3_PRES_NOSCALE,
|
||||
MA_OPT3_PRES_SCALE43,
|
||||
MA_OPT3_PRES_FULLSCR,
|
||||
MA_OPT3_GAMMAA, /* psp (all OPT3) */
|
||||
MA_OPT3_FILTERING,
|
||||
MA_OPT3_VSYNC,
|
||||
MA_OPT3_BLACKLVL,
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#define Weight1_1(A, B) (Half(A) + Half(B) + Corr1_1(A, B))
|
||||
|
||||
static void *shadow_fb;
|
||||
static struct area { int w, h; } area;
|
||||
|
||||
static struct in_pdata in_sdl_platform_data = {
|
||||
.defbinds = in_sdl_defbinds,
|
||||
@@ -144,39 +145,44 @@ void bgr_to_uyvy_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
void rgb565_to_uyvy(void *d, const void *s, int pixels, int x2)
|
||||
void rgb565_to_uyvy(void *d, const void *s, int w, int h, int pitch, int x2)
|
||||
{
|
||||
uint32_t *dst = d;
|
||||
const uint16_t *src = s;
|
||||
int i;
|
||||
|
||||
if (x2)
|
||||
for (; pixels > 0; src += 4, dst += 4, pixels -= 4)
|
||||
{
|
||||
struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
|
||||
struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
|
||||
if (x2) while (h--) {
|
||||
for (i = w; i > 0; src += 4, dst += 4, i -= 4)
|
||||
{
|
||||
struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
|
||||
struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
|
||||
#if CPU_IS_LE
|
||||
dst[0] = (uyvy0->y << 24) | uyvy0->vyu;
|
||||
dst[1] = (uyvy1->y << 24) | uyvy1->vyu;
|
||||
dst[2] = (uyvy2->y << 24) | uyvy2->vyu;
|
||||
dst[3] = (uyvy3->y << 24) | uyvy3->vyu;
|
||||
dst[0] = (uyvy0->y << 24) | uyvy0->vyu;
|
||||
dst[1] = (uyvy1->y << 24) | uyvy1->vyu;
|
||||
dst[2] = (uyvy2->y << 24) | uyvy2->vyu;
|
||||
dst[3] = (uyvy3->y << 24) | uyvy3->vyu;
|
||||
#else
|
||||
dst[0] = uyvy0->y | (uyvy0->vyu << 8);
|
||||
dst[1] = uyvy1->y | (uyvy1->vyu << 8);
|
||||
dst[2] = uyvy2->y | (uyvy2->vyu << 8);
|
||||
dst[3] = uyvy3->y | (uyvy3->vyu << 8);
|
||||
dst[0] = uyvy0->y | (uyvy0->vyu << 8);
|
||||
dst[1] = uyvy1->y | (uyvy1->vyu << 8);
|
||||
dst[2] = uyvy2->y | (uyvy2->vyu << 8);
|
||||
dst[3] = uyvy3->y | (uyvy3->vyu << 8);
|
||||
#endif
|
||||
} else
|
||||
for (; pixels > 0; src += 4, dst += 2, pixels -= 4)
|
||||
{
|
||||
struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
|
||||
struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
|
||||
}
|
||||
src += pitch - w;
|
||||
} else while (h--) {
|
||||
for (i = w; i > 0; src += 4, dst += 2, i -= 4)
|
||||
{
|
||||
struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
|
||||
struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
|
||||
#if CPU_IS_LE
|
||||
dst[0] = (uyvy1->y << 24) | uyvy0->vyu;
|
||||
dst[1] = (uyvy3->y << 24) | uyvy2->vyu;
|
||||
dst[0] = (uyvy1->y << 24) | uyvy0->vyu;
|
||||
dst[1] = (uyvy3->y << 24) | uyvy2->vyu;
|
||||
#else
|
||||
dst[0] = uyvy1->y | (uyvy0->vyu << 8);
|
||||
dst[1] = uyvy3->y | (uyvy2->vyu << 8);
|
||||
dst[0] = uyvy1->y | (uyvy0->vyu << 8);
|
||||
dst[1] = uyvy3->y | (uyvy2->vyu << 8);
|
||||
#endif
|
||||
}
|
||||
src += pitch - w;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1511,16 +1517,34 @@ void SDL_Rotate_270(SDL_Surface * hw_surface, SDL_Surface * virtual_hw_surface){
|
||||
|
||||
static int clear_buf_cnt, clear_stat_cnt;
|
||||
|
||||
void plat_video_set_size(int w, int h)
|
||||
{
|
||||
if (area.w != w || area.h != h) {
|
||||
area = (struct area) { w, h };
|
||||
|
||||
if (plat_sdl_change_video_mode(w, h, 0) < 0) {
|
||||
// failed, revert to original resolution
|
||||
plat_sdl_change_video_mode(g_screen_width, g_screen_height, 0);
|
||||
w = g_screen_width, h = g_screen_height;
|
||||
}
|
||||
if (!plat_sdl_overlay && !plat_sdl_gl_active) {
|
||||
g_screen_width = w;
|
||||
g_screen_height = h;
|
||||
g_screen_ppitch = w;
|
||||
g_screen_ptr = plat_sdl_screen->pixels;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plat_video_flip(void)
|
||||
{
|
||||
if (plat_sdl_overlay != NULL) {
|
||||
SDL_Rect dstrect =
|
||||
{ 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
|
||||
|
||||
SDL_LockYUVOverlay(plat_sdl_overlay);
|
||||
rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
|
||||
g_screen_ppitch * g_screen_height,
|
||||
plat_sdl_overlay->w > 2*plat_sdl_overlay->h);
|
||||
area.w, area.h, g_screen_ppitch,
|
||||
plat_sdl_overlay->w >= 2*area.w);
|
||||
SDL_UnlockYUVOverlay(plat_sdl_overlay);
|
||||
SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
|
||||
}
|
||||
@@ -1696,7 +1720,7 @@ void plat_video_menu_end(void)
|
||||
|
||||
SDL_LockYUVOverlay(plat_sdl_overlay);
|
||||
rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
|
||||
g_menuscreen_pp * g_menuscreen_h, 0);
|
||||
g_menuscreen_w, g_menuscreen_h, g_menuscreen_pp, 0);
|
||||
SDL_UnlockYUVOverlay(plat_sdl_overlay);
|
||||
|
||||
SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
|
||||
@@ -1723,10 +1747,10 @@ void plat_video_menu_leave(void)
|
||||
|
||||
void plat_video_loop_prepare(void)
|
||||
{
|
||||
// take over any new vout settings XXX ask plat_sdl for scaling instead!
|
||||
// take over any new vout settings
|
||||
plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, 0);
|
||||
// switch over to scaled output if available
|
||||
if (plat_sdl_overlay != NULL || plat_sdl_gl_active || currentConfig.scaling != EOPT_SCALE_NONE) {
|
||||
if (plat_sdl_overlay != NULL || plat_sdl_gl_active) {
|
||||
g_screen_width = 320;
|
||||
g_screen_height = 240;
|
||||
g_screen_ppitch = g_screen_width;
|
||||
@@ -1742,6 +1766,7 @@ void plat_video_loop_prepare(void)
|
||||
g_screen_ptr = plat_sdl_screen->pixels;
|
||||
}
|
||||
plat_video_set_buffer(g_screen_ptr);
|
||||
plat_video_set_size(g_screen_width, g_screen_height);
|
||||
}
|
||||
|
||||
void plat_early_init(void)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* nn: nearest neighbour
|
||||
* snn: "smoothed" nearest neighbour (see below)
|
||||
* bln: n-level-bilinear with n quantized weights
|
||||
* quantization: 0: a<1/2*n, 1/n: 1/2*n<=a<3/2*n, etc
|
||||
* quantization: 0: a<1/(2*n), 1/n: 1/(2*n)<=a<3/(2*n), etc
|
||||
* currently n=2, n=4 are implemented (there's n=8 mixing, but no filters)
|
||||
* [NB this has been brought to my attn, which is probably the same as bl2:
|
||||
* https://www.drdobbs.com/image-scaling-with-bresenham/184405045?pgno=1]
|
||||
@@ -18,490 +18,586 @@
|
||||
* a sharper look than a bilinear filter, at the price of some visible jags
|
||||
* on diagonal edges.
|
||||
*
|
||||
* scaling modes:
|
||||
* 256x___ -> 320x___ only horizontal scaling. Produces an aspect error of
|
||||
* ~7% for NTSC 224 line modes, but is correct for PAL
|
||||
* 256/320x224/240
|
||||
* -> 320x240 always produces 320x240 at DAR 4:3
|
||||
* 160x144 -> 320x240 game gear (currently unused)
|
||||
* example scaling modes:
|
||||
* 256x_Y_ -> 320x_Y_, H32/mode 4, PAR 5:4, for PAL DAR 4:3 (NTSC 7% aspect err)
|
||||
* 256x224 -> 320x240, H32/mode 4, PAR 5:4, for NTSC DAR 4:3 (PAL 7% aspect err)
|
||||
* 320x224 -> 320x240, PAR 1:1, for NTSC, DAR 4:3 (PAL 7% etc etc...)
|
||||
* 160x144 -> 320x240: GG, PAR 6:5, scaling to 320x240 for DAR 4:3
|
||||
*
|
||||
* (C) 2021 kub <derkub@gmail.com>
|
||||
*/
|
||||
|
||||
#include "upscale.h"
|
||||
|
||||
/* 256x___ -> 320x___, H32/mode 4, PAR 5:4, for PAL DAR 4:3 (wrong for NTSC) */
|
||||
void upscale_clut_nn_256_320x___(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int height)
|
||||
/* X x Y -> X*5/4 x Y */
|
||||
void upscale_clut_nn_x_4_5(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
|
||||
{
|
||||
int y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
h_upscale_nn_4_5(di, ds, si, ss, 256, f_nop);
|
||||
h_upscale_nn_4_5(di, ds, si, ss, width, f_nop);
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_nn_256_320x___(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int height, u16 *pal)
|
||||
void upscale_rgb_nn_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
h_upscale_nn_4_5(di, ds, si, ss, 256, f_pal);
|
||||
h_upscale_nn_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_snn_256_320x___(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int height, u16 *pal)
|
||||
void upscale_rgb_snn_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
h_upscale_snn_4_5(di, ds, si, ss, 256, f_pal);
|
||||
h_upscale_snn_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl2_256_320x___(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int height, u16 *pal)
|
||||
void upscale_rgb_bl2_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
h_upscale_bl2_4_5(di, ds, si, ss, 256, f_pal);
|
||||
h_upscale_bl2_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl4_256_320x___(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int height, u16 *pal)
|
||||
void upscale_rgb_bl4_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
h_upscale_bl4_4_5(di, ds, si, ss, 256, f_pal);
|
||||
h_upscale_bl4_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
}
|
||||
|
||||
/* 256x224 -> 320x240, H32/mode 4, PAR 5:4, for NTSC DAR 4:3 (wrong for PAL) */
|
||||
void upscale_clut_nn_256_320x224_240(u8 *__restrict di, int ds, u8 *__restrict si, int ss)
|
||||
/* X x Y -> X*5/4 x Y*17/16 */
|
||||
void upscale_clut_nn_x_4_5_y_16_17(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
|
||||
{
|
||||
int swidth = width * 5/4;
|
||||
int y, j;
|
||||
|
||||
/* 14:15, 0 1 2 3 4 5 6 6 7 8 9 10 11 12 13 */
|
||||
for (y = 0; y < 224; y += 14) {
|
||||
/* lines 0-6 */
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_upscale_nn_4_5(di, ds, si, ss, 256, f_nop);
|
||||
}
|
||||
/* lines 8-14 */
|
||||
di += ds;
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_upscale_nn_4_5(di, ds, si, ss, 256, f_nop);
|
||||
}
|
||||
/* line 7 */
|
||||
di -= 8*ds;
|
||||
v_copy(&di[0], &di[-ds], 320, f_nop);
|
||||
di += 8*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_nn_256_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < 224; y += 14) {
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_upscale_nn_4_5(di, ds, si, ss, 256, f_pal);
|
||||
for (y = 0; y < height; y += 16) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
h_upscale_nn_4_5(di, ds, si, ss, width, f_nop);
|
||||
}
|
||||
di += ds;
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_upscale_nn_4_5(di, ds, si, ss, 256, f_pal);
|
||||
for (j = 0; j < 8; j++) {
|
||||
h_upscale_nn_4_5(di, ds, si, ss, width, f_nop);
|
||||
}
|
||||
|
||||
di -= 8*ds;
|
||||
v_copy(&di[0], &di[-ds], 320, f_nop);
|
||||
di += 8*ds;
|
||||
di -= 9*ds;
|
||||
v_copy(&di[0], &di[-ds], swidth, f_nop);
|
||||
di += 9*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_snn_256_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
void upscale_rgb_nn_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int swidth = width * 5/4;
|
||||
int y, j;
|
||||
|
||||
/* 14:15, 0 1 2 3 4 5 5+6 6+7 7+8 8 9 10 11 12 13 */
|
||||
for (y = 0; y < 224; y += 14) {
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_upscale_snn_4_5(di, ds, si, ss, 256, f_pal);
|
||||
for (y = 0; y < height; y += 16) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
h_upscale_nn_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di += ds;
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_upscale_snn_4_5(di, ds, si, ss, 256, f_pal);
|
||||
for (j = 0; j < 8; j++) {
|
||||
h_upscale_nn_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
|
||||
di -= 9*ds;
|
||||
v_copy(&di[0], &di[-ds], swidth, f_nop);
|
||||
di += 9*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_snn_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int swidth = width * 5/4;
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < height; y += 16) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
h_upscale_snn_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di += ds;
|
||||
for (j = 0; j < 8; j++) {
|
||||
h_upscale_snn_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
|
||||
/* mix lines 6-8 */
|
||||
di -= 8*ds;
|
||||
v_mix(&di[0], &di[-ds], &di[ds], 320, p_05, f_nop);
|
||||
v_mix(&di[-ds], &di[-2*ds], &di[-ds], 320, p_05, f_nop);
|
||||
v_mix(&di[ ds], &di[ ds], &di[ 2*ds], 320, p_05, f_nop);
|
||||
di += 8*ds;
|
||||
di -= 9*ds;
|
||||
v_mix(&di[0], &di[-ds], &di[ds], swidth, p_05, f_nop);
|
||||
v_mix(&di[-ds], &di[-2*ds], &di[-ds], swidth, p_05, f_nop);
|
||||
v_mix(&di[ ds], &di[ ds], &di[ 2*ds], swidth, p_05, f_nop);
|
||||
di += 9*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bln_256_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
void upscale_rgb_bl2_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int swidth = width * 5/4;
|
||||
int y, j;
|
||||
|
||||
/* 14:15, 0 1 2 2+3 3+4 4+5 5+6 6+7 7+8 8+9 9+10 10+11 11 12 13 */
|
||||
for (y = 0; y < 224; y += 14) {
|
||||
/* lines 0-2 */
|
||||
for (j = 0; j < 3; j++) {
|
||||
h_upscale_bln_4_5(di, ds, si, ss, 256, f_pal);
|
||||
for (y = 0; y < height; y += 16) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
h_upscale_bl2_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
/* lines 3-11 mixing prep */
|
||||
di += ds;
|
||||
for (j = 0; j < 11; j++) {
|
||||
h_upscale_bln_4_5(di, ds, si, ss, 256, f_pal);
|
||||
di += ds;
|
||||
for (j = 0; j < 12; j++) {
|
||||
h_upscale_bl2_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di -= 12*ds;
|
||||
/* mixing line 3: line 2 = -ds, line 3 = +ds */
|
||||
v_mix(&di[0], &di[-ds], &di[ds], 320, p_025, f_nop);
|
||||
/* mix lines 3-10 */
|
||||
di -= 13*ds;
|
||||
v_mix(&di[0], &di[-ds], &di[ds], swidth, p_05, f_nop);
|
||||
for (j = 0; j < 7; j++) {
|
||||
di += ds;
|
||||
/* mixing lines 4-5: line n-1 = 0, line n = +ds */
|
||||
v_mix(&di[0], &di[0], &di[ds], swidth, p_05, f_nop);
|
||||
}
|
||||
di += 6*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl4_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int swidth = width * 5/4;
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < height; y += 16) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_025, f_nop);
|
||||
h_upscale_bl4_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di += ds;
|
||||
for (j = 0; j < 14; j++) {
|
||||
h_upscale_bl4_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di -= 15*ds;
|
||||
/* mixing line 2: line 1 = -ds, line 2 = +ds */
|
||||
v_mix(&di[0], &di[-ds], &di[ds], swidth, p_025, f_nop);
|
||||
di += ds;
|
||||
/* mixing lines 3-5: line n-1 = 0, line n = +ds */
|
||||
for (j = 0; j < 3; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], swidth, p_025, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* mixing line 6-8 */
|
||||
for (j = 0; j < 3; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_05, f_nop);
|
||||
/* mixing lines 6-9 */
|
||||
for (j = 0; j < 4; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], swidth, p_05, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* mixing lines 9-11 */
|
||||
for (j = 0; j < 3; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_075, f_nop);
|
||||
/* mixing lines 10-13 */
|
||||
for (j = 0; j < 4; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], swidth, p_075, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* lines 12-14, already in place */
|
||||
/* lines 14-16, already in place */
|
||||
di += 3*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl2_256_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
/* "classic" upscaler as found in several emulators. It's really more like a
|
||||
* x*4/3, y*16/15 upscaler, with an additional 5th row/17th line just inserted
|
||||
* from the source image. That gives nice n/4,n/16 alpha values plus better
|
||||
* symmetry in each block and avoids "borrowing" a row/line between blocks.
|
||||
*/
|
||||
void upscale_rgb_bln_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int swidth = width * 5/4;
|
||||
int y, j;
|
||||
|
||||
/* 14:15, 0 1 2 2+3 3+4 4+5 5+6 6+7 7+8 8+9 9+10 10 11 12 13 */
|
||||
for (y = 0; y < 224; y += 14) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
h_upscale_bl2_4_5(di, ds, si, ss, 256, f_pal);
|
||||
for (y = 0; y < height; y += 16) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
h_upscale_bln_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di += ds;
|
||||
for (j = 0; j < 11; j++) {
|
||||
h_upscale_bl2_4_5(di, ds, si, ss, 256, f_pal);
|
||||
}
|
||||
/* mix lines 3-10 */
|
||||
di -= 12*ds;
|
||||
v_mix(&di[0], &di[-ds], &di[ds], 320, p_05, f_nop);
|
||||
for (j = 0; j < 7; j++) {
|
||||
di += ds;
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_05, f_nop);
|
||||
}
|
||||
di += 5*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl4_256_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
/* 14:15, 0 0+1 1+2 2+3 3+4 4+5 5+6 6+7 7+8 8+9 9+10 10+11 11+12 12 13 */
|
||||
for (y = 0; y < 224; y += 14) {
|
||||
/* line 0 */
|
||||
h_upscale_bl4_4_5(di, ds, si, ss, 256, f_pal);
|
||||
/* lines 1-14 mixing prep */
|
||||
di += ds;
|
||||
for (j = 0; j < 13; j++) {
|
||||
h_upscale_bl4_4_5(di, ds, si, ss, 256, f_pal);
|
||||
for (j = 0; j < 12; j++) {
|
||||
h_upscale_bln_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di -= 14*ds;
|
||||
/* mixing line 1: line 0 = -ds, line 1 = +ds */
|
||||
v_mix(&di[0], &di[-ds], &di[ds], 320, p_025, f_nop);
|
||||
di -= 13*ds;
|
||||
/* mixing line 4: line 3 = -ds, line 4 = +ds */
|
||||
v_mix(&di[0], &di[-ds], &di[ds], swidth, p_025, f_nop);
|
||||
di += ds;
|
||||
/* mixing lines 2-4: line n-1 = 0, line n = +ds */
|
||||
for (j = 0; j < 3; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_025, f_nop);
|
||||
/* mixing lines 5-6: line n-1 = 0, line n = +ds */
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], swidth, p_025, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* mixing lines 5-8 */
|
||||
for (j = 0; j < 4; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_05, f_nop);
|
||||
/* mixing line 7-9 */
|
||||
for (j = 0; j < 3; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], swidth, p_05, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* mixing lines 9-12 */
|
||||
for (j = 0; j < 4; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_075, f_nop);
|
||||
/* mixing lines 10-12 */
|
||||
for (j = 0; j < 3; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], swidth, p_075, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* lines 13-14, already in place */
|
||||
di += 2*ds;
|
||||
/* lines 13-16, already in place */
|
||||
di += 4*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl8_256_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
/* experimental 8 level bilinear for quality assessment */
|
||||
void upscale_rgb_bl8_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y, j, d;
|
||||
int swidth = width * 5/4;
|
||||
int y, j;
|
||||
|
||||
/* 14:15, -1+0 0+1 1+2 2+3 3+4 4+5 5+6 6+7 7+8 8+9 9+10 10+11 11+12 12+13 13 */
|
||||
for (y = 0, d = ds; y < 224; y += 14, d = -ds) {
|
||||
/* lines 0-14 mixing prep */
|
||||
for (y = 0; y < 224; y += 16) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
h_upscale_bl8_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di += ds;
|
||||
for (j = 0; j < 14; j++) {
|
||||
h_upscale_bl8_4_5(di, ds, si, ss, 256, f_pal);
|
||||
h_upscale_bl8_4_5(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di -= 15*ds;
|
||||
/* mixing line 0: line 0 = -ds, line 1 = +ds */
|
||||
v_mix(&di[0], &di[d], &di[ds], 320, p_0125, f_nop);
|
||||
/* mixing line 2: line 2 = -ds, line 3 = +ds */
|
||||
v_mix(&di[0], &di[-ds], &di[ds], swidth, p_0125, f_nop);
|
||||
di += ds;
|
||||
/* mixing line 1: line 1 = 0, line 2 = +ds */
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_0125, f_nop);
|
||||
/* mixing line 3: line 3 = 0, line 4 = +ds */
|
||||
v_mix(&di[0], &di[0], &di[ds], swidth, p_0125, f_nop);
|
||||
di += ds;
|
||||
/* mixing lines 2-3: line n-1 = 0, line n = +ds */
|
||||
/* mixing lines 4-5: line n-1 = 0, line n = +ds */
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_025, f_nop);
|
||||
v_mix(&di[0], &di[0], &di[ds], swidth, p_025, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* mixing lines 4-5 */
|
||||
/* mixing lines 6-7 */
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_0375, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* mixing lines 6-7 */
|
||||
/* mixing lines 8-9 */
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_05, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* mixing lines 8-9 */
|
||||
/* mixing lines 10-11 */
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_0625, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* mixing lines 10-11 */
|
||||
/* mixing lines 12-13 */
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_075, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* mixing lines 12-13 */
|
||||
/* mixing lines 14-15 */
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], 320, p_0875, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* line 14, already in place */
|
||||
/* line 16, already in place */
|
||||
di += ds;
|
||||
}
|
||||
}
|
||||
|
||||
/* 320x224 -> 320x240, PAR 1:1, for NTSC, DAR 4:3 (wrong for PAL) */
|
||||
void upscale_clut_nn_320x224_240(u8 *__restrict di, int ds, u8 *__restrict si, int ss)
|
||||
/* X x Y -> X x Y*17/16 */
|
||||
void upscale_clut_nn_y_16_17(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < 224; y += 14) {
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_copy(di, ds, si, ss, 320, f_nop);
|
||||
}
|
||||
di += ds;
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_copy(di, ds, si, ss, 320, f_nop);
|
||||
}
|
||||
|
||||
di -= 8*ds;
|
||||
v_copy(&di[0], &di[-ds], 320, f_nop);
|
||||
di += 8*ds;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_nn_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < 224; y += 14) {
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_copy(di, ds, si, ss, 320, f_pal);
|
||||
}
|
||||
di += ds;
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_copy(di, ds, si, ss, 320, f_pal);
|
||||
}
|
||||
|
||||
di -= 8*ds;
|
||||
v_copy(&di[0], &di[-ds], 320, f_nop);
|
||||
di += 8*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_snn_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < 224; y += 14) {
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_copy(di, ds, si, ss, 320, f_pal);
|
||||
}
|
||||
di += ds;
|
||||
for (j = 0; j < 7; j++) {
|
||||
h_copy(di, ds, si, ss, 320, f_pal);
|
||||
}
|
||||
|
||||
di -= 8*ds;
|
||||
v_mix(&di[ 0], &di[-ds], &di[ds], 320, p_05, f_nop);
|
||||
v_mix(&di[-ds], &di[-2*ds], &di[-ds], 320, p_05, f_nop);
|
||||
v_mix(&di[ ds], &di[ ds], &di[ 2*ds], 320, p_05, f_nop);
|
||||
di += 8*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl2_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < 224; y += 14) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
h_copy(di, ds, si, ss, 320, f_pal);
|
||||
}
|
||||
for (y = 0; y < height; y += 16) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
v_mix(&di[0], &si[-ss], &si[0], 320, p_05, f_pal);
|
||||
di += ds;
|
||||
si += ss;
|
||||
h_copy(di, ds, si, ss, width, f_nop);
|
||||
}
|
||||
si -= ss;
|
||||
for (j = 0; j < 4; j++) {
|
||||
h_copy(di, ds, si, ss, 320, f_pal);
|
||||
di += ds;
|
||||
for (j = 0; j < 8; j++) {
|
||||
h_copy(di, ds, si, ss, width, f_nop);
|
||||
}
|
||||
|
||||
di -= 9*ds;
|
||||
v_copy(&di[0], &di[-ds], width, f_nop);
|
||||
di += 9*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl4_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
void upscale_rgb_nn_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < 224; y += 14) {
|
||||
h_copy(di, ds, si, ss, 320, f_pal);
|
||||
for (j = 0; j < 4; j++) {
|
||||
v_mix(&di[0], &si[-ss], &si[0], 320, p_025, f_pal);
|
||||
di += ds;
|
||||
si += ss;
|
||||
for (y = 0; y < height; y += 16) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
h_copy(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
for (j = 0; j < 4; j++) {
|
||||
v_mix(&di[0], &si[-ss], &si[0], 320, p_05, f_pal);
|
||||
di += ds;
|
||||
si += ss;
|
||||
di += ds;
|
||||
for (j = 0; j < 8; j++) {
|
||||
h_copy(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
for (j = 0; j < 4; j++) {
|
||||
v_mix(&di[0], &si[-ss], &si[0], 320, p_075, f_pal);
|
||||
di += ds;
|
||||
si += ss;
|
||||
|
||||
di -= 9*ds;
|
||||
v_copy(&di[0], &di[-ds], width, f_nop);
|
||||
di += 9*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_snn_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < height; y += 16) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
h_copy(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
si -= ss;
|
||||
di += ds;
|
||||
for (j = 0; j < 8; j++) {
|
||||
h_copy(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
|
||||
/* mix lines 6-8 */
|
||||
di -= 9*ds;
|
||||
v_mix(&di[0], &di[-ds], &di[ds], width, p_05, f_nop);
|
||||
v_mix(&di[-ds], &di[-2*ds], &di[-ds], width, p_05, f_nop);
|
||||
v_mix(&di[ ds], &di[ ds], &di[ 2*ds], width, p_05, f_nop);
|
||||
di += 9*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl2_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < height; y += 16) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
h_copy(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di += ds;
|
||||
for (j = 0; j < 12; j++) {
|
||||
h_copy(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
/* mix lines 3-10 */
|
||||
di -= 13*ds;
|
||||
v_mix(&di[0], &di[-ds], &di[ds], width, p_05, f_nop);
|
||||
for (j = 0; j < 7; j++) {
|
||||
di += ds;
|
||||
v_mix(&di[0], &di[0], &di[ds], width, p_05, f_nop);
|
||||
}
|
||||
di += 6*ds;
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl4_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < height; y += 16) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
h_copy(di, ds, si, ss, 320, f_pal);
|
||||
h_copy(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di += ds;
|
||||
for (j = 0; j < 14; j++) {
|
||||
h_copy(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di -= 15*ds;
|
||||
/* mixing line 2: line 1 = -ds, line 2 = +ds */
|
||||
v_mix(&di[0], &di[-ds], &di[ds], width, p_025, f_nop);
|
||||
di += ds;
|
||||
/* mixing lines 3-5: line n-1 = 0, line n = +ds */
|
||||
for (j = 0; j < 3; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], width, p_025, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* mixing lines 6-9 */
|
||||
for (j = 0; j < 4; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], width, p_05, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* mixing lines 10-13 */
|
||||
for (j = 0; j < 4; j++) {
|
||||
v_mix(&di[0], &di[0], &di[ds], width, p_075, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* lines 14-16, already in place */
|
||||
di += 3*ds;
|
||||
}
|
||||
}
|
||||
|
||||
/* 160x144 -> 320x240: GG, PAR 6:5, scaling to 320x240 for DAR 4:3 */
|
||||
/* NB for smoother image could scale to 288x216, x*9/5, y*3/2 ?
|
||||
* h: 11111 11112 22222 22233 33333 33444 44444 45555 55555
|
||||
* 1 1 2 2+3 3 3+4 4 5 5
|
||||
* v: 11 12 22
|
||||
* 1 1+2 2
|
||||
*/
|
||||
void upscale_clut_nn_160_320x144_240(u8 *__restrict di, int ds, u8 *__restrict si, int ss)
|
||||
/* X x Y -> X*2/1 x Y, e.g. for X 160->320 (GG) */
|
||||
void upscale_clut_nn_x_1_2(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
|
||||
{
|
||||
int y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
h_upscale_nn_1_2(di, ds, si, ss, width, f_nop);
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_nn_x_1_2(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
h_upscale_nn_1_2(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl2_x_1_2(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
h_upscale_bl2_1_2(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
}
|
||||
|
||||
/* X x Y -> X*2/1 x Y*5/3 (GG) */
|
||||
void upscale_clut_nn_x_1_2_y_3_5(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
|
||||
{
|
||||
int swidth = width * 2;
|
||||
int y, j;
|
||||
|
||||
/* 3:5, 0 0 1 1 2 */
|
||||
for (y = 0; y < 144; y += 3) {
|
||||
for (y = 0; y < height; y += 3) {
|
||||
/* lines 0,2,4 */
|
||||
for (j = 0; j < 3; j++) {
|
||||
h_upscale_nn_1_2(di, ds, si, ss, 160, f_nop);
|
||||
h_upscale_nn_1_2(di, ds, si, ss, width, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* lines 1,3 */
|
||||
di -= 5*ds;
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_copy(&di[0], &di[-ds], 320, f_nop);
|
||||
v_copy(&di[0], &di[-ds], swidth, f_nop);
|
||||
di += 2*ds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_nn_160_320x144_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
void upscale_rgb_nn_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int swidth = width * 2;
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < 144; y += 3) {
|
||||
for (y = 0; y < height; y += 3) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
h_upscale_nn_1_2(di, ds, si, ss, 160, f_pal);
|
||||
h_upscale_nn_1_2(di, ds, si, ss, width, f_pal);
|
||||
di += ds;
|
||||
}
|
||||
di -= 5*ds;
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_copy(&di[0], &di[-ds], 320, f_nop);
|
||||
v_copy(&di[0], &di[-ds], swidth, f_nop);
|
||||
di += 2*ds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_snn_160_320x144_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
void upscale_rgb_bl2_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int swidth = width * 2;
|
||||
int y, j;
|
||||
|
||||
/* 3:5, 0 0+1 1 1+2 2 */
|
||||
for (y = 0; y < 144; y += 3) {
|
||||
for (y = 0; y < height; y += 3) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
h_upscale_nn_1_2(di, ds, si, ss, 160, f_pal);
|
||||
h_upscale_bl2_1_2(di, ds, si, ss, width, f_pal);
|
||||
di += ds;
|
||||
}
|
||||
di -= 5*ds;
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_mix(&di[0], &di[-ds], &di[ds], 320, p_05, f_nop);
|
||||
v_mix(&di[0], &di[-ds], &di[ds], swidth, p_05, f_nop);
|
||||
di += 2*ds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl2_160_320x144_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
void upscale_rgb_bl4_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int swidth = width * 2;
|
||||
int y, j, d;
|
||||
|
||||
/* for 1st block backwards reference virtually duplicate source line 0 */
|
||||
for (y = 0, d = 2*ds; y < height; y += 3, d = -ds) {
|
||||
di += 2*ds;
|
||||
for (j = 0; j < 3; j++) {
|
||||
h_upscale_bl2_1_2(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di -= 5*ds;
|
||||
v_mix(&di[0], &di[d ], &di[2*ds], swidth, p_05, f_nop); /*-1+0 */
|
||||
di += ds;
|
||||
v_mix(&di[0], &di[ds], &di[2*ds], swidth, p_075, f_nop);/* 0+1 */
|
||||
di += ds;
|
||||
v_mix(&di[0], &di[ 0], &di[ ds], swidth, p_025, f_nop);/* 0+1 */
|
||||
di += ds;
|
||||
v_mix(&di[0], &di[ 0], &di[ ds], swidth, p_05, f_nop); /* 1+2 */
|
||||
di += 2*ds;
|
||||
}
|
||||
}
|
||||
|
||||
/* X x Y -> X x Y*5/3, e.g. for Y 144->240 (GG) */
|
||||
void upscale_clut_nn_y_3_5(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
/* 3:5, 0 0+1 1 1+2 2 */
|
||||
for (y = 0; y < 144; y += 3) {
|
||||
for (y = 0; y < height; y += 3) {
|
||||
/* lines 0,2,4 */
|
||||
for (j = 0; j < 3; j++) {
|
||||
h_upscale_bl2_1_2(di, ds, si, ss, 160, f_pal);
|
||||
h_copy(di, ds, si, ss, width, f_nop);
|
||||
di += ds;
|
||||
}
|
||||
/* lines 1,3 */
|
||||
di -= 5*ds;
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_copy(&di[0], &di[-ds], width, f_nop);
|
||||
di += 2*ds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_nn_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < height; y += 3) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
h_copy(di, ds, si, ss, width, f_pal);
|
||||
di += ds;
|
||||
}
|
||||
di -= 5*ds;
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_mix(&di[0], &di[-ds], &di[ds], 320, p_05, f_nop);
|
||||
v_copy(&di[0], &di[-ds], width, f_nop);
|
||||
di += 2*ds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl4_160_320x144_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal)
|
||||
void upscale_rgb_bl2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y, j;
|
||||
|
||||
for (y = 0; y < height; y += 3) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
h_copy(di, ds, si, ss, width, f_pal);
|
||||
di += ds;
|
||||
}
|
||||
di -= 5*ds;
|
||||
for (j = 0; j < 2; j++) {
|
||||
v_mix(&di[0], &di[-ds], &di[ds], width, p_05, f_nop);
|
||||
di += 2*ds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void upscale_rgb_bl4_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
|
||||
{
|
||||
int y, j, d;
|
||||
|
||||
/* 3:5, -1+0, 0+1 0+1 1+2 2
|
||||
* for 1st block backwards reference virtually duplicate source line 0 */
|
||||
for (y = 0, d = 2*ds; y < 144; y += 3, d = -ds) {
|
||||
/* for 1st block backwards reference virtually duplicate source line 0 */
|
||||
for (y = 0, d = 2*ds; y < height; y += 3, d = -ds) {
|
||||
di += 2*ds;
|
||||
for (j = 0; j < 3; j++) {
|
||||
h_upscale_bl2_1_2(di, ds, si, ss, 160, f_pal);
|
||||
h_copy(di, ds, si, ss, width, f_pal);
|
||||
}
|
||||
di -= 5*ds;
|
||||
v_mix(&di[0], &di[d ], &di[2*ds], 320, p_05, f_nop); /*-1+0 */
|
||||
v_mix(&di[0], &di[d ], &di[2*ds], width, p_05, f_nop); /*-1+0 */
|
||||
di += ds;
|
||||
v_mix(&di[0], &di[ds], &di[2*ds], 320, p_075, f_nop); /* 0+1 */
|
||||
v_mix(&di[0], &di[ds], &di[2*ds], width, p_075, f_nop);/* 0+1 */
|
||||
di += ds;
|
||||
v_mix(&di[0], &di[ 0], &di[ ds], 320, p_025, f_nop); /* 0+1 */
|
||||
v_mix(&di[0], &di[ 0], &di[ ds], width, p_025, f_nop);/* 0+1 */
|
||||
di += ds;
|
||||
v_mix(&di[0], &di[ 0], &di[ ds], 320, p_05, f_nop); /* 1+2 */
|
||||
v_mix(&di[0], &di[ 0], &di[ ds], width, p_05, f_nop); /* 1+2 */
|
||||
di += 2*ds;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* nn: nearest neighbour
|
||||
* snn: "smoothed" nearest neighbour (see below)
|
||||
* bln: n-level-bilinear with n quantized weights
|
||||
* quantization: 0: a<1/2*n, 1/n: 1/2*n<=a<3/2*n, etc
|
||||
* quantization: 0: a<1/(2*n), 1/n: 1/(2*n)<=a<3/(2*n), etc
|
||||
* currently n=2, n=4 are implemented (there's n=8 mixing, but no filters)
|
||||
* [NB this has been brought to my attn, which is probably the same as bl2:
|
||||
* https://www.drdobbs.com/image-scaling-with-bresenham/184405045?pgno=1]
|
||||
@@ -18,34 +18,37 @@
|
||||
* a sharper look than a bilinear filter, at the price of some visible jags
|
||||
* on diagonal edges.
|
||||
*
|
||||
* scaling modes:
|
||||
* 256x___ -> 320x___ only horizontal scaling. Produces an aspect error of
|
||||
* ~7% for NTSC 224 line modes, but is correct for PAL
|
||||
* 256/320x224/240
|
||||
* -> 320x240 always produces 320x240 at DAR 4:3
|
||||
* 160x144 -> 320x240 game gear (currently unused)
|
||||
*
|
||||
* example scaling modes:
|
||||
* 256x_Y_ -> 320x_Y_, H32/mode 4, PAR 5:4, for PAL DAR 4:3 (NTSC 7% aspect err)
|
||||
* 256x224 -> 320x240, H32/mode 4, PAR 5:4, for NTSC DAR 4:3 (PAL 7% aspect err)
|
||||
* 320x224 -> 320x240, PAR 1:1, for NTSC, DAR 4:3 (PAL 7% etc etc...)
|
||||
* 160x144 -> 320x240: GG, PAR 6:5, scaling to 320x240 for DAR 4:3
|
||||
*
|
||||
*
|
||||
* (C) 2021 kub <derkub@gmail.com>
|
||||
*
|
||||
* This work is licensed under the terms of MAME license.
|
||||
* See COPYING file in the top-level directory.
|
||||
*/
|
||||
#include <pico/pico_types.h>
|
||||
|
||||
/* RGB565 pixel mixing, see https://www.compuphase.com/graphic/scale3.htm and
|
||||
http://blargg.8bitalley.com/info/rgb_mixing.html */
|
||||
/* 2-level mixing */
|
||||
//#define p_05(p1,p2) (((p1)+(p2) + ( ((p1)^(p2))&0x0821))>>1) // round up
|
||||
//#define p_05(p1,p2) (((p1)+(p2) - ( ((p1)^(p2))&0x0821))>>1) // round down
|
||||
#define p_05(p1,p2) (((p1)&(p2)) + ((((p1)^(p2))&~0x0821)>>1))
|
||||
//#define p_05(d,p1,p2) d=(((p1)+(p2) + ( ((p1)^(p2))&0x0821))>>1) // round up
|
||||
//#define p_05(d,p1,p2) d=(((p1)+(p2) - ( ((p1)^(p2))&0x0821))>>1) // round down
|
||||
#define p_05(d,p1,p2) d=(((p1)&(p2)) + ((((p1)^(p2))&~0x0821)>>1))
|
||||
/* 4-level mixing, 2 times slower */
|
||||
// 1/4*p1 + 3/4*p2 = 1/2*(1/2*(p1+p2) + p2)
|
||||
#define p_025(p1,p2) (t=p_05(p1, p2), p_05( t, p2))
|
||||
#define p_075(p1,p2) p_025(p2,p1)
|
||||
#define p_025(d,p1,p2) p_05(t, p1, p2); p_05( d, t, p2)
|
||||
#define p_075(d,p1,p2) p_025(d,p2,p1)
|
||||
/* 8-level mixing, 3 times slower */
|
||||
// 1/8*p1 + 7/8*p2 = 1/2*(1/2*(1/2*(p1+p2) + p2) + p2)
|
||||
#define p_0125(p1,p2) (t=p_05(p1, p2), u=p_05( t, p2), p_05( u, p2))
|
||||
#define p_0125(d,p1,p2) p_05(t, p1, p2); p_05( u, t, p2); p_05( d, u, p2)
|
||||
// 3/8*p1 + 5/8*p2 = 1/2*(1/2*(1/2*(p1+p2) + p2) + 1/2*(p1+p2))
|
||||
#define p_0375(p1,p2) (t=p_05(p1, p2), u=p_05( t, p2), p_05( u, t))
|
||||
#define p_0625(p1,p2) p_0375(p2,p1)
|
||||
#define p_0875(p1,p2) p_0125(p2,p1)
|
||||
#define p_0375(d,p1,p2) p_05(t, p1, p2); p_05( u, t, p2); p_05( d, u, t)
|
||||
#define p_0625(d,p1,p2) p_0375(d,p2,p1)
|
||||
#define p_0875(d,p1,p2) p_0125(d,p2,p1)
|
||||
|
||||
/* pixel transforms */
|
||||
#define f_pal(v) pal[v] // convert CLUT index -> RGB565
|
||||
@@ -55,7 +58,7 @@
|
||||
/*
|
||||
scalers h:
|
||||
256->320: - (4:5) (256x224/240 -> 320x224/240)
|
||||
256->299: - (6:7) (256x224 -> 299x224, DAR 4:3, 10.5 px border )
|
||||
256->299: - (6:7) (256x224 -> 299x224, alt?)
|
||||
160->320: - (1:2) 2x (160x144 -> 320x240, GG)
|
||||
160->288: - (5:9) (160x144 -> 288x216, GG alt?)
|
||||
*/
|
||||
@@ -95,7 +98,7 @@ scalers h:
|
||||
for (i = w/4; i > 0; i--, si += 4, di += 5) { \
|
||||
di[0] = f(si[0]); \
|
||||
di[1] = f(si[1]); \
|
||||
di[2] = p_05(f(si[1]),f(si[2])); \
|
||||
p_05(di[2], f(si[1]),f(si[2])); \
|
||||
di[3] = f(si[2]); \
|
||||
di[4] = f(si[3]); \
|
||||
} \
|
||||
@@ -104,12 +107,12 @@ scalers h:
|
||||
} while (0)
|
||||
|
||||
#define h_upscale_bln_4_5(di,ds,si,ss,w,f) do { \
|
||||
int i, t; \
|
||||
int i; u16 t; \
|
||||
for (i = w/4; i > 0; i--, si += 4, di += 5) { \
|
||||
di[0] = f(si[0]); \
|
||||
di[1] = p_025(f(si[0]),f(si[1])); \
|
||||
di[2] = p_05 (f(si[1]),f(si[2])); \
|
||||
di[3] = p_075(f(si[2]),f(si[3])); \
|
||||
p_025(di[1], f(si[0]),f(si[1])); \
|
||||
p_05 (di[2], f(si[1]),f(si[2])); \
|
||||
p_075(di[3], f(si[2]),f(si[3])); \
|
||||
di[4] = f(si[3]); \
|
||||
} \
|
||||
di += ds - w/4*5; \
|
||||
@@ -120,8 +123,8 @@ scalers h:
|
||||
int i; \
|
||||
for (i = w/4; i > 0; i--, si += 4, di += 5) { \
|
||||
di[0] = f(si[0]); \
|
||||
di[1] = p_05(f(si[0]),f(si[1])); \
|
||||
di[2] = p_05(f(si[1]),f(si[2])); \
|
||||
p_05(di[1], f(si[0]),f(si[1])); \
|
||||
p_05(di[2], f(si[1]),f(si[2])); \
|
||||
di[3] = f(si[2]); \
|
||||
di[4] = f(si[3]); \
|
||||
} \
|
||||
@@ -130,12 +133,12 @@ scalers h:
|
||||
} while (0)
|
||||
|
||||
#define h_upscale_bl4_4_5(di,ds,si,ss,w,f) do { \
|
||||
int i, t; uint p = f(si[0]); \
|
||||
int i; u16 t, p = f(si[0]); \
|
||||
for (i = w/4; i > 0; i--, si += 4, di += 5) { \
|
||||
di[0] = p_025(p, f(si[0])); \
|
||||
di[1] = p_05 (f(si[0]),f(si[1])); \
|
||||
di[2] = p_05 (f(si[1]),f(si[2])); \
|
||||
di[3] = p_075(f(si[2]),f(si[3])); \
|
||||
p_025(di[0], p, f(si[0])); \
|
||||
p_05 (di[1], f(si[0]),f(si[1])); \
|
||||
p_05 (di[2], f(si[1]),f(si[2])); \
|
||||
p_075(di[3], f(si[2]),f(si[3])); \
|
||||
di[4] = p = f(si[3]); \
|
||||
} \
|
||||
di += ds - w/4*5; \
|
||||
@@ -143,12 +146,12 @@ scalers h:
|
||||
} while (0)
|
||||
|
||||
#define h_upscale_bl8_4_5(di,ds,si,ss,w,f) do { \
|
||||
int i, t, u; uint p = f(si[0]); \
|
||||
int i; u16 t, u, p = f(si[0]); \
|
||||
for (i = w/4; i > 0; i--, si += 4, di += 5) { \
|
||||
di[0] = p_025(p, f(si[0])); \
|
||||
di[1] = p_0375(f(si[0]),f(si[1])); \
|
||||
di[2] = p_0625(f(si[1]),f(si[2])); \
|
||||
di[3] = p_075(f(si[2]),f(si[3])); \
|
||||
p_025 (di[0], p, f(si[0])); \
|
||||
p_0375(di[1], f(si[0]),f(si[1])); \
|
||||
p_0625(di[2], f(si[1]),f(si[2])); \
|
||||
p_075 (di[3], f(si[2]),f(si[3])); \
|
||||
di[4] = p = f(si[3]); \
|
||||
} \
|
||||
di += ds - w/4*5; \
|
||||
@@ -195,7 +198,7 @@ scalers h:
|
||||
di[0] = f(si[0]); \
|
||||
di[1] = f(si[1]); \
|
||||
di[2] = f(si[2]); \
|
||||
di[3] = p_05(f(si[2]),f(si[3])); \
|
||||
p_05(di[3], f(si[2]),f(si[3])); \
|
||||
di[4] = f(si[3]); \
|
||||
di[5] = f(si[4]); \
|
||||
di[6] = f(si[5]); \
|
||||
@@ -208,10 +211,10 @@ scalers h:
|
||||
int i; \
|
||||
for (i = w/6; i > 0; i--, si += 6, di += 7) { \
|
||||
di[0] = f(si[0]); \
|
||||
di[1] = p_05(f(si[0]),f(si[1])); \
|
||||
di[2] = p_05(f(si[1]),f(si[2])); \
|
||||
di[3] = p_05(f(si[2]),f(si[3])); \
|
||||
di[4] = p_05(f(si[3]),f(si[4])); \
|
||||
p_05(di[1], f(si[0]),f(si[1])); \
|
||||
p_05(di[2], f(si[1]),f(si[2])); \
|
||||
p_05(di[3], f(si[2]),f(si[3])); \
|
||||
p_05(di[4], f(si[3]),f(si[4])); \
|
||||
di[5] = f(si[4]); \
|
||||
di[6] = f(si[5]); \
|
||||
} \
|
||||
@@ -220,14 +223,14 @@ scalers h:
|
||||
} while (0)
|
||||
|
||||
#define h_upscale_bl4_6_7(di,ds,si,ss,w,f) do { \
|
||||
int i, t; uint p = f(si[0]); \
|
||||
int i; u16 t p = f(si[0]); \
|
||||
for (i = w/6; i > 0; i--, si += 6, di += 7) { \
|
||||
di[0] = p_025(p,f(si[0])); \
|
||||
di[1] = p_025(f(si[0]),f(si[1])); \
|
||||
di[2] = p_05 (f(si[1]),f(si[2])); \
|
||||
di[3] = p_05 (f(si[2]),f(si[3])); \
|
||||
di[4] = p_075(f(si[3]),f(si[4])); \
|
||||
di[5] = p_075(f(si[4]),f(si[5])); \
|
||||
p_025(di[0], p, f(si[0])); \
|
||||
p_025(di[1], f(si[0]),f(si[1])); \
|
||||
p_05 (di[2], f(si[1]),f(si[2])); \
|
||||
p_05 (di[3], f(si[2]),f(si[3])); \
|
||||
p_075(di[4], f(si[3]),f(si[4])); \
|
||||
p_075(di[5], f(si[4]),f(si[5])); \
|
||||
di[6] = p = f(si[5]); \
|
||||
} \
|
||||
di += ds - w/6*7; \
|
||||
@@ -258,9 +261,9 @@ scalers h:
|
||||
di[0] = f(si[0]); \
|
||||
di[1] = f(si[0]); \
|
||||
di[2] = f(si[1]); \
|
||||
di[3] = p_05(f(si[1]),f(si[2])); \
|
||||
p_05(di[3], f(si[1]),f(si[2])); \
|
||||
di[4] = f(si[2]); \
|
||||
di[5] = p_05(f(si[2]),f(si[3])); \
|
||||
p_05(di[5], f(si[2]),f(si[3])); \
|
||||
di[6] = f(si[3]); \
|
||||
di[7] = f(si[4]); \
|
||||
di[8] = f(si[4]); \
|
||||
@@ -273,13 +276,13 @@ scalers h:
|
||||
int i; \
|
||||
for (i = w/5; i > 0; i--, si += 5, di += 9) { \
|
||||
di[0] = f(si[0]); \
|
||||
di[1] = p_05(f(si[0]),f(si[1])); \
|
||||
p_05(di[1], f(si[0]),f(si[1])); \
|
||||
di[2] = f(si[1]); \
|
||||
di[3] = p_05(f(si[1]),f(si[2])); \
|
||||
p_05(di[3], f(si[1]),f(si[2])); \
|
||||
di[4] = f(si[2]); \
|
||||
di[5] = p_05(f(si[2]),f(si[3])); \
|
||||
p_05(di[5], f(si[2]),f(si[3])); \
|
||||
di[6] = f(si[3]); \
|
||||
di[7] = p_05(f(si[3]),f(si[4])); \
|
||||
p_05(di[7], f(si[3]),f(si[4])); \
|
||||
di[8] = f(si[4]); \
|
||||
} \
|
||||
di += ds - w/5*9; \
|
||||
@@ -287,16 +290,16 @@ scalers h:
|
||||
} while (0)
|
||||
|
||||
#define h_upscale_bl4_5_9(di,ds,si,ss,w,f) do { \
|
||||
int i, t; uint p = f(si[0]); \
|
||||
int i; u16 t, p = f(si[0]); \
|
||||
for (i = w/5; i > 0; i--, si += 5, di += 9) { \
|
||||
di[0] = p_05 (p,f(si[0])); \
|
||||
p_05 (di[0], p, f(si[0])); \
|
||||
di[1] = f(si[0]); \
|
||||
di[2] = p_025(f(si[0]),f(si[1])); \
|
||||
di[3] = p_075(f(si[1]),f(si[2])); \
|
||||
di[4] = p_025(f(si[1]),f(si[2])); \
|
||||
di[5] = p_075(f(si[2]),f(si[3])); \
|
||||
p_025(di[2], f(si[0]),f(si[1])); \
|
||||
p_075(di[3], f(si[1]),f(si[2])); \
|
||||
p_025(di[4], f(si[1]),f(si[2])); \
|
||||
p_075(di[5], f(si[2]),f(si[3])); \
|
||||
di[6] = f(si[3]); \
|
||||
di[7] = p_05 (f(si[3]),f(si[4])); \
|
||||
p_05 (di[7], f(si[3]),f(si[4])); \
|
||||
di[8] = p = f(si[4]); \
|
||||
} \
|
||||
di += ds - w/5*9; \
|
||||
@@ -319,9 +322,9 @@ scalers h:
|
||||
#define h_upscale_bl2_1_2(di,ds,si,ss,w,f) do { \
|
||||
int i; uint p = f(si[0]); \
|
||||
for (i = w/2; i > 0; i--, si += 2, di += 4) { \
|
||||
di[0] = p_05 (p, f(si[0])); \
|
||||
p_05 (di[0], p, f(si[0])); \
|
||||
di[1] = f(si[0]); \
|
||||
di[2] = p_05 (f(si[0]), f(si[1])); \
|
||||
p_05 (di[2], f(si[0]),f(si[1])); \
|
||||
di[3] = p = f(si[1]); \
|
||||
} \
|
||||
di += ds - w*2; \
|
||||
@@ -350,12 +353,12 @@ scalers v:
|
||||
*/
|
||||
|
||||
#define v_mix(di,li,ri,w,p_mix,f) do { \
|
||||
int i, t, u; (void)t, (void)u; \
|
||||
u16 i, t, u; (void)t, (void)u; \
|
||||
for (i = 0; i < w; i += 4) { \
|
||||
(di)[i ] = p_mix(f((li)[i ]), f((ri)[i ])); \
|
||||
(di)[i+1] = p_mix(f((li)[i+1]), f((ri)[i+1])); \
|
||||
(di)[i+2] = p_mix(f((li)[i+2]), f((ri)[i+2])); \
|
||||
(di)[i+3] = p_mix(f((li)[i+3]), f((ri)[i+3])); \
|
||||
p_mix((di)[i ], f((li)[i ]),f((ri)[i ])); \
|
||||
p_mix((di)[i+1], f((li)[i+1]),f((ri)[i+1])); \
|
||||
p_mix((di)[i+2], f((li)[i+2]),f((ri)[i+2])); \
|
||||
p_mix((di)[i+3], f((li)[i+3]),f((ri)[i+3])); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -369,32 +372,222 @@ scalers v:
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* scale 14:15 */
|
||||
#define v_upscale_nn_14_15(di,ds,w,l) do { \
|
||||
if (++l == 7) { \
|
||||
di += ds; \
|
||||
} else if (l >= 14) { \
|
||||
l = 0; \
|
||||
di -= 7*ds; \
|
||||
v_copy(&di[0], &di[-ds], w, f_nop); \
|
||||
di += 7*ds; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define v_upscale_snn_14_15(di,ds,w,l) do { \
|
||||
if (++l == 7) { \
|
||||
di += ds; \
|
||||
} else if (l >= 14) { \
|
||||
l = 0; \
|
||||
di -= 7*ds; \
|
||||
v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
|
||||
v_mix(&di[-ds], &di[-2*ds], &di[-ds], w, p_05, f_nop); \
|
||||
v_mix(&di[ ds], &di[ ds], &di[ 2*ds], w, p_05, f_nop); \
|
||||
di += 7*ds; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define v_upscale_bl2_14_15(di,ds,w,l) do { \
|
||||
if (++l == 3) { \
|
||||
di += ds; \
|
||||
} else if (l >= 14) { \
|
||||
int j; \
|
||||
l = 0; \
|
||||
di -= 11*ds; \
|
||||
v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
|
||||
for (j = 0; j < 7; j++) { \
|
||||
di += ds; \
|
||||
v_mix(&di[0], &di[0], &di[ds], w, p_05, f_nop); \
|
||||
} \
|
||||
di += 4*ds; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define v_upscale_bl4_14_15(di,ds,w,l) do { \
|
||||
if (++l == 1) { \
|
||||
di += ds; \
|
||||
} else if (l >= 14) { \
|
||||
int j; \
|
||||
l = 0; \
|
||||
di -= 13*ds; \
|
||||
v_mix(&di[0], &di[-ds], &di[ds], w, p_025, f_nop); \
|
||||
di += ds; \
|
||||
for (j = 0; j < 3; j++) { \
|
||||
v_mix(&di[0], &di[0], &di[ds], w, p_025, f_nop); \
|
||||
di += ds; \
|
||||
} \
|
||||
for (j = 0; j < 4; j++) { \
|
||||
v_mix(&di[0], &di[0], &di[ds], w, p_05, f_nop); \
|
||||
di += ds; \
|
||||
} \
|
||||
for (j = 0; j < 4; j++) { \
|
||||
v_mix(&di[0], &di[0], &di[ds], w, p_075, f_nop); \
|
||||
di += ds; \
|
||||
} \
|
||||
di += 1*ds; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* scale 16:17 */
|
||||
#define v_upscale_nn_16_17(di,ds,w,l) do { \
|
||||
if (++l == 8) { \
|
||||
di += ds; \
|
||||
} else if (l >= 16) { \
|
||||
l = 0; \
|
||||
di -= 8*ds; \
|
||||
v_copy(&di[0], &di[-ds], w, f_nop); \
|
||||
di += 8*ds; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define v_upscale_snn_16_17(di,ds,w,l) do { \
|
||||
if (++l == 8) { \
|
||||
di += ds; \
|
||||
} else if (l >= 16) { \
|
||||
l = 0; \
|
||||
di -= 8*ds; \
|
||||
v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
|
||||
v_mix(&di[-ds], &di[-2*ds], &di[-ds], w, p_05, f_nop); \
|
||||
v_mix(&di[ ds], &di[ ds], &di[ 2*ds], w, p_05, f_nop); \
|
||||
di += 8*ds; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define v_upscale_bl2_16_17(di,ds,w,l) do { \
|
||||
if (++l == 4) { \
|
||||
di += ds; \
|
||||
} else if (l >= 16) { \
|
||||
int j; \
|
||||
l = 0; \
|
||||
di -= 12*ds; \
|
||||
v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
|
||||
for (j = 0; j < 7; j++) { \
|
||||
di += ds; \
|
||||
v_mix(&di[0], &di[0], &di[ds], w, p_05, f_nop); \
|
||||
} \
|
||||
di += 5*ds; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define v_upscale_bl4_16_17(di,ds,w,l) do { \
|
||||
if (++l == 2) { \
|
||||
di += ds; \
|
||||
} else if (l >= 16) { \
|
||||
int j; \
|
||||
l = 0; \
|
||||
di -= 14*ds; \
|
||||
v_mix(&di[0], &di[-ds], &di[ds], w, p_025, f_nop); \
|
||||
di += ds; \
|
||||
for (j = 0; j < 3; j++) { \
|
||||
v_mix(&di[0], &di[0], &di[ds], w, p_025, f_nop); \
|
||||
di += ds; \
|
||||
} \
|
||||
for (j = 0; j < 4; j++) { \
|
||||
v_mix(&di[0], &di[0], &di[ds], w, p_05, f_nop); \
|
||||
di += ds; \
|
||||
} \
|
||||
for (j = 0; j < 4; j++) { \
|
||||
v_mix(&di[0], &di[0], &di[ds], w, p_075, f_nop); \
|
||||
di += ds; \
|
||||
} \
|
||||
di += 2*ds; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* scale 3:5 */
|
||||
#define v_upscale_nn_3_5(di,ds,w,l) do { \
|
||||
if (++l < 3) { \
|
||||
di += ds; \
|
||||
} else { \
|
||||
int j; \
|
||||
l = 0; \
|
||||
di -= 4*ds; \
|
||||
for (j = 0; j < 2; j++) { \
|
||||
v_copy(&di[0], &di[-ds], w, f_nop); \
|
||||
di += 2*ds; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define v_upscale_snn_3_5(di,ds,w,l) do { \
|
||||
if (++l < 3) { \
|
||||
di += ds; \
|
||||
} else { \
|
||||
int j; \
|
||||
l = 0; \
|
||||
di -= 4*ds; \
|
||||
for (j = 0; j < 2; j++) { \
|
||||
v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
|
||||
di += 2*ds; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* scale 2:3 */
|
||||
#define v_upscale_nn_2_3(di,ds,w,l) do { \
|
||||
if (++l < 2) { \
|
||||
di += ds; \
|
||||
} else { \
|
||||
int j; \
|
||||
l = 0; \
|
||||
di -= 2*ds; \
|
||||
v_copy(&di[0], &di[-ds], w, f_nop); \
|
||||
di += 2*ds; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define v_upscale_snn_2_3(di,ds,w,l) do { \
|
||||
if (++l < 2) { \
|
||||
di += ds; \
|
||||
} else { \
|
||||
int j; \
|
||||
l = 0; \
|
||||
di -= 2*ds; \
|
||||
v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
|
||||
di += 2*ds; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* 256x___ -> 320x___, H32/mode 4, PAR 5:4, for PAL DAR 4:3 (wrong for NTSC) */
|
||||
void upscale_clut_nn_256_320x___(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int height);
|
||||
void upscale_rgb_nn_256_320x___(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int height, u16 *pal);
|
||||
void upscale_rgb_snn_256_320x___(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int height, u16 *pal);
|
||||
void upscale_rgb_bl2_256_320x___(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int height, u16 *pal);
|
||||
void upscale_rgb_bl4_256_320x___(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int height, u16 *pal);
|
||||
/* X x Y -> X*5/4 x Y, for X 256->320 */
|
||||
void upscale_rgb_nn_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_snn_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_bl2_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_bl4_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
|
||||
/* 256x224 -> 320x240, H32/mode 4, PAR 5:4, for NTSC DAR 4:3 (wrong for PAL) */
|
||||
void upscale_clut_nn_256_320x224_240(u8 *__restrict di, int ds, u8 *__restrict si, int ss);
|
||||
void upscale_rgb_nn_256_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
void upscale_rgb_snn_256_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
void upscale_rgb_bl2_256_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
void upscale_rgb_bl4_256_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
/* X x Y -> X x Y*17/16, for Y 224->238 or 192->204 (SMS) */
|
||||
void upscale_rgb_nn_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_snn_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_bl2_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_bl4_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
|
||||
/* 320x224 -> 320x240, PAR 1:1, for NTSC, DAR 4:3 (wrong for PAL) */
|
||||
void upscale_clut_nn_320x224_240(u8 *__restrict di, int ds, u8 *__restrict si, int ss);
|
||||
void upscale_rgb_nn_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
void upscale_rgb_snn_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
void upscale_rgb_bl2_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
void upscale_rgb_bl4_320x224_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
/* X x Y -> X*5/4 x Y*17/16 */
|
||||
void upscale_rgb_nn_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_snn_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_bl2_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_bl4_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
|
||||
/* X x Y -> X*2/1 x Y, e.g. for X 160->320 (GG) */
|
||||
void upscale_rgb_nn_x_1_2(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_bl2_x_1_2(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
|
||||
/* X x Y -> X x Y*5/3, e.g. for Y 144->240 (GG) */
|
||||
void upscale_rgb_nn_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_bl2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_bl4_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
|
||||
/* X x Y -> X*2/1 x Y*5/3 (GG) */
|
||||
void upscale_rgb_nn_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_bl2_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
void upscale_rgb_bl4_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|
||||
|
||||
/* 160x144 -> 320x240: GG, PAR 6:5, scaling to 320x240 for DAR 4:3 */
|
||||
void upscale_clut_nn_160_320x144_240(u8 *__restrict di, int ds, u8 *__restrict si, int ss);
|
||||
void upscale_rgb_nn_160_320x144_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
void upscale_rgb_snn_160_320x144_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
void upscale_rgb_bl2_160_320x144_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
void upscale_rgb_bl4_160_320x144_240(u16 *__restrict di, int ds, u8 *__restrict si, int ss, u16 *pal);
|
||||
|
||||
@@ -558,14 +558,16 @@ static void vid_reset_mode(void)
|
||||
Pico.m.dirtyPal = 1;
|
||||
|
||||
PicoIn.opt &= ~POPT_EN_SOFTSCALE;
|
||||
if (currentConfig.scaling == EOPT_SCALE_SW)
|
||||
if (currentConfig.scaling == EOPT_SCALE_SW) {
|
||||
PicoIn.opt |= POPT_EN_SOFTSCALE;
|
||||
PicoIn.filter = EOPT_FILTER_BILINEAR2;
|
||||
}
|
||||
|
||||
// palette converters for 8bit modes
|
||||
make_local_pal = (PicoIn.AHW & PAHW_SMS) ? make_local_pal_sms : make_local_pal_md;
|
||||
}
|
||||
|
||||
void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
||||
void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count)
|
||||
{
|
||||
int scalex = 320, scaley = 240;
|
||||
int ln_offs = 0;
|
||||
@@ -578,10 +580,10 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
||||
|
||||
/* set up hwscaling here */
|
||||
PicoIn.opt &= ~POPT_DIS_32C_BORDER;
|
||||
if (is_32cols && currentConfig.scaling == EOPT_SCALE_HW) {
|
||||
scalex = 256;
|
||||
if (col_count < 320 && currentConfig.scaling == EOPT_SCALE_HW) {
|
||||
scalex = col_count;
|
||||
PicoIn.opt |= POPT_DIS_32C_BORDER;
|
||||
osd_fps_x = OSD_FPS_X - 64;
|
||||
osd_fps_x = col_count - (320-OSD_FPS_X);
|
||||
}
|
||||
|
||||
if (currentConfig.vscaling == EOPT_SCALE_HW) {
|
||||
|
||||
@@ -84,7 +84,6 @@ static retro_environment_t environ_cb;
|
||||
static retro_audio_sample_batch_t audio_batch_cb;
|
||||
|
||||
#define VOUT_MAX_WIDTH 320
|
||||
#define VOUT_32COL_WIDTH 256
|
||||
#define VOUT_MAX_HEIGHT 240
|
||||
|
||||
#define INITIAL_SND_RATE 44100
|
||||
@@ -99,7 +98,8 @@ static bool old_show_overscan = false;
|
||||
/* Required to allow on the fly changes to 'show overscan' */
|
||||
static int vm_current_start_line = -1;
|
||||
static int vm_current_line_count = -1;
|
||||
static int vm_current_is_32cols = -1;
|
||||
static int vm_current_start_col = -1;
|
||||
static int vm_current_col_count = -1;
|
||||
|
||||
static int vout_16bit = 1;
|
||||
static int vout_format = PDF_RGB555;
|
||||
@@ -615,13 +615,14 @@ int plat_mem_set_exec(void *ptr, size_t size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
||||
void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count)
|
||||
{
|
||||
struct retro_system_av_info av_info;
|
||||
|
||||
vm_current_start_line = start_line;
|
||||
vm_current_line_count = line_count;
|
||||
vm_current_is_32cols = is_32cols;
|
||||
vm_current_start_col = start_col;
|
||||
vm_current_col_count = col_count;
|
||||
|
||||
// 8bit renderes create a 328x256 CLUT image, while 16bit creates 320x240 RGB
|
||||
vout_16bit = vout_format == PDF_RGB555 || (PicoIn.AHW & PAHW_32X);
|
||||
@@ -631,13 +632,7 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
||||
vout_width = (vout_16bit ? VOUT_MAX_WIDTH : VOUT_8BIT_WIDTH);
|
||||
vout_height = (vout_16bit ? VOUT_MAX_HEIGHT : VOUT_8BIT_HEIGHT);
|
||||
vout_offset = (vout_16bit ? 0 : 8); // 8bit has 8 px overlap area on the left
|
||||
if (is_32cols) {
|
||||
// 256x240, with or w/o overlap on the left and 64 px on the right
|
||||
padding = (struct retro_hw_ps2_insets){start_line, vout_offset, vout_height - line_count - start_line, vout_width - 256.0f - vout_offset};
|
||||
} else {
|
||||
// 320x240, with or w/o overlap on the left and none on the right
|
||||
padding = (struct retro_hw_ps2_insets){start_line, vout_offset, vout_height - line_count - start_line, vout_width - 320.0f - vout_offset};
|
||||
}
|
||||
padding = (struct retro_hw_ps2_insets){start_line, vout_offset, vout_height - line_count - start_line, vout_width - col_count - vout_offset};
|
||||
|
||||
int pxsz = (vout_16bit ? 2 : 1); // pixel size: RGB = 16 bits, CLUT = 8 bits
|
||||
memset(vout_buf, 0, pxsz * vout_width * vout_height);
|
||||
@@ -651,7 +646,7 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
||||
ps2->padding = padding;
|
||||
}
|
||||
#else
|
||||
vout_width = is_32cols ? VOUT_32COL_WIDTH : VOUT_MAX_WIDTH;
|
||||
vout_width = col_count;
|
||||
memset(vout_buf, 0, VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2);
|
||||
if (vout_16bit)
|
||||
PicoDrawSetOutBuf(vout_buf, vout_width * 2);
|
||||
@@ -686,11 +681,11 @@ void emu_32x_startup(void)
|
||||
PicoDrawSetOutFormat(vout_format, 0);
|
||||
if ((vm_current_start_line != -1) &&
|
||||
(vm_current_line_count != -1) &&
|
||||
(vm_current_is_32cols != -1))
|
||||
(vm_current_start_col != -1) &&
|
||||
(vm_current_col_count != -1))
|
||||
emu_video_mode_change(
|
||||
vm_current_start_line,
|
||||
vm_current_line_count,
|
||||
vm_current_is_32cols);
|
||||
vm_current_start_line, vm_current_line_count,
|
||||
vm_current_start_col, vm_current_col_count);
|
||||
}
|
||||
|
||||
void lprintf(const char *fmt, ...)
|
||||
@@ -1621,11 +1616,11 @@ static void update_variables(bool first_run)
|
||||
{
|
||||
if ((vm_current_start_line != -1) &&
|
||||
(vm_current_line_count != -1) &&
|
||||
(vm_current_is_32cols != -1))
|
||||
(vm_current_start_col != -1) &&
|
||||
(vm_current_col_count != -1))
|
||||
emu_video_mode_change(
|
||||
vm_current_start_line,
|
||||
vm_current_line_count,
|
||||
vm_current_is_32cols);
|
||||
vm_current_start_line, vm_current_line_count,
|
||||
vm_current_start_col, vm_current_col_count);
|
||||
}
|
||||
|
||||
/* Reinitialise frameskipping, if required */
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "../libpicofe/plat.h"
|
||||
#include "../common/emu.h"
|
||||
#include "../common/arm_utils.h"
|
||||
#include "../common/upscale.h"
|
||||
#include "../common/version.h"
|
||||
|
||||
#include <pico/pico_int.h>
|
||||
@@ -23,8 +24,9 @@ const char *renderer_names[] = { "16bit accurate", " 8bit accurate", " 8bit fast
|
||||
const char *renderer_names32x[] = { "accurate", "faster", "fastest", NULL };
|
||||
enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT };
|
||||
|
||||
static int out_x, out_y;
|
||||
static int out_w, out_h;
|
||||
static int out_x, out_y, out_w, out_h; // renderer output in render buffer
|
||||
static int screen_x, screen_y, screen_w, screen_h; // final render destination
|
||||
static int render_bg; // force 16bit mode for bg render
|
||||
|
||||
void pemu_prep_defconfig(void)
|
||||
{
|
||||
@@ -38,7 +40,7 @@ void pemu_validate_config(void)
|
||||
}
|
||||
|
||||
#define is_16bit_mode() \
|
||||
(currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X))
|
||||
(currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X) || render_bg)
|
||||
|
||||
static int get_renderer(void)
|
||||
{
|
||||
@@ -82,33 +84,79 @@ static void draw_cd_leds(void)
|
||||
#undef p
|
||||
}
|
||||
|
||||
static unsigned short *get_16bit_start(unsigned short *buf)
|
||||
/* render/screen buffer handling:
|
||||
* In 16 bit mode, render output is directly placed in the screen buffer.
|
||||
* SW scaling is handled in renderer (x) and in vscaling callbacks here (y).
|
||||
* In 8 bit modes, output goes to the internal Draw2FB buffer in alternate
|
||||
* renderer format (8 pix overscan at left/top/bottom), left aligned (DIS_32C).
|
||||
* It is converted to 16 bit and SW scaled in pemu_finalize_frame.
|
||||
*
|
||||
* HW scaling always aligns the image to the left/top, since selecting an area
|
||||
* for display isn't always possible.
|
||||
*/
|
||||
|
||||
static u16 *screen_buffer(u16 *buf)
|
||||
{
|
||||
// center the output on the screen
|
||||
int offs = (g_screen_height-240)/2 * g_screen_ppitch + (g_screen_width-320)/2;
|
||||
return buf + offs;
|
||||
// center the emulator display on the screen if screen is larger
|
||||
if (currentConfig.scaling != EOPT_SCALE_HW)
|
||||
buf += (g_screen_width-320)/2;
|
||||
if (currentConfig.vscaling != EOPT_SCALE_HW)
|
||||
buf += (g_screen_height-240)/2 * g_screen_ppitch;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void screen_blit(u16 *pd, int pp, u8* ps, int ss, u16 *pal)
|
||||
{
|
||||
typedef void (*upscale_t)
|
||||
(u16 *di,int ds, u8 *si,int ss, int w,int h, u16 *pal);
|
||||
upscale_t upscale_hv[] = {
|
||||
upscale_rgb_nn_x_4_5_y_16_17, upscale_rgb_snn_x_4_5_y_16_17,
|
||||
upscale_rgb_bl2_x_4_5_y_16_17, upscale_rgb_bl4_x_4_5_y_16_17,
|
||||
};
|
||||
upscale_t upscale_h[] = {
|
||||
upscale_rgb_nn_x_4_5, upscale_rgb_snn_x_4_5,
|
||||
upscale_rgb_bl2_x_4_5, upscale_rgb_bl4_x_4_5,
|
||||
};
|
||||
upscale_t upscale_v[] = {
|
||||
upscale_rgb_nn_y_16_17, upscale_rgb_snn_y_16_17,
|
||||
upscale_rgb_bl2_y_16_17, upscale_rgb_bl4_y_16_17,
|
||||
};
|
||||
upscale_t *upscale;
|
||||
int y;
|
||||
|
||||
// handle software upscaling
|
||||
upscale = NULL;
|
||||
if (currentConfig.scaling == EOPT_SCALE_SW && out_w == 256) {
|
||||
if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224)
|
||||
// h+v scaling
|
||||
upscale = upscale_hv;
|
||||
else
|
||||
// h scaling
|
||||
upscale = upscale_h;
|
||||
} else if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224) {
|
||||
// v scaling
|
||||
upscale = upscale_v;
|
||||
} else {
|
||||
// no scaling
|
||||
for (y = 0; y < out_h; y++)
|
||||
h_copy(pd, pp, ps, 328, out_w, f_pal);
|
||||
return;
|
||||
}
|
||||
|
||||
upscale[currentConfig.filter & 0x3](pd, pp, ps, ss, out_w, out_h, pal);
|
||||
}
|
||||
|
||||
void pemu_finalize_frame(const char *fps, const char *notice)
|
||||
{
|
||||
|
||||
|
||||
if (!is_16bit_mode()) {
|
||||
// convert the 8 bit CLUT output to 16 bit RGB
|
||||
unsigned short *pd = (unsigned short *)g_screen_ptr +
|
||||
out_y * g_screen_ppitch + out_x;
|
||||
unsigned char *ps = Pico.est.Draw2FB + 328*out_y + 8;
|
||||
unsigned short *pal = Pico.est.HighPal;
|
||||
int i, x;
|
||||
u16 *pd = screen_buffer(g_screen_ptr) +
|
||||
screen_y * g_screen_ppitch + screen_x;
|
||||
u8 *ps = Pico.est.Draw2FB + 328*out_y + out_x + 8;
|
||||
|
||||
pd = get_16bit_start(pd);
|
||||
PicoDrawUpdateHighPal();
|
||||
for (i = 0; i < out_h; i++, ps += 8) {
|
||||
for (x = 0; x < out_w; x++)
|
||||
*pd++ = pal[*ps++];
|
||||
pd += g_screen_ppitch - out_w;
|
||||
ps += 320 - out_w;
|
||||
}
|
||||
|
||||
screen_blit(pd, g_screen_ppitch, ps, 328, Pico.est.HighPal);
|
||||
}
|
||||
|
||||
//#define FUNKEY_AUTHORIZE_TEXT_OVERLAY
|
||||
@@ -127,33 +175,44 @@ void pemu_finalize_frame(const char *fps, const char *notice)
|
||||
void plat_video_set_buffer(void *buf)
|
||||
{
|
||||
if (is_16bit_mode())
|
||||
PicoDrawSetOutBuf(get_16bit_start(buf), g_screen_ppitch * 2);
|
||||
PicoDrawSetOutBuf(screen_buffer(buf), g_screen_ppitch * 2);
|
||||
}
|
||||
|
||||
static void apply_renderer(void)
|
||||
{
|
||||
PicoIn.opt &= ~(POPT_ALT_RENDERER|POPT_EN_SOFTSCALE|POPT_DIS_32C_BORDER);
|
||||
switch (get_renderer()) {
|
||||
case RT_16BIT:
|
||||
PicoIn.opt &= ~POPT_ALT_RENDERER;
|
||||
PicoIn.opt &= ~POPT_DIS_32C_BORDER;
|
||||
PicoDrawSetOutFormat(PDF_RGB555, 0);
|
||||
PicoDrawSetOutBuf(get_16bit_start(g_screen_ptr), g_screen_ppitch * 2);
|
||||
// 32X uses line mode for vscaling with accurate renderer, since
|
||||
// the MD VDP layer must be unscaled and merging the scaled 32X
|
||||
// image data will fail.
|
||||
PicoDrawSetOutFormat(PDF_RGB555,
|
||||
(PicoIn.AHW & PAHW_32X) && currentConfig.vscaling);
|
||||
PicoDrawSetOutBuf(screen_buffer(g_screen_ptr), g_screen_ppitch * 2);
|
||||
break;
|
||||
case RT_8BIT_ACC:
|
||||
PicoIn.opt &= ~POPT_ALT_RENDERER;
|
||||
PicoIn.opt |= POPT_DIS_32C_BORDER;
|
||||
// for simplification the 8 bit accurate renderer uses the same
|
||||
// storage format as the fast renderer
|
||||
PicoDrawSetOutFormat(PDF_8BIT, 0);
|
||||
PicoDrawSetOutBuf(Pico.est.Draw2FB, 328);
|
||||
break;
|
||||
case RT_8BIT_FAST:
|
||||
PicoIn.opt |= POPT_ALT_RENDERER;
|
||||
PicoIn.opt |= POPT_DIS_32C_BORDER;
|
||||
PicoDrawSetOutFormat(PDF_NONE, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (PicoIn.AHW & PAHW_32X)
|
||||
PicoDrawSetOutBuf(get_16bit_start(g_screen_ptr), g_screen_ppitch * 2);
|
||||
PicoDrawSetOutBuf(screen_buffer(g_screen_ptr), g_screen_ppitch * 2);
|
||||
else if (is_16bit_mode()) {
|
||||
if (currentConfig.scaling == EOPT_SCALE_SW) {
|
||||
PicoIn.opt |= POPT_EN_SOFTSCALE;
|
||||
PicoIn.filter = currentConfig.filter;
|
||||
} else if (currentConfig.scaling == EOPT_SCALE_HW)
|
||||
// hw scaling, render without any padding
|
||||
PicoIn.opt |= POPT_DIS_32C_BORDER;
|
||||
} else
|
||||
PicoIn.opt |= POPT_DIS_32C_BORDER;
|
||||
|
||||
Pico.m.dirtyPal = 1;
|
||||
}
|
||||
@@ -196,19 +255,6 @@ void plat_update_volume(int has_changed, int is_up)
|
||||
{
|
||||
}
|
||||
|
||||
void pemu_forced_frame(int no_scale, int do_emu)
|
||||
{
|
||||
unsigned short *pd = get_16bit_start(g_screen_ptr);
|
||||
|
||||
PicoIn.opt &= ~POPT_DIS_32C_BORDER;
|
||||
PicoDrawSetCallbacks(NULL, NULL);
|
||||
Pico.m.dirtyPal = 1;
|
||||
|
||||
emu_cmn_forced_frame(no_scale, do_emu, pd);
|
||||
|
||||
g_menubg_src_ptr = g_screen_ptr;
|
||||
}
|
||||
|
||||
void pemu_sound_start(void)
|
||||
{
|
||||
emu_sound_start();
|
||||
@@ -218,15 +264,116 @@ void plat_debug_cat(char *str)
|
||||
{
|
||||
}
|
||||
|
||||
void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
||||
void pemu_forced_frame(int no_scale, int do_emu)
|
||||
{
|
||||
u16 *pd = screen_buffer(g_screen_ptr);
|
||||
int hs = currentConfig.scaling, vs = currentConfig.vscaling;
|
||||
|
||||
// create centered and sw scaled (if scaling enabled) 16 bit output
|
||||
PicoIn.opt &= ~POPT_DIS_32C_BORDER;
|
||||
Pico.m.dirtyPal = 1;
|
||||
if (currentConfig.scaling) currentConfig.scaling = EOPT_SCALE_SW;
|
||||
if (currentConfig.vscaling) currentConfig.vscaling = EOPT_SCALE_SW;
|
||||
plat_video_set_size(320, 240);
|
||||
|
||||
// render a frame in 16 bit mode
|
||||
render_bg = 1;
|
||||
emu_cmn_forced_frame(no_scale, do_emu, pd);
|
||||
render_bg = 0;
|
||||
|
||||
g_menubg_src_ptr = g_screen_ptr;
|
||||
currentConfig.scaling = hs, currentConfig.vscaling = vs;
|
||||
}
|
||||
|
||||
/* vertical sw scaling, 16 bit mode */
|
||||
static int vscale_state;
|
||||
|
||||
static int cb_vscaling_begin(unsigned int line)
|
||||
{
|
||||
static int prevline = 999;
|
||||
|
||||
// at start of new frame?
|
||||
if (line < prevline) {
|
||||
// set y frame offset (see emu_change_video_mode)
|
||||
u16 *dest = g_screen_ptr;
|
||||
Pico.est.DrawLineDest = dest + screen_y * g_screen_ppitch;
|
||||
vscale_state = 0;
|
||||
}
|
||||
prevline = line;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cb_vscaling_nop(unsigned int line)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cb_vscaling_end(unsigned int line)
|
||||
{
|
||||
u16 *dest = Pico.est.DrawLineDest;
|
||||
switch (currentConfig.filter) {
|
||||
case 3: v_upscale_bl4_16_17(dest, g_screen_ppitch, 320, vscale_state);
|
||||
break;
|
||||
case 2: v_upscale_bl2_16_17(dest, g_screen_ppitch, 320, vscale_state);
|
||||
break;
|
||||
case 1: v_upscale_snn_16_17(dest, g_screen_ppitch, 320, vscale_state);
|
||||
break;
|
||||
default: v_upscale_nn_16_17(dest, g_screen_ppitch, 320, vscale_state);
|
||||
break;
|
||||
}
|
||||
Pico.est.DrawLineDest = dest;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count)
|
||||
{
|
||||
// relative position in core fb and screen fb
|
||||
out_y = start_line; out_x = start_col;
|
||||
out_h = line_count; out_w = col_count;
|
||||
|
||||
PicoDrawSetCallbacks(NULL, NULL);
|
||||
screen_x = screen_y = 0;
|
||||
screen_w = 320, screen_h = 240;
|
||||
|
||||
switch (currentConfig.scaling) {
|
||||
case EOPT_SCALE_HW:
|
||||
screen_w = out_w;
|
||||
break;
|
||||
case EOPT_SCALE_NONE:
|
||||
// center output in screen
|
||||
screen_x = (screen_w - out_w)/2;
|
||||
break;
|
||||
}
|
||||
switch (currentConfig.vscaling) {
|
||||
case EOPT_SCALE_HW:
|
||||
// NTSC always has 224 visible lines, anything smaller has bars
|
||||
screen_h = (out_h < 224 ? 224 : out_h);
|
||||
// handle vertical centering for 16 bit mode
|
||||
screen_y = (screen_h - out_h) / 2;
|
||||
if (is_16bit_mode())
|
||||
PicoDrawSetCallbacks(cb_vscaling_begin, cb_vscaling_nop);
|
||||
break;
|
||||
case EOPT_SCALE_SW:
|
||||
// NTSC always has 224 visible lines, anything smaller has bars
|
||||
if (out_y > 7)
|
||||
screen_y = out_y - 7;
|
||||
// in 16 bit mode sw scaling is divided between core and platform
|
||||
if (is_16bit_mode() && out_h < 240)
|
||||
PicoDrawSetCallbacks(cb_vscaling_begin, cb_vscaling_end);
|
||||
break;
|
||||
case EOPT_SCALE_NONE:
|
||||
// center output in screen
|
||||
screen_y = (screen_h - out_h)/2;
|
||||
break;
|
||||
}
|
||||
|
||||
plat_video_set_size(screen_w, screen_h);
|
||||
plat_video_set_buffer(g_screen_ptr);
|
||||
|
||||
// clear whole screen in all buffers
|
||||
if (!is_16bit_mode())
|
||||
memset32(Pico.est.Draw2FB, 0xe0e0e0e0, (320+8) * (8+240+8) / 4);
|
||||
plat_video_clear_buffers();
|
||||
|
||||
out_y = start_line; out_x = (is_32cols ? 32 : 0);
|
||||
out_h = line_count; out_w = (is_32cols ? 256:320);
|
||||
}
|
||||
|
||||
void pemu_loop_prep(void)
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#include "../libpicofe/gp2x/plat_gp2x.h"
|
||||
|
||||
// ------------ gfx options menu ------------
|
||||
|
||||
static const char *men_scaling_opts[] = { "OFF", "software", "hardware", NULL };
|
||||
static const char *men_filter_opts[] = { "nearest", "smoother", "bilinear 1", "bilinear 2", NULL };
|
||||
|
||||
const char *men_scaling_opts[] = { "OFF", "ON", NULL };
|
||||
static const char h_scale[] = "hardware scaling may not be working on some devices";
|
||||
|
||||
#define MENU_OPTIONS_GFX \
|
||||
// mee_enum ("screen scaling", MA_OPT_SCALING, currentConfig.scaling, men_scaling_opts), \
|
||||
mee_enum_h ("Horizontal scaling", MA_OPT_SCALING, currentConfig.scaling, men_scaling_opts, h_scale), \
|
||||
mee_enum_h ("Vertical scaling", MA_OPT_VSCALING, currentConfig.vscaling, men_scaling_opts, h_scale), \
|
||||
mee_enum_h ("Scaler type", MA_OPT3_FILTERING, currentConfig.filter, men_filter_opts, NULL), \
|
||||
|
||||
#define MENU_OPTIONS_ADV
|
||||
|
||||
|
||||
@@ -331,17 +331,16 @@ void pnd_restore_layer_data(void)
|
||||
plat_video_flip();
|
||||
}
|
||||
|
||||
void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
||||
void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count)
|
||||
{
|
||||
int fb_w = 320, fb_h = 240, fb_left = 0, fb_right = 0, fb_top = 0, fb_bottom = 0;
|
||||
|
||||
if (doing_bg_frame)
|
||||
return;
|
||||
|
||||
if (is_32cols) {
|
||||
fb_w = 256;
|
||||
fb_left = fb_right = 32;
|
||||
}
|
||||
fb_w = col_count;
|
||||
fb_left = start_col;
|
||||
fb_right = 320 - (fb_w+fb_left);;
|
||||
|
||||
switch (currentConfig.scaling) {
|
||||
case SCALE_1x1:
|
||||
@@ -349,7 +348,7 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
||||
g_layer_h = fb_h;
|
||||
break;
|
||||
case SCALE_2x2_3x2:
|
||||
g_layer_w = fb_w * (is_32cols ? 3 : 2);
|
||||
g_layer_w = fb_w * (col_count < 320 ? 3 : 2);
|
||||
g_layer_h = fb_h * 2;
|
||||
break;
|
||||
case SCALE_2x2_2x2:
|
||||
@@ -381,7 +380,7 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
||||
fb_h = line_count;
|
||||
break;
|
||||
}
|
||||
g_osd_fps_x = is_32cols ? 232 : 264;
|
||||
g_osd_fps_x = col_count < 320 ? 232 : 264;
|
||||
g_osd_y = fb_top + fb_h - 8;
|
||||
|
||||
pnd_setup_layer(1, g_layer_x, g_layer_y, g_layer_w, g_layer_h);
|
||||
|
||||
@@ -50,9 +50,9 @@ static int need_pal_upload = 0;
|
||||
|
||||
static u16 __attribute__((aligned(16))) osd_buf[512*8]; // buffer for osd text
|
||||
|
||||
static int h32_mode = 0;
|
||||
static int out_x, out_y;
|
||||
static int out_w, out_h;
|
||||
static float hscale, vscale;
|
||||
|
||||
static struct in_default_bind in_psp_defbinds[] =
|
||||
{
|
||||
@@ -152,11 +152,8 @@ static void set_scaling_params(void)
|
||||
int fbimg_width, fbimg_height, fbimg_xoffs, fbimg_yoffs, border_hack = 0;
|
||||
g_vertices[0].z = g_vertices[1].z = 0;
|
||||
|
||||
fbimg_height = (int)(out_h * currentConfig.scale + 0.5);
|
||||
if (!h32_mode)
|
||||
fbimg_width = (int)(out_w * currentConfig.scale * currentConfig.hscale40 + 0.5);
|
||||
else
|
||||
fbimg_width = (int)(out_w * currentConfig.scale * currentConfig.hscale32 + 0.5);
|
||||
fbimg_height = (int)(out_h * vscale + 0.5);
|
||||
fbimg_width = (int)(out_w * hscale + 0.5);
|
||||
|
||||
if (fbimg_width & 1) fbimg_width++; // make even
|
||||
if (fbimg_height & 1) fbimg_height++;
|
||||
@@ -370,7 +367,7 @@ static void vidResetMode(void)
|
||||
|
||||
sceGuClutMode(GU_PSM_5650,0,0xff,0);
|
||||
sceGuTexFunc(GU_TFX_REPLACE,GU_TCC_RGB);
|
||||
if (currentConfig.scaling)
|
||||
if (currentConfig.filter)
|
||||
sceGuTexFilter(GU_LINEAR, GU_LINEAR);
|
||||
else sceGuTexFilter(GU_NEAREST, GU_NEAREST);
|
||||
sceGuTexScale(1.0f,1.0f);
|
||||
@@ -575,10 +572,9 @@ void pemu_prep_defconfig(void)
|
||||
defaultConfig.s_PsndRate = 22050;
|
||||
defaultConfig.s_PicoCDBuffers = 64;
|
||||
defaultConfig.CPUclock = 333;
|
||||
defaultConfig.scaling = 1; // bilinear filtering for psp
|
||||
defaultConfig.scale = 1.20; // fullscreen
|
||||
defaultConfig.hscale40 = 1.25;
|
||||
defaultConfig.hscale32 = 1.56;
|
||||
defaultConfig.filter = EOPT_FILTER_BILINEAR; // bilinear filtering
|
||||
defaultConfig.scaling = EOPT_SCALE_43;
|
||||
defaultConfig.vscaling = EOPT_VSCALE_FULL;
|
||||
defaultConfig.EmuOpt |= EOPT_SHOW_RTC;
|
||||
}
|
||||
|
||||
@@ -587,12 +583,6 @@ void pemu_validate_config(void)
|
||||
{
|
||||
if (currentConfig.CPUclock < 33 || currentConfig.CPUclock > 333)
|
||||
currentConfig.CPUclock = 333;
|
||||
if (currentConfig.scaling < 0.01)
|
||||
currentConfig.scaling = 0.01;
|
||||
if (currentConfig.hscale40 < 0.01)
|
||||
currentConfig.hscale40 = 0.01;
|
||||
if (currentConfig.hscale32 < 0.01)
|
||||
currentConfig.hscale32 = 0.01;
|
||||
if (currentConfig.gamma < -4 || currentConfig.gamma > 16)
|
||||
currentConfig.gamma = 0;
|
||||
if (currentConfig.gamma2 < 0 || currentConfig.gamma2 > 2)
|
||||
@@ -674,14 +664,39 @@ void plat_update_volume(int has_changed, int is_up)
|
||||
}
|
||||
|
||||
/* prepare for MD screen mode change */
|
||||
void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
||||
void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count)
|
||||
{
|
||||
h32_mode = is_32cols;
|
||||
out_y = start_line; out_x = (is_32cols ? 32 : 0);
|
||||
out_h = line_count; out_w = (is_32cols ? 256:320);
|
||||
out_y = start_line; out_x = start_col;
|
||||
out_h = line_count; out_w = col_count;
|
||||
|
||||
switch (currentConfig.vscaling) {
|
||||
case EOPT_VSCALE_PAL:
|
||||
vscale = (float)270/240;
|
||||
break;
|
||||
case EOPT_VSCALE_FULL:
|
||||
vscale = (float)270/line_count;
|
||||
break;
|
||||
default:
|
||||
vscale = 1;
|
||||
break;
|
||||
}
|
||||
switch (currentConfig.scaling) {
|
||||
case EOPT_SCALE_43:
|
||||
hscale = (float)360/col_count;
|
||||
break;
|
||||
case EOPT_SCALE_WIDE:
|
||||
hscale = (float)420/col_count;
|
||||
break;
|
||||
case EOPT_SCALE_FULL:
|
||||
hscale = (float)480/col_count;
|
||||
break;
|
||||
default:
|
||||
hscale = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
vidResetMode();
|
||||
if (h32_mode) // clear borders from h40 remnants
|
||||
if (col_count < 320) // clear borders from h40 remnants
|
||||
clearArea(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,84 +1,18 @@
|
||||
|
||||
static const char h_scale43[] = "Scales low and high res to 4:3 screen size.\n"
|
||||
"For 240 line PAL use Scale factor 1.12";
|
||||
static const char h_scalefull[] = "Scales low and high res to full screen.\n"
|
||||
"For 240 line PAL use scaling 1.12, 1.6, 1.28";
|
||||
static const char *men_hscaling_opts[] = { "OFF", "4:3", "wide", "fullscreen", NULL };
|
||||
static const char *men_vscaling_opts[] = { "OFF", "PAL", "fullscreen", NULL };
|
||||
static const char *men_filter_opts[] = { "OFF", "bilinear" };
|
||||
|
||||
#define MENU_OPTIONS_GFX \
|
||||
mee_cust("Scale factor", MA_OPT3_SCALE, mh_scale, ms_scale), \
|
||||
mee_cust("Hor. scale (for low res. games)", MA_OPT3_HSCALE32, mh_scale, ms_scale), \
|
||||
mee_cust("Hor. scale (for hi res. games)", MA_OPT3_HSCALE40, mh_scale, ms_scale), \
|
||||
mee_onoff("Bilinear filtering", MA_OPT3_FILTERING, currentConfig.scaling, 1), \
|
||||
mee_range("Gamma adjustment", MA_OPT3_GAMMAA, currentConfig.gamma, -4, 16), \
|
||||
mee_range("Black level", MA_OPT3_BLACKLVL, currentConfig.gamma2, 0, 2), \
|
||||
mee_onoff("wait for vsync", MA_OPT3_VSYNC, currentConfig.EmuOpt, EOPT_VSYNC), \
|
||||
mee_cust_nosave("Set to unscaled centered", MA_OPT3_PRES_NOSCALE, mh_preset_scale, NULL), \
|
||||
mee_cust_nosave("Set to 4:3 scaled", MA_OPT3_PRES_SCALE43, mh_preset_scale, NULL), \
|
||||
mee_cust_nosave("Set to fullscreen", MA_OPT3_PRES_FULLSCR, mh_preset_scale, NULL), \
|
||||
mee_enum ("Horizontal scaling", MA_OPT_SCALING, currentConfig.scaling, men_hscaling_opts), \
|
||||
mee_enum ("Vertical scaling", MA_OPT_VSCALING, currentConfig.vscaling, men_vscaling_opts), \
|
||||
mee_enum_h ("Scaler type", MA_OPT3_FILTERING, currentConfig.filter, men_filter_opts, NULL), \
|
||||
mee_range ("Gamma adjustment", MA_OPT3_GAMMAA, currentConfig.gamma, -4, 16), \
|
||||
mee_range ("Black level", MA_OPT3_BLACKLVL, currentConfig.gamma2, 0, 2), \
|
||||
mee_onoff ("Wait for vsync", MA_OPT3_VSYNC, currentConfig.EmuOpt, EOPT_VSYNC), \
|
||||
|
||||
#define MENU_OPTIONS_ADV
|
||||
|
||||
|
||||
static const char *ms_scale(int id, int *offs)
|
||||
{
|
||||
float val = 0;
|
||||
switch (id) {
|
||||
case MA_OPT3_SCALE: val = currentConfig.scale; break;
|
||||
case MA_OPT3_HSCALE32: val = currentConfig.hscale32; break;
|
||||
case MA_OPT3_HSCALE40: val = currentConfig.hscale40; break;
|
||||
}
|
||||
sprintf(static_buff, "%.2f", val);
|
||||
return static_buff;
|
||||
}
|
||||
|
||||
static int mh_scale(int id, int keys)
|
||||
{
|
||||
float *val = NULL;
|
||||
switch (id) {
|
||||
case MA_OPT3_SCALE: val = ¤tConfig.scale; break;
|
||||
case MA_OPT3_HSCALE32: val = ¤tConfig.hscale32; break;
|
||||
case MA_OPT3_HSCALE40: val = ¤tConfig.hscale40; break;
|
||||
}
|
||||
if (keys & PBTN_LEFT) *val += -0.01;
|
||||
if (keys & PBTN_RIGHT) *val += +0.01;
|
||||
if (*val < 0.01) *val = +0.01;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int mh_preset_scale(int id, int keys)
|
||||
{
|
||||
switch (id) {
|
||||
case MA_OPT3_PRES_NOSCALE:
|
||||
currentConfig.scale = 1.0;
|
||||
currentConfig.hscale32 = 1.0;
|
||||
currentConfig.hscale40 = 1.0;
|
||||
break;
|
||||
case MA_OPT3_PRES_SCALE43:
|
||||
// parameters for 224 lines; for 240 lines scale = 1.125
|
||||
// moreover, H32 and H40 had the same width on a TV.
|
||||
currentConfig.scale = 1.2;
|
||||
currentConfig.hscale32 = 1.25;
|
||||
currentConfig.hscale40 = 1.0;
|
||||
break;
|
||||
case MA_OPT3_PRES_FULLSCR:
|
||||
// uses width 460 to avoid some ugly moiree effects
|
||||
currentConfig.scale = 1.2;
|
||||
currentConfig.hscale32 = 1.5;
|
||||
currentConfig.hscale40 = 1.2;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static menu_entry e_menu_gfx_options[];
|
||||
|
||||
void psp_menu_init(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; e_menu_gfx_options[i].name; i++) {
|
||||
switch (e_menu_gfx_options[i].id) {
|
||||
case MA_OPT3_PRES_SCALE43: e_menu_gfx_options[i].help = h_scale43; break;
|
||||
case MA_OPT3_PRES_FULLSCR: e_menu_gfx_options[i].help = h_scalefull; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,10 +107,10 @@ void plat_video_toggle_renderer(int change, int is_menu)
|
||||
PicoDrawSetOutFormat(PDF_RGB555, 1);
|
||||
}
|
||||
|
||||
void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
||||
void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count)
|
||||
{
|
||||
EmuScreenRect.left = is_32cols ? 32 : 0;
|
||||
EmuScreenRect.right = is_32cols ? 256+32 : 320;
|
||||
EmuScreenRect.left = start_col;
|
||||
EmuScreenRect.right = start_col + col_count;
|
||||
EmuScreenRect.top = start_line;
|
||||
EmuScreenRect.bottom = start_line + line_count;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user