aboutsummaryrefslogtreecommitdiff
path: root/scale.c
diff options
context:
space:
mode:
authorneonloop2023-01-11 16:28:41 +0000
committerneonloop2023-01-11 16:28:41 +0000
commit13447e236c51cd48372355e5c4d5e5379d39b892 (patch)
tree274173ac0d1e8cc0ef251f43e5dc37b2be058d90 /scale.c
parent319f038a28907277890b6122c4caf07842a4936c (diff)
downloadpicoarch-13447e236c51cd48372355e5c4d5e5379d39b892.tar.gz
picoarch-13447e236c51cd48372355e5c4d5e5379d39b892.tar.bz2
picoarch-13447e236c51cd48372355e5c4d5e5379d39b892.zip
Limits width for crop scaler to 320px
Makes crop scaler more useful for PlayStation / SNES games that use high horizontal resolution
Diffstat (limited to 'scale.c')
-rw-r--r--scale.c74
1 files changed, 50 insertions, 24 deletions
diff --git a/scale.c b/scale.c
index 583ca5d..7097380 100644
--- a/scale.c
+++ b/scale.c
@@ -25,7 +25,8 @@ struct blend_args {
} blend_args;
static scaler_t scaler;
-static unsigned dst_w, dst_h, dst_offs;
+static scaler_t crop_scaler;
+static unsigned dst_w, dst_h, dst_offs, src_offs, w_offs;
struct dimensions prev;
#if __ARM_ARCH >= 5
@@ -105,26 +106,10 @@ static void scale_1x(unsigned w, unsigned h, size_t pitch, const void *src, void
}
static void scale_crop(unsigned w, unsigned h, size_t pitch, const void *src, void *dst) {
- int dst_y = ((SCREEN_HEIGHT - (short)h) / 2);
- int dst_x = ((SCREEN_WIDTH - (short)w) * SCREEN_BPP / 2);
+ src += src_offs;
+ w += w_offs;
- if (dst_y < 0) {
- src += -dst_y * pitch;
- dst_y = 0;
- h = SCREEN_HEIGHT;
- }
-
- if (dst_x < 0) {
- src += -dst_x;
- dst_x = 0;
- w = SCREEN_WIDTH;
- }
-
- dst += dst_y * SCREEN_PITCH + dst_x;
-
- for (unsigned y = 0; y < h; y++) {
- memcpy(dst + y * SCREEN_PITCH, src + y * pitch, w * SCREEN_BPP);
- }
+ crop_scaler(w, h, pitch, src, dst);
}
static void scale_nearest(unsigned w, unsigned h, size_t pitch, const void *src, void *dst) {
@@ -440,8 +425,42 @@ static void scale_select_scaler(unsigned w, unsigned h, size_t pitch) {
}
if (scale_size == SCALE_SIZE_CROP) {
- scaler = scale_crop;
- return;
+ int dst_x, dst_y;
+ src_offs = 0;
+
+ if (w <= 320) {
+ dst_x = ((SCREEN_WIDTH - (short)w) / 2);
+ } else {
+ /* Crop to 320px maximum. If larger, scale down after crop. */
+ int src_w;
+ if (strstr(core_name, "snes9x")) {
+ /* For SNES, keep aspect ratio same for hi-res and normal */
+ src_w = SCREEN_WIDTH * 2;
+ } else {
+ src_w = w / current_aspect_ratio;
+ }
+
+ dst_x = ((src_w - (short)w) / 2);
+ }
+
+ dst_y = ((SCREEN_HEIGHT - (short)h) / 2);
+ dst_w = w;
+ dst_h = h;
+
+ if (dst_y < 0) {
+ dst_y = 0;
+ dst_h = SCREEN_HEIGHT;
+ }
+
+ if (dst_x < 0) {
+ src_offs += -dst_x * SCREEN_BPP;
+ w_offs = dst_x * 2;
+ w += w_offs;
+ dst_x = 0;
+ dst_w = SCREEN_WIDTH;
+ }
+
+ dst_offs = dst_y * SCREEN_PITCH + dst_x * SCREEN_BPP;
} else if (scale_size == SCALE_SIZE_FULL) {
dst_w = SCREEN_WIDTH;
dst_h = SCREEN_HEIGHT;
@@ -499,7 +518,6 @@ static void scale_select_scaler(unsigned w, unsigned h, size_t pitch) {
if (!scaler && scale_filter == SCALE_FILTER_NEAREST) {
scaler = scale_nearest;
- return;
}
if (!scaler && (scale_filter == SCALE_FILTER_SHARP || scale_filter == SCALE_FILTER_SMOOTH)) {
@@ -523,12 +541,20 @@ static void scale_select_scaler(unsigned w, unsigned h, size_t pitch) {
blend_args.h_bp[1] = blend_args.h_ratio_out >> 1;
scaler = scale_blend;
- return;
}
if (!scaler) {
scaler = scale_1x;
}
+
+ if (scale_size == SCALE_SIZE_CROP) {
+ if (w <= SCREEN_WIDTH && h <= SCREEN_HEIGHT) {
+ crop_scaler = scale_1x;
+ } else {
+ crop_scaler = scaler;
+ }
+ scaler = scale_crop;
+ }
}
void scale_update_scaler(void) {