From 74f723c3b0ca42ba9fa06d4db0b881327a1cae8e Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 7 Nov 2009 16:45:22 +0000 Subject: [PATCH] Added save function for amstrad cpc scr images. No load available yet, and the code was pretty quickly hacked. Thanks to CloudStrife for providing libraw2crtc. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1158 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- Makefile | 2 +- const.h | 1 + libraw2crtc.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++ libraw2crtc.h | 12 +++ loadsave.c | 4 + loadsave.h | 4 +- miscfileformats.c | 41 +++++++++++ 7 files changed, 242 insertions(+), 3 deletions(-) create mode 100644 libraw2crtc.c create mode 100644 libraw2crtc.h diff --git a/Makefile b/Makefile index d9a0a3ae..0bf5c4f1 100644 --- a/Makefile +++ b/Makefile @@ -279,7 +279,7 @@ endif .PHONY : all debug release clean depend zip version force install uninstall # This is the list of the objects we want to build. Dependancies are built by "make depend" automatically. -OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o +OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o $(OBJDIR)/libraw2crtc.o SKIN_FILES = skins/skin_classic.png skins/skin_modern.png skins/font_Classic.png skins/font_Fun.png diff --git a/const.h b/const.h index 01a5df4c..e88d32f2 100644 --- a/const.h +++ b/const.h @@ -112,6 +112,7 @@ enum FILE_FORMATS FORMAT_C64, FORMAT_KCF, FORMAT_PAL, + FORMAT_SCR, FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image }; diff --git a/libraw2crtc.c b/libraw2crtc.c new file mode 100644 index 00000000..2ad786db --- /dev/null +++ b/libraw2crtc.c @@ -0,0 +1,181 @@ +/* GFX2CRTC - libraw2crtc.c + * CloudStrife - 20080921 + * Diffusé sous licence libre CeCILL v2 + * Voire LICENCE + */ + +#include +#include +#include + +#include "global.h" + +unsigned short addrCalc(unsigned char vcc, unsigned char rcc, unsigned char hcc, unsigned char cclk, unsigned char r1, unsigned char r12, unsigned char r13) +{ + unsigned short MA; + unsigned short addr; + + //MA = vcc*r1 + hcc + (0x0C)*256; + MA = vcc*r1 + hcc + r12*256 + r13; + addr = cclk | ((MA & 0x03FF) << 1); + addr = addr | ((rcc & 0x07) << 11); + addr = addr | ((MA & 0x3000) << 2); + + return addr; +} + +unsigned char mode0interlace(unsigned char *x) +{ + unsigned char mode0pixel[] = {0, 64, 4, 68, 16, 80, 20, 84, 1, 65, 5, 69, 17, 81, 21, 85}; + return mode0pixel[x[0]] << 1 | mode0pixel[x[1]]; +} + +unsigned char mode1interlace(unsigned char *x) +{ + unsigned char mode1pixel[] = {0, 16, 1, 17}; + return mode1pixel[x[0]] << 3 | mode1pixel[x[1]] << 2 | mode1pixel[x[2]] << 1 | mode1pixel[x[3]]; +} + +unsigned char mode2interlace(unsigned char *x) +{ + unsigned char out = 0; + int i; + for(i = 0; i < 8; i++) out += ((x[7-i]&1) << i); + return out; +} + +unsigned char mode3interlace(unsigned char *x) +{ + unsigned char mode3pixel[] = {0, 16, 1, 17}; + return mode3pixel[x[0]] << 3 | mode3pixel[x[1]] << 2; +} + +unsigned char (*ptrMode)(unsigned char *x); + +unsigned char *raw2crtc(unsigned short width, unsigned short height, unsigned char mode, unsigned char r9, unsigned long *outSize, unsigned char *r1, unsigned char r12, unsigned char r13) +{ + unsigned char *outBuffer; + unsigned char *tmpBuffer; + unsigned char *allocationBuffer; + unsigned short minAddr = 0; + unsigned char minAddrIsDefined = 0; + unsigned short maxAddr; + + unsigned char nbPixPerByte; + int y,x; + + switch(mode) + { + case 0: + { + *r1 = (width+3)/4; + nbPixPerByte = 2; + ptrMode = mode0interlace; + break; + } + case 1: + { + *r1 = (width+7)/8; + nbPixPerByte = 4; + ptrMode = mode1interlace; + break; + } + case 2: + { + *r1 = (width+15)/16; + nbPixPerByte = 8; + ptrMode = mode2interlace; + break; + } + case 3: + { + *r1 = (width+3)/4; + nbPixPerByte = 2; + ptrMode = mode3interlace; + break; + } + default: + { + exit(4); + } + } + + tmpBuffer = (unsigned char*)malloc(0xFFFF); + if (tmpBuffer == NULL) + { + printf("Allocation tmpBuffer raté\n"); + exit(4); + } + + allocationBuffer = (unsigned char*)malloc(0xFFFF); + if(allocationBuffer == NULL) + { + printf("Allocation allocationBuffer raté\n"); + exit(4); + } + memset(allocationBuffer, 0, 0xFFFF); + + unsigned char r6; + r6 = height/(r9+1); + + for(unsigned char vcc = 0; vcc < r6; vcc++) + { + for(unsigned char rcc = 0; rcc < (r9+1); rcc++) + { + for(unsigned char hcc = 0; hcc < *r1; hcc++) + { + for(unsigned char cclk = 0; cclk < 2; cclk++) + { + x = (hcc << 1 | cclk); + y = vcc*(r9+1) + rcc; + // TODO : make this work properly when saving a brush... + *(tmpBuffer + addrCalc(vcc, rcc, hcc, cclk, *r1, r12, r13)) = (*ptrMode)(Main_screen+y*width+x); + *(allocationBuffer + addrCalc(vcc, rcc, hcc, cclk, *r1, r12, r13)) += 1; + } + } + } + } + + for(unsigned short i = 0; i < 0xFFFF; i++) + { + if(*(allocationBuffer + i) > 1) + { + printf("Attention : Ecriture multiple a l'adresse mémoire %d\n",i); + } + if(*(allocationBuffer + i) > 0) + { + maxAddr = i; + } + if((*(allocationBuffer + i) == 1) && (minAddrIsDefined == 0)) + { + minAddr = i; + minAddrIsDefined = 1; + } + } + + *outSize = (maxAddr + 1) - minAddr; + + outBuffer = (unsigned char*)malloc((*outSize)); + if (outBuffer == NULL) + { + printf("Allocation outBuffer raté\n"); + exit(4); + } + + unsigned char *ptrTmp; + unsigned char *ptrOut; + ptrTmp = tmpBuffer + minAddr; + ptrOut = outBuffer; + + for(unsigned short i = minAddr; i <= maxAddr; i++) + { + *(ptrOut++) = *(ptrTmp++); + } + + free(tmpBuffer); + tmpBuffer = NULL; + free(allocationBuffer); + allocationBuffer = NULL; + + return outBuffer; +} diff --git a/libraw2crtc.h b/libraw2crtc.h new file mode 100644 index 00000000..a192c10c --- /dev/null +++ b/libraw2crtc.h @@ -0,0 +1,12 @@ +/* GFX2CRTC - libraw2crtc.h + * CloudStrife - 20080921 + * Diffusé sous licence libre CeCILL v2 + * Voire LICENCE + */ + +#ifndef LIBRAW2CRTC_H +#define LIBRAW2CRTC_H 1 + +unsigned char * raw2crtc(unsigned short width, unsigned short height, unsigned char mode, unsigned char r9, unsigned long *outSize, unsigned char *r1, unsigned char r12, unsigned char r13); + +#endif diff --git a/loadsave.c b/loadsave.c index ef0e93f6..7a79384b 100644 --- a/loadsave.c +++ b/loadsave.c @@ -115,6 +115,9 @@ void Test_C64(void); void Load_C64(void); void Save_C64(void); +// -- SCR (Amstrad CPC) +void Save_SCR(void); + // -- PNG ------------------------------------------------------------------- #ifndef __no_pnglib__ void Test_PNG(void); @@ -150,6 +153,7 @@ T_Format File_formats[NB_KNOWN_FORMATS] = { {FORMAT_KCF, " kcf", Test_KCF, Load_KCF, Save_KCF, 0, 0, "kcf", "kcf"}, {FORMAT_PAL, " pal", Test_PAL, Load_PAL, Save_PAL, 0, 0, "pal", "pal"}, {FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, "c64", "c64;koa"}, + {FORMAT_SCR, " cpc", NULL, NULL, Save_SCR, 0, 0, "cpc", "cpc;scr"}, {FORMAT_MISC,"misc.", NULL, NULL, NULL, 1, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"}, }; diff --git a/loadsave.h b/loadsave.h index 679a2038..5277bff1 100644 --- a/loadsave.h +++ b/loadsave.h @@ -68,10 +68,10 @@ T_Format * Get_fileformat(byte format); // -- File formats #ifndef __no_pnglib__ -#define NB_KNOWN_FORMATS 18 ///< Total number of known file formats. +#define NB_KNOWN_FORMATS 19 ///< Total number of known file formats. #else // Without pnglib -#define NB_KNOWN_FORMATS 17 ///< Total number of known file formats. +#define NB_KNOWN_FORMATS 18 ///< Total number of known file formats. #endif // This is here and not in fileformats.c because the emergency save uses it... diff --git a/miscfileformats.c b/miscfileformats.c index 08baa76e..3dd50593 100644 --- a/miscfileformats.c +++ b/miscfileformats.c @@ -23,9 +23,11 @@ ///@file miscfileformats.c /// Formats that aren't fully saving, either because of palette restrictions or other things +#include "engine.h" #include "errors.h" #include "global.h" #include "io.h" +#include "libraw2crtc.h" #include "limits.h" #include "loadsave.h" #include "misc.h" @@ -2534,3 +2536,42 @@ void Save_C64(void) File_error = Save_C64_multi(filename,saveWhat,loadAddr); } + +// SCR (Amstrad CPC) + +void Save_SCR(void) +{ + unsigned char* output; + unsigned long outsize; + unsigned char r1; + int cpc_mode; + FILE* file; + char filename[MAX_PATH_CHARACTERS]; + long file_size; + + Get_full_filename(filename,0); + + + switch(Pixel_ratio) + { + case PIXEL_WIDE: + case PIXEL_WIDE2: + cpc_mode = 0; + break; + case PIXEL_TALL: + case PIXEL_TALL2: + cpc_mode = 2; + break; + default: + cpc_mode = 1; + break; + } + + output = raw2crtc(Main_image_width,Main_image_height,cpc_mode,7,&outsize,&r1,0,0); + + file = fopen(filename,"wb"); + Write_bytes(file, output, outsize); + fclose(file); + + File_error = 0; +}