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_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_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_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_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_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"},
|
{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);
|
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