From ea4eec359e0234535961da6887e5e57336e90da7 Mon Sep 17 00:00:00 2001 From: beeanyew Date: Tue, 27 Jul 2021 03:21:35 +0200 Subject: [PATCH] Add RTG scaling commands to PiStorm device This temporarily breaks the PiStorm temperature display, since I had to adjust the register offset for it. Scale filtering currently doesn't work properly, probably due to unexpected use of shaders, will look into it later. Stick to point filtering for now. --- .../amiga/pistorm-dev/pistorm-dev-enums.h | 25 +- platforms/amiga/pistorm-dev/pistorm-dev.c | 13 + .../pistorm-dev/pistorm_dev_amiga/CopyMems | Bin 10120 -> 10344 bytes .../pistorm-dev/pistorm_dev_amiga/PiSimple | Bin 17804 -> 19972 bytes .../pistorm_dev_amiga/pistorm_dev.c | 19 ++ .../pistorm_dev_amiga/pistorm_dev.h | 3 + .../pistorm_dev_amiga/simple_interact.c | 154 +++++++++--- platforms/amiga/rtg/rtg-output-raylib.c | 232 +++++++++++++----- platforms/amiga/rtg/rtg.h | 3 + 9 files changed, 356 insertions(+), 93 deletions(-) diff --git a/platforms/amiga/pistorm-dev/pistorm-dev-enums.h b/platforms/amiga/pistorm-dev/pistorm-dev-enums.h index 15fb424..4cdbc72 100644 --- a/platforms/amiga/pistorm-dev/pistorm-dev-enums.h +++ b/platforms/amiga/pistorm-dev/pistorm-dev-enums.h @@ -5,6 +5,7 @@ // [R], [W] and [RW] indicate read, write or both access modes for register // Any failure or result code from a write command should be put in PI_CMDRESULT +// Try to make sure to align any new registers to word/longword offsets enum pistorm_dev_cmds { PI_CMD_RESET = 0x00, // [W] Reset the host system. PI_CMD_SWITCHCONFIG = 0x02, // [W] Switch config file to string at PI_STR1, if it exists. @@ -34,7 +35,10 @@ enum pistorm_dev_cmds { PI_CMD_SHOWFPS = 0x0118, // [W] Enable/disable RTG FPS display. PI_CMD_PALETTEDEBUG = 0x011A, // [W] Enable/disable RTG palette debug. PI_CMD_MEMCPY_Q = 0x0120, // [W] CopyMemQuick debug thing - PI_CMD_GET_TEMP = 0x0121, // [R] Get the CPU core temperature + PI_CMD_GET_TEMP = 0x0124, // [R] Get the CPU core temperature + + PI_CMD_RTG_SCALING = 0x0200, // [W] Set RTG scaling mode + PI_CMD_RTG_SCALE_FILTER = 0x0202, // [W] Set RTG scale filter PI_CMD_QBASIC = 0x0FFC, // QBasic PI_CMD_NIBBLES = 0x0FFE, // Nibbles @@ -92,6 +96,25 @@ enum pistorm_dev_cmds { PI_CMDRESULT = 0x2100, // [R] Check the result of any command that provides a "return value". }; +enum rtg_scaling_commands { + PIGFX_SCALE_NONE, // No scaling, display at 1:1 size even if it doesn't fit on screen + PIGFX_SCALE_INTEGER_MAX, // Scale to max integer multiple that fits on screen + PIGFX_SCALE_FULL_ASPECT, // Scale to full width and/or height of screen, preserve source aspect ratio + PIGFX_SCALE_FULL_43, // Scale to full width and/or height of screen at 4:3 aspect ratio + PIGFX_SCALE_FULL_169, // Scale to full width and/or height of screen at 16:9 aspect ratio + PIGFX_SCALE_FULL, // Scale to full width and height of screen, ignoring source aspect ratio + PIGFX_SCALE_CUSTOM, // Scale to custom position and size specified in PI_WORD1 through PI_WORD4 + PIGFX_SCALE_CUSTOM_RECT, // Scale to custom rectangle coordinates specified in PI_WORD1 through PI_WORD4 + PIGFX_SCALE_NUM, +}; + +enum rtg_scale_filter_commands { + PIGFX_FILTER_POINT, // Nearest neighbor scaling, sharp image, may cause uneven pixels + PIGFX_FILTER_SMOOTH, // Linear/bilinear texture scaling, blurry, may improve visibility or perceived "squareness" of pixels + PIGFX_FILTER_SHADER, // Load and use a pixel shader specified in PI_STR1 for scaling RTG output [NYI] + PIGFX_FILTER_NUM, +}; + enum pistorm_piscsi_commands { PISCSI_CTRL_NONE, PISCSI_CTRL_MAP, // For hard drives diff --git a/platforms/amiga/pistorm-dev/pistorm-dev.c b/platforms/amiga/pistorm-dev/pistorm-dev.c index a013909..d722577 100644 --- a/platforms/amiga/pistorm-dev/pistorm-dev.c +++ b/platforms/amiga/pistorm-dev/pistorm-dev.c @@ -369,6 +369,19 @@ void handle_pistorm_dev_write(uint32_t addr_, uint32_t val, uint8_t type) { } adjust_ranges_amiga(cfg); break; + case PI_CMD_RTG_SCALING: + DEBUG("[PISTORM-DEV] Write to RTG_SCALING: %d\n", val); + if (val == PIGFX_SCALE_CUSTOM || val == PIGFX_SCALE_CUSTOM_RECT) { + rtg_set_scale_rect(val, (int16_t)pi_word[0], (int16_t)pi_word[1], (int16_t)pi_word[2], (int16_t)pi_word[3]); + } else { + rtg_set_scale_mode(val); + } + break; + case PI_CMD_RTG_SCALE_FILTER: + DEBUG("[PISTORM-DEV] Write to RTG_SCALE_FILTER: %d\n", val); + rtg_set_scale_filter(val); + break; + case PI_CMD_NETSTATUS: DEBUG("[PISTORM-DEV] Write to NETSTATUS: %d\n", val); if (val == 1 && !pinet_enabled) { diff --git a/platforms/amiga/pistorm-dev/pistorm_dev_amiga/CopyMems b/platforms/amiga/pistorm-dev/pistorm_dev_amiga/CopyMems index 8c48396c4ca15a10ff9aa8e8af3b28664e89f5de..85f9b5e15482112cccc956a633acafbf0d2db079 100755 GIT binary patch delta 2519 zcmZvdYiJzT6@br-_HFG`tCb_m(n=P!>&lU2lGvCKwk=gu*WIeFQ-p9mTJ6qS%o$d6D=8-fTXm>`0Gn2;ZCFs%rsxFDQ)x5Y_>;R6%U#KJ5h=j|k+#2!_}5?CXBq3SUHsZ8tzI-{&B@W!fI^pj$I;Z>pjGvdhSPK%#BgGo(eBj&3_x9WuA8QlCk>~$| z_Ly1=9O{_PtNu%mtbd^O4fP-}Y%HlKgL`*h9bZUD{>qc@i|Bds^7KE(&wt&oy+%r_ zZt!oWv8IkhE(G%IjBKeJkv|$=sQDe1QBt4oIFpEv59TH>A6+^|@lVWjP7NlW#=}%%Obgc%`(n|NmNC3vhO`4z8;S2=>`OX~ zwd9(&CG{iYifW{mwP&+qNb5#Aa!jjk$Chb!^{7VX^5Q;f*T0h@1_U5+kHQA&TN-*rQg4dH(I>CLVdP1A_o>MK zWV=X52?0e1jys;gfP7N7(7h^>VPghoGOgb1Dvz~&EaK~i&)@-fitYYy!Eq?Vd3XhW z3!IPtCVT`gaz25-VrFtqJ$_mjKeT34&O(~$%S|h z;XFiL5n-lz;ls>7MnG=mFLLqDczUa{V3lXfZoOJAX>*B>Gk89> z?GXbx2Gb&@mp`9jHL^Q%G|qj-l-y`avsH5HoTBcV7tXE~W-7K-vvtc6~FNwdQmUnk8uJdSG6}vF+wKVW6WbM7!m@CfOI%kO-_H3MHq18IaV@w|(r%>7{p3d7^kX*?S7>!N(ynN|yxO8sH;GA4S{atlt==Eddam(@^jw;32xxikj`+ zYg|>!y~FyVdD%2M2-mGqs_^B%)q8NDOP@$Um&Tgq9d)rl<<)x0E2Qm)3iTZ~GgInh zUw5}ZjkQk2sX493QtA9iE%)tu;==Z-ZfV7taSN_v)AY=yy3u#&>GQ0b*8g^;Z+mjN zSgAL4sE!;%n>FUtN+$|U-7s2oOpRopH-4!WvU@1#YIaxQ8*(i>70M#91Y1n&tn0MA z+}rh~;PzR~vomvL4uJOux$%Dye`dGF=4!>3Q|A<7OX_a+pc&Yydir})e%)8o8mqfA zj&>HCR>%7H@ORtj?^@LP`?rs!Sg%$KwNk~Yd6C1s?GKNC_Qk?X-PN}!3izrP9DUd{ zU0)gRu2$_T&DT2f1BP#?(6x)+dfSFJvb+MkBTsFpd;NP~(Bb$RdH0tW$GaJM-FWn) zpnnlQt2!ih-c97-lPk#BcYegI?WdTx?St#9vje6v5F0|rFLsz=ng53+Eiu0&l4H(H Kt-i8ntL?wW<_eGi delta 2326 zcmYk7e`u6t9KfIV-TU6{=H2ant4p`r9L>y}N$CiQVKs-tPp;$eX@rqPy1I6$aAY_PXu=3K6<36aFo6(IcBbd93{!a$0!3F?oHN zr5SQ_aBn2M*xK2DbjP7R`_z@-l)Mnk>%lp>BD6*G$==W(q|q5JY1%<~p?+SEFUYaT zi&(fE=~5d#x;7k~bG7z$V!bkes3ZC;%DJe+_)~PoyApd{+a%{=6Uy>He7%xQ#55g<-Yt%+UVOZ#kuN%#>6 z!$pCb#KNR5? zznig1yfk%e>Qx(jd^xr7|M(LQjg!^`k3dI`9~kibC-@2QvIbI8jhD|e07{7$gk zGdf`qCSZYBHvzGjpTJ4D2-n~y43HeAw5{aO1(R?AD1;yXzRQ3;KgICZL7M#`xX*e8 zoPas=mkojm}lO~Oh(D~;4pj%+)q-K=?oeJ)^Vn&AK%JX?44#))O68B=w1?gvcCsJQbakHG zDvVh9!F;7Ol+P)35ng2QY%J-sH5V9k3!h&6{36S#)u|m}`WaPXqbOB3=ai^}s+;G| zE@lP_wpFxM)WW#W;MHSEUUsV4s-upC8JTQcK3ZU3N?#(b%Ayv+`17lhz?`G`4A5C!5+;n|Z-hd4@`*NTPzjfLEI~>8Uw+ylJPNyeDrr zH8dDAoG4FD(Q*IpX|GJDpIS+KKZ&E@3{)}|$EKvI3E7w4@?rz0y7lB%;-I(BXA7mO zDoJdCp~mWRin+c_Rn>!lZ_BIc?OKbhZC*pX>zki?UbpsF9M`L1&_IRWv8wwAhV%3a z-H(NLY`1H;n01{JMGL3p+2&2Uc}d=CZj2dcyc=Dm%7CN#AuMFDWexw68(Ws!DjsvG zirLc8P^OqGI7QD>fbZs`*BbmNGf=9iHxEuRsC*ptHgueNVXw1>>>&!NWcpP#SdUW_ zu@O1j()O;h*1yzDbg}nNJ*rN~p9l4!fBniLdR|{_Cz0%*yjDGSS^OC;5Fx|aI e*IGie$oPa*FJVtRq;||?*U6l`H(hAGU-KW|pWDU& diff --git a/platforms/amiga/pistorm-dev/pistorm_dev_amiga/PiSimple b/platforms/amiga/pistorm-dev/pistorm_dev_amiga/PiSimple index 9c73f73bd1e8a14cd6e6f36bcbcf1096b71e693a..c626888fea556ba37f14d3652c0ce43879ea8c56 100755 GIT binary patch delta 7942 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
NFz4SdlZ z^#o!{UErNX-#mYgOX2#qMFVlpHdeBx<}%?N>u5HMW&2sOx!Pt@6V~VL!!Kr#X==iU zy)DsPOkw9AuJNU$WzD;F&r#pLyU3p@D)$w#M zUmDYOd6p3hZ+a5*W>&CbS@}(cn;pfdTH@;thLwoT-^79|TKF6FsTI|UWf_OLUFqtX z_ntCedWG`9!~%l|j_@7$KNEpW`AEac%$Xce)mI9Q2yg4^$2L)YN};iW(3qD$f-KozA^ zN5!|;X}h^yS>7laWhR_9%9_9mui&6DjB&} delta 5710 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 8), (pi_get_hw_rev() & 0xFF)); - printf ("Software revision: %d.%d\n", (pi_get_sw_rev() >> 8), (pi_get_sw_rev() & 0xFF)); - printf ("RTG: %s - %s\n", (pi_get_rtg_status() & 0x01) ? "Enabled" : "Disabled", (pi_get_rtg_status() & 0x02) ? "In use" : "Not in use"); - printf ("NET: %s\n", pi_get_net_status() ? "Enabled" : "Disabled"); - printf ("PiSCSI: %s\n", pi_get_piscsi_status() ? "Enabled" : "Disabled"); + printf("PiStorm ----------------------------\n"); + printf("Hardware revision: %d.%d\n", (pi_get_hw_rev() >> 8), (pi_get_hw_rev() & 0xFF)); + printf("Software revision: %d.%d\n", (pi_get_sw_rev() >> 8), (pi_get_sw_rev() & 0xFF)); + printf("RTG: %s - %s\n", (pi_get_rtg_status() & 0x01) ? "Enabled" : "Disabled", (pi_get_rtg_status() & 0x02) ? "In use" : "Not in use"); + printf("NET: %s\n", pi_get_net_status() ? "Enabled" : "Disabled"); + printf("PiSCSI: %s\n", pi_get_piscsi_status() ? "Enabled" : "Disabled"); break; case PI_CMD_SWITCHCONFIG: if (cmd_arg == PICFG_LOAD) { if (argc < 3) { - printf ("User asked to load config, but no config filename specified.\n"); + printf("User asked to load config, but no config filename specified.\n"); } } pi_handle_config(cmd_arg, argv[2]); break; case PI_CMD_TRANSFERFILE: if (argc < 4) { - printf ("Please specify a source and destination filename in addition to the command.\n"); - printf ("Example: %s --transfer platforms/platform.h snakes.h\n", argv[0]); + printf("Please specify a source and destination filename in addition to the command.\n"); + printf("Example: %s --transfer platforms/platform.h snakes.h\n", argv[0]); } if (pi_get_filesize(argv[2], &tmpvalue) == PI_RES_FILENOTFOUND) { - printf ("File %s not found on the Pi side.\n", argv[2]); + printf("File %s not found on the Pi side.\n", argv[2]); } else { unsigned int filesize = tmpvalue; unsigned char *dest = malloc(filesize); if (dest == NULL) { - printf ("Failed to allocate memory buffer for file. Aborting file transfer.\n"); + printf("Failed to allocate memory buffer for file. Aborting file transfer.\n"); } else { - printf ("Found a %u byte file on the Pi side. Eating it.\n", filesize); + printf("Found a %u byte file on the Pi side. Eating it.\n", filesize); if (pi_transfer_file(argv[2], dest) != PI_RES_OK) { - printf ("Something went horribly wrong during the file transfer.\n"); + printf("Something went horribly wrong during the file transfer.\n"); } else { FILE *out = fopen(argv[3], "wb+"); if (out == NULL) { - printf ("Failed to open output file %s for writing.\n", argv[3]); + printf("Failed to open output file %s for writing.\n", argv[3]); } else { fwrite(dest, filesize, 1, out); fclose(out); - printf ("%u bytes transferred to file %s.\n", filesize, argv[3]); + printf("%u bytes transferred to file %s.\n", filesize, argv[3]); } } free(dest); } } break; - case PI_CMD_GET_TEMP: - { - unsigned short temp = pi_get_temperature(); - if (temp == 0) { - printf("Error getting temperature\n"); - } else { - printf("CPU temp: %u%cC\n", temp, 0xb0); - } + case PI_CMD_GET_TEMP: { + unsigned short temp = pi_get_temperature(); + if (temp == 0) { + printf("Error getting temperature\n"); + } else { + printf("CPU temp: %u%cC\n", temp, 0xb0); + } + break; + } + case PI_CMD_RTG_SCALE_FILTER: { + if (argc < 3) { + printf("Failed to set RTG scale filter: No scale filter specified.\n"); break; } + unsigned short scale_filter = get_scale_filter(argv[2]); + if (scale_filter != PIGFX_FILTER_NUM) { + pi_set_rtg_scale_filter(scale_filter); + } else { + printf("Failed to set RTG scale filter: Unknown scale filter %s.\n", argv[2]); + } + + break; + } + case PI_CMD_RTG_SCALING: + if (scale_rect != 0) { + if (argc < 6) { + printf("Missing command line arguments for RTG scale rect. Example:\n"); + if (scale_rect == 1) { + printf("%s --rtg-rect 16 16 640 480\n", argv[0]); + printf("Arguments being a rect: [X] [Y] [Width] [Height]\n"); + } + if (scale_rect == 2) { + printf("%s --rtg-rect 16 16 1264 705\n", argv[0]); + printf("Arguments being coordinates of rect corners: [X] [Y] [X2] [Y2]\n"); + } + break; + } else { + signed short x1, y1, x2, y2; + x1 = atoi(argv[2]); + y1 = atoi(argv[3]); + x2 = atoi(argv[4]); + y2 = atoi(argv[5]); + pi_set_rtg_scale_rect(scale_rect == 1 ? PIGFX_SCALE_CUSTOM_RECT : PIGFX_SCALE_CUSTOM, x1, y1, x2, y2); + break; + } + } else { + if (argc < 3) { + printf("Failed to set RTG scale mode: No scale mode type specified.\n"); + break; + } + unsigned short scale_mode = get_scale_mode(argv[2]); + if (scale_mode != PIGFX_SCALE_NUM) { + pi_set_rtg_scale_mode(scale_mode); + } else { + printf("Failed to set RTG scale mode: Unknown RTG scale mode %s.\n", argv[2]); + printf("Valid options are 4:3, 16:9, 1:1, full, aspect and integer\n"); + } + } + break; default: - printf ("Unhandled command %s.\n", argv[1]); + printf("Unhandled command %s.\n", argv[1]); return 1; break; } @@ -166,19 +218,57 @@ int get_command(char *cmd) { if (strcmp(cmd, "--transfer-file") == 0 || strcmp(cmd, "--transfer") == 0 || strcmp(cmd, "--getfile") == 0) { return PI_CMD_TRANSFERFILE; } - if (strcmp(cmd, "--get-temperature") == 0) { + if (strcmp(cmd, "--get-temperature") == 0 || strcmp(cmd, "--get-temp") == 0 || strcmp(cmd, "--temp") == 0) { return PI_CMD_GET_TEMP; } + if (strcmp(cmd, "--rtg-scaling") == 0 || strcmp(cmd, "--rtg-scale-mode") == 0 || strcmp(cmd, "--rtgscale") == 0) { + return PI_CMD_RTG_SCALING; + } + if (strcmp(cmd, "--rtg-rect") == 0 || strcmp(cmd, "--rtg-scale-rect") == 0 || strcmp(cmd, "--rtgrect") == 0) { + scale_rect = 1; + return PI_CMD_RTG_SCALING; + } + if (strcmp(cmd, "--rtg-custom") == 0 || strcmp(cmd, "--rtg-scale-custom") == 0 || strcmp(cmd, "--rtgcustom") == 0) { + scale_rect = 2; + return PI_CMD_RTG_SCALING; + } + if (strcmp(cmd, "--rtg-filter") == 0 || strcmp(cmd, "--rtg-scale-filter") == 0 || strcmp(cmd, "--rtgfilter") == 0) { + return PI_CMD_RTG_SCALE_FILTER; + } + return -1; } +unsigned short get_scale_mode(char *mode) { + if (strcmp(mode, "4:3") == 0) return PIGFX_SCALE_FULL_43; + if (strcmp(mode, "16:9") == 0) return PIGFX_SCALE_FULL_169; + if (strcmp(mode, "1:1") == 0) return PIGFX_SCALE_NONE; + if (strcmp(mode, "full") == 0) return PIGFX_SCALE_FULL; + if (strcmp(mode, "aspect") == 0) return PIGFX_SCALE_FULL_ASPECT; + if (strcmp(mode, "integer") == 0) return PIGFX_SCALE_INTEGER_MAX; + + return PIGFX_SCALE_NUM; +} + +unsigned short get_scale_filter(char *mode) { + if (strcmp(mode, "sharp") == 0) return PIGFX_FILTER_POINT; + if (strcmp(mode, "point") == 0) return PIGFX_FILTER_POINT; + if (strcmp(mode, "smooth") == 0) return PIGFX_FILTER_SMOOTH; + if (strcmp(mode, "blurry") == 0) return PIGFX_FILTER_SMOOTH; + if (strcmp(mode, "bilinear") == 0) return PIGFX_FILTER_SMOOTH; + if (strcmp(mode, "linear") == 0) return PIGFX_FILTER_SMOOTH; + if (strcmp(mode, "shader") == 0) return PIGFX_FILTER_SHADER; + + return PIGFX_FILTER_NUM; +} + void print_usage(char *exe) { - printf ("Usage: %s --[command] (arguments)\n", exe); - printf ("Example: %s --restart, --reboot or --reset\n", exe); - printf (" Restarts the Amiga.\n"); - printf (" %s --check, --find or --info\n", exe); - printf (" Finds the PiStorm device and prints some data.\n"); + printf("Usage: %s --[command] (arguments)\n", exe); + printf("Example: %s --restart, --reboot or --reset\n", exe); + printf(" Restarts the Amiga.\n"); + printf(" %s --check, --find or --info\n", exe); + printf(" Finds the PiStorm device and prints some data.\n"); return; } diff --git a/platforms/amiga/rtg/rtg-output-raylib.c b/platforms/amiga/rtg/rtg-output-raylib.c index 11da7d7..4934111 100644 --- a/platforms/amiga/rtg/rtg-output-raylib.c +++ b/platforms/amiga/rtg/rtg-output-raylib.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT #include "config_file/config_file.h" +#include "platforms/amiga/pistorm-dev/pistorm-dev-enums.h" #include "emulator.h" #include "rtg.h" @@ -39,6 +40,7 @@ static pthread_t thread_id; static uint8_t mouse_cursor_enabled = 0, cursor_image_updated = 0, updating_screen = 0, debug_palette = 0, show_fps = 0; static uint8_t mouse_cursor_w = 16, mouse_cursor_h = 16; static int16_t mouse_cursor_x = 0, mouse_cursor_y = 0; +static int16_t mouse_cursor_x_adj = 0, mouse_cursor_y_adj = 0; struct rtg_shared_data { uint16_t *width, *height; @@ -49,6 +51,12 @@ struct rtg_shared_data { uint8_t *running; }; +float scale_x = 1.0f, scale_y = 1.0f; +static Rectangle srcrect, dstscale; +static Vector2 origin; +static uint8_t scale_mode = PIGFX_SCALE_FULL_ASPECT; +static uint8_t filter_mode = 0; + struct rtg_shared_data rtg_share_data; static uint32_t palette[256]; static uint32_t cursor_palette[256]; @@ -71,12 +79,119 @@ uint32_t rtg_pixel_size[RTGFMT_NUM] = { 2, }; +void rtg_scale_output(uint16_t width, uint16_t height) { + static uint8_t fit_to_screen = 1, center = 1; + srcrect.x = srcrect.y = 0; + srcrect.width = width; + srcrect.height = height; + if (scale_mode != PIGFX_SCALE_CUSTOM && scale_mode != PIGFX_SCALE_CUSTOM_RECT) { + dstscale.x = dstscale.y = 0; + dstscale.width = width; + dstscale.height = height; + mouse_cursor_x_adj = 0; + mouse_cursor_y_adj = 0; + } + + if (dstscale.width == 0.0f || dstscale.height == 0.0f) { + dstscale.width = 128.0f; + dstscale.height = 128.0f; + } + if (srcrect.width == 0.0f || srcrect.height == 0.0f) { + dstscale.width = 128.0f; + dstscale.height = 128.0f; + } + + switch (scale_mode) { + case PIGFX_SCALE_INTEGER_MAX: + default: + if (dstscale.height * 2 <= GetScreenHeight()) { + if (width == 320) { + if (GetScreenHeight() == 720) { + dstscale.width = 960; + dstscale.height = 720; + } else if (GetScreenHeight() == 1080) { + dstscale.width = 1440; + dstscale.height = 1080; + } else if (GetScreenHeight() == 1200) { + dstscale.width = 1600; + dstscale.height = 1200; + } + } + while (dstscale.height + height <= GetScreenHeight()) { + dstscale.height += height; + dstscale.width += width; + } + } + break; + case PIGFX_SCALE_FULL_ASPECT: + dstscale.height = (float)GetScreenHeight(); + dstscale.width = srcrect.width * (dstscale.height / srcrect.height); + break; + case PIGFX_SCALE_FULL_43: + dstscale.height = (float)GetScreenHeight(); + dstscale.width = ((float)GetScreenHeight() / 3.0f) * 4.0f; + break; + case PIGFX_SCALE_FULL_169: + dstscale.height = (float)GetScreenHeight(); + dstscale.width = ((float)GetScreenHeight() / 9.0f) * 16.0f; + break; + case PIGFX_SCALE_FULL: + dstscale.height = GetScreenHeight(); + dstscale.width = GetScreenWidth(); + break; + case PIGFX_SCALE_NONE: + dstscale.width = srcrect.width; + dstscale.height = srcrect.height; + fit_to_screen = 0; + break; + case PIGFX_SCALE_CUSTOM: + case PIGFX_SCALE_CUSTOM_RECT: + fit_to_screen = 0; + center = 0; + break; + } + + if (fit_to_screen) { + if (dstscale.width > GetScreenWidth() || dstscale.height > GetScreenHeight()) { + if (dstscale.height > GetScreenHeight()) { + DEBUG("[H > SH]\n"); + DEBUG("Adjusted width from %d to", (int)dstscale.width); + dstscale.width = dstscale.width * ((float)GetScreenHeight() / srcrect.height); + DEBUG("%d.\n", (int)dstscale.width); + DEBUG("Adjusted height from %d to", (int)dstscale.height); + dstscale.height = GetScreenHeight(); + DEBUG("%d.\n", (int)dstscale.height); + } + if (dstscale.width > GetScreenWidth()) { + // First scaling attempt failed, do not double adjust, re-adjust + dstscale.width = width; + dstscale.height = height; + DEBUG("[W > SW]\n"); + DEBUG("Adjusted height from %d to", (int)dstscale.height); + dstscale.height = dstscale.height * ((float)GetScreenWidth() / srcrect.width); + DEBUG("%d.\n", (int)dstscale.height); + DEBUG("Adjusted width from %d to", (int)dstscale.width); + dstscale.width = GetScreenWidth(); + DEBUG("%d.\n", (int)dstscale.width); + } + } + } + + scale_x = dstscale.width / srcrect.width; + scale_y = dstscale.height / srcrect.height; + + if (center) { + origin.x = (dstscale.width - GetScreenWidth()) * 0.5; + origin.y = (dstscale.height - GetScreenHeight()) * 0.5; + } +} + void *rtgThread(void *args) { printf("RTG thread running\n"); fflush(stdout); - int reinit = 0; + int reinit = 0, old_filter_mode = -1; rtg_on = 1; uint32_t *indexed_buf = NULL; @@ -106,7 +221,6 @@ void *rtgThread(void *args) { SetTargetFPS(60); Color bef = { 0, 64, 128, 255 }; - float scale_x = 1.0f, scale_y = 1.0f; Shader clut_shader = LoadShader(NULL, "platforms/amiga/rtg/clut.shader"); Shader swizzle_shader = LoadShader(NULL, "platforms/amiga/rtg/argbswizzle.shader"); @@ -127,9 +241,6 @@ void *rtgThread(void *args) { raylib_cursor.data = cursor_data; raylib_cursor_texture = LoadTextureFromImage(raylib_cursor); - Rectangle srcrect, dstscale; - Vector2 origin; - reinit_raylib:; if (reinit) { printf("Reinitializing raylib...\n"); @@ -168,62 +279,17 @@ reinit_raylib:; printf("Loaded framebuffer texture.\n"); - srcrect.x = srcrect.y = 0; - srcrect.width = width; - srcrect.height = height; - dstscale.x = dstscale.y = 0; - dstscale.width = width; - dstscale.height = height; - - if (dstscale.height * 2 <= GetScreenHeight()) { - if (width == 320) { - if (GetScreenHeight() == 720) { - dstscale.width = 960; - dstscale.height = 720; - } else if (GetScreenHeight() == 1080) { - dstscale.width = 1440; - dstscale.height = 1080; - } else if (GetScreenHeight() == 1200) { - dstscale.width = 1600; - dstscale.height = 1200; - } - } - while (dstscale.height + height <= GetScreenHeight()) { - dstscale.height += height; - dstscale.width += width; - } - } else if (dstscale.width > GetScreenWidth() || dstscale.height > GetScreenHeight()) { - if (dstscale.height > GetScreenHeight()) { - DEBUG("[H > SH]\n"); - DEBUG("Adjusted width from %d to", (int)dstscale.width); - dstscale.width = dstscale.width * ((float)GetScreenHeight() / (float)height); - DEBUG("%d.\n", (int)dstscale.width); - DEBUG("Adjusted height from %d to", (int)dstscale.height); - dstscale.height = GetScreenHeight(); - DEBUG("%d.\n", (int)dstscale.height); - } - if (dstscale.width > GetScreenWidth()) { - // First scaling attempt failed, do not double adjust, re-adjust - dstscale.width = width; - dstscale.height = height; - DEBUG("[W > SW]\n"); - DEBUG("Adjusted height from %d to", (int)dstscale.height); - dstscale.height = dstscale.height * ((float)GetScreenWidth() / (float)width); - DEBUG("%d.\n", (int)dstscale.height); - DEBUG("Adjusted width from %d to", (int)dstscale.width); - dstscale.width = GetScreenWidth(); - DEBUG("%d.\n", (int)dstscale.width); - } - } - - scale_x = dstscale.width / (float)width; - scale_y = dstscale.height / (float)height; - - origin.x = (dstscale.width - GetScreenWidth()) * 0.5; - origin.y = (dstscale.height - GetScreenHeight()) * 0.5; + rtg_scale_output(width, height); while (1) { if (rtg_on) { + if (old_filter_mode != filter_mode) { + old_filter_mode = filter_mode; + SetTextureFilter(raylib_clut_texture, filter_mode); + SetTextureFilter(raylib_texture, filter_mode); + SetTextureFilter(raylib_cursor_texture, filter_mode); + } + BeginDrawing(); rtg_output_in_vblank = 0; updating_screen = 1; @@ -249,8 +315,8 @@ reinit_raylib:; } if (mouse_cursor_enabled) { - float mc_x = mouse_cursor_x - rtg_offset_x; - float mc_y = mouse_cursor_y - rtg_offset_y; + float mc_x = mouse_cursor_x - rtg_offset_x + mouse_cursor_x_adj; + float mc_y = mouse_cursor_y - rtg_offset_y + mouse_cursor_y_adj; Rectangle cursor_srcrect = { 0, 0, mouse_cursor_w, mouse_cursor_h }; Rectangle dstrect = { mc_x * scale_x, mc_y * scale_y, (float)mouse_cursor_w * scale_x, (float)mouse_cursor_h * scale_y }; DrawTexturePro(raylib_cursor_texture, cursor_srcrect, dstrect, origin, 0.0f, RAYWHITE); @@ -442,3 +508,49 @@ void rtg_show_fps(uint8_t enable) { void rtg_palette_debug(uint8_t enable) { debug_palette = (enable != 0); } + +void rtg_set_scale_mode(uint16_t _scale_mode) { + switch (_scale_mode) { + case PIGFX_SCALE_INTEGER_MAX: + case PIGFX_SCALE_FULL_ASPECT: + case PIGFX_SCALE_FULL_43: + case PIGFX_SCALE_FULL_169: + case PIGFX_SCALE_FULL: + case PIGFX_SCALE_NONE: + scale_mode = _scale_mode; + rtg_scale_output(rtg_display_width, rtg_display_height); + break; + case PIGFX_SCALE_CUSTOM: + case PIGFX_SCALE_CUSTOM_RECT: + printf("[!!!RTG] Tried to set RTG scale mode to custom or custom rect using the wrong function. Ignored.\n"); + break; + } +} + +void rtg_set_scale_rect(uint16_t _scale_mode, int16_t x1, int16_t y1, int16_t x2, int16_t y2) { + scale_mode = _scale_mode; + + origin.x = 0.0f; + origin.y = 0.0f; + mouse_cursor_x_adj = x1; + mouse_cursor_y_adj = y1; + dstscale.x = (float)x1; + dstscale.y = (float)y1; + + switch (scale_mode) { + case PIGFX_SCALE_CUSTOM_RECT: + dstscale.width = (float)x2; + dstscale.height = (float)y2; + break; + case PIGFX_SCALE_CUSTOM: + dstscale.width = (float)x2 - (float)x1; + dstscale.height = (float)y2 - (float)y1; + break; + } + + rtg_scale_output(rtg_display_width, rtg_display_height); +} + +void rtg_set_scale_filter(uint16_t _filter_mode) { + filter_mode = _filter_mode; +} diff --git a/platforms/amiga/rtg/rtg.h b/platforms/amiga/rtg/rtg.h index 63decc7..7bbdb88 100644 --- a/platforms/amiga/rtg/rtg.h +++ b/platforms/amiga/rtg/rtg.h @@ -24,6 +24,9 @@ void rtg_set_cursor_clut_entry(uint8_t r, uint8_t g, uint8_t b, uint8_t idx); void rtg_set_mouse_cursor_image(uint8_t *src, uint8_t w, uint8_t h); void rtg_show_fps(uint8_t enable); +void rtg_set_scale_mode(uint16_t scale_mode); +void rtg_set_scale_rect(uint16_t scale_mode, int16_t x1, int16_t y1, int16_t x2, int16_t y2); +void rtg_set_scale_filter(uint16_t _filter_mode); void rtg_palette_debug(uint8_t enable); int init_rtg_data(struct emulator_config *cfg);