Support for saving SymbOS .SGX graphics files
This commit is contained in:
		
							parent
							
								
									713fd9ff71
								
							
						
					
					
						commit
						9ed89cc860
					
				
							
								
								
									
										125
									
								
								src/cpcformats.c
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								src/cpcformats.c
									
									
									
									
									
								
							@ -30,9 +30,14 @@
 | 
				
			|||||||
#include "loadsavefuncs.h"
 | 
					#include "loadsavefuncs.h"
 | 
				
			||||||
#include "libraw2crtc.h"
 | 
					#include "libraw2crtc.h"
 | 
				
			||||||
#include "oldies.h"
 | 
					#include "oldies.h"
 | 
				
			||||||
 | 
					#include "windows.h"
 | 
				
			||||||
 | 
					#include "misc.h"
 | 
				
			||||||
#include "gfx2mem.h"
 | 
					#include "gfx2mem.h"
 | 
				
			||||||
#include "gfx2log.h"
 | 
					#include "gfx2log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef MIN
 | 
				
			||||||
 | 
					#define MIN(a,b) (((a)<(b)) ? (a) : (b))
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#ifndef MAX
 | 
					#ifndef MAX
 | 
				
			||||||
#define MAX(a,b) (((a)>(b)) ? (a) : (b))
 | 
					#define MAX(a,b) (((a)>(b)) ? (a) : (b))
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -275,6 +280,126 @@ void Load_SGX(T_IO_Context * context)
 | 
				
			|||||||
  fclose(data.file);
 | 
					  fclose(data.file);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Write SGX file format as specified here :
 | 
				
			||||||
 | 
					 * http://www.cpcwiki.eu/index.php/Format:SGX_(SymbOS_graphic_files)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * We are using only simple chunks for 4 colors pictures.
 | 
				
			||||||
 | 
					 * Chunk dimentions are limited to the ones of simple chunks (252x255),
 | 
				
			||||||
 | 
					 * we could go up to 508x65535 with extended chunks.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 for error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int Save_SGX_Sub(T_IO_Context * context, FILE * file, word n_colors)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  word posy = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (posy < context->Height)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    word posx = 0;
 | 
				
			||||||
 | 
					    word height = MIN(context->Height - posy, 255);
 | 
				
			||||||
 | 
					    if (posy != 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      // Write Line Feed
 | 
				
			||||||
 | 
					      if (!Write_byte(file, 255)
 | 
				
			||||||
 | 
					          || !Write_byte(file, 255) || !Write_byte(file, 255))
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    while (posx < context->Width)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      word width = MIN(context->Width - posx, 252);
 | 
				
			||||||
 | 
					      GFX2_Log(GFX2_DEBUG, "Save_SGX : (%hu,%hu) %hux%hu %huc\n",
 | 
				
			||||||
 | 
					               posx, posy, width, height, n_colors);
 | 
				
			||||||
 | 
					      if (n_colors == 4)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        word y;
 | 
				
			||||||
 | 
					        byte byte_width = (width + 3) >> 2;
 | 
				
			||||||
 | 
					        if (!Write_byte(file, byte_width)
 | 
				
			||||||
 | 
					            || !Write_byte(file, (byte)width) || !Write_byte(file, (byte)height))
 | 
				
			||||||
 | 
					          return 0;
 | 
				
			||||||
 | 
					        for (y = 0; y < height; y++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          byte i;
 | 
				
			||||||
 | 
					          word x;
 | 
				
			||||||
 | 
					          for (i = 0, x = 0; i < byte_width; i++)
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            byte b = 0;
 | 
				
			||||||
 | 
					            do
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              byte c = Get_pixel(context, posx + x++, posy + y);
 | 
				
			||||||
 | 
					              b <<= 1;
 | 
				
			||||||
 | 
					              b |= (c & 1) << 4;
 | 
				
			||||||
 | 
					              b |= (c & 2) >> 1;
 | 
				
			||||||
 | 
					            } while (x & 3);
 | 
				
			||||||
 | 
					            if (!Write_byte(file, b))
 | 
				
			||||||
 | 
					              return 0;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        word y;
 | 
				
			||||||
 | 
					        word byte_width = (width + 1) >> 1;
 | 
				
			||||||
 | 
					        if (!Write_byte(file, 64) || !Write_byte(file, 5)
 | 
				
			||||||
 | 
					            || !Write_word_le(file, byte_width) || !Write_word_le(file, width) || !Write_word_le(file, height))
 | 
				
			||||||
 | 
					          return 0;
 | 
				
			||||||
 | 
					        for (y = 0; y < height; y++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          word i, x;
 | 
				
			||||||
 | 
					          for (i = 0, x = 0; i < byte_width; i++)
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            byte b = Get_pixel(context, posx + x++, posy + y) << 4;
 | 
				
			||||||
 | 
					            b |= Get_pixel(context, posx + x++, posy + y) & 0x0f;
 | 
				
			||||||
 | 
					            if (!Write_byte(file, b))
 | 
				
			||||||
 | 
					              return 0;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      posx += width;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    posy += height;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // Write EOF marker
 | 
				
			||||||
 | 
					  for (posy = 0; posy < 3; posy++)
 | 
				
			||||||
 | 
					    Write_byte(file, 0);
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Save_SGX(T_IO_Context * context)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  FILE * file;
 | 
				
			||||||
 | 
					  dword color_usage[256];
 | 
				
			||||||
 | 
					  word n_colors;
 | 
				
			||||||
 | 
					  int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  File_error =  1;
 | 
				
			||||||
 | 
					  n_colors = Count_used_colors(color_usage);
 | 
				
			||||||
 | 
					  for (i = 16; i < 256; i++)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    if (color_usage[i] != 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Warning_message("SGX format is limited to 16 colors");
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // 4 colors mode if sufficient, otherwise 16 colors
 | 
				
			||||||
 | 
					  n_colors = 4;
 | 
				
			||||||
 | 
					  for (i = 4; i < 16; i++)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    if (color_usage[i] != 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      n_colors = 16;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  file = Open_file_write(context);
 | 
				
			||||||
 | 
					  if (file == NULL)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  if (Save_SGX_Sub(context, file, n_colors))
 | 
				
			||||||
 | 
					    File_error = 0;
 | 
				
			||||||
 | 
					  fclose(file);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Test for SCR file (Amstrad CPC)
 | 
					 * Test for SCR file (Amstrad CPC)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
@ -151,6 +151,7 @@ void Save_GOS(T_IO_Context *);
 | 
				
			|||||||
// -- SGX (SymbOS)
 | 
					// -- SGX (SymbOS)
 | 
				
			||||||
void Test_SGX(T_IO_Context *, FILE *);
 | 
					void Test_SGX(T_IO_Context *, FILE *);
 | 
				
			||||||
void Load_SGX(T_IO_Context *);
 | 
					void Load_SGX(T_IO_Context *);
 | 
				
			||||||
 | 
					void Save_SGX(T_IO_Context *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// -- XPM (X PixMap)
 | 
					// -- XPM (X PixMap)
 | 
				
			||||||
// Loading is done through SDL_Image
 | 
					// Loading is done through SDL_Image
 | 
				
			||||||
 | 
				
			|||||||
@ -148,7 +148,7 @@ const T_Format File_formats[] = {
 | 
				
			|||||||
  {FORMAT_CM5, " cm5", Test_CM5, Load_CM5, Save_CM5, 0, 0, 1, "cm5", "cm5"},
 | 
					  {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_PPH, " pph", Test_PPH, Load_PPH, Save_PPH, 0, 0, 1, "pph", "pph"},
 | 
				
			||||||
  {FORMAT_GOS, " go1", Test_GOS, Load_GOS, Save_GOS, 0, 0, 0, "go1", "go1"},
 | 
					  {FORMAT_GOS, " go1", Test_GOS, Load_GOS, Save_GOS, 0, 0, 0, "go1", "go1"},
 | 
				
			||||||
  {FORMAT_SGX, " sgx", Test_SGX, Load_SGX, NULL,     0, 0, 1, "sgx", "sgx"},
 | 
					  {FORMAT_SGX, " sgx", Test_SGX, Load_SGX, Save_SGX, 0, 0, 1, "sgx", "sgx"},
 | 
				
			||||||
  {FORMAT_XPM, " xpm", NULL,     NULL,     Save_XPM, 0, 0, 0, "xpm", "xpm"},
 | 
					  {FORMAT_XPM, " xpm", NULL,     NULL,     Save_XPM, 0, 0, 0, "xpm", "xpm"},
 | 
				
			||||||
  {FORMAT_ICO, " ico", Test_ICO, Load_ICO, Save_ICO, 0, 0, 0, "ico", "ico;ic2;cur"},
 | 
					  {FORMAT_ICO, " ico", Test_ICO, Load_ICO, Save_ICO, 0, 0, 0, "ico", "ico;ic2;cur"},
 | 
				
			||||||
  {FORMAT_INFO," info",Test_INFO,Load_INFO,NULL,     0, 0, 0, "info", "info"},
 | 
					  {FORMAT_INFO," info",Test_INFO,Load_INFO,NULL,     0, 0, 0, "info", "info"},
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user