From 5f61330edfbc73acf8422de1a2d6fdd0aec8a94c Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Tue, 30 Jun 2020 14:14:25 +0100 Subject: [PATCH 1/4] defc: Use GCC builtin opcodes for byte swapping GCC has pretty handy builtin for that sort of things, often reduces to a single opcode on the target processor Signed-off-by: Michel Pollet --- src/defc.h | 127 ++++++++++++++++++++++++++++------------------------- 1 file changed, 67 insertions(+), 60 deletions(-) diff --git a/src/defc.h b/src/defc.h index 9283d7e..a28fd13 100644 --- a/src/defc.h +++ b/src/defc.h @@ -1,35 +1,35 @@ /* GSport - an Apple //gs Emulator Copyright (C) 2010 by GSport contributors - + Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "defcomm.h" -// OG redirect printf to console -#ifdef ACTIVEGS -#include -extern "C" int outputInfo(const char* format,...); -extern "C" int fOutputInfo(FILE*,const char* format,...); -#define printf outputInfo -#define fprintf fOutputInfo -#endif - +// OG redirect printf to console +#ifdef ACTIVEGS +#include +extern "C" int outputInfo(const char* format,...); +extern "C" int fOutputInfo(FILE*,const char* format,...); +#define printf outputInfo +#define fprintf fOutputInfo +#endif + #define STRUCT(a) typedef struct _ ## a a; struct _ ## a typedef unsigned char byte; @@ -58,12 +58,18 @@ void U_STACK_TRACE(); #define DRECIP_DCYCS_IN_16MS (1.0 / (DCYCS_IN_16MS)) #ifdef GSPORT_LITTLE_ENDIAN +#ifdef __GNUC__ +# define BIGEND(a) __builtin_bswap32(a) +# define GET_BE_WORD16(a) __builtin_bswap16(a) +# define GET_BE_WORD32(a) (BIGEND(a)) +#else # define BIGEND(a) ((((a) >> 24) & 0xff) + \ (((a) >> 8) & 0xff00) + \ (((a) << 8) & 0xff0000) + \ (((a) << 24) & 0xff000000)) # define GET_BE_WORD16(a) ((((a) >> 8) & 0xff) + (((a) << 8) & 0xff00)) # define GET_BE_WORD32(a) (BIGEND(a)) +#endif #else # define BIGEND(a) (a) # define GET_BE_WORD16(a) (a) @@ -83,45 +89,45 @@ void U_STACK_TRACE(); #endif #include -#include -#include - -#include -#include -#include - -#ifndef UNDER_CE // OG CE SPecific +#include +#include + +#include +#include +#include + +#ifndef UNDER_CE // OG CE SPecific #include #include #include #include -// OG Adding support for open -#ifdef WIN32 -#include -#endif - -#else -extern int errno; -extern int open(const char* name,int,...); -extern int read(int,char*,int); -extern int close(int); -extern int write( int fd, const void *buffer, unsigned int count ); -extern int lseek(int,int,int); -struct stat { int st_size; }; -extern int stat(const char* name, struct stat*); -extern int fstat(int, struct stat*); -#define O_RDWR 1 -#define O_BINARY 2 -#define O_RDONLY 4 -#define O_WRONLY 8 -#define O_CREAT 16 -#define O_TRUNC 32 -#define EAGAIN 11 -#define EINTR 4 - -#endif - - +// OG Adding support for open +#ifdef WIN32 +#include +#endif + +#else +extern int errno; +extern int open(const char* name,int,...); +extern int read(int,char*,int); +extern int close(int); +extern int write( int fd, const void *buffer, unsigned int count ); +extern int lseek(int,int,int); +struct stat { int st_size; }; +extern int stat(const char* name, struct stat*); +extern int fstat(int, struct stat*); +#define O_RDWR 1 +#define O_BINARY 2 +#define O_RDONLY 4 +#define O_WRONLY 8 +#define O_CREAT 16 +#define O_TRUNC 32 +#define EAGAIN 11 +#define EINTR 4 + +#endif + + #ifdef HPUX # include /* for GET_ITIMER */ #endif @@ -184,6 +190,7 @@ STRUCT(Engine_reg) { STRUCT(Kimage) { void *dev_handle; void *dev_handle2; + void *dev_handle3; /* for xrender ! */ byte *data_ptr; int width_req; int width_act; @@ -361,10 +368,10 @@ STRUCT(Emustate_word32list) { #include "iwm.h" #include "protos.h" -// OG Added define for joystick -#define JOYSTICK_TYPE_KEYPAD 0 -#define JOYSTICK_TYPE_MOUSE 1 -#define JOYSTICK_TYPE_NATIVE_1 2 -#define JOYSTICK_TYPE_NATIVE_2 3 -#define JOYSTICK_TYPE_NONE 4 // OG Added Joystick None -#define NB_JOYSTICK_TYPE 5 +// OG Added define for joystick +#define JOYSTICK_TYPE_KEYPAD 0 +#define JOYSTICK_TYPE_MOUSE 1 +#define JOYSTICK_TYPE_NATIVE_1 2 +#define JOYSTICK_TYPE_NATIVE_2 3 +#define JOYSTICK_TYPE_NONE 4 // OG Added Joystick None +#define NB_JOYSTICK_TYPE 5 From a1b3cf67a3a252a1b5131023c2416fee055ef40a Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Tue, 30 Jun 2020 14:16:30 +0100 Subject: [PATCH 2/4] defcomm: Allow customization of BORDER_WIDTH Allow Makefile to define BORDER_WIDTH Signed-off-by: Michel Pollet --- src/defcomm.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/defcomm.h b/src/defcomm.h index 8e16e5e..4724058 100644 --- a/src/defcomm.h +++ b/src/defcomm.h @@ -146,7 +146,9 @@ #define ALL_STAT_FLASH_STATE (1 << (BIT_ALL_STAT_FLASH_STATE)) #define ALL_STAT_A2VID_PALETTE (0xf << (BIT_ALL_STAT_A2VID_PALETTE)) +#ifndef BORDER_WIDTH #define BORDER_WIDTH 32 +#endif //#define EFF_BORDER_WIDTH (BORDER_WIDTH + (640-560)) @@ -155,8 +157,8 @@ /* BASE_MARGIN_BOTTOM+MARGIN_TOP must equal 62. There are 262 scan lines */ /* at 60Hz (15.7KHz line rate) and so we just make 62 border lines */ -#define BASE_MARGIN_TOP 32 -#define BASE_MARGIN_BOTTOM 30 +#define BASE_MARGIN_TOP BORDER_WIDTH +#define BASE_MARGIN_BOTTOM (BORDER_WIDTH-2) #define BASE_MARGIN_LEFT BORDER_WIDTH #define BASE_MARGIN_RIGHT BORDER_WIDTH From 9a0219660552e7454a7becc460129eb76e8bfd41 Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Tue, 30 Jun 2020 14:17:43 +0100 Subject: [PATCH 3/4] Make sure prodos.h structs are Packed Use __attribute__((packed)) for gcc, so make sure these structures are byte aligned Signed-off-by: Michel Pollet --- src/prodos.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/prodos.h b/src/prodos.h index 9702546..741a73f 100755 --- a/src/prodos.h +++ b/src/prodos.h @@ -19,25 +19,31 @@ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifdef __linux__ +#define PACKED __attribute__((packed)) +#else +#define PACKED +#endif + typedef struct l2byte_st L2byte; struct l2byte_st { byte low; byte hi; -}; +} PACKED; typedef struct l3byte_st L3byte; struct l3byte_st { byte low; byte hi; byte higher; -}; +} PACKED; typedef L2byte Block; typedef struct pro_time_st Pro_time; struct pro_time_st { byte times[4]; -}; +} PACKED; typedef struct file_entry_st File_entry; struct file_entry_st { @@ -63,7 +69,7 @@ struct file_entry_st { Pro_time last_mod; /* 0x25 */ Block header_pointer; -}; +} PACKED; STRUCT(Vol_hdr) { /* 0x4 */ @@ -86,14 +92,14 @@ STRUCT(Vol_hdr) { Block bit_map; /* 0x29 */ L2byte total_blocks; -}; +} PACKED; typedef struct directory_st Directory; struct directory_st { Block prev_blk; Block next_blk; File_entry file_entries[13]; -}; +} PACKED; STRUCT(ProDisk) { int fd; From ca601903b82cdba77c7c28d20fb66e6696c2ee08 Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Tue, 30 Jun 2020 14:22:50 +0100 Subject: [PATCH 4/4] x11/linux: Support for XRender and Scaling This adds support for scaling the window of the emulator. On 4K screens, GSport window is really tiny and unreadable. This implements another stage to the rendering using the XRender extension with a scaling transform. This appears to work with or without shared memory Also, modifies the Makefile to easily switch scaling on or off -- technically if could be made configurable at runtime too, for the moment the constant is passed as a #define Signed-off-by: Michel Pollet --- src/Makefile | 5 +- src/xdriver.c | 150 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 139 insertions(+), 16 deletions(-) diff --git a/src/Makefile b/src/Makefile index b9b60cc..ffca2e0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -61,8 +61,11 @@ gsportmac: $(OBJECTS) compile_time.o arch/mac/makedmg.sh .. GSportDmg GSport GSport 7 # Linux for X builds: +gsportx: CCOPTS += -DX_RENDER -DX_RENDER_SCALE=2 -DBORDER_WIDTH=8 +gsportx: EXTRA_LIBS += -lXrender gsportx: $(OBJECTS) compile_time.o - $(LD) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(XLIBS) $(EXTRA_LIBS) -lX11 + $(LD) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) \ + $(XLIBS) $(EXTRA_LIBS) -lX11 echo $(OBJECTS) mv gsportx .. cp -f ../config.template ../config.txt diff --git a/src/xdriver.c b/src/xdriver.c index f31a316..ec2a83c 100644 --- a/src/xdriver.c +++ b/src/xdriver.c @@ -21,7 +21,14 @@ # if !defined(__CYGWIN__) && !defined(__POWERPC__) /* No shared memory on Cygwin */ + +#ifndef X_RENDER +/* Enabled in the Makefile: Required to enable scaling */ +/* # define X_RENDER */ +#endif + # define X_SHARED_MEM + #endif /* CYGWIN */ #include @@ -37,6 +44,10 @@ # include #endif +#ifdef X_RENDER +#include +#endif + int XShmQueryExtension(Display *display); #include "defc.h" @@ -90,6 +101,18 @@ int g_use_shmem = 1; int g_use_shmem = 0; #endif +#ifdef X_RENDER +#ifndef X_RENDER_SCALE +# define X_RENDER_SCALE 1 +#endif +int g_use_xrender = 1; +unsigned int g_xscreen_scale = X_RENDER_SCALE; +Picture g_xrender_win; +Picture g_xrender_a2_screen; +Pixmap g_xrender_a2_pix; +GC g_xrender_gc; +#endif + extern Kimage g_mainwin_kimage; extern int Max_color_size; @@ -307,7 +330,7 @@ show_xcolor_array() for(i = 0; i < 256; i++) { printf("%02x: %08x\n", i, g_palette_8to1624[i]); - + #if 0 printf("%02x: %04x %04x %04x, %02x %x\n", i, xcolor_array[i].red, xcolor_array[i].green, @@ -397,6 +420,7 @@ dev_video_init() int cnt; int font_height; int base_height; + int base_width = X_A2_WINDOW_WIDTH; int screen_num; char *myTextString[1]; word32 lores_col; @@ -523,11 +547,30 @@ dev_video_init() create_win_list |= CWColormap | CWBorderPixel | CWBackPixel; base_height = X_A2_WINDOW_HEIGHT; + +#ifdef X_RENDER + if (g_use_xrender) { + int dummy = 0; + ret = XRenderQueryExtension(g_display, &dummy, &dummy); + if(ret == 0) { + printf("XRenderQueryExtension ret: %d\n", ret); + printf("not using XRender memory\n"); + g_use_xrender = 0; + } else { + printf("Will use XRender for X\n"); + // g_use_shmem = 0; // not necessary + } + } + if (g_use_xrender) { + base_width *= g_xscreen_scale; + base_height *= g_xscreen_scale; + } +#endif if (g_win_status_debug) base_height += MAX_STATUS_LINES * 13; g_a2_win = XCreateWindow(g_display, RootWindow(g_display, screen_num), - 0, 0, BASE_WINDOW_WIDTH, base_height, + 0, 0, base_width, base_height, 0, g_screen_depth, InputOutput, g_vis, create_win_list, &win_attr); @@ -535,6 +578,36 @@ dev_video_init() XFlush(g_display); +#ifdef X_RENDER + if (g_use_xrender) { + XWindowAttributes attrs; + XGetWindowAttributes(g_display, g_a2_win, &attrs); + + XRenderPictFormat* format = XRenderFindVisualFormat(g_display, attrs.visual); + + g_xrender_win = XRenderCreatePicture(g_display, g_a2_win, + format, 0, NULL); + /* Also create the backbuffer we transfer to, we don't + * 'draw' in the window itself */ + Pixmap pix = XCreatePixmap(g_display, + g_a2_win, X_A2_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT, 24); + g_xrender_gc = XCreateGC(g_display, pix, 0, NULL); + g_xrender_a2_screen = XRenderCreatePicture( + g_display, pix, + XRenderFindStandardFormat(g_display, PictStandardRGB24), + 0, NULL); + if (g_xscreen_scale != 1) { + XTransform t = {}; + t.matrix[0][0] = XDoubleToFixed(1); + t.matrix[1][1] = XDoubleToFixed(1); + t.matrix[2][2] = XDoubleToFixed(g_xscreen_scale); + + XRenderSetPictureTransform(g_display, g_xrender_a2_screen, &t); + } + g_xrender_a2_pix = pix; + } +#endif + /* Check for XShm */ #ifdef X_SHARED_MEM if(g_use_shmem) { @@ -582,11 +655,11 @@ dev_video_init() XStringListToTextProperty(myTextString, 1, &my_winText); my_winSizeHints.flags = PSize | PMinSize | PMaxSize; - my_winSizeHints.width = BASE_WINDOW_WIDTH; + my_winSizeHints.width = base_width; my_winSizeHints.height = base_height; - my_winSizeHints.min_width = BASE_WINDOW_WIDTH; + my_winSizeHints.min_width = base_width; my_winSizeHints.min_height = base_height; - my_winSizeHints.max_width = BASE_WINDOW_WIDTH; + my_winSizeHints.max_width = base_width; my_winSizeHints.max_height = base_height; my_winClassHint.res_name = "GSport"; my_winClassHint.res_class = "GSport"; @@ -746,7 +819,10 @@ x_set_mask_and_shift(word32 x_mask, word32 *mask_ptr, int *shift_left_ptr, int i; /* Shift until we find first set bit in mask, then remember mask,shift*/ - +#ifdef __GCC__ + shift = x_mask? ffs(x_mask) - 1 : 0; + x_mask >>= shift; +#else shift = 0; for(i = 0; i < 32; i++) { if(x_mask & 1) { @@ -756,6 +832,7 @@ x_set_mask_and_shift(word32 x_mask, word32 *mask_ptr, int *shift_left_ptr, x_mask = x_mask >> 1; shift++; } +#endif *mask_ptr = x_mask; *shift_left_ptr = shift; /* Now, calculate shift_right_ptr */ @@ -924,21 +1001,27 @@ get_ximage(Kimage *kimage_ptr) } -void +void x_toggle_status_lines() { XSizeHints my_winSizeHints; XClassHint my_winClassHint; int base_height = X_A2_WINDOW_HEIGHT; + int base_width = X_A2_WINDOW_WIDTH; + +#ifdef X_RENDER + base_height *= g_xscreen_scale; + base_width *= g_xscreen_scale; +#endif if ((g_win_status_debug = !g_win_status_debug)) base_height += MAX_STATUS_LINES * 13; //printf("Resize returns %d\n", XResizeWindow(g_display, g_a2_win, BASE_WINDOW_WIDTH, base_height)); my_winSizeHints.flags = PSize | PMinSize | PMaxSize; - my_winSizeHints.width = BASE_WINDOW_WIDTH; + my_winSizeHints.width = base_width; my_winSizeHints.height = base_height; - my_winSizeHints.min_width = BASE_WINDOW_WIDTH; + my_winSizeHints.min_width = base_width; my_winSizeHints.min_height = base_height; - my_winSizeHints.max_width = BASE_WINDOW_WIDTH; + my_winSizeHints.max_width = base_width; my_winSizeHints.max_height = base_height; my_winClassHint.res_name = "GSport"; my_winClassHint.res_class = "GSport"; @@ -956,8 +1039,14 @@ x_redraw_status_lines() int line; int height; int margin; + int base = X_A2_WINDOW_HEIGHT; word32 white, black; +#ifdef X_RENDER + if (g_use_xrender) { + base *= g_xscreen_scale; + } +#endif if (g_win_status_debug) { height = g_text_FontSt->ascent + g_text_FontSt->descent; @@ -979,10 +1068,10 @@ x_redraw_status_lines() continue; } XDrawImageString(g_display, g_a2_win, g_a2_winGC, 0, - X_A2_WINDOW_HEIGHT + height*line + margin, + base + height*line + margin, buf, strlen(buf)); } - + XFlush(g_display); } } @@ -996,6 +1085,27 @@ x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, xim = (XImage *)kimage_ptr->dev_handle; +#ifdef X_RENDER + if (g_use_xrender) { +#ifdef X_SHARED_MEM + if(g_use_shmem) { + XShmPutImage(g_display, g_xrender_a2_pix, g_xrender_gc, xim, + srcx, srcy, destx, desty, width, height, False); + } else +#endif + /* transfer to server */ + XPutImage(g_display, g_xrender_a2_pix, g_xrender_gc, xim, + srcx, srcy, destx, desty, width, height); + /* accerated copy + scale to window */ + XRenderComposite(g_display, PictOpSrc, + g_xrender_a2_screen, None, g_xrender_win, + 0, 0, 0, 0, 0, 0, + X_A2_WINDOW_WIDTH * g_xscreen_scale, + X_A2_WINDOW_HEIGHT * g_xscreen_scale); + return; + } +#endif + #ifdef X_SHARED_MEM if(g_use_shmem) { XShmPutImage(g_display, g_a2_win, g_a2_winGC, xim, @@ -1024,9 +1134,19 @@ int x_update_mouse(int raw_x, int raw_y, int button_states, int buttons_valid) { int x, y; - - x = raw_x - BASE_MARGIN_LEFT; - y = raw_y - BASE_MARGIN_TOP; +#ifdef X_RENDER + if (g_use_xrender) { + int ml = BASE_MARGIN_LEFT * g_xscreen_scale; + int mt = BASE_MARGIN_TOP * g_xscreen_scale; + + x = (raw_x - ml) / g_xscreen_scale; + y = (raw_y - mt) / g_xscreen_scale; + } else +#endif + { + x = raw_x - BASE_MARGIN_LEFT; + y = raw_y - BASE_MARGIN_TOP; + } if(g_warp_pointer && (x == A2_WINDOW_WIDTH/2) && (y == A2_WINDOW_HEIGHT/2) && (buttons_valid == 0) ) {