From 65c57a08cf318063e82961d17fe37c6214f71652 Mon Sep 17 00:00:00 2001
From: Jeffrey Lee <jlee@gitlab.riscosopen.org>
Date: Sat, 26 Nov 2016 13:00:33 +0000
Subject: [PATCH] Use different layouts for different screen modes

Detail:
  Rather than using a fixed layout (which assumes a fixed screen size), BootFX now supports multiple layouts, which are able to adjust their scale to fit the current screen.
  First the layout most appropriate to the aspect ratio is chosen, and then coordinates and scale factors are adjusted in order to account for any difference in resolution.
  If the scaling results in a text window which is deemed to be "too small" then another layout will be tried, or in extreme cases BootFX will give up and go inactive for that mode.
  For cases where there is an inexact aspect ratio match, borders will be added to the layout in order to allow it to maintain the correct aspect ratio. This may result in some wasted space but sufficient for most purposes.
  File changes:
  - Docs/Spec.txt - Document BootFX_BarLoad addition to allow custom bar scale factors to be used
  - c/bootfx - Move hard-coded layout parameters into layout_t structs, and implement the layout adjustment logic. Define two layouts for Raspberry Pi; 4:3 layout will crop off the top portion of the splash so that a large text window can be placed underneath.
  - h/bootfx - Remove a few constants which are defined elsewhere in shared headers
Admin:
  Tested on Raspberry Pi, in a variety of screen modes


Version 0.07. Tagged as 'BootFX-0_07'
---
 Docs/Spec.txt |   6 +-
 VersionNum    |  20 ++--
 c/bootfx      | 306 ++++++++++++++++++++++++++++++++++++++++----------
 h/BootFX      |  11 +-
 4 files changed, 265 insertions(+), 78 deletions(-)

diff --git a/Docs/Spec.txt b/Docs/Spec.txt
index 7e86236..dd3f758 100644
--- a/Docs/Spec.txt
+++ b/Docs/Spec.txt
@@ -173,7 +173,10 @@ BootFX_BarLoad (0x59141)
 
 In...
   R0 = flags (unspecified bits should be zero)
+    0 - if set, R2 is a pointer to scale factors
   R1 = pointer to zero-terminated filename
+  R2 = pointer to scale factors (if flag bit 0 set), as per "plot scaled"
+       SpriteOps
 Out...
   R0 = progress bar handle
 
@@ -231,4 +234,5 @@ Out...
   R3 = width (OS units)
   R4 = height (OS units)
 
-Return information about the specified progress bar.
+Return information about the specified progress bar. Width and height take into
+account any scale factors that were provided to SWI BootFX_BarLoad.
diff --git a/VersionNum b/VersionNum
index ca973e2..ac0aa5b 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,23 +1,23 @@
-/* (0.06)
+/* (0.07)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  * Last processed by srccommit version: 1.1.
  *
  */
-#define Module_MajorVersion_CMHG        0.06
+#define Module_MajorVersion_CMHG        0.07
 #define Module_MinorVersion_CMHG        
-#define Module_Date_CMHG                10 Oct 2012
+#define Module_Date_CMHG                26 Nov 2016
 
-#define Module_MajorVersion             "0.06"
-#define Module_Version                  6
+#define Module_MajorVersion             "0.07"
+#define Module_Version                  7
 #define Module_MinorVersion             ""
-#define Module_Date                     "10 Oct 2012"
+#define Module_Date                     "26 Nov 2016"
 
-#define Module_ApplicationDate          "10-Oct-12"
+#define Module_ApplicationDate          "26-Nov-16"
 
 #define Module_ComponentName            "BootFX"
 #define Module_ComponentPath            "bsd/RiscOS/Sources/Video/UserI/BootFX"
 
