SCR (Amstrad CPC) file format
- Implements Test_SCR() / Load_SCR() for standard formats pictures - Save .PAL file in Save_SCR()
This commit is contained in:
		
							parent
							
								
									bf461a8a52
								
							
						
					
					
						commit
						67a1220085
					
				@ -112,6 +112,8 @@ void Load_C64(T_IO_Context *);
 | 
			
		||||
void Save_C64(T_IO_Context *);
 | 
			
		||||
 | 
			
		||||
// -- SCR (Amstrad CPC)
 | 
			
		||||
void Test_SCR(T_IO_Context *, FILE *);
 | 
			
		||||
void Load_SCR(T_IO_Context *);
 | 
			
		||||
void Save_SCR(T_IO_Context *);
 | 
			
		||||
 | 
			
		||||
// -- CM5 (Amstrad CPC)
 | 
			
		||||
 | 
			
		||||
@ -64,6 +64,7 @@ unsigned char mode3interlace(T_IO_Context * context, unsigned char x, unsigned c
 | 
			
		||||
  return mode3pixel[Get_pixel(context, x,y) & 3] << 3 | mode3pixel[Get_pixel(context,x+1,y) & 3] << 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///@ingroup cpc
 | 
			
		||||
unsigned char *raw2crtc(T_IO_Context *context, unsigned char mode, unsigned char r9, unsigned long *outSize, unsigned char *r1, unsigned char r12, unsigned char r13)
 | 
			
		||||
{
 | 
			
		||||
  unsigned char *outBuffer;
 | 
			
		||||
 | 
			
		||||
@ -90,6 +90,7 @@ const T_Format File_formats[] = {
 | 
			
		||||
  {FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "",
 | 
			
		||||
    "gif;png;bmp;2bp;pcx;pkm;iff;lbm;ilbm;sham;ham;ham6;ham8;acbm;pic;anim;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;"
 | 
			
		||||
    "c64;p64;a64;pi;rp;aas;art;dd;iph;ipt;hpc;ocp;koa;koala;fli;bml;cdu;prg;pmg;rpm;"
 | 
			
		||||
    "cpc;scr;win;"
 | 
			
		||||
    "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;ic2;cur;cm5;pph;info;flc;bin;map"},
 | 
			
		||||
  {FORMAT_ALL_PALETTES, "(pal)", NULL, NULL, NULL, 1, 0, 0, "", "kcf;pal;gpl"},
 | 
			
		||||
  {FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"},
 | 
			
		||||
@ -114,7 +115,7 @@ const T_Format File_formats[] = {
 | 
			
		||||
  {FORMAT_GPL, " gpl", Test_GPL, Load_GPL, Save_GPL, 1, 0, 0, "gpl", "gpl"},
 | 
			
		||||
  {FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, 0, "c64",
 | 
			
		||||
    "c64;p64;a64;pi;rp;aas;art;dd;iph;ipt;hpc;ocp;koa;koala;fli;bml;cdu;prg;pmg;rpm"},
 | 
			
		||||
  {FORMAT_SCR, " cpc", NULL,     NULL,     Save_SCR, 0, 0, 0, "cpc", "cpc;scr"},
 | 
			
		||||
  {FORMAT_SCR, " cpc", Test_SCR, Load_SCR, Save_SCR, 0, 0, 0, "scr", "cpc;scr;win"},
 | 
			
		||||
  {FORMAT_CM5, " cm5", Test_CM5, Load_CM5, Save_CM5, 0, 0, 1, "cm5", "cm5"},
 | 
			
		||||
  {FORMAT_PPH, " pph", Test_PPH, Load_PPH, Save_PPH, 0, 0, 1, "pph", "pph"},
 | 
			
		||||
  {FORMAT_XPM, " xpm", NULL,     NULL,     Save_XPM, 0, 0, 0, "xpm", "xpm"},
 | 
			
		||||
 | 
			
		||||
@ -3733,24 +3733,65 @@ void Save_C64(T_IO_Context * context)
 | 
			
		||||
/**
 | 
			
		||||
 * Test for SCR file (Amstrad CPC)
 | 
			
		||||
 *
 | 
			
		||||
 * TODO
 | 
			
		||||
 * SCR file format is from "Advanced OCP Art Studio" :
 | 
			
		||||
 * http://www.cpcwiki.eu/index.php/Format:Advanced_OCP_Art_Studio_File_Formats
 | 
			
		||||
 *
 | 
			
		||||
 * For now we check the presence of a valid PAL file.
 | 
			
		||||
 * If the PAL file is not there the pixel data may still be valid.
 | 
			
		||||
 * The file size depends on the screen resolution.
 | 
			
		||||
 * An AMSDOS header would be a good indication but in some cases it may not
 | 
			
		||||
 * be there.
 | 
			
		||||
 */
 | 
			
		||||
void Test_SCR(T_IO_Context * context, FILE * file)
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Mmh... not sure what we could test. Any idea ?
 | 
			
		||||
     * The palette file can be tested, if it exists and have the right size it's
 | 
			
		||||
     * ok. But if it's not there the pixel data may still be valid. And we can't
 | 
			
		||||
     * use the filesize as this depends on the screen format.
 | 
			
		||||
  FILE * pal_file;
 | 
			
		||||
  unsigned long pal_size;
 | 
			
		||||
  byte mode, color_anim_flag;
 | 
			
		||||
 | 
			
		||||
     * An AMSDOS header would be a good indication but in some cases it may not
 | 
			
		||||
     * be there */
 | 
			
		||||
    (void)context; // unused
 | 
			
		||||
    (void)file;
 | 
			
		||||
  (void)file;
 | 
			
		||||
 | 
			
		||||
  File_error = 1;
 | 
			
		||||
  // requires the PAL file
 | 
			
		||||
  pal_file = Open_file_read_with_alternate_ext(context, "pal");
 | 
			
		||||
  if (pal_file == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  pal_size = File_length_file(pal_file);
 | 
			
		||||
  if (pal_size == 239+128)
 | 
			
		||||
  {
 | 
			
		||||
    if (!CPC_check_AMSDOS(pal_file, NULL, NULL))
 | 
			
		||||
    {
 | 
			
		||||
      fclose(pal_file);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    fseek(pal_file, 128, SEEK_SET); // right after AMSDOS header
 | 
			
		||||
  }
 | 
			
		||||
  else if (pal_size != 239)
 | 
			
		||||
  {
 | 
			
		||||
    fclose(pal_file);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!Read_byte(pal_file, &mode) || !Read_byte(pal_file, &color_anim_flag))
 | 
			
		||||
  {
 | 
			
		||||
    fclose(pal_file);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  GFX2_Log(GFX2_DEBUG, "Test_SCR() mode=%d color animation flag %02X\n", mode, color_anim_flag);
 | 
			
		||||
  if (mode <= 2 && (color_anim_flag == 0 || color_anim_flag == 0xff))
 | 
			
		||||
    File_error = 0;
 | 
			
		||||
  fclose(pal_file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TODO
 | 
			
		||||
 * Load Advanced OCP Art Studio files (Amstrad CPC)
 | 
			
		||||
 *
 | 
			
		||||
 * Only standard resolution files (Mode 0 160x200, mode 1 320x200 and
 | 
			
		||||
 * mode 2 640x200) are supported. The .PAL file presence is required.
 | 
			
		||||
 * "MJH" RLE packing is supported.
 | 
			
		||||
 *
 | 
			
		||||
 * @todo Ask user for screen size (or register values) in order to support
 | 
			
		||||
 * non standard resolutions.
 | 
			
		||||
 */
 | 
			
		||||
void Load_SCR(T_IO_Context * context)
 | 
			
		||||
{
 | 
			
		||||
@ -3772,61 +3813,283 @@ void Load_SCR(T_IO_Context * context)
 | 
			
		||||
 | 
			
		||||
    // All this mess enforces us to load (and unpack if needed) the file to a
 | 
			
		||||
    // temporary 32k buffer before actually decoding it.
 | 
			
		||||
  FILE * pal_file, * file;
 | 
			
		||||
  unsigned long file_size, amsdos_file_size = 0;
 | 
			
		||||
  byte mode, color_anim_flag, color_anim_delay;
 | 
			
		||||
  byte pal_data[236]; // 12 palettes of 16+1 colors + 16 excluded inks + 16 protected inks
 | 
			
		||||
  word width, height = 200;
 | 
			
		||||
  byte bpp;
 | 
			
		||||
  enum PIXEL_RATIO ratio;
 | 
			
		||||
  byte * pixel_data;
 | 
			
		||||
  word x, y;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
    // 1) Seek for a palette
 | 
			
		||||
    // 2) If palette found get screenmode from there, else ask user
 | 
			
		||||
    // 3) ask user for screen size (or register values)
 | 
			
		||||
    // 4) Load color data from palette (if found)
 | 
			
		||||
    // 5) Close palette
 | 
			
		||||
    // 6) Open the file
 | 
			
		||||
    // 7) Run around the screen to untangle the pixeldata
 | 
			
		||||
    // 8) Close the file
 | 
			
		||||
    (void)context; // unused
 | 
			
		||||
  File_error = 1;
 | 
			
		||||
  // requires the PAL file
 | 
			
		||||
  pal_file = Open_file_read_with_alternate_ext(context, "pal");
 | 
			
		||||
  if (pal_file == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
  file_size = File_length_file(pal_file);
 | 
			
		||||
  if (file_size == 239+128)
 | 
			
		||||
  {
 | 
			
		||||
    if (!CPC_check_AMSDOS(pal_file, NULL, NULL))
 | 
			
		||||
    {
 | 
			
		||||
      fclose(pal_file);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    fseek(pal_file, 128, SEEK_SET); // right after AMSDOS header
 | 
			
		||||
  }
 | 
			
		||||
  if (!Read_byte(pal_file, &mode) || !Read_byte(pal_file, &color_anim_flag)
 | 
			
		||||
      || !Read_byte(pal_file, &color_anim_delay) || !Read_bytes(pal_file, pal_data, 236))
 | 
			
		||||
  {
 | 
			
		||||
    GFX2_Log(GFX2_WARNING, "Load_SCR() failed to load .PAL file\n");
 | 
			
		||||
    fclose(pal_file);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  fclose(pal_file);
 | 
			
		||||
  GFX2_Log(GFX2_DEBUG, "Load_SCR() mode=%d color animation flag=%02X delay=%u\n",
 | 
			
		||||
           mode, color_anim_flag, color_anim_delay);
 | 
			
		||||
  switch (mode)
 | 
			
		||||
  {
 | 
			
		||||
    case 0:
 | 
			
		||||
      width = 160;
 | 
			
		||||
      bpp = 4;
 | 
			
		||||
      ratio = PIXEL_WIDE;
 | 
			
		||||
      break;
 | 
			
		||||
    case 1:
 | 
			
		||||
      width = 320;
 | 
			
		||||
      bpp = 2;
 | 
			
		||||
      ratio = PIXEL_SIMPLE;
 | 
			
		||||
      break;
 | 
			
		||||
    case 2:
 | 
			
		||||
      width = 640;
 | 
			
		||||
      bpp = 1;
 | 
			
		||||
      ratio = PIXEL_TALL;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      return; // unsupported
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (Config.Clear_palette)
 | 
			
		||||
    memset(context->Palette,0,sizeof(T_Palette));
 | 
			
		||||
  // Setup the palette (amstrad hardware palette)
 | 
			
		||||
  CPC_set_HW_palette(context->Palette + 0x40);
 | 
			
		||||
 | 
			
		||||
  // Set the palette for this picture
 | 
			
		||||
  for (i = 0; i < 16; i++)
 | 
			
		||||
    context->Palette[i] = context->Palette[pal_data[12*i]];
 | 
			
		||||
 | 
			
		||||
  file = Open_file_read(context);
 | 
			
		||||
  if (file == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
  file_size = File_length_file(file);
 | 
			
		||||
  if (CPC_check_AMSDOS(file, NULL, &amsdos_file_size))
 | 
			
		||||
  {
 | 
			
		||||
    if (file_size < (amsdos_file_size + 128))
 | 
			
		||||
    {
 | 
			
		||||
      GFX2_Log(GFX2_ERROR, "Load_SCR() mismatch in file size. AMSDOS file size %lu, should be %lu\n", amsdos_file_size, file_size - 128);
 | 
			
		||||
      fclose(file);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    else if (file_size > (amsdos_file_size + 128))
 | 
			
		||||
      GFX2_Log(GFX2_INFO, "Load_SCR() %lu extra bytes at end of file\n", file_size - 128 - amsdos_file_size);
 | 
			
		||||
    fseek(file, 128, SEEK_SET); // right after AMSDOS header
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
    fseek(file, 0, SEEK_SET);
 | 
			
		||||
  Pre_load(context, width, height, file_size, FORMAT_SCR, ratio, bpp);
 | 
			
		||||
  if(amsdos_file_size != 0)
 | 
			
		||||
    file_size = amsdos_file_size;
 | 
			
		||||
 | 
			
		||||
  pixel_data = malloc(16384);
 | 
			
		||||
 | 
			
		||||
  if (file_size >= 16336 && file_size <= 16384)
 | 
			
		||||
    Read_bytes(file, pixel_data, file_size);
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    byte sig[3];
 | 
			
		||||
    word block_length;
 | 
			
		||||
    // MJH packed format
 | 
			
		||||
    i = 0;
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
      if (!Read_bytes(file, sig, 3) || !Read_word_le(file, &block_length))
 | 
			
		||||
        break;
 | 
			
		||||
      if (0 != memcmp(sig, "MJH", 3))
 | 
			
		||||
        break;
 | 
			
		||||
      GFX2_Log(GFX2_DEBUG, "  %.3s %u\n", sig, block_length);
 | 
			
		||||
      file_size -= 5;
 | 
			
		||||
      while (block_length > 0)
 | 
			
		||||
      {
 | 
			
		||||
        byte code;
 | 
			
		||||
        if (!Read_byte(file, &code))
 | 
			
		||||
          break;
 | 
			
		||||
        file_size--;
 | 
			
		||||
        if (code == 1)
 | 
			
		||||
        {
 | 
			
		||||
          byte repeat, value;
 | 
			
		||||
          if (!Read_byte(file, &repeat) || !Read_byte(file, &value))
 | 
			
		||||
            break;
 | 
			
		||||
          file_size -= 2;
 | 
			
		||||
          do
 | 
			
		||||
          {
 | 
			
		||||
            pixel_data[i++] = value;
 | 
			
		||||
            block_length--;
 | 
			
		||||
          }
 | 
			
		||||
          while(--repeat != 0);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
          pixel_data[i++] = code;
 | 
			
		||||
          block_length--;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    while(file_size > 0 && i < 16384);
 | 
			
		||||
  }
 | 
			
		||||
  fclose(file);
 | 
			
		||||
 | 
			
		||||
  for (y = 0; y < height; y++)
 | 
			
		||||
  {
 | 
			
		||||
    const byte * line;
 | 
			
		||||
 | 
			
		||||
    line = pixel_data + ((y & 7) << 11) + ((y >> 3) * 80);
 | 
			
		||||
    x = 0;
 | 
			
		||||
    for (i = 0; i < 80; i++)
 | 
			
		||||
    {
 | 
			
		||||
      byte pixels = line[i];
 | 
			
		||||
      switch (mode)
 | 
			
		||||
      {
 | 
			
		||||
        case 0:
 | 
			
		||||
          Set_pixel(context, x++, y, (pixels & 0x80) >> 7 | (pixels & 0x08) >> 2 | (pixels & 0x20) >> 3 | (pixels & 0x02) << 2);
 | 
			
		||||
          Set_pixel(context, x++, y, (pixels & 0x40) >> 6 | (pixels & 0x04) >> 1 | (pixels & 0x10) >> 2 | (pixels & 0x01) << 3);
 | 
			
		||||
          break;
 | 
			
		||||
        case 1:
 | 
			
		||||
          do {
 | 
			
		||||
            // upper nibble is 4 lower color bits, lower nibble is 4 upper color bits
 | 
			
		||||
            Set_pixel(context, x++, y, (pixels & 0x80) >> 7 | (pixels & 0x08) >> 2);
 | 
			
		||||
            pixels <<= 1;
 | 
			
		||||
          }
 | 
			
		||||
          while ((x & 3) != 0);
 | 
			
		||||
          break;
 | 
			
		||||
        case 2:
 | 
			
		||||
          do {
 | 
			
		||||
            Set_pixel(context, x++, y, (pixels & 0x80) >> 7);
 | 
			
		||||
            pixels <<= 1;
 | 
			
		||||
          }
 | 
			
		||||
          while ((x & 7) != 0);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  free(pixel_data);
 | 
			
		||||
 | 
			
		||||
  File_error = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Save Amstrad SCR file
 | 
			
		||||
 *
 | 
			
		||||
 * guess mode from aspect ratio :
 | 
			
		||||
 * - normal pixels are mode 1
 | 
			
		||||
 * - wide pixels are mode 0
 | 
			
		||||
 * - tall pixels are mode 2
 | 
			
		||||
 *
 | 
			
		||||
 * Mode and palette are stored in a .PAL file.
 | 
			
		||||
 *
 | 
			
		||||
 * The picture color index should be 0-15,
 | 
			
		||||
 * The CPC Hardware palette is expected to be set (indexes 64 to 95)
 | 
			
		||||
 *
 | 
			
		||||
 * @todo Add possibility to set R9, R12, R13 values
 | 
			
		||||
 * @todo Add OCP packing support
 | 
			
		||||
 * @todo Add possibility to include AMSDOS header, with proper loading
 | 
			
		||||
 *       address guessed from r12/r13 values.
 | 
			
		||||
 */
 | 
			
		||||
void Save_SCR(T_IO_Context * context)
 | 
			
		||||
{
 | 
			
		||||
    // TODO : Add possibility to set R9, R12, R13 values
 | 
			
		||||
    // TODO : Add OCP packing support
 | 
			
		||||
    // TODO : Add possibility to include AMSDOS header, with proper loading
 | 
			
		||||
    // address guessed from r12/r13 values.
 | 
			
		||||
 | 
			
		||||
    unsigned char* output;
 | 
			
		||||
    unsigned long outsize;
 | 
			
		||||
    unsigned char r1;
 | 
			
		||||
    int cpc_mode;
 | 
			
		||||
    FILE* file;
 | 
			
		||||
  int i, j;
 | 
			
		||||
  unsigned char* output;
 | 
			
		||||
  unsigned long outsize = 0;
 | 
			
		||||
  unsigned char r1 = 0;
 | 
			
		||||
  int cpc_mode;
 | 
			
		||||
  FILE* file;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    switch(Pixel_ratio)
 | 
			
		||||
    {
 | 
			
		||||
        case PIXEL_WIDE:
 | 
			
		||||
        case PIXEL_WIDE2:
 | 
			
		||||
            cpc_mode = 0;
 | 
			
		||||
            break;
 | 
			
		||||
        case PIXEL_TALL:
 | 
			
		||||
        case PIXEL_TALL2:
 | 
			
		||||
        case PIXEL_TALL3:
 | 
			
		||||
            cpc_mode = 2;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            cpc_mode = 1;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
  switch(Pixel_ratio)
 | 
			
		||||
  {
 | 
			
		||||
    case PIXEL_WIDE:
 | 
			
		||||
    case PIXEL_WIDE2:
 | 
			
		||||
      cpc_mode = 0;
 | 
			
		||||
      break;
 | 
			
		||||
    case PIXEL_TALL:
 | 
			
		||||
    case PIXEL_TALL2:
 | 
			
		||||
    case PIXEL_TALL3:
 | 
			
		||||
      cpc_mode = 2;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      cpc_mode = 1;
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    output = raw2crtc(context, cpc_mode, 7, &outsize, &r1, 0x0C, 0);
 | 
			
		||||
 | 
			
		||||
    file = Open_file_write(context);
 | 
			
		||||
    Write_bytes(file, output, outsize);
 | 
			
		||||
  file = Open_file_write_with_alternate_ext(context, "pal");
 | 
			
		||||
  if (file == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
  if (!Write_byte(file, cpc_mode) || !Write_byte(file, 0) || !Write_byte(file, 0))
 | 
			
		||||
  {
 | 
			
		||||
    fclose(file);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  for (i = 0; i < 16; i++)
 | 
			
		||||
  {
 | 
			
		||||
    // search for the color in the HW palette (0x40-0x5F)
 | 
			
		||||
    byte index = 0x40;
 | 
			
		||||
    while ((index < 0x60) &&
 | 
			
		||||
        (0 != memcmp(context->Palette + i, context->Palette + index, sizeof(T_Components))))
 | 
			
		||||
      index++;
 | 
			
		||||
    if (index >= 0x60)
 | 
			
		||||
    {
 | 
			
		||||
      GFX2_Log(GFX2_WARNING, "Save_SCR() color #%i not found in CPC HW palette.\n", i);
 | 
			
		||||
      index = 0x54 - i; // default
 | 
			
		||||
    }
 | 
			
		||||
    for (j = 0; j < 12; j++)  // write the same color for the 12 frames
 | 
			
		||||
    {
 | 
			
		||||
      Write_byte(file, index);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  // border
 | 
			
		||||
  for (j = 0; j < 12; j++)
 | 
			
		||||
  {
 | 
			
		||||
    Write_byte(file, 0x54); // black
 | 
			
		||||
  }
 | 
			
		||||
  // excluded inks
 | 
			
		||||
  for (i = 0; i < 16; i++)
 | 
			
		||||
  {
 | 
			
		||||
    Write_byte(file, 0);
 | 
			
		||||
  }
 | 
			
		||||
  // protected inks
 | 
			
		||||
  for (i = 0; i < 16; i++)
 | 
			
		||||
  {
 | 
			
		||||
    Write_byte(file, 0);
 | 
			
		||||
  }
 | 
			
		||||
  fclose(file);
 | 
			
		||||
 | 
			
		||||
    free (output);
 | 
			
		||||
    output = NULL;
 | 
			
		||||
  output = raw2crtc(context, cpc_mode, 7, &outsize, &r1, 0x0C, 0);
 | 
			
		||||
  GFX2_Log(GFX2_DEBUG, "Save_SCR() output=%p outsize=%lu r1=$%02X\n", output, outsize, r1);
 | 
			
		||||
 | 
			
		||||
  if (output == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  file = Open_file_write(context);
 | 
			
		||||
  if (file == NULL)
 | 
			
		||||
    File_error = 1;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    File_error = 0;
 | 
			
		||||
    if (!Write_bytes(file, output, outsize))
 | 
			
		||||
      File_error = 1;
 | 
			
		||||
    fclose(file);
 | 
			
		||||
  }
 | 
			
		||||
  free (output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										35
									
								
								src/oldies.c
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								src/oldies.c
									
									
									
									
									
								
							@ -504,6 +504,41 @@ void CPC_set_HW_palette(T_Components * palette)
 | 
			
		||||
  memcpy(palette, CPC_Hw_Palette, sizeof(CPC_Hw_Palette));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int CPC_check_AMSDOS(FILE * file, word * loading_address, unsigned long * file_length)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
  byte data[128];
 | 
			
		||||
  word checksum = 0;
 | 
			
		||||
 | 
			
		||||
  fseek(file, 0, SEEK_SET);
 | 
			
		||||
  if (!Read_bytes(file, data, 128))
 | 
			
		||||
    return 0;
 | 
			
		||||
  for (i = 1; i <= 11; i++) // check filename and extension
 | 
			
		||||
  {
 | 
			
		||||
    if (data[i] < ' ' || data[i] >= 0x7F)
 | 
			
		||||
      return 0;
 | 
			
		||||
  }
 | 
			
		||||
  for (i = 0; i < 67; i++)
 | 
			
		||||
    checksum += (word)data[i];
 | 
			
		||||
  if (checksum != (data[67] | (data[68] << 8)))
 | 
			
		||||
  {
 | 
			
		||||
    GFX2_Log(GFX2_INFO, "AMSDOS header checksum mismatch %04X != %04X\n",
 | 
			
		||||
             checksum, data[67] | (data[68] << 8));
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  GFX2_Log(GFX2_DEBUG, "AMSDOS : user=%02X %.8s.%.3s %d %u(%u) bytes, load at $%04X checksum $%04X\n",
 | 
			
		||||
           data[0],
 | 
			
		||||
           (char *)(data + 1), (char *)(data + 9), data[18],
 | 
			
		||||
           data[24] | (data[25] << 8), data[64] | (data[65] << 8) | (data[66] << 16),
 | 
			
		||||
           data[26] | (data[27] << 8), checksum);
 | 
			
		||||
  if (loading_address)
 | 
			
		||||
    *loading_address = data[26] | (data[27] << 8);
 | 
			
		||||
  if (file_length)
 | 
			
		||||
    *file_length = data[64] | (data[65] << 8) | (data[66] << 16); // 24bit size
 | 
			
		||||
  //  *file_length = data[24] | (data[25] << 8);  // 16bit size
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int DECB_Check_binary_file(FILE * f)
 | 
			
		||||
{
 | 
			
		||||
  byte code;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								src/oldies.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/oldies.h
									
									
									
									
									
								
							@ -73,6 +73,19 @@ void ZX_Spectrum_set_palette(T_Components * palette);
 | 
			
		||||
 */
 | 
			
		||||
void CPC_set_HW_palette(T_Components * palette);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Check AMSDOS header
 | 
			
		||||
 *
 | 
			
		||||
 * see http://www.cpcwiki.eu/index.php/AMSDOS_Header
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] file an open file
 | 
			
		||||
 * @param[out] loading_address the loading address from the header
 | 
			
		||||
 * @param[out] file_length the file length written in the header
 | 
			
		||||
 * @return 0 if the file does not contain a valid AMSDOS header
 | 
			
		||||
 * @return 1 if it does.
 | 
			
		||||
 */
 | 
			
		||||
int CPC_check_AMSDOS(FILE * file, word * loading_address, unsigned long * file_length);
 | 
			
		||||
 | 
			
		||||
/** @}*/
 | 
			
		||||
 | 
			
		||||
/** @defgroup decb DECB binary format
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user