From d8bd7c9f8b277550e66070eccaff690ad039cc67 Mon Sep 17 00:00:00 2001 From: Jeffrey Lee Date: Sat, 1 Jun 2019 18:27:46 +0100 Subject: [PATCH] riscos: Add support for more pixel formats * Add support for red/blue swapped, 12bpp, and 16bpp screen modes * Clean up code a bit by moving all local 'extern' declarations into headers & making local functions static * Fix toggling to fullscreen to retain the current palette --- src/video/riscos/SDL_riscosFullScreenVideo.c | 235 ++++++++++--------- src/video/riscos/SDL_riscosevents.c | 23 +- src/video/riscos/SDL_riscosevents_c.h | 10 +- src/video/riscos/SDL_riscosmouse.c | 8 +- src/video/riscos/SDL_riscosmouse_c.h | 17 +- src/video/riscos/SDL_riscossprite.c | 146 +++++++----- src/video/riscos/SDL_riscostask.c | 4 +- src/video/riscos/SDL_riscostask.h | 3 + src/video/riscos/SDL_riscosvideo.c | 132 ++++++----- src/video/riscos/SDL_riscosvideo.h | 56 ++++- src/video/riscos/SDL_wimppoll.c | 13 - src/video/riscos/SDL_wimpvideo.c | 104 +++----- 12 files changed, 415 insertions(+), 336 deletions(-) diff --git a/src/video/riscos/SDL_riscosFullScreenVideo.c b/src/video/riscos/SDL_riscosFullScreenVideo.c index 205504b62..b497ec4bb 100644 --- a/src/video/riscos/SDL_riscosFullScreenVideo.c +++ b/src/video/riscos/SDL_riscosFullScreenVideo.c @@ -51,20 +51,17 @@ typedef struct tagScreenModeBlock int y_pixels; int pixel_depth; // 2^pixel_depth = bpp,i.e. 0 = 1, 1 = 2, 4 = 16, 5 = 32 int frame_rate; // -1 use first match - int mode_vars[5]; // array of index, value pairs terminated by -1 + int mode_vars[7]; // array of index, value pairs terminated by -1 } SCREENMODEBLOCK; /* Helper functions */ -void FULLSCREEN_SetDeviceMode(_THIS); -int FULLSCREEN_SetMode(int width, int height, int bpp); -void FULLSCREEN_SetupBanks(_THIS); +static void FULLSCREEN_SetupBanks(_THIS); /* SDL video device functions for fullscreen mode */ static int FULLSCREEN_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); static int FULLSCREEN_FlipHWSurface(_THIS, SDL_Surface *surface); -void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon); -extern int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info); +static void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon); /* UpdateRects variants */ static void FULLSCREEN_UpdateRects(_THIS, int numrects, SDL_Rect *rects); @@ -77,56 +74,19 @@ static void FULLSCREEN_UpdateRectsOS(_THIS, int numrects, SDL_Rect *rects); /* Local helper functions */ static int cmpmodes(const void *va, const void *vb); static int FULLSCREEN_AddMode(_THIS, int bpp, int w, int h); -void FULLSCREEN_SetWriteBank(int bank); -void FULLSCREEN_SetDisplayBank(int bank); +static void FULLSCREEN_SetWriteBank(int bank); +static void FULLSCREEN_SetDisplayBank(int bank); static void FULLSCREEN_DisableEscape(); static void FULLSCREEN_EnableEscape(); -void FULLSCREEN_BuildModeList(_THIS); - -/* Following variable is set up in riskosTask.c */ -extern int riscos_backbuffer; /* Create a back buffer in system memory for full screen mode */ - -/* Following is used to create a sprite back buffer */ -extern unsigned char *WIMP_CreateBuffer(int width, int height, int bpp); - -/* Fast assembler copy */ -extern void RISCOS_Put32(void *to, int pixels, int pitch, int rows, void *from, int src_skip_bytes); SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) { _kernel_swi_regs regs; - Uint32 Rmask = 0; - Uint32 Gmask = 0; - Uint32 Bmask = 0; int create_back_buffer = riscos_backbuffer; - switch(bpp) - { - case 8: - flags |= SDL_HWPALETTE; - break; - - case 15: - case 16: - Bmask = 0x00007c00; - Gmask = 0x000003e0; - Rmask = 0x0000001f; - break; - - case 32: - Bmask = 0x00ff0000; - Gmask = 0x0000ff00; - Rmask = 0x000000ff; - break; - - default: - SDL_SetError("Pixel depth not supported"); - return NULL; - break; - } - - if (FULLSCREEN_SetMode(width, height, bpp) == 0) + const RISCOS_SDL_PixelFormat *fmt = FULLSCREEN_SetMode(width, height, bpp); + if (fmt == NULL) { SDL_SetError("Couldn't set requested mode"); return (NULL); @@ -135,7 +95,7 @@ SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, /* printf("Setting mode %dx%d\n", width, height); */ /* Allocate the new pixel format for the screen */ - if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) { + if ( ! SDL_ReallocFormat(current, fmt->sdl_bpp, fmt->rmask, fmt->gmask, fmt->bmask, 0) ) { RISCOS_RestoreWimpMode(); SDL_SetError("Couldn't allocate new pixel format for requested mode"); return(NULL); @@ -167,6 +127,11 @@ SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, flags &= ~SDL_DOUBLEBUF; } } + + if (fmt->sdl_bpp == 8) + { + flags |= SDL_HWPALETTE; + } current->flags = flags | SDL_FULLSCREEN | SDL_HWSURFACE | SDL_PREALLOC; @@ -190,7 +155,7 @@ SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, ** SDL$$BackBuffer >= 1 */ if (riscos_backbuffer == 3) - this->hidden->bank[0] = WIMP_CreateBuffer(width, height, bpp); + this->hidden->bank[0] = WIMP_CreateBuffer(width, height, &fmt->ro); else this->hidden->bank[0] = SDL_malloc(height * current->pitch); if (this->hidden->bank[0] == 0) @@ -222,6 +187,7 @@ SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, this->hidden->current_bank = 0; current->pixels = this->hidden->bank[0]; + this->hidden->format = fmt; /* Have to set the screen here, so SetDeviceMode will pick it up */ this->screen = current; @@ -288,6 +254,46 @@ void FULLSCREEN_SetDeviceMode(_THIS) this->PumpEvents = FULLSCREEN_PumpEvents; } +static void FULLSCREEN_CheckModeListEntry(_THIS, const int *blockInfo) +{ + if ((blockInfo[1] & 255) == 1) /* Old format mode entry */ + { + switch(blockInfo[4]) + { + case 3: /* 8 bits per pixel */ + FULLSCREEN_AddMode(this, 8, blockInfo[2], blockInfo[3]); + break; + case 4: /* 15 bits per pixel */ + FULLSCREEN_AddMode(this, 15, blockInfo[2], blockInfo[3]); + break; + case 5: /* 32 bits per pixel */ + FULLSCREEN_AddMode(this, 32, blockInfo[2], blockInfo[3]); + break; + } + } + else if ((blockInfo[1] & 255) == 3) /* Newer format mode entry */ + { + /* Check it's RGB colourspace */ + if ((blockInfo[5] & 0x3000) != 0) + { + return; + } + + switch(blockInfo[6]) + { + case 3: /* 8 bits per pixel */ + FULLSCREEN_AddMode(this, 8, blockInfo[2], blockInfo[3]); + break; + case 4: /* 12, 15 or 16 bits per pixel */ + FULLSCREEN_AddMode(this, 15, blockInfo[2], blockInfo[3]); + break; + case 5: /* 32 bits per pixel */ + FULLSCREEN_AddMode(this, 32, blockInfo[2], blockInfo[3]); + break; + } + } +} + /* Query for the list of available video modes */ void FULLSCREEN_BuildModeList(_THIS) { @@ -327,21 +333,7 @@ void FULLSCREEN_BuildModeList(_THIS) for (j =0; j < num_modes;j++) { blockInfo = (int *)enum_ptr; - if ((blockInfo[1] & 255) == 1) /* We understand this format */ - { - switch(blockInfo[4]) - { - case 3: /* 8 bits per pixel */ - FULLSCREEN_AddMode(this, 8, blockInfo[2], blockInfo[3]); - break; - case 4: /* 15 bits per pixel */ - FULLSCREEN_AddMode(this, 15, blockInfo[2], blockInfo[3]); - break; - case 5: /* 32 bits per pixel */ - FULLSCREEN_AddMode(this, 32, blockInfo[2], blockInfo[3]); - break; - } - } + FULLSCREEN_CheckModeListEntry(this, blockInfo); enum_ptr += blockInfo[0]; } @@ -641,64 +633,79 @@ void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon) SDL_strlcpy(this->hidden->title, title, SDL_arraysize(this->hidden->title)); } -/* Set screen mode -* -* Returns 1 if mode is set ok, otherwise 0 -*/ - -int FULLSCREEN_SetMode(int width, int height, int bpp) +/* Try and set the exact screen mode specified */ +static int FULLSCREEN_TrySetMode(int width,int height,const RISCOS_PixelFormat *fmt) { SCREENMODEBLOCK smb; _kernel_swi_regs regs; + /* To cope with dodgy validation by the OS or video drivers, check that the OS understands the corresponding sprite format */ + if (WIMP_IsSupportedSpriteFormat(fmt)) + { + return -1; + } + smb.flags = 1; smb.x_pixels = width; smb.y_pixels = height; - smb.mode_vars[0] = -1; - - switch(bpp) - { - case 8: - smb.pixel_depth = 3; - /* Note: Need to set ModeFlags to 128 and NColour variables to 255 get full 8 bit palette */ - smb.mode_vars[0] = 0; smb.mode_vars[1] = 128; /* Mode flags */ - smb.mode_vars[2] = 3; smb.mode_vars[3] = 255; /* NColour (number of colours -1) */ - smb.mode_vars[4] = -1; /* End of list */ - break; - - case 15: - case 16: - smb.pixel_depth = 4; - break; - - case 32: - smb.pixel_depth = 5; - break; - - default: - SDL_SetError("Pixel depth not supported"); - return 0; - break; - } - + smb.pixel_depth = fmt->log2bpp; smb.frame_rate = -1; + smb.mode_vars[0] = 3; /* NColour */ + smb.mode_vars[1] = fmt->ncolour; + smb.mode_vars[2] = 0; /* ModeFlags */ + smb.mode_vars[3] = fmt->modeflags; + smb.mode_vars[4] = -1; regs.r[0] = 0; regs.r[1] = (int)&smb; - if (_kernel_swi(OS_ScreenMode, ®s, ®s) != 0) + if (_kernel_swi(OS_ScreenMode, ®s, ®s) == 0) { - SDL_SetError("Couldn't set requested mode"); - return 0; + /* Turn cursor off*/ + _kernel_oswrch(23);_kernel_oswrch(1);_kernel_oswrch(0); + _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0); + _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0); + _kernel_oswrch(0);_kernel_oswrch(0); + + return 0; } + + return -1; +} + +/* Set screen mode +* +* Returns ptr to pixel format if mode is set ok, otherwise 0 +*/ + +const RISCOS_SDL_PixelFormat *FULLSCREEN_SetMode(int width, int height, int bpp) +{ + int pass; + const RISCOS_SDL_PixelFormat *fmt; + + for(pass=0;pass<2;pass++) + { + for (fmt = RISCOS_SDL_PixelFormats;fmt->sdl_bpp;fmt++) + { + if (fmt->sdl_bpp != bpp) + { + continue; + } + + if (!FULLSCREEN_TrySetMode(width,height,&fmt->ro)) + { + return fmt; + } + } - /* Turn cursor off*/ - _kernel_oswrch(23);_kernel_oswrch(1);_kernel_oswrch(0); - _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0); - _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0); - _kernel_oswrch(0);_kernel_oswrch(0); + /* Fuzzy matching for 15bpp & 16bpp */ + if (bpp == 15) { bpp = 16; } + else if (bpp == 16) { bpp = 15; } + else { break; } + } - return 1; + SDL_SetError("Couldn't set requested mode"); + return NULL; } /* Get Start addresses for the screen banks */ @@ -731,7 +738,7 @@ int FULLSCREEN_ToggleFromWimp(_THIS) int bpp = this->screen->format->BitsPerPixel; RISCOS_StoreWimpMode(); - if (FULLSCREEN_SetMode(width, height, bpp)) + if (!FULLSCREEN_TrySetMode(width, height, &this->hidden->format->ro)) { unsigned char *buffer = this->hidden->alloc_bank; /* This is start of sprite data */ /* Support back buffer mode only */ @@ -740,7 +747,19 @@ int FULLSCREEN_ToggleFromWimp(_THIS) FULLSCREEN_SetupBanks(this); this->hidden->bank[0] = buffer + 60; /* Start of sprite data */ - if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */ + if (bpp == 8) + { + /* Retain the SDL palette */ + _kernel_swi_regs regs; + regs.r[0] = -1; + regs.r[1] = -1; + regs.r[2] = (int) this->hidden->bank[0]; + regs.r[3] = 0; + regs.r[4] = 2; /* Flashing colours provided (source is sprite palette) */ + _kernel_swi(ColourTrans_WritePalette,®s,®s); + + this->hidden->bank[0] += 2048; + } this->hidden->current_bank = 0; this->screen->pixels = this->hidden->bank[0]; diff --git a/src/video/riscos/SDL_riscosevents.c b/src/video/riscos/SDL_riscosevents.c index 319fd9dcd..bab555f6a 100644 --- a/src/video/riscos/SDL_riscosevents.c +++ b/src/video/riscos/SDL_riscosevents.c @@ -48,6 +48,11 @@ #include #endif +#if SDL_THREADS_DISABLED +/* Timer running function */ +extern void RISCOS_CheckTimer(); +#endif + /* The translation table from a RISC OS internal key numbers to a SDL keysym */ static SDLKey RO_keymap[SDLK_LAST]; @@ -76,20 +81,11 @@ static char RO_pressed[ROKEYBD_ARRAYSIZE]; static SDL_keysym *TranslateKey(int intkey, SDL_keysym *keysym, int pressed); -void RISCOS_PollMouse(_THIS); -void RISCOS_PollKeyboard(); - -void RISCOS_PollMouseHelper(_THIS, int fullscreen); - -#if SDL_THREADS_DISABLED -extern void DRenderer_FillBuffers(); - -/* Timer running function */ -extern void RISCOS_CheckTimer(); +static void RISCOS_PollMouse(_THIS); +static void RISCOS_PollMouseHelper(_THIS, int fullscreen); -#else +#if !SDL_THREAD_DISABLED extern int riscos_using_threads; - #endif void FULLSCREEN_PumpEvents(_THIS) @@ -98,7 +94,6 @@ void FULLSCREEN_PumpEvents(_THIS) RISCOS_PollKeyboard(); RISCOS_PollMouse(this); #if SDL_THREADS_DISABLED -// DRenderer_FillBuffers(); if (SDL_timer_running) RISCOS_CheckTimer(); #else /* Stop thread starvation, which will occur if the main loop @@ -255,8 +250,6 @@ void RISCOS_PollMouse(_THIS) RISCOS_PollMouseHelper(this, 1); } -extern int mouseInWindow; - void WIMP_PollMouse(_THIS) { /* Only poll when mouse is over the window */ diff --git a/src/video/riscos/SDL_riscosevents_c.h b/src/video/riscos/SDL_riscosevents_c.h index 189b3c0cf..39669b0d7 100644 --- a/src/video/riscos/SDL_riscosevents_c.h +++ b/src/video/riscos/SDL_riscosevents_c.h @@ -23,12 +23,14 @@ #include "SDL_riscosvideo.h" -/* Variables and functions exported by SDL_sysevents.c to other parts - of the native video subsystem (SDL_sysvideo.c) +/* Variables and functions exported by SDL_riscosevents.c to other parts + of the native video subsystem */ extern void RISCOS_InitOSKeymap(_THIS); extern void FULLSCREEN_PumpEvents(_THIS); -extern void WIMP_PumpEvents(_THIS); +extern void RISCOS_PollKeyboard(); +extern void RISCOS_CheckMouseMode(_THIS); +extern void WIMP_PollMouse(_THIS); -/* end of SDL_nullevents_c.h ... */ +/* end of SDL_riscosevents_c.h ... */ diff --git a/src/video/riscos/SDL_riscosmouse.c b/src/video/riscos/SDL_riscosmouse.c index 2730605c5..8b3b74a88 100644 --- a/src/video/riscos/SDL_riscosmouse.c +++ b/src/video/riscos/SDL_riscosmouse.c @@ -39,8 +39,6 @@ static WMcursor *current_cursor = NULL; static WMcursor *defined_cursor = NULL; -extern int mouseInWindow; - /* Area to save cursor palette colours changed by SDL. Actual values will be read before we change to the SDL cursor */ static Uint8 wimp_cursor_palette[2][5] = { @@ -50,9 +48,8 @@ static Uint8 wimp_cursor_palette[2][5] = { static int cursor_palette_saved = 0; -void WIMP_SaveCursorPalette(); -void WIMP_RestoreWimpCursor(); -void WIMP_SetSDLCursorPalette(); +static void WIMP_SaveCursorPalette(); +static void WIMP_SetSDLCursorPalette(); void RISCOS_FreeWMCursor(_THIS, WMcursor *cursor) @@ -188,7 +185,6 @@ int RISCOS_ShowWMCursor(_THIS, WMcursor *cursor) void FULLSCREEN_WarpWMCursor(_THIS, Uint16 x, Uint16 y) { Uint8 move_block[5]; - _kernel_swi_regs regs; int os_x, os_y; int topLeftY; diff --git a/src/video/riscos/SDL_riscosmouse_c.h b/src/video/riscos/SDL_riscosmouse_c.h index 86d138771..8ad76df60 100644 --- a/src/video/riscos/SDL_riscosmouse_c.h +++ b/src/video/riscos/SDL_riscosmouse_c.h @@ -33,13 +33,16 @@ struct WMcursor { }; /* Functions to be exported */ -void RISCOS_FreeWMCursor(_THIS, WMcursor *cursor); -WMcursor *RISCOS_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern void RISCOS_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *RISCOS_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); -int RISCOS_ShowWMCursor(_THIS, WMcursor *cursor); -void FULLSCREEN_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +extern int RISCOS_ShowWMCursor(_THIS, WMcursor *cursor); +extern void FULLSCREEN_WarpWMCursor(_THIS, Uint16 x, Uint16 y); -int WIMP_ShowWMCursor(_THIS, WMcursor *cursor); -void WIMP_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +extern int WIMP_ShowWMCursor(_THIS, WMcursor *cursor); +extern void WIMP_WarpWMCursor(_THIS, Uint16 x, Uint16 y); -void WIMP_RestoreWimpCursor(); +extern void WIMP_RestoreWimpCursor(); +extern SDL_GrabMode RISCOS_GrabInput(_THIS, SDL_GrabMode mode); + +extern void WIMP_ReshowCursor(_THIS); diff --git a/src/video/riscos/SDL_riscossprite.c b/src/video/riscos/SDL_riscossprite.c index 1a71520be..5930e81fd 100644 --- a/src/video/riscos/SDL_riscossprite.c +++ b/src/video/riscos/SDL_riscossprite.c @@ -23,7 +23,7 @@ /* File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability - 27 March 2003 + 27 March 2003 Implements Sprite plotting code for wimp display.window */ @@ -34,73 +34,107 @@ #include "SDL_stdinc.h" #include "SDL_riscosvideo.h" -extern void WIMP_ReadModeInfo(_THIS); +/* Check if the given pixel format is supported as a sprite */ +int WIMP_IsSupportedSpriteFormat(const RISCOS_PixelFormat *fmt) +{ + _kernel_swi_regs r; + int c; + + /* HACK: Mode 28 won't report as having a full palette. Just assume it's supported */ + if (fmt->sprite_mode_word == 28) return 0; + + /* OS_ReadModeVariable supports sprite mode words, so we can use that to sanity check things */ + r.r[0] = fmt->sprite_mode_word; + r.r[1] = 3; /* NColour */ + _kernel_swi_c(OS_ReadModeVariable,&r,&r,&c); + if (c || (r.r[2] != fmt->ncolour)) return -1; + r.r[1] = 0; /* ModeFlags */ + _kernel_swi_c(OS_ReadModeVariable,&r,&r,&c); + if (c || ((r.r[2] & 0xf280) != fmt->modeflags)) return -1; + r.r[1] = 9; /* Log2BPP */ + _kernel_swi_c(OS_ReadModeVariable,&r,&r,&c); + if (c || (r.r[2] != fmt->log2bpp)) return -1; + + /* Looks good */ + return 0; +} + +/* Find a supported sprite format in the given BPP */ +const RISCOS_SDL_PixelFormat *WIMP_FindSupportedSpriteFormat(int bpp) +{ + int pass; + const RISCOS_SDL_PixelFormat *fmt; + + for(pass=0;pass<2;pass++) + { + for (fmt = RISCOS_SDL_PixelFormats;fmt->sdl_bpp;fmt++) + { + if (fmt->sdl_bpp != bpp) + { + continue; + } + + if (!WIMP_IsSupportedSpriteFormat(&fmt->ro)) + { + return fmt; + } + } + + /* Fuzzy matching for 15bpp & 16bpp */ + if (bpp == 15) { bpp = 16; } + else if (bpp == 16) { bpp = 15; } + else { break; } + } + return NULL; +} /* Create sprite buffer for screen */ -unsigned char *WIMP_CreateBuffer(int width, int height, int bpp) +unsigned char *WIMP_CreateBuffer(int width, int height, const RISCOS_PixelFormat *format) { - int size; - char sprite_name[12] = "display"; - unsigned char *buffer; - _kernel_swi_regs regs; - int bytesPerPixel; - int bytesPerRow; - int offsetToSpriteData = 60; - - switch(bpp) - { - case 32: bytesPerPixel = 4; break; - case 16: bytesPerPixel = 2; break; - case 8: - bytesPerPixel = 1; - offsetToSpriteData += 2048; /* Add in size of palette */ - break; - default: - return NULL; - break; - } - - bytesPerRow = bytesPerPixel * width; - - if ((bytesPerRow & 3) != 0) - { - bytesPerRow += 4 - (bytesPerRow & 3); - } - size = bytesPerRow * height; - - buffer = SDL_malloc( (size_t) size + offsetToSpriteData ); - if (!buffer) return NULL; + int size; + char sprite_name[12] = "display"; + unsigned char *buffer; + _kernel_swi_regs regs; + int bytesPerPixel = 1 << (format->log2bpp-3); + int bytesPerRow; + int offsetToSpriteData = 60; + + if (format->log2bpp == 3) + { + offsetToSpriteData += 2048; /* Add in size of palette */ + } + + bytesPerRow = bytesPerPixel * width; + + if ((bytesPerRow & 3) != 0) + { + bytesPerRow += 4 - (bytesPerRow & 3); + } + size = bytesPerRow * height; + + buffer = SDL_malloc( (size_t) size + offsetToSpriteData ); + if (!buffer) return NULL; /* Initialise a sprite area */ - *(unsigned int *)buffer = size + offsetToSpriteData; - *(unsigned int *)(buffer + 8) = 16; + *(unsigned int *)buffer = size + offsetToSpriteData; + *(unsigned int *)(buffer + 8) = 16; - regs.r[0] = 256+9; - regs.r[1] = (unsigned int)buffer; + regs.r[0] = 256+9; + regs.r[1] = (unsigned int)buffer; _kernel_swi(OS_SpriteOp, ®s, ®s); - regs.r[0] = 256+15; - regs.r[1] = (unsigned int)buffer; - regs.r[2] = (unsigned int)&sprite_name; - regs.r[3] = 0; /* Palette flag: 0 = no palette */ - regs.r[4] = width; - regs.r[5] = height; - if (bpp == 8) - { - /* Use old style mode number */ - regs.r[6] = 28; /* 8bpp 90x90dpi */ - } else - { - regs.r[6] = (((bpp == 16) ? 5 : 6) << 27) /* Type 6 = 32bpp sprite, 5 = 16bpp sprite */ - | (90 << 14) /* Vertical dpi */ - | (90 << 1) /* Horizontal dpi */ - | 1; /* Marker to distinguish between mode selectors and sprite modes */ - } + regs.r[0] = 256+15; + regs.r[1] = (unsigned int)buffer; + regs.r[2] = (unsigned int)&sprite_name; + regs.r[3] = 0; /* Palette flag: 0 = no palette */ + regs.r[4] = width; + regs.r[5] = height; + regs.r[6] = format->sprite_mode_word; if (_kernel_swi(OS_SpriteOp, ®s, ®s) == NULL) { - if (bpp == 8) + if (format->log2bpp == 3) { /* Modify sprite to take into account 256 colour palette */ int *sprite = (int *)(buffer + 16); diff --git a/src/video/riscos/SDL_riscostask.c b/src/video/riscos/SDL_riscostask.c index 908a0505f..04f58fc5a 100644 --- a/src/video/riscos/SDL_riscostask.c +++ b/src/video/riscos/SDL_riscostask.c @@ -37,6 +37,8 @@ #include "SDL_stdinc.h" #include "SDL_riscostask.h" +#include "SDL_riscosvideo.h" +#include "SDL_riscosmouse_c.h" #if !SDL_THREADS_DISABLED #include @@ -54,8 +56,6 @@ int riscos_closeaction = 1; /* Close icon action */ static int stored_mode = -1; /* -1 when in desktop, mode number or pointer when full screen */ -extern int mouseInWindow; /* Mouse is in WIMP window */ - /* Local function */ static int RISCOS_GetTaskName(char *task_name, size_t maxlen); diff --git a/src/video/riscos/SDL_riscostask.h b/src/video/riscos/SDL_riscostask.h index 5744afa9d..052fac8b4 100644 --- a/src/video/riscos/SDL_riscostask.h +++ b/src/video/riscos/SDL_riscostask.h @@ -26,6 +26,9 @@ 26 March 2003 */ +extern int riscos_backbuffer; /* Create a back buffer in system memory for full screen mode */ +extern int riscos_closeaction; /* Close icon action */ + /* Task initialisation/Clean up */ extern int RISCOS_InitTask(); diff --git a/src/video/riscos/SDL_riscosvideo.c b/src/video/riscos/SDL_riscosvideo.c index bae5e374d..14a45799d 100644 --- a/src/video/riscos/SDL_riscosvideo.c +++ b/src/video/riscos/SDL_riscosvideo.c @@ -54,30 +54,63 @@ static void RISCOS_VideoQuit(_THIS); static SDL_Rect **RISCOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); static SDL_Surface *RISCOS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); -int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info); - -int RISCOS_ToggleFullScreen(_THIS, int fullscreen); -/* Mouse checking */ -void RISCOS_CheckMouseMode(_THIS); -extern SDL_GrabMode RISCOS_GrabInput(_THIS, SDL_GrabMode mode); - -/* Fullscreen mode functions */ -extern SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); -extern void FULLSCREEN_BuildModeList(_THIS); -extern void FULLSCREEN_SetDeviceMode(_THIS); -extern int FULLSCREEN_ToggleFromWimp(_THIS); - -/* Wimp mode functions */ -extern SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); -extern void WIMP_DeleteWindow(_THIS); -extern int WIMP_ToggleFromFullScreen(_THIS); - /* Hardware surface functions - common to WIMP and FULLSCREEN */ static int RISCOS_AllocHWSurface(_THIS, SDL_Surface *surface); static int RISCOS_LockHWSurface(_THIS, SDL_Surface *surface); static void RISCOS_UnlockHWSurface(_THIS, SDL_Surface *surface); static void RISCOS_FreeHWSurface(_THIS, SDL_Surface *surface); +/* Table of known pixel formats */ +const RISCOS_SDL_PixelFormat *RISCOS_SDL_PixelFormats = (const RISCOS_SDL_PixelFormat[]) { +/* 8bpp palettized */ +{ { 255, 0x0080, 3, 28 }, 8, 0, 0, 0 }, +/* 12bpp true colour */ +{ { 4095, 0x0000, 4, 0x79004051 }, 12, 0x0f, 0x0f<<4, 0x0f<<8 }, +{ { 4095, 0x4000, 4, 0x79004051 }, 12, 0x0f<<8, 0x0f<<4, 0x0f }, +/* 15bpp true colour */ +{ { 65535, 0x0000, 4, 0x28168003 }, 15, 0x1f, 0x1f<<5, 0x1f<<10 }, +{ { 65535, 0x4000, 4, 0x78504051 }, 15, 0x1f<<10, 0x1f<<5, 0x1f }, +/* 16bpp true colour */ +{ { 65535, 0x0080, 4, 0x50168003 }, 16, 0x1f, 0x3f<<5, 0x1f<<11 }, +{ { 65535, 0x4080, 4, 0x78A04051 }, 16, 0x1f<<11, 0x3f<<5, 0x1f }, +/* 32bpp true colour */ +{ { -1, 0x0000, 5, 0x30168003 }, 32, 0xff, 0xff<<8, 0xff<<16 }, +{ { -1, 0x4000, 5, 0x78604051 }, 32, 0xff<<16, 0xff<<8, 0xff }, +/* Terminator */ +{ }, +}; + +const RISCOS_SDL_PixelFormat *RISCOS_CurrentPixelFormat() +{ + _kernel_swi_regs regs; + int vduvars[4]; + const RISCOS_SDL_PixelFormat *fmt; + + vduvars[0] = 3; /* NColour */ + vduvars[1] = 0; /* ModeFlags */ + vduvars[2] = 9; /* Log2BPP */ + vduvars[3] = -1; + + regs.r[0] = (int) vduvars; + regs.r[1] = (int) vduvars; + + _kernel_swi(OS_ReadVduVariables, ®s, ®s); + + vduvars[1] &= 0xf280; /* Mask out the bits we don't care about */ + + fmt = RISCOS_SDL_PixelFormats; + while (fmt->sdl_bpp) + { + if ((fmt->ro.ncolour == vduvars[0]) && (fmt->ro.modeflags == vduvars[1]) && (fmt->ro.log2bpp == vduvars[2])) + { + return fmt; + } + fmt++; + } + + return NULL; +} + /* RISC OS driver bootstrap functions */ static int RISCOS_Available(void) @@ -162,7 +195,9 @@ VideoBootStrap RISCOS_bootstrap = { int RISCOS_VideoInit(_THIS, SDL_PixelFormat *vformat) { _kernel_swi_regs regs; - int vars[4], vals[3]; + int vars[3]; + const RISCOS_SDL_PixelFormat *fmt; + SDL_PixelFormat *fmt2 = NULL; if (RISCOS_InitTask() == 0) { @@ -170,49 +205,36 @@ int RISCOS_VideoInit(_THIS, SDL_PixelFormat *vformat) return 0; } - vars[0] = 9; /* Log base 2 bpp */ - vars[1] = 11; /* XWndLimit - num x pixels -1 */ - vars[2] = 12; /* YWndLimit - num y pixels -1 */ - vars[3] = -1; /* Terminate list */ + vars[0] = 11; /* XWndLimit - num x pixels -1 */ + vars[1] = 12; /* YWndLimit - num y pixels -1 */ + vars[2] = -1; /* Terminate list */ regs.r[0] = (int)vars; - regs.r[1] = (int)vals; + regs.r[1] = (int)vars; _kernel_swi(OS_ReadVduVariables, ®s, ®s); - vformat->BitsPerPixel = (1 << vals[0]); /* Determine the current screen size */ - this->info.current_w = vals[1] + 1; - this->info.current_h = vals[2] + 1; + this->info.current_w = vars[0] + 1; + this->info.current_h = vars[1] + 1; - /* Minimum bpp for SDL is 8 */ - if (vformat->BitsPerPixel < 8) vformat->BitsPerPixel = 8; - - - switch (vformat->BitsPerPixel) + fmt = RISCOS_CurrentPixelFormat(); + if (fmt != NULL) + { + fmt2 = SDL_AllocFormat(fmt->sdl_bpp,fmt->rmask,fmt->gmask,fmt->bmask,0); + } + if (fmt2 != NULL) + { + *vformat = *fmt2; + SDL_free(fmt2); + } + else { - case 15: - case 16: - vformat->Bmask = 0x00007c00; - vformat->Gmask = 0x000003e0; - vformat->Rmask = 0x0000001f; - vformat->BitsPerPixel = 16; /* SDL wants actual number of bits used */ - vformat->BytesPerPixel = 2; - break; - - case 24: - case 32: - vformat->Bmask = 0x00ff0000; - vformat->Gmask = 0x0000ff00; - vformat->Rmask = 0x000000ff; - vformat->BytesPerPixel = 4; - break; - - default: - vformat->Bmask = 0; - vformat->Gmask = 0; - vformat->Rmask = 0; - vformat->BytesPerPixel = 1; - break; + /* Panic! */ + vformat->BitsPerPixel = 8; + vformat->Bmask = 0; + vformat->Gmask = 0; + vformat->Rmask = 0; + vformat->BytesPerPixel = 1; } /* Fill in some window manager capabilities */ diff --git a/src/video/riscos/SDL_riscosvideo.h b/src/video/riscos/SDL_riscosvideo.h index a1afc40fc..dd060dc02 100644 --- a/src/video/riscos/SDL_riscosvideo.h +++ b/src/video/riscos/SDL_riscosvideo.h @@ -31,6 +31,23 @@ /* Hidden "this" pointer for the video functions */ #define _THIS SDL_VideoDevice *this +/* Information that RISC OS uses to identify/describe pixel formats */ +typedef struct { + int ncolour,modeflags,log2bpp; + Uint32 sprite_mode_word; +} RISCOS_PixelFormat; + +/* RISC OS information combined with SDL information */ +typedef struct { + RISCOS_PixelFormat ro; + int sdl_bpp; + Uint32 rmask; + Uint32 gmask; + Uint32 bmask; +} RISCOS_SDL_PixelFormat; + +extern const RISCOS_SDL_PixelFormat *RISCOS_SDL_PixelFormats; /* Table of known formats */ + /* Private display data */ @@ -41,7 +58,6 @@ struct SDL_PrivateVideoData { int height; int xeig; int yeig; - int screen_bpp; int screen_width; int screen_height; char *pixtrans; @@ -51,6 +67,8 @@ struct SDL_PrivateVideoData { unsigned int window_handle; char title[256]; + const RISCOS_SDL_PixelFormat *format; /* Format of current SDL display */ + #define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ int SDL_nummodes[NUM_MODELISTS]; SDL_Rect **SDL_modelist[NUM_MODELISTS]; @@ -60,4 +78,40 @@ struct SDL_PrivateVideoData { #define SDL_nummodes (this->hidden->SDL_nummodes) #define SDL_modelist (this->hidden->SDL_modelist) +/* SDL_riscosvideo.c */ +extern const RISCOS_SDL_PixelFormat *RISCOS_CurrentPixelFormat(); /* Find the current format */ +extern int RISCOS_ToggleFullScreen(_THIS, int fullscreen); +extern int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info); + +/* SDL_riscossprite.c */ +extern int WIMP_IsSupportedSpriteFormat(const RISCOS_PixelFormat *fmt); +extern const RISCOS_SDL_PixelFormat *WIMP_FindSupportedSpriteFormat(int bpp); +extern unsigned char *WIMP_CreateBuffer(int width, int height, const RISCOS_PixelFormat *format); +extern void WIMP_SetupPlotInfo(_THIS); +extern void WIMP_PlotSprite(_THIS, int x, int y); + +/* SDL_wimpvideo.c */ +extern void WIMP_PumpEvents(_THIS); +extern void WIMP_SetFocus(int win); +extern void WIMP_ReadModeInfo(_THIS); +extern void WIMP_DeleteWindow(_THIS); +extern SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +extern int WIMP_ToggleFromFullScreen(_THIS); + +/* SDL_riscosFullScreenVideo.c */ +extern void FULLSCREEN_SetDeviceMode(_THIS); +extern const RISCOS_SDL_PixelFormat *FULLSCREEN_SetMode(int width, int height, int bpp); +extern void FULLSCREEN_BuildModeList(_THIS); +extern SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +extern int FULLSCREEN_ToggleFromWimp(_THIS); + +/* SDL_riscosASM.S */ +extern void RISCOS_Put32(void *to, int pixels, int pitch, int rows, void *from, int src_skip_bytes); /* Fast assembler copy */ + +/* SDL_wimppoll.c */ +extern int mouseInWindow; /* Mouse is in WIMP window */ +extern int hasFocus; +extern void WIMP_Poll(_THIS, int waitTime); + + #endif /* _SDL_risosvideo_h */ diff --git a/src/video/riscos/SDL_wimppoll.c b/src/video/riscos/SDL_wimppoll.c index 420c1b003..948c03f54 100644 --- a/src/video/riscos/SDL_wimppoll.c +++ b/src/video/riscos/SDL_wimppoll.c @@ -48,16 +48,7 @@ #include #endif -/* Local functions */ -void WIMP_Poll(_THIS, int waitTime); -void WIMP_SetFocus(int win); -/* SDL_riscossprite functions */ -void WIMP_PlotSprite(_THIS, int x, int y); - - -extern void WIMP_PollMouse(_THIS); -extern void RISCOS_PollKeyboard(); #if SDL_THREADS_DISABLED /* Timer running function */ @@ -66,10 +57,6 @@ extern void RISCOS_CheckTimer(); extern int riscos_using_threads; #endif -/* Mouse cursor handling */ -extern void WIMP_ReshowCursor(_THIS); -extern void WIMP_RestoreWimpCursor(); - int hasFocus = 0; int mouseInWindow = 0; diff --git a/src/video/riscos/SDL_wimpvideo.c b/src/video/riscos/SDL_wimpvideo.c index d28ff385e..dba7ea3d4 100644 --- a/src/video/riscos/SDL_wimpvideo.c +++ b/src/video/riscos/SDL_wimpvideo.c @@ -43,87 +43,51 @@ #include "kernel.h" #include "swis.h" -/* Initialization/Query functions */ -SDL_Rect **WIMP_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); -SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); -int WIMP_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); -void WIMP_SetWMCaption(_THIS, const char *title, const char *icon); - - -extern unsigned char *WIMP_CreateBuffer(int width, int height, int bpp); -extern void WIMP_PumpEvents(_THIS); -extern void WIMP_PlotSprite(_THIS, int x, int y); -extern void WIMP_SetupPlotInfo(_THIS); -extern void WIMP_SetFocus(int win); - -/* etc. */ +static int WIMP_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void WIMP_SetWMCaption(_THIS, const char *title, const char *icon); static void WIMP_UpdateRects(_THIS, int numrects, SDL_Rect *rects); /* RISC OS Wimp handling helpers */ -void WIMP_ReadModeInfo(_THIS); -unsigned int WIMP_SetupWindow(_THIS, SDL_Surface *surface); -void WIMP_SetDeviceMode(_THIS); -void WIMP_DeleteWindow(_THIS); +static unsigned int WIMP_SetupWindow(_THIS, SDL_Surface *surface); +static void WIMP_SetDeviceMode(_THIS); -/* FULLSCREEN function required for wimp/fullscreen toggling */ -extern int FULLSCREEN_SetMode(int width, int height, int bpp); - -/* Currently need to set this up here as it only works if you - start up in a Wimp mode */ -extern int RISCOS_ToggleFullScreen(_THIS, int fullscreen); - -extern int riscos_backbuffer; -extern int riscos_closeaction; - -/* Following needed to ensure window is shown immediately */ -extern int hasFocus; -extern void WIMP_Poll(_THIS, int waitTime); SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) { - Uint32 Rmask = 0; - Uint32 Gmask = 0; - Uint32 Bmask = 0; - unsigned char *buffer = NULL; - int bytesPerPixel = 1; - - /* Don't support double buffering in Wimp mode */ - flags &= ~SDL_DOUBLEBUF; - flags &= ~SDL_HWSURFACE; + unsigned char *buffer = NULL; + int bytesPerPixel; + const RISCOS_SDL_PixelFormat *fmt; + + /* Don't support double buffering in Wimp mode */ + flags &= ~SDL_DOUBLEBUF; + flags &= ~SDL_HWSURFACE; + + /* Identify the current pixel format */ + fmt = RISCOS_CurrentPixelFormat(); + /* If it's the same (approximate) BPP as the desired BPP, use it directly (less overhead in sprite rendering) */ + if ((fmt == NULL) || (fmt->sdl_bpp != ((bpp+1)&~1))) + { + /* Not a good match - look for a supported format which is correct */ + fmt = WIMP_FindSupportedSpriteFormat(bpp); + if (fmt == NULL) + { + SDL_SetError("Pixel depth not supported"); + return NULL; + } + } - switch(bpp) - { - case 8: + if (fmt->sdl_bpp == 8) + { /* Emulated palette using ColourTrans */ flags |= SDL_HWPALETTE; - break; - - case 15: - case 16: - Bmask = 0x00007c00; - Gmask = 0x000003e0; - Rmask = 0x0000001f; - bytesPerPixel = 2; - break; - - case 32: - Bmask = 0x00ff0000; - Gmask = 0x0000ff00; - Rmask = 0x000000ff; - bytesPerPixel = 4; - break; - - default: - SDL_SetError("Pixel depth not supported"); - return NULL; - break; - } + } + bytesPerPixel = 1 << (fmt->ro.log2bpp - 3); /* printf("Setting mode %dx%d\n", width, height);*/ /* Allocate the new pixel format for the screen */ - if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) { + if ( ! SDL_ReallocFormat(current, fmt->sdl_bpp, fmt->rmask, fmt->gmask, fmt->bmask, 0) ) { SDL_SetError("Couldn't allocate new pixel format for requested mode"); return(NULL); } @@ -133,7 +97,7 @@ SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, this->hidden->height = current->h = height; if (bpp == 15) bpp = 16; - buffer = WIMP_CreateBuffer(width, height, bpp); + buffer = WIMP_CreateBuffer(width, height, &fmt->ro); if (buffer == NULL) { SDL_SetError("Couldn't create sprite for video memory"); @@ -155,6 +119,7 @@ SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, /* Sprites are 32bit word aligned */ current->pitch += (4 - (current->pitch & 3)); } + this->hidden->format = fmt; current->flags = flags | SDL_PREALLOC; @@ -214,7 +179,6 @@ void WIMP_ReadModeInfo(_THIS) _kernel_swi(OS_ReadVduVariables, ®s, ®s); this->hidden->xeig = vals[0]; this->hidden->yeig = vals[1]; - this->hidden->screen_bpp = 1 << vals[2]; this->hidden->screen_width = vals[3] + 1; this->hidden->screen_height = vals[4] + 1; } @@ -238,6 +202,8 @@ void WIMP_SetDeviceMode(_THIS) this->ShowWMCursor = WIMP_ShowWMCursor; this->WarpWMCursor = WIMP_WarpWMCursor; +/* Currently need to set this up here as it only works if you + start up in a Wimp mode */ this->ToggleFullScreen = RISCOS_ToggleFullScreen; this->PumpEvents = WIMP_PumpEvents; @@ -432,7 +398,7 @@ int WIMP_ToggleFromFullScreen(_THIS) { /* Need to create a sprite for the screen and copy the data to it */ unsigned char *data; - buffer = WIMP_CreateBuffer(width, height, bpp); + buffer = WIMP_CreateBuffer(width, height, &this->hidden->format->ro); data = buffer + 60; /* Start of sprite data */ if (bpp == 8) data += 2048; /* 8bpp sprite have palette first */