-#define Module_FullVersion              "0.06"
-#define Module_HelpVersion              "0.06 (10 Oct 2012)"
-#define Module_LibraryVersionInfo       "0:6"
+#define Module_FullVersion              "0.07"
+#define Module_HelpVersion              "0.07 (26 Nov 2016)"
+#define Module_LibraryVersionInfo       "0:7"
diff --git a/c/bootfx b/c/bootfx
index cfe55be..f4c816c 100644
--- a/c/bootfx
+++ b/c/bootfx
@@ -16,6 +16,7 @@
 #include "Global/Services.h"
 #include "Global/Sprite.h"
 #include "Global/CMOS.h"
+#include "Global/OSMem.h"
 #include "Interface/HighFSI.h"
 #include "swis.h"
 #include "bootfxHdr.h"
@@ -57,12 +58,6 @@
 /** Location of our logo JPEG. */
 #define LOGO_JPEG_FILE RESFS_PATH "Logo"
 
-/** Location of our splash screen JPEG. */
-#define SPLASH_JPEG_FILE RESFS_PATH "1920x1080"
-
-/** Location of our default progress bar sprite file (currently only 24bpp supported). */
-#define SPRITE_FILE RESFS_PATH "Bar24"
-
 /** Time to fade out before plotting splash screen (centiseconds). */
 #define FADE_OUT_CS (10)
 
@@ -88,6 +83,7 @@ typedef struct trans_s trans_t;
 typedef struct squash_s squash_t;
 typedef struct barinfo_s barinfo_t;
 typedef struct infochain_s infochain_t;
+typedef struct layout_s layout_t;
 
 /** An OS sprite area structure.
  */
@@ -125,7 +121,7 @@ struct mode_s
   uint32_t  yeig;          /**< Y eigen value. */
 };
 
-/** A structure to gold graphics clipping window information.
+/** A structure to hold graphics clipping window information.
  */
 struct gclip_s
 {
@@ -136,15 +132,15 @@ struct gclip_s
   int16_t ymax;            /**< Top edge (OS units, inclusive). */
 };
 
-/** A structure to gold text window information.
+/** A structure to hold text window information.
  */
 struct tclip_s
 {
   uint8_t vdu;             /**< VDU code (28). */
-  uint8_t xmin;            /**< Left edge (OS units, inclusive). */
-  uint8_t ymin;            /**< Bottom edge (OS units, inclusive). */
-  uint8_t xmax;            /**< Right edge (OS units, inclusive). */
-  uint8_t ymax;            /**< Top edge (OS units, inclusive). */
+  uint8_t xmin;            /**< Left edge (chracters, inclusive). */
+  uint8_t ymin;            /**< Bottom edge (characters, inclusive). */
+  uint8_t xmax;            /**< Right edge (characters, inclusive). */
+  uint8_t ymax;            /**< Top edge (characters, inclusive). */
 };
 
 /** JPEG transformatio matrix for plotting scaled.
@@ -183,6 +179,7 @@ struct barinfo_s
   sprite_t      *border_spr;       /**< Progress bar 'border' sprite pointer. */
   sprite_t      *fill_spr;         /**< Progress bar 'fill' sprite pointer. */
   sprite_t      *bar_spr;          /**< Progress bar 'bar' sprite pointer. */
+  uint32_t       user_scale[4];    /**< User-supplied scale factor block. */
   uint32_t       scale_matrix[4];  /**< Scale factor block (for current mode). */
   uint32_t       pixel_trans[4];   /**< Pixel translation table (for current mode). */
 };
@@ -196,19 +193,61 @@ struct infochain_s
   infochain_t *next;
 };
 
+/** Layout parameters
+ */
+struct layout_s
+{
+  uint16_t dimensions[2];      /**< Dimensions of layout (OS units) */
+  uint16_t splash_x, splash_y; /**< Bottom-left corner of splash (OS units) */
+  uint16_t splash_scale[2];    /**< Scale factor for splash */
+  uint16_t bar_x, bar_y;       /**< Bottom-left corner of bar (OS units) */
+  uint16_t bar_scale[2];       /**< Scale factor for bar */
+  tclip_t  text_window;        /**< Text window to use (assuming 16x16 OS unit font) */
+  uint8_t  min_row, min_col;   /**< Minimum text window size to consider acceptable */
+  const char * splash_file;    /**< Path to splash file */
+  const char * bar_file;       /**< Path to bar file */
+};
+
 /** The text window that we set up after the first mode change depends upon the UserIF at build time.
  */
 #if (defined UserIF_Raspberry)
-#define BAR_X (1280)
-#define BAR_Y (786)
-static tclip_t text_window = { 28, 80, 125, 159, 94 };
+static const layout_t layouts[] =
+{
+  {
+    .dimensions = {3840, 2160},
+    .splash_x = 0,
+    .splash_y = 0,
+    .splash_scale = {1, 1},
+    .bar_x = 1280,
+    .bar_y = 786,
+    .bar_scale = {1, 1},
+    .text_window = {28, 80, 125, 159, 94},
+    .min_row = 10,
+    .min_col = 30,
+    .splash_file = RESFS_PATH "1920x1080",
+    .bar_file = RESFS_PATH "Bar24",
+  },
+  {
+    .dimensions = {3840, 2880},
+    .splash_x = 0,
+    .splash_y = 1152,
+    .splash_scale = {1, 1},
+    .bar_x = 640,
+    .bar_y = 1720,
+    .bar_scale = {2, 1},
+    .text_window = {28, 0, 179, 239, 108},
+    .min_row = 10,
+    .min_col = 30,
+    .splash_file = RESFS_PATH "1920x1080",
+    .bar_file = RESFS_PATH "Bar24",
+  },
+};
 #else
-#define BAR_X (400)
-#define BAR_Y (400)
-static tclip_t text_window = { 28, 0, 0, 255, 255 };
+static const layout_t layouts[] = {};
 #endif
 
 static _kernel_oserror *swi_bar_display(const uint32_t flags, barinfo_t * const barinfo, const int32_t x, const int32_t y);
+static _kernel_oserror *swi_bar_load(const uint32_t flags, const char * const file, const uint32_t * const user_scale, barinfo_t **handle);
 
 static mode_t         mode_info;               /**< Current screen mode information. */
 static barinfo_t     *bootbar        = NULL;   /**< Default progress bar (during the boot sequence). */
@@ -221,6 +260,7 @@ static size_t         splash_size    = 0;      /**< Size (bytes) of the splash s
 static bool           splash_disable = false;  /**< BootFX has disabled its splash screen (and mode change) behaviour */
 static void          *Workspace      = NULL;   /**< Module workspace pointer. */
 static infochain_t   *infochain      = NULL;   /**< List of all allocated progress bar info blocks. */
+static layout_t       layout;                  /**< Layout to use */
 
 
 /********************************************************************************
@@ -442,7 +482,7 @@ static _kernel_oserror *load_squashed_sprites(const char *arg_string, const size
 
   /* Allocate a buffer to unsquash the sprites into */
   out_sz = 64 + hdr->size;
-  ERR(_swix(OS_DynamicArea, _INR(0,8) | _OUT(1) | _OUT(3), OSDA_Create, -1, out_sz, -1, 1<<7, out_sz, NULL, NULL, DA_NAME, danum, &out));
+  ERR(_swix(OS_DynamicArea, _INR(0,8) | _OUT(1) | _OUT(3), DAReason_Create, -1, out_sz, -1, 1<<7, out_sz, NULL, NULL, DA_NAME, danum, &out));
 
   /* Check how much workspace the decompress SWI needs */
   ERR_GOTO(_swix(Squash_Decompress, _INR(0,1) | _OUT(0), 1<<3, -1, &wsp_sz));
@@ -474,7 +514,7 @@ error:
   FREE(buf);
   if (*danum)
   {
-    (void) _swix(OS_DynamicArea, _INR(0,1), OSDA_Remove, *danum);
+    (void) _swix(OS_DynamicArea, _INR(0,1), DAReason_Remove, *danum);
     *danum = 0;
   }
   return err;
@@ -488,7 +528,7 @@ error:
  *
  *  @return Pointer to RISC OS error block or NULL if no error.
  */
-static _kernel_oserror *plot_centred_jepg(const void * const jpeg, const size_t size)
+static _kernel_oserror *plot_centred_jpeg(const void * const jpeg, const size_t size)
 {
   int32_t j_width, j_height, j_xdpi, j_ydpi;
   int32_t x, y;
@@ -521,26 +561,23 @@ static _kernel_oserror *plot_centred_jepg(const void * const jpeg, const size_t
 }
 
 
-/** Plot a JPEG, scaled to fit the whole screen.
+/** Plot a JPEG, scaled and positioned for use as the splash image.
  *
  *  @param jpeg Pointer to the loaded JPEG data (NULL if failed).
  *  @param size Size (bytes) of the JPEG data.
  *
  *  @return Pointer to RISC OS error block or NULL if no error.
  */
-static _kernel_oserror *plot_fullscreen_jepg(const void * const jpeg, const size_t size)
+static _kernel_oserror *plot_splash_jpeg(const void * const jpeg, const size_t size)
 {
-  int32_t j_width, j_height;
   trans_t trans;
 
-  ERR(_swix(JPEG_Info, _INR(0,2) | _OUTR(2,3), 1, jpeg, size, &j_width, &j_height));
-
-  trans.mx = mode_info.screen_x >> mode_info.xeig;
-  trans.my = mode_info.screen_y >> mode_info.yeig;
-  trans.dx = j_width;
-  trans.dy = j_height;
+  trans.mx = layout.splash_scale[0];
+  trans.my = layout.splash_scale[0];
+  trans.dx = layout.splash_scale[1];
+  trans.dy = layout.splash_scale[1];
 
-  return _swix(JPEG_PlotScaled, _INR(0,5), jpeg, 0, 0, &trans, size, 3);
+  return _swix(JPEG_PlotScaled, _INR(0,5), jpeg, layout.splash_x, layout.splash_y, &trans, size, 3);
 }
 
 
@@ -594,11 +631,15 @@ static _kernel_oserror *new_barinfo(barinfo_t **handle)
  *
  *  @return Pointer to RISC OS error block or NULL if no error.
  */
-static _kernel_oserror *udpate_barinfo_for_mode(const barinfo_t * const barinfo)
+static _kernel_oserror *udpate_barinfo_for_mode(barinfo_t *barinfo)
 {
   if (NULL != barinfo)
   {
     ERR(_swix(Wimp_ReadPixTrans, _INR(0,2) | _INR(6,7), 0x200 + SpriteReason_PutSpriteScaled, barinfo->spr_area, barinfo->border_spr, barinfo->scale_matrix, barinfo->pixel_trans));
+    barinfo->scale_matrix[0] *= barinfo->user_scale[0];
+    barinfo->scale_matrix[1] *= barinfo->user_scale[1];
+    barinfo->scale_matrix[2] *= barinfo->user_scale[2];
+    barinfo->scale_matrix[3] *= barinfo->user_scale[3];
   }
   return NULL;
 }
@@ -684,7 +725,7 @@ static _kernel_oserror *free_sprites(barinfo_t *barinfo)
     {
       if (barinfo->danum)
       {
-        err               = _swix(OS_DynamicArea, _INR(0,1), OSDA_Remove, barinfo->danum);
+        err               = _swix(OS_DynamicArea, _INR(0,1), DAReason_Remove, barinfo->danum);
         barinfo->danum    = 0;
         barinfo->spr_area = NULL;
       }
@@ -739,6 +780,64 @@ static _kernel_oserror *read_mode_info(void)
 }
 
 
+/** Calculate the layout parameters for the current mode, based around the given template
+ *
+ *  @param template Pointer to layout parameters to use as a template.
+ *
+ *  @return Calculated layout parameters for the current mode.
+ */
+static layout_t calculate_layout(const layout_t * const template)
+{
+  layout_t ret = *template;
+  ret.dimensions[0] = mode_info.screen_x;
+  ret.dimensions[1] = mode_info.screen_y;
+  uint16_t scale[2];
+  uint16_t offset[2];
+  /* Scale the reference layout, while maintaining aspect ratio */
+  if (template->dimensions[0] * ret.dimensions[1] > template->dimensions[1] * ret.dimensions[0])
+  {
+    /* Screen aspect is taller, scale to fit width */
+    scale[0] = ret.dimensions[0];
+    scale[1] = template->dimensions[0];
+    offset[0] = 0;
+    offset[1] = (ret.dimensions[1]-((template->dimensions[1]*scale[0])/scale[1]))/2;
+  }
+  else
+  {
+    /* Screen aspect is wider, scale to fit height */
+    scale[0] = ret.dimensions[1];
+    scale[1] = template->dimensions[1];
+    offset[0] = (ret.dimensions[0]-((template->dimensions[0]*scale[0])/scale[1]))/2;
+    offset[1] = 0;
+  }
+  /* Adjust parameters */
+  ret.splash_x = ((template->splash_x*scale[0])/scale[1])+offset[0];
+  ret.splash_y = ((template->splash_y*scale[0])/scale[1])+offset[1];
+  ret.splash_scale[0] *= scale[0];
+  ret.splash_scale[1] *= scale[1];
+  ret.bar_x = ((template->bar_x*scale[0])/scale[1])+offset[0];
+  ret.bar_y = ((template->bar_y*scale[0])/scale[1])+offset[1];
+  ret.bar_scale[0] *= scale[0];
+  ret.bar_scale[1] *= scale[1];
+  ret.text_window.xmin = ((template->text_window.xmin*scale[0])/scale[1])+(offset[0]>>4);
+  uint32_t ymin = ((template->text_window.ymin*scale[0])/scale[1])+(offset[1]>>4);
+  uint32_t xmax = ((template->text_window.xmax*scale[0])/scale[1])+(offset[0]>>4);
+  ret.text_window.ymax = ((template->text_window.ymax*scale[0])/scale[1])+(offset[1]>>4);
+  /* Currently the only way of setting the text window coordinates is via VDU 28, which uses bytes for the coordinate values. This causes problems for large modes (dimensions > 2048)
+     Detect out-of-range values and set a zero-size window, this will cause us to fail the size check in pick_layout */
+  if ((ymin > 255) || (xmax > 255))
+  {
+    ret.text_window.ymin = ret.text_window.ymax;
+    ret.text_window.xmax = ret.text_window.xmin;
+  }
+  else
+  {
+    ret.text_window.ymin = ymin;
+    ret.text_window.xmax = xmax;
+  }
+  return ret;
+}
+
 /** Return true if we are not in the desktop.
  *
  *  @return As above. Also, if anything goes wrong, return false.
@@ -784,7 +883,7 @@ static bool conf_lang_is_desktop(void)
 static _kernel_oserror *set_text_window(void)
 {
   /* Set the text window */
-  ERR(_swix(OS_WriteN, _INR(0,1), &text_window, sizeof(text_window)));
+  ERR(_swix(OS_WriteN, _INR(0,1), &layout.text_window, sizeof(layout.text_window)));
 
   /* Clear the text window to the text background colour */
   ERR(_swix(OS_WriteI+12, 0));
@@ -792,6 +891,78 @@ static _kernel_oserror *set_text_window(void)
   return NULL;
 }
 
+/** Pick a layout to use for the current mode.
+ *
+ *  @return True if a suitable layout was selected
+ */
+static bool pick_layout(void)
+{
+  /* Forget any current splash */
+  splash_jpeg = NULL;
+  splash_size = 0;
+
+  /* Pick the layout that has the closest aspect ratio to the current mode and which passes our criteria */
+  uint32_t mode_aspect = (mode_info.screen_x<<16)/mode_info.screen_y;
+  int32_t best_diff = INT32_MAX;
+
+  for (int i=0;i < sizeof(layouts)/sizeof(layouts[0]); i++)
+  {
+    /* Check aspect ratio */
+    uint32_t candidate_aspect = (layouts[i].dimensions[0]<<16)/layouts[i].dimensions[1];
+    int32_t diff = candidate_aspect - mode_aspect;
+    if (diff < 0)
+    {
+      diff = -diff;
+    }
+    if (diff >= best_diff)
+    {
+      continue;
+    }
+
+    layout_t candidate = calculate_layout(&layouts[i]);
+
+    /* Check layout criteria */
+    if ((candidate.text_window.xmax+1-candidate.text_window.xmin < candidate.min_col)
+     || (candidate.text_window.ymin+1-candidate.text_window.ymax < candidate.min_row))
+    {
+      continue;
+    }
+
+    layout = candidate;
+    best_diff = diff;
+  }
+
+  if (best_diff != INT32_MAX)
+  {
+    /* Try and load the relevant files */
+    free_sprites(bootbar);
+    bootbar = NULL;
+    uint32_t scale[4];
+    scale[0] = scale[1] = layout.bar_scale[0];
+    scale[2] = scale[3] = layout.bar_scale[1];
+    if (swi_bar_load(1, layout.bar_file, scale, &bootbar) != NULL)
+    {
+      goto fail;
+    }
+
+    if (resfs_file_to_ptr_and_size(layout.splash_file, &splash_jpeg, &splash_size) != NULL)
+    {
+      goto fail;
+    }
+
+    return true;
+  }
+
+fail:
+  /* Set some default scale factors for safety */
+  layout = (layout_t) {
+    .splash_scale = {1, 1},
+    .bar_scale = {1, 1},
+  };
+
+  return false;
+}
+
 
 /** Do all sorts of stuff on a mode change.
  *
@@ -816,19 +987,25 @@ static _kernel_oserror *mode_has_changed(void)
     return NULL;
   }
 
+  /* Don't do anything special for this mode if we can't find a suitable layout */
+  if (!pick_layout())
+  {
+    return NULL;
+  }
+
   /* Fade quickly to black */
   (void) _swix(ScreenFX_Fade, _INR(0,3), 1, 0, 0, FADE_OUT_CS);
 
   /* Plot the splash screen JPEG full-screen */
   if (splash_jpeg)
   {
-    ERR_GOTO(plot_fullscreen_jepg(splash_jpeg, splash_size));
+    ERR_GOTO(plot_splash_jpeg(splash_jpeg, splash_size));
   }
 
   /* Plot the booting progress bar at the default position */
   if (bootbar)
   {
-    ERR(swi_bar_display(0, bootbar, BAR_X, BAR_Y));
+    ERR(swi_bar_display(0, bootbar, layout.bar_x, layout.bar_y));
   }
 
   /* Fade in from black (more slowly and in the background) */
@@ -854,13 +1031,14 @@ error:
 
 /** Load some progress bar sprites and return a handle for this progress bar.
  *
- *  @param flags   Flags word (currently unused).
- *  @param file    Pointer to zero-terminated filename string.
- *  @param handle  Returned: pointer to the progress bar information block.
+ *  @param flags      Flags word.
+ *  @param file       Pointer to zero-terminated filename string.
+ *  @param user_scale User-provided scale factors (optional)
+ *  @param handle     Returned: pointer to the progress bar information block.
  *
  *  @return Pointer to RISC OS error block or NULL if no error.
  */
-static _kernel_oserror *swi_bar_load(const uint32_t flags, const char * const file, barinfo_t **handle)
+static _kernel_oserror *swi_bar_load(const uint32_t flags, const char * const file, const uint32_t * const user_scale, barinfo_t **handle)
 {
   _kernel_oserror *err = NULL;
   barinfo_t       *barinfo;
@@ -868,8 +1046,6 @@ static _kernel_oserror *swi_bar_load(const uint32_t flags, const char * const fi
   size_t           size;
   uint32_t         type;
 
-  IGNORE(flags);
-
   /* If anything goes wrong, make sure we return a null handle */
   *handle = NULL;
 
@@ -912,7 +1088,7 @@ static _kernel_oserror *swi_bar_load(const uint32_t flags, const char * const fi
     {
       void *ptr;
 
-      ERR(resfs_file_to_ptr_and_size(SPRITE_FILE, &ptr, &size));
+      ERR(resfs_file_to_ptr_and_size(file, &ptr, &size));
       barinfo->resfs    = true;
       barinfo->spr_area = (sprite_area_t *)((uint32_t)ptr - 4);
     }
@@ -939,6 +1115,17 @@ static _kernel_oserror *swi_bar_load(const uint32_t flags, const char * const fi
   ERR_GOTO(_swix(OS_SpriteOp, _INR(0,2) | _OUTR(3,4), 512 + SpriteReason_ReadSpriteSize, barinfo->spr_area, barinfo->border_spr, &barinfo->width, &barinfo->height));
 
   /* Initialise the scale factors and pixel translation table for plotting this progress bar */
+  if (flags & 1)
+  {
+    barinfo->user_scale[0] = user_scale[0];
+    barinfo->user_scale[1] = user_scale[1];
+    barinfo->user_scale[2] = user_scale[2];
+    barinfo->user_scale[3] = user_scale[3];
+  }
+  else
+  {
+    barinfo->user_scale[0] = barinfo->user_scale[1] = barinfo->user_scale[2] = barinfo->user_scale[3] = 1;
+  }
   ERR_GOTO(udpate_barinfo_for_mode(barinfo));
 
   *handle = barinfo;
@@ -989,16 +1176,20 @@ static _kernel_oserror *swi_bar_update(const uint32_t flags, barinfo_t * barinfo
   else if (percent > 100)
     percent = 100;
 
+  /* Calculate scaled bar size */
+  int32_t width = (barinfo->width*barinfo->user_scale[0])/barinfo->user_scale[2];
+  int32_t height = (barinfo->height*barinfo->user_scale[1])/barinfo->user_scale[3];
+
   /* Calculate how far back (pixels) the bar needs to be plotted from the origin of the border */
-  offset       = -barinfo->width + ((barinfo->width * percent) / 100);
+  offset       = -width + ((width * percent) / 100);
   barinfo->val = (int32_t)percent;
 
   /* Create the graphics clipping rectangle */
   vdu.vdu  = 24;
   vdu.xmin = barinfo->x;
   vdu.ymin = barinfo->y;
-  vdu.xmax = barinfo->x + ((barinfo->width + offset) << mode_info.xeig);
-  vdu.ymax = barinfo->y + (barinfo->height << mode_info.yeig);
+  vdu.xmax = barinfo->x + ((width + offset) << mode_info.xeig);
+  vdu.ymax = barinfo->y + (height << mode_info.yeig);
 
   /* Set the graphics clipping rectangle */
   ERR(_swix(OS_WriteN, _INR(0,1), &vdu, sizeof(vdu)));
@@ -1102,8 +1293,8 @@ static _kernel_oserror *swi_bar_readinfo(const uint32_t flags, barinfo_t * const
   *val    = barinfo->val;
   *x      = barinfo->x;
   *y      = barinfo->y;
-  *width  = barinfo->width;
-  *height = barinfo->height;
+  *width  = (barinfo->width*barinfo->user_scale[0])/barinfo->user_scale[2];
+  *height = (barinfo->height*barinfo->user_scale[1])/barinfo->user_scale[3];
 
   return NULL;
 }
@@ -1144,7 +1335,7 @@ static _kernel_oserror *cli_bar_load(const char *arg_string)
   ERR(free_sprites(bootbar));
   bootbar = NULL;
 
-  return swi_bar_load(0, arg_string, &bootbar);
+  return swi_bar_load(0, arg_string, NULL, &bootbar);
 }
 
 
@@ -1210,6 +1401,11 @@ static _kernel_oserror *cli_debug(const char *arg_string)
   }
   printf("  logo JPEG at &%08X size = %d\n", (uint32_t)logo_jpeg, logo_size);
   printf("  splash JPEG at &%08X size = %d\n", (uint32_t)splash_jpeg, splash_size);
+  printf("  layout:\n");
+  printf("    dims %dx%d\n", layout.dimensions[0], layout.dimensions[1]);
+  printf("    splash %d,%d scale %d:%d\n", layout.splash_x, layout.splash_y, layout.splash_scale[0], layout.splash_scale[1]);
+  printf("    bar %d,%d scale %d:%d\n", layout.bar_x, layout.bar_y, layout.bar_scale[0], layout.bar_scale[1]);
+  printf("    text window %d,%d %d,%d\n", layout.text_window.xmin, layout.text_window.ymin, layout.text_window.xmax, layout.text_window.ymax);
   return NULL;
 }
 
@@ -1283,10 +1479,7 @@ _kernel_oserror *Module_Init(const char *cmd_tail, int podule_base, void *pw)
         ERR(_swix(OS_WriteN, _INR(0,1), cursoff, sizeof cursoff));
 
         /* Plot the logo image */
-        ERR(plot_centred_jepg(logo_jpeg, logo_size));
-
-        /* Load our default sprites from ResourceFS */
-        ERR(cli_bar_load(SPRITE_FILE));
+        ERR(plot_centred_jpeg(logo_jpeg, logo_size));
       }
       else
       {
@@ -1297,9 +1490,6 @@ _kernel_oserror *Module_Init(const char *cmd_tail, int podule_base, void *pw)
     {
       splash_disable = true;
     }
-
-    /* Get a pointer to the splash screen JPEG (or disable splash screen if not found) */
-    (void) resfs_file_to_ptr_and_size(SPLASH_JPEG_FILE, &splash_jpeg, &splash_size);
   }
   return err;
 }
@@ -1355,7 +1545,7 @@ void Module_Service(int service_number, _kernel_swi_regs *r, void *pw)
       /* Stop doing splash screen plotting */
       if (splash_jpeg)
       {
-        (void) plot_fullscreen_jepg(splash_jpeg, splash_size);
+        (void) plot_splash_jpeg(splash_jpeg, splash_size);
         splash_jpeg = NULL;
         splash_size = 0;
       }
@@ -1389,7 +1579,7 @@ _kernel_oserror *Module_SWI(int swi_offset, _kernel_swi_regs *r, void *pw)
     {
       barinfo_t *handle = NULL;
 
-      ERR(swi_bar_load(r->r[0], (char *)r->r[1], &handle));
+      ERR(swi_bar_load(r->r[0], (char *)r->r[1], (const uint32_t * const)r->r[2], &handle));
       r->r[0] = (int32_t)handle;
 
       return NULL;
diff --git a/h/BootFX b/h/BootFX
index 8223d86..fab90c6 100644
--- a/h/BootFX
+++ b/h/BootFX
@@ -41,18 +41,11 @@
 #ifndef ScreenFX_Fade
 #define ScreenFX_Fade (0x58440)
 #endif
+/** Global/ModHand.h defines this, but also defines macros that conflict with our CMHG handler functions
+ */
 #ifndef ModHandReason_LookupName
 #define ModHandReason_LookupName (18)
 #endif
-#ifndef OSFind_Close
-#define OSFind_Close (0)
-#endif
-#ifndef OSDA_Create
-#define OSDA_Create (0)
-#endif
-#ifndef OSDA_Remove
-#define OSDA_Remove (1)
-#endif
 
 #endif
 
-- 
GitLab