/*
 * config.c
 * --------
 * Reads and saves the choices file. Not all settings can be changed
 * whilst playing. The saving facility is mainly for the following settings,
 *
 * lock aspect
 * lock size
 * control panel on/off
 * brightness
 * contrast
 * colour
 * volume
 * non multitasking initial zoom
 *
 * The following settings retain their initial values when saved. i.e. they
 * are unaffected by changes made whilst playing.
 *
 * play audio
 * save audio
 * multitasking initial zoom
 *
 * The Play and Save audio settings can be automatically changed during
 * initialisation due to prevailing conditions. i.e. A video only file,
 * or problems with starting AMPlayer, or inability to open a sountrack
 * file. This is why the current play settings are not saved.
 *
 * The internal zoom setting is fixed at 100% when multitasking
 * to allow variable scale factors. For this reason, when multitasking,
 * the current zoom setting is not saved.
 *
 * The multitask on/off setting is saved unchanged because it is switched
 * off before play automatically if using a full screen mode.
 *
 * note. The debug setting is not loaded here as it makes more sense to
 * let the config program append it to the command line along with any
 * redirection. Any debug and comment strings are saved unchanged.
 * However, bit 0 of debug is loaded here (all frames).
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "kernel.h"
#include "swis.h"
#include "inttypes.h"
#include "config.h"
#include "ka_error.h"

static const int c_col_depth[KA_COL_MAX] = {3, 4, 4, 4, 5};
static const int c_col_colours[KA_COL_MAX] = {1<<8, 1<<12, 1<<15, 1<<16, 1<<24};
static const char c_mode_char[KA_MODE_MAX] = {'M', 'D', 'A', 'F'};

static char
  debug_str[80],
  comment_str[80],
  *debug = NULL,
  *comment = NULL;

static int set_bool(const char* s, const char* format, int* var, int bit)
{
  char c;

  if (!sscanf(s, format, &c))
    return 0;

  if (c == 'Y')
    *var |= bit;
  else if (c == 'N')
    *var &= ~bit;
  else
    return 0;

  return 1;
}

static int set_int(const char* s, const char* format, int* var, int min, int max)
{
  int v;

  if (!sscanf(s, format, &v))
    return 0;

  if ((v < min) || (v > max))
    return 0;

  *var = v;

  return 1;
}

/**
 * Initializes config structure.
 */
void config_init(ka_config_t* pconfig)
{
  pconfig->debug = 0; // no debug
  pconfig->control = cfg_ctrl_scroll_bars | cfg_ctrl_controls | cfg_ctrl_autoexit
                   | cfg_ctrl_accel_inteldma | cfg_ctrl_accel_geminus | cfg_ctrl_accel_videooverlay;
  pconfig->audio.cfg = cfg_audio_play | cfg_audio_sync | cfg_audio_autoselect;
  pconfig->audio.stream = 1;
  pconfig->audio.volume = 127;
  pconfig->audio.module = 1;
  pconfig->video.stream = 0;
  pconfig->video.demux_ps = 0;
  pconfig->video.position_x = pconfig->video.position_y = -1; // centered (desktop only)
  pconfig->video.colour = 100;
  pconfig->video.brightness = 100;
  pconfig->video.contrast = 100;
  pconfig->video.cfg = cfg_video_lock_aspect | cfg_video_pixel_aspect;
  pconfig->video.mode = KA_MODE_MULTITASK;
  pconfig->video.deinterlace = KA_DEINTERLACE_BLEND;
  pconfig->video.resizemode = KA_RESIZE_NONE;
  pconfig->video.resizeto = KA_RESIZETO_MONITOR;
  pconfig->video.monitor_aspect.x = 16;
  pconfig->video.monitor_aspect.y = 9;
  pconfig->video.modes[KA_MODE_MULTITASK].cfg    = cfg_video_fit_screen | cfg_video_dither;
  pconfig->video.modes[KA_MODE_MULTITASK].width  = 0; // irrelevant
  pconfig->video.modes[KA_MODE_MULTITASK].height = 0; // irrelevant
  pconfig->video.modes[KA_MODE_MULTITASK].cols   = 0; // irrelevant
  pconfig->video.modes[KA_MODE_MULTITASK].scaler = KA_SCALER_INTERNAL;
  pconfig->video.modes[KA_MODE_MULTITASK].zoom   = 100;
  pconfig->video.modes[KA_MODE_DESKTOP].cfg    = cfg_video_dither;
  pconfig->video.modes[KA_MODE_DESKTOP].width  = 0; // irrelevant
  pconfig->video.modes[KA_MODE_DESKTOP].height = 0; // irrelevant
  pconfig->video.modes[KA_MODE_DESKTOP].cols   = 0; // irrelevant
  pconfig->video.modes[KA_MODE_DESKTOP].scaler = KA_SCALER_INTERNAL;
  pconfig->video.modes[KA_MODE_DESKTOP].zoom   = 100;
  pconfig->video.modes[KA_MODE_AUTO].cfg    = cfg_video_fit_screen | cfg_video_force_scaler | cfg_video_dither;
  pconfig->video.modes[KA_MODE_AUTO].width  = 0; // min size
  pconfig->video.modes[KA_MODE_AUTO].height = 0; // min size
  pconfig->video.modes[KA_MODE_AUTO].cols   = KA_COL_16M; // 16m max colours
  pconfig->video.modes[KA_MODE_AUTO].scaler = KA_SCALER_BILINEAR;
  pconfig->video.modes[KA_MODE_AUTO].zoom   = 100;
  pconfig->video.modes[KA_MODE_MANUAL].cfg    = cfg_video_dither;
  pconfig->video.modes[KA_MODE_MANUAL].width  = 640;
  pconfig->video.modes[KA_MODE_MANUAL].height = 480;
  pconfig->video.modes[KA_MODE_MANUAL].cols   = KA_COL_16M; // 16m colours
  pconfig->video.modes[KA_MODE_MANUAL].scaler = KA_SCALER_INTERNAL;
  pconfig->video.modes[KA_MODE_MANUAL].zoom   = 100;
  strcpy(pconfig->skin, "Black");
  strcpy(pconfig->language, "en");
}

/**
 * Checks choices values against invalid values or combinations.
 */
void config_validate(ka_config_t* pconfig)
{
  int i;

  if (pconfig->video.colour < 0) pconfig->video.colour = 0;
  if (pconfig->video.colour > 200) pconfig->video.colour = 200;
  if (pconfig->video.brightness < 0) pconfig->video.brightness = 0;
  if (pconfig->video.brightness > 200) pconfig->video.brightness = 200;
  if (pconfig->video.contrast < 0) pconfig->video.contrast = 0;
  if (pconfig->video.contrast > 200) pconfig->video.contrast = 200;

  if ((pconfig->video.monitor_aspect.x / pconfig->video.monitor_aspect.y > 4)
  ||  (pconfig->video.monitor_aspect.y / pconfig->video.monitor_aspect.x > 4))
  {
  	pconfig->video.monitor_aspect.x = 16;
  	pconfig->video.monitor_aspect.y = 9;
  }

  for (i = 0; i < KA_MODE_MAX; i++)
  {
    video_mode* pmode = &pconfig->video.modes[i];
    if (pmode->cols < KA_COL_256) pmode->cols = KA_COL_256;
    if (pmode->cols > KA_COL_16M) pmode->cols = KA_COL_16M;
    if (pmode->zoom <= 50) pmode->zoom = 50;
    else if (pmode->zoom <= 100) pmode->zoom = 100;
    else if (pmode->zoom <= 200) pmode->zoom = 200;
    else if (pmode->zoom <= 300) pmode->zoom = 300;
    else pmode->zoom = 400;
  }
}

/**
 * Set playing options from the choices file.
 *
 * @param  filename  Name of the file to read options from.
 */
void config_read(ka_config_t* pconfig, const char* filename)
{
  FILE* f;
  char s[80], c;
  int brightness = 100, contrast = 100, colour = 100, def_video = 1;
  int volume = 127, def_vol = 1;
  int log2bpp = 5, colours = 0;
  int log2bpp_max = 5, colours_max = 0;
  int val;
  video_mode* pmode;

  debug = comment = NULL;

  if ((f = fopen(filename, "r")) != 0)
  {
    while (fgets(s, 78, f))
    {
      video_mode* p_curr_mode = &pconfig->video.modes[pconfig->video.mode];;

      s[strlen(s)-1] = 0;

      if      (strncmp(s, "M ", 1) == 0)
        pmode = &pconfig->video.modes[KA_MODE_MULTITASK];
      else if (strncmp(s, "D ", 1) == 0)
        pmode = &pconfig->video.modes[KA_MODE_DESKTOP];
      else if (strncmp(s, "A ", 1) == 0)
        pmode = &pconfig->video.modes[KA_MODE_AUTO];
      else if (strncmp(s, "F ", 1) == 0)
        pmode = &pconfig->video.modes[KA_MODE_MANUAL];
      else
        pmode = NULL;

      if (pmode != NULL)
      {
        const char* ps = s + 2;
        if      (sscanf  (ps, "x resolution = %d", &pmode->width)) ;
        else if (sscanf  (ps, "y resolution = %d", &pmode->height)) ;
        else if (set_int (ps, "colours = %d", &colours, 1<<8, 1<<24))
        {
          if (colours < (1<<12))
            pmode->cols = KA_COL_256;
          else if (colours < (1<<15))
            pmode->cols = KA_COL_4K;
          else if (colours < (1<<16))
            pmode->cols = KA_COL_32K;
          else if (colours < (1<<24))
            pmode->cols = KA_COL_64K;
          else
            pmode->cols = KA_COL_16M;
        }
        else if (sscanf  (ps, "zoom percent = %d", &pmode->zoom)) ;
        else if (set_int (ps, "scaler = %d"      , &pmode->scaler, 0, KA_SCALER_MAX - 1)) ;
        else if (set_bool(ps, "monochrome = %c"  , &pmode->cfg, cfg_video_mono)) ;
        else if (set_bool(ps, "dither = %c"      , &pmode->cfg, cfg_video_dither)) ;
        else if (set_bool(ps, "fit screen = %c"  , &pmode->cfg, cfg_video_fit_screen)) ;
        else if (set_bool(ps, "force scaler = %c", &pmode->cfg, cfg_video_force_scaler)) ;
        else if (set_bool(ps, "to BGR = %c"      , &pmode->cfg, cfg_video_to_BGR)) ;
      }

      else if (set_bool(s, "all frames = %c"   , &pconfig->debug, cfg_displayall)) ;
      else if (set_bool(s, "play audio = %c"   , &pconfig->audio.cfg, cfg_audio_play)) ;
      else if (set_bool(s, "save audio = %c"   , &pconfig->audio.cfg, cfg_audio_save)) ;
      else if (set_bool(s, "synchronize = %c"  , &pconfig->audio.cfg, cfg_audio_sync)) ;
      else if (set_bool(s, "auto audio = %c"   , &pconfig->audio.cfg, cfg_audio_autoselect)) ;
      else if (set_bool(s, "disksmp audio = %c", &pconfig->audio.module, 1)) ;
      else if (set_int (s, "audio channel = %d", &pconfig->audio.stream, 1, 9)) ;
      else if (set_int (s, "volume = %d"       , &volume, 0, 127)) ;
      else if (set_bool(s, "current volume= %c", &def_vol, 1)) ;

      else if (sscanf(s, "screen mode = %c", &c))
      {
        for (val = 0; val < KA_MODE_MAX; val++)
        {
          if (c_mode_char[val] == c)
            pconfig->video.mode = val;
        }
      }

      else if (sscanf  (s, "skin = %31s"       , pconfig->skin)) ;
      else if (sscanf  (s, "language = %2s"    , pconfig->language)) ;
      else if (set_bool(s, "control panel = %c", &pconfig->control, cfg_ctrl_controls)) ;
      else if (set_int (s, "brightness = %d"   , &brightness, 0, 200)) ;
      else if (set_int (s, "contrast = %d"     , &contrast, 0, 200)) ;
      else if (set_int (s, "colour = %d"       , &colour, 0, 200)) ;
      else if (set_bool(s, "video defaults= %c", &def_video, 1)) ;
      else if (set_bool(s, "auto exit = %c"    , &pconfig->control, cfg_ctrl_autoexit)) ;
      else if (set_bool(s, "loop = %c"         , &pconfig->control, cfg_ctrl_loop)) ;
      else if (set_bool(s, "scroll bars = %c"  , &pconfig->control, cfg_ctrl_scroll_bars)) ;
      else if (set_bool(s, "multi windows = %c", &pconfig->control, cfg_ctrl_multiple_wins)) ;
      else if (set_bool(s, "random = %c"       , &pconfig->control, cfg_ctrl_random)) ;
      else if (set_bool(s, "lock aspect = %c"  , &pconfig->video.cfg, cfg_video_lock_aspect)) ;
      else if (set_bool(s, "pixel aspect = %c" , &pconfig->video.cfg, cfg_video_pixel_aspect)) ;
      else if (set_int (s, "deinterlace = %d"  , &pconfig->video.deinterlace, KA_DEINTERLACE_NONE, KA_DEINTERLACE_MAX - 1)) ;
      else if (set_int (s, "resizemode = %d"   , &pconfig->video.resizemode, KA_RESIZE_NONE, KA_RESIZE_MAX - 1)) ;
      else if (set_int (s, "resizeto = %d"     , &pconfig->video.resizeto, KA_RESIZETO_MONITOR, KA_RESIZETO_MAX - 1)) ;
      else if (set_int (s, "monitor ratiox= %d", &pconfig->video.monitor_aspect.x, 1, 10000)) ;
      else if (set_int (s, "monitor ratioy= %d", &pconfig->video.monitor_aspect.y, 1, 10000)) ;
      else if (set_bool(s, "accel inteldma= %c", &pconfig->control, cfg_ctrl_accel_inteldma)) ;
      else if (set_bool(s, "accel geminus = %c", &pconfig->control, cfg_ctrl_accel_geminus));
      else if (set_bool(s, "accel videooverlay = %c", &pconfig->control, cfg_ctrl_accel_videooverlay));
      else if (set_bool(s, "accel videooverlay not multitasking = %c", &pconfig->control, cfg_ctrl_accel_videooverlay_not_multitasking));

      // >> compatibility section
      else if (set_bool(s, "multitask = %c"    , &val, 1))
      {
        if ((val & 1) && (pconfig->video.mode == KA_MODE_DESKTOP))
          pconfig->video.mode = KA_MODE_MULTITASK;
      }
      else if (sscanf (s, "x resolution = %d", &pconfig->video.modes[KA_MODE_MANUAL].width)) ;
      else if (sscanf (s, "y resolution = %d", &pconfig->video.modes[KA_MODE_MANUAL].height)) ;
      else if (set_int(s, "colour depth = %d", &log2bpp, 3, 5)) ;
      else if (set_int(s, "colours = %d"     , &colours, 1<<8, 1<<24)) ;
      else if (sscanf (s, "zoom percent = %d", &pconfig->video.modes[KA_MODE_MANUAL].zoom)) ;

      else if (sscanf (s, "auto x min = %d"  , &pconfig->video.modes[KA_MODE_AUTO].width)) ;
      else if (sscanf (s, "auto y min = %d"  , &pconfig->video.modes[KA_MODE_AUTO].height)) ;
      else if (set_int(s, "auto depth = %d"  , &log2bpp_max, 3, 5)) ;
      else if (set_int(s, "auto colours = %d", &colours_max, 1<<8, 1<<24)) ;

      else if (sscanf (s, "desktop zoom = %d", &val))
      {
        pconfig->video.modes[KA_MODE_MULTITASK].zoom = val;
        pconfig->video.modes[KA_MODE_DESKTOP].zoom = val;
      }

      else if (set_bool(s, "monochrome = %c"   , &p_curr_mode->cfg, cfg_video_mono)) ;
      else if (set_bool(s, "dither = %c"       , &p_curr_mode->cfg, cfg_video_dither)) ;
      else if (set_bool(s, "lock size = %c"    , &pconfig->video.modes[KA_MODE_MULTITASK].cfg, cfg_video_fit_screen)) ;
      else if (set_bool(s, "fit screen = %c"   , &p_curr_mode->cfg, cfg_video_fit_screen)) ;
      else if (set_bool(s, "force scaler = %c" , &p_curr_mode->cfg, cfg_video_force_scaler)) ;
      else if (set_int (s, "scaler = %d"       , &p_curr_mode->scaler, 0, KA_SCALER_MAX - 1)) ;

      else if (strncmp("debug options = ", s, 16) == 0)
        snprintf(debug = debug_str, sizeof(debug_str), "%s", s);
      else if(s[0] == '#')
        snprintf(comment = comment_str, sizeof(comment_str), "%s", s);
    }

    fclose(f);
  }

  if (colours != 0)
  {
    if (colours < (1<<12))
      pconfig->video.modes[KA_MODE_MANUAL].cols = KA_COL_256;
    else if (colours < (1<<15))
      pconfig->video.modes[KA_MODE_MANUAL].cols = KA_COL_4K;
    else if (colours < (1<<16))
      pconfig->video.modes[KA_MODE_MANUAL].cols = KA_COL_32K;
    else if (colours < (1<<24))
      pconfig->video.modes[KA_MODE_MANUAL].cols = KA_COL_64K;
    else
      pconfig->video.modes[KA_MODE_MANUAL].cols = KA_COL_16M;
  }
  else if (log2bpp != 0)
  {
    if (log2bpp < 4)
      pconfig->video.modes[KA_MODE_MANUAL].cols = KA_COL_256;
    else if (log2bpp < 5)
      pconfig->video.modes[KA_MODE_MANUAL].cols = KA_COL_32K;
    else
      pconfig->video.modes[KA_MODE_MANUAL].cols = KA_COL_16M;
  }

  if (colours_max != 0)
  {
    if (colours_max < (1<<12))
      pconfig->video.modes[KA_MODE_AUTO].cols = KA_COL_256;
    else if (colours_max < (1<<15))
      pconfig->video.modes[KA_MODE_AUTO].cols = KA_COL_4K;
    else if (colours_max < (1<<16))
      pconfig->video.modes[KA_MODE_AUTO].cols = KA_COL_32K;
    else if (colours_max < (1<<24))
      pconfig->video.modes[KA_MODE_AUTO].cols = KA_COL_64K;
    else
      pconfig->video.modes[KA_MODE_AUTO].cols = KA_COL_16M;
  }
  else if (log2bpp_max != 0)
  {
    if (log2bpp_max < 4)
      pconfig->video.modes[KA_MODE_AUTO].cols = KA_COL_256;
    else if (log2bpp_max < 5)
      pconfig->video.modes[KA_MODE_AUTO].cols = KA_COL_32K;
    else
      pconfig->video.modes[KA_MODE_AUTO].cols = KA_COL_16M;
  }

  if (!def_vol)
    pconfig->audio.volume = volume;

  if (!def_video)
  {
    pconfig->video.brightness = brightness;
    pconfig->video.contrast = contrast;
    pconfig->video.colour = colour;
  }

  config_validate(pconfig);
}

/**
 * Saves the Choices configuration file from the last read one.
 * Checks if the Config setup task is running. If it is then a message
 * is sent to it so it knows the Choices file has changed.
 */
void config_save(ka_config_t* pconfig, const char* filename)
{
  FILE* f;
  int i;
  video_mode* pmode;

  if ((f = fopen(filename, "w")) == 0)
    report_error(0, "error15"); // (Cannot write choices)
  else
  {
    if (comment)
      fprintf(f, "%s\n", comment);

    if (debug)
      fprintf(f, "%s\n", debug);

    fprintf(f, "all frames    = %c\n", (pconfig->debug & cfg_displayall) ? 'Y' : 'N');
    fprintf(f, "play audio    = %c\n", (pconfig->audio.cfg & cfg_audio_play) ? 'Y' : 'N');
    fprintf(f, "save audio    = %c\n", (pconfig->audio.cfg & cfg_audio_save) ? 'Y' : 'N');
    fprintf(f, "synchronize   = %c\n", (pconfig->audio.cfg & cfg_audio_sync) ? 'Y' : 'N');
    fprintf(f, "auto audio    = %c\n", (pconfig->audio.cfg & cfg_audio_autoselect) ? 'Y' : 'N');
    fprintf(f, "disksmp audio = %c\n", (pconfig->audio.module) ? 'Y' : 'N');
    fprintf(f, "audio channel = %d\n", pconfig->audio.stream);
    fprintf(f, "volume        = %d\n", pconfig->audio.volume);
    fprintf(f, "current volume= N\n"); // so we will use the new value next time

    fprintf(f, "screen mode   = %c\n", c_mode_char[pconfig->video.mode]);

    fprintf(f, "skin          = %s\n", pconfig->skin);
    fprintf(f, "language      = %s\n", pconfig->language);
    fprintf(f, "control panel = %c\n", (pconfig->control & cfg_ctrl_controls) ? 'Y' : 'N');
    fprintf(f, "brightness    = %d\n", pconfig->video.brightness);
    fprintf(f, "contrast      = %d\n", pconfig->video.contrast);
    fprintf(f, "colour        = %d\n", pconfig->video.colour);
    fprintf(f, "video defaults= %c\n", (pconfig->control & cfg_ctrl_defaultcols) ? 'Y' : 'N');
    fprintf(f, "auto exit     = %c\n", (pconfig->control & cfg_ctrl_autoexit) ? 'Y' : 'N');
    fprintf(f, "loop          = %c\n", (pconfig->control & cfg_ctrl_loop) ? 'Y' : 'N');
    fprintf(f, "scroll bars   = %c\n", (pconfig->control & cfg_ctrl_scroll_bars) ? 'Y' : 'N');
    fprintf(f, "multi windows = %c\n", (pconfig->control & cfg_ctrl_multiple_wins) ? 'Y' : 'N');
    fprintf(f, "random        = %c\n", (pconfig->control & cfg_ctrl_random) ? 'Y' : 'N');
    fprintf(f, "lock aspect   = %c\n", (pconfig->video.cfg & cfg_video_lock_aspect) ? 'Y' : 'N');
    fprintf(f, "pixel aspect  = %c\n", (pconfig->video.cfg & cfg_video_pixel_aspect) ? 'Y' : 'N');
    fprintf(f, "deinterlace   = %d\n", pconfig->video.deinterlace);
    fprintf(f, "resizemode    = %d\n", pconfig->video.resizemode);
    fprintf(f, "resizeto      = %d\n", pconfig->video.resizeto);
    fprintf(f, "monitor ratiox= %d\n", pconfig->video.monitor_aspect.x);
    fprintf(f, "monitor ratioy= %d\n", pconfig->video.monitor_aspect.y);
    fprintf(f, "accel inteldma= %c\n", (pconfig->control & cfg_ctrl_accel_inteldma) ? 'Y' : 'N');
    fprintf(f, "accel geminus = %c\n", (pconfig->control & cfg_ctrl_accel_geminus) ? 'Y' : 'N');
    fprintf(f, "accel videooverlay = %c\n", (pconfig->control & cfg_ctrl_accel_videooverlay) ? 'Y' : 'N');
    fprintf(f, "accel videooverlay not multitasking = %c\n", (pconfig->control & cfg_ctrl_accel_videooverlay_not_multitasking) ? 'Y' : 'N');

    // >> compatibility section
    fprintf(f, "multitask     = %c\n", (pconfig->video.mode == 0) ? 'Y' : 'N');

    fprintf(f, "x resolution  = %d\n", pconfig->video.modes[KA_MODE_MANUAL].width);
    fprintf(f, "y resolution  = %d\n", pconfig->video.modes[KA_MODE_MANUAL].height);
    fprintf(f, "colour depth  = %d\n", c_col_depth[pconfig->video.modes[KA_MODE_MANUAL].cols]);
    fprintf(f, "colours       = %d\n", c_col_colours[pconfig->video.modes[KA_MODE_MANUAL].cols]);
    fprintf(f, "zoom percent  = %d\n", pconfig->video.modes[KA_MODE_MANUAL].zoom);

    fprintf(f, "auto x min    = %d\n", pconfig->video.modes[KA_MODE_AUTO].width);
    fprintf(f, "auto y min    = %d\n", pconfig->video.modes[KA_MODE_AUTO].height);
    fprintf(f, "auto depth    = %d\n", c_col_depth[pconfig->video.modes[KA_MODE_AUTO].cols]);
    fprintf(f, "auto colours  = %d\n", c_col_colours[pconfig->video.modes[KA_MODE_AUTO].cols]);

    fprintf(f, "desktop zoom  = %d\n", pconfig->video.modes[KA_MODE_MULTITASK].zoom);

    pmode = &pconfig->video.modes[pconfig->video.mode];
    fprintf(f, "monochrome    = %c\n", (pmode->cfg & cfg_video_mono) ? 'Y' : 'N');
    fprintf(f, "dither        = %c\n", (pmode->cfg & cfg_video_dither) ? 'Y' : 'N');
    fprintf(f, "lock size     = %c\n", (pconfig->video.modes[KA_MODE_MULTITASK].cfg & cfg_video_fit_screen) ? 'Y' : 'N');
    fprintf(f, "fit screen    = %c\n", (pmode->cfg & cfg_video_fit_screen) ? 'Y' : 'N');
    fprintf(f, "force scaler  = %c\n", (pmode->cfg & cfg_video_force_scaler) ? 'Y' : 'N');
    fprintf(f, "scaler        = %d\n", pmode->scaler);
    // << compatibility section

    for (i = 0; i < KA_MODE_MAX; i++)
    {
      video_mode* pmode = &pconfig->video.modes[i];
      char mode_char = c_mode_char[i];

      fprintf(f, "%c x resolution = %d\n", mode_char, pmode->width);
      fprintf(f, "%c y resolution = %d\n", mode_char, pmode->height);
      fprintf(f, "%c colours      = %d\n", mode_char, c_col_colours[pmode->cols]);
      fprintf(f, "%c zoom percent = %d\n", mode_char, pmode->zoom);
      fprintf(f, "%c scaler       = %d\n", mode_char, pmode->scaler);
      fprintf(f, "%c monochrome   = %c\n", mode_char, (pmode->cfg & cfg_video_mono) ? 'Y' : 'N');
      fprintf(f, "%c dither       = %c\n", mode_char, (pmode->cfg & cfg_video_dither) ? 'Y' : 'N');
      fprintf(f, "%c fit screen   = %c\n", mode_char, (pmode->cfg & cfg_video_fit_screen) ? 'Y' : 'N');
      fprintf(f, "%c force scaler = %c\n", mode_char, (pmode->cfg & cfg_video_force_scaler) ? 'Y' : 'N');
      fprintf(f, "%c to BGR       = %c\n", mode_char, (pmode->cfg & cfg_video_to_BGR) ? 'Y' : 'N');
    }

    fclose(f);
  }
}

void config_aspect_ratio(ka_config_t* pconfig, int* px, int* py)
{
  // default, no scaling
  if (pconfig->video.resizemode == KA_RESIZE_NONE)
  {
    *px = 0;
    *py = 0;
    return;
  }

  switch(pconfig->video.resizeto)
  {
    case KA_RESIZETO_MONITOR:
    {
      *px = pconfig->video.monitor_aspect.x;
      *py = pconfig->video.monitor_aspect.y;
    }
    break;
    case KA_RESIZETO_5x4:
    {
      *px = 5;
      *py = 4;
    }
    break;
    case KA_RESIZETO_4x3:
    {
      *px = 4;
      *py = 3;
    }
    break;
    case KA_RESIZETO_16x10:
    {
      *px = 16;
      *py = 10;
    }
    break;
    case KA_RESIZETO_16x9:
    {
      *px = 16;
      *py = 9;
    }
    break;
    case KA_RESIZETO_256x135:
    {
      *px = 256;
      *py = 135;
    }
    break;
    case KA_RESIZETO_21x9:
    {
      *px = 21;
      *py = 9;
    }
    break;
    default:
    {
      *px = 0;
      *py = 0;
    }
  }
}
