Saving of atari ST TNY format
This commit is contained in:
		
							parent
							
								
									5e78ad6282
								
							
						
					
					
						commit
						9eba486c47
					
				@ -138,7 +138,7 @@ const T_Format File_formats[] = {
 | 
			
		||||
  {FORMAT_SCx, " sc?", Test_SCx, Load_SCx, Save_SCx, 0, 0, 0, "sc?", "sci;scq;scf;scn;sco"},
 | 
			
		||||
  {FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 0, 0, 0, "pi1", "pi1;pi2;pi3"},
 | 
			
		||||
  {FORMAT_PC1, " pc1", Test_PC1, Load_PC1, Save_PC1, 0, 0, 0, "pc1", "pc1;pc2;pc3"},
 | 
			
		||||
  {FORMAT_TNY, " tny", Test_TNY, Load_TNY, NULL,     0, 0, 0, "tny", "tny;tn1;tn2;tn3;tn4"},
 | 
			
		||||
  {FORMAT_TNY, " tny", Test_TNY, Load_TNY, Save_TNY, 0, 0, 0, "tny", "tny;tn1;tn2;tn3;tn4"},
 | 
			
		||||
  {FORMAT_CEL, " cel", Test_CEL, Load_CEL, Save_CEL, 0, 0, 0, "cel", "cel"},
 | 
			
		||||
  {FORMAT_NEO, " neo", Test_NEO, Load_NEO, Save_NEO, 0, 0, 0, "neo", "neo"},
 | 
			
		||||
  {FORMAT_KCF, " kcf", Test_KCF, Load_KCF, Save_KCF, 1, 0, 0, "kcf", "kcf"},
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										124
									
								
								src/stformats.c
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								src/stformats.c
									
									
									
									
									
								
							@ -1390,4 +1390,128 @@ void Load_TNY(T_IO_Context * context)
 | 
			
		||||
  fclose(file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Save_TNY(T_IO_Context * context)
 | 
			
		||||
{
 | 
			
		||||
  byte res = 0;
 | 
			
		||||
  FILE * file;
 | 
			
		||||
  byte buffer[32000];
 | 
			
		||||
  byte control[16000];
 | 
			
		||||
  byte data[32000];
 | 
			
		||||
  word cc = 0, dc = 0;  // control count, data count
 | 
			
		||||
  int line, dst, src;
 | 
			
		||||
 | 
			
		||||
  File_error = 1;
 | 
			
		||||
  file = Open_file_write(context);
 | 
			
		||||
  if (file == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  // TODO : detect color cycling
 | 
			
		||||
  if (!Write_byte(file, res)) // resolution +3 with color cycling
 | 
			
		||||
    goto error;
 | 
			
		||||
 | 
			
		||||
  // palette
 | 
			
		||||
  PI1_code_palette(context->Palette, buffer);
 | 
			
		||||
  if (!Write_bytes(file, buffer, 16*2))
 | 
			
		||||
    goto error;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * fill the buffer with the special Tiny Stuff organization
 | 
			
		||||
   * @see Load_TNY
 | 
			
		||||
   */
 | 
			
		||||
  for (line = 0; line < 200; line++)
 | 
			
		||||
  {
 | 
			
		||||
    int col;
 | 
			
		||||
    for (col = 0; col < 20; col++)
 | 
			
		||||
    {
 | 
			
		||||
      byte planar[8];
 | 
			
		||||
 | 
			
		||||
      // Low res
 | 
			
		||||
      PI1_16p_to_8b(context->Target_address + line * context->Pitch + col*16, planar);
 | 
			
		||||
      dst = (line + col * 200) * 2;
 | 
			
		||||
      for (src = 0; src < 8;)
 | 
			
		||||
      {
 | 
			
		||||
        buffer[dst] = planar[src++];
 | 
			
		||||
        buffer[dst+1] = planar[src++];
 | 
			
		||||
        dst += 8000;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#define WORDS_EQU(p1, p2) (((p1)[0] == (p2)[0]) && ((p1)[1] == (p2)[1]))
 | 
			
		||||
 | 
			
		||||
  // now the compression
 | 
			
		||||
  for (src = 0; src < 32000; )
 | 
			
		||||
  {
 | 
			
		||||
    word count;
 | 
			
		||||
 | 
			
		||||
    // count repeat
 | 
			
		||||
    count = 0;
 | 
			
		||||
    while ((src + count * 2) < 32000 && WORDS_EQU(buffer + src, buffer + src + count * 2))
 | 
			
		||||
      count++;
 | 
			
		||||
    if (count > 127)
 | 
			
		||||
    {
 | 
			
		||||
      GFX2_Log(GFX2_DEBUG, "%5d REPEAT %d %02x%02x\n", src, count, buffer[src+1], buffer[src]);
 | 
			
		||||
      control[cc++] = 0;  // repeat word
 | 
			
		||||
      control[cc++] = count >> 8;
 | 
			
		||||
      control[cc++] = count & 0xff;
 | 
			
		||||
      data[dc * 2] = buffer[src];
 | 
			
		||||
      data[dc * 2 + 1] = buffer[src+1];
 | 
			
		||||
      dc++;
 | 
			
		||||
      src += count * 2;
 | 
			
		||||
      count = 1;
 | 
			
		||||
    }
 | 
			
		||||
    else if (count > 1)
 | 
			
		||||
    {
 | 
			
		||||
      // TODO: merge a repeat count of 2 between 2 copy count ?
 | 
			
		||||
      GFX2_Log(GFX2_DEBUG, "%5d REPEAT %d %02x%02x\n", src, count, buffer[src+1], buffer[src]);
 | 
			
		||||
      control[cc++] = (byte)count;
 | 
			
		||||
      data[dc * 2] = buffer[src];
 | 
			
		||||
      data[dc * 2 + 1] = buffer[src+1];
 | 
			
		||||
      dc++;
 | 
			
		||||
      src += count * 2;
 | 
			
		||||
      count = 1;
 | 
			
		||||
    }
 | 
			
		||||
    if (src >= 32000)
 | 
			
		||||
      break;
 | 
			
		||||
    // count copy
 | 
			
		||||
    while ((src + count * 2) < 32000 && !WORDS_EQU(buffer + src + (count - 1) * 2, buffer + src + count * 2))
 | 
			
		||||
      count++;
 | 
			
		||||
 | 
			
		||||
    if ((src + count * 2) < 32000)
 | 
			
		||||
      count--;
 | 
			
		||||
    if (count > 128)
 | 
			
		||||
    {
 | 
			
		||||
      GFX2_Log(GFX2_DEBUG, "%5d COPY  %d %02x%02x %02x%02x...\n",
 | 
			
		||||
               src, count, buffer[src+1], buffer[src], buffer[src+3], buffer[src+2]);
 | 
			
		||||
      control[cc++] = 1;  // copy word
 | 
			
		||||
      control[cc++] = count >> 8;
 | 
			
		||||
      control[cc++] = count & 0xff;
 | 
			
		||||
      memcpy(data + dc * 2, buffer + src, count * 2);
 | 
			
		||||
      dc += count;
 | 
			
		||||
      src += count * 2;
 | 
			
		||||
    }
 | 
			
		||||
    else if (count > 0)
 | 
			
		||||
    {
 | 
			
		||||
      GFX2_Log(GFX2_DEBUG, "%5d COPY  %d %02x%02x ...\n",
 | 
			
		||||
               src, count, buffer[src+1], buffer[src]);
 | 
			
		||||
      control[cc++] = (byte)(256 - count);  // copy byte
 | 
			
		||||
      memcpy(data + dc * 2, buffer + src, count * 2);
 | 
			
		||||
      dc += count;
 | 
			
		||||
      src += count * 2;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!Write_word_be(file, cc) || !Write_word_be(file, dc))
 | 
			
		||||
    goto error;
 | 
			
		||||
  if (!Write_bytes(file, control, cc) || !Write_bytes(file, data, dc * 2))
 | 
			
		||||
    goto error;
 | 
			
		||||
  fclose(file);
 | 
			
		||||
  File_error = 0;
 | 
			
		||||
  return;
 | 
			
		||||
error:
 | 
			
		||||
  if (file != NULL)
 | 
			
		||||
    fclose(file);
 | 
			
		||||
  Remove_file(context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* @} */
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user