diff --git a/.gitignore b/.gitignore
index 19bbe17..4de0864 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,13 @@
obj/
xrick.sys16
bmp/
+*.vpj
+*.vpw
+*.vpwhist
+*.vtg
+bin/mrsprite/.vs/
+bin/mrsprite/Debug/
+bin/mrsprite/dep/
+bin/mrsprite/lst/
+*.lst
+*.d
diff --git a/bin/mrsprite/Makefile b/bin/mrsprite/Makefile
new file mode 100644
index 0000000..b1d3ba1
--- /dev/null
+++ b/bin/mrsprite/Makefile
@@ -0,0 +1,159 @@
+#--------------------------------------------------------
+# $File: Makefile,v $
+#
+# $Date: 8/12/2018 $
+# $Author: jandersen $
+# $Revision: #1 $
+#--------------------------------------------------------
+#
+# MrSprite GCC-Gnu Makefile
+#
+# Latest update - Just link with system libpng
+# You should keep this up2date anyways
+# On Ubuntu, something like this to install
+# sudo apt-get install libpng-dev
+#
+SHELL = /bin/sh
+MKDIR = mkdir
+
+TARGET = mrsprite
+
+PROJROOT = .
+
+#SYSTEM = /usr
+#SYSLIBDIR = $(SYSTEM)/lib
+#SYSINCDIR = $(SYSTEM)/include
+
+INCCMD = -I$(SYSINCDIR)
+INCCMD += -I$(PROJROOT)/source
+INCCMD += -I$(PROJROOT)/include
+
+OBJDIR = $(PROJROOT)/obj
+DEPDIR = $(PROJROOT)/dep
+LSTDIR = $(PROJROOT)/lst
+
+#
+# Special GnuMake Search Path Directive
+#
+VPATH = $(PROJROOT)/source
+
+#
+# Dedicated Search Paths for Specific Types
+#
+# Can be used to speed up compile by using this feature
+# for each filetype (reducing the amount of searching)
+#
+vpath %.o $(OBJDIR)
+vpath %.d $(DEPDIR)
+
+LIBCMD +=-lm -lpng
+
+OBJS := Main.o
+OBJS += Dc_Code.o
+OBJS += Dc_Gif.o
+OBJS += Dc_Graphic.o
+OBJS += Dc_Memory.o
+OBJS += Dc_Shared.o
+
+# change list of .o's into a list of .d's
+
+DEPS := $(OBJS:%.o=%.d)
+
+AS = gcc
+CC = gcc
+LD = gcc
+RM = /bin/rm -rfv
+
+CFLAGS = -O2 -Wall -Werror -Wa,-al -fno-common
+CXXFLAGS = -O2 -Wall -Werror -Wa,-al -fno-common
+ASFLAGS = -c -xassembler-with-cpp -Wa,-al
+LDFLAGS = -Wl,-Map,$(TARGET).map $(LIBCMD)
+
+# Clear Default Suffixes
+.SUFFIXES:
+# Set my Own Suffixes
+.SUFFIXES: .c .s .cc .d .o
+
+all: $(TARGET)
+
+$(TARGET): $(DEPS) $(OBJS) $(LIBS)
+ $(LD) -o $@ $(addprefix $(OBJDIR)/,$(OBJS)) $(LIBS) $(LDFLAGS)
+
+# Object Rules
+
+.s.o:
+ $(AS) $(ASFLAGS) $(TMPFLAGS) $(INCCMD) -o $(OBJDIR)/$@ $< > $(LSTDIR)/$*.lst
+
+.c.o:
+ $(CC) $(CFLAGS) $(TMPFLAGS) $(INCCMD) -c $< -o $(OBJDIR)/$*.o > $(LSTDIR)/$*.lst
+
+.cc.o:
+ $(CC) $(CXXFLAGS) $(TMPFLAGS) $(INCCMD) -c $< -o $(OBJDIR)/$*.o > $(LSTDIR)/$*.lst
+
+# Dependencie Rules
+#
+# for now just touch, to create the file if its not defined
+#
+.s.d:
+ touch $(DEPDIR)/$*.d
+
+.c.d:
+ set -e; $(CC) -M $(CFLAGS) $(INCCMD) $< \
+ | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $(DEPDIR)/$@; \
+ [ -s $(DEPDIR)/$@ ] || rm -f $(DEPDIR)/$@
+
+.cc.d:
+ set -e; $(CC) -M $(CXXFLAGS) $(INCCMD) $< \
+ | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $(DEPDIR)/$@; \
+ [ -s $(DEPDIR)/$@ ] || rm -f $(DEPDIR)/$@
+
+.PHONY: install
+install: $(TARGET)
+ cp $(TARGET).exe $(PROJROOT)/../bin
+
+.PHONY: clean
+clean:
+ $(RM) $(OBJDIR) *.o $(DEPDIR) *.map $(LSTDIR) $(TARGET) $(TARGET).exe
+
+
+########################################
+#
+# HELPER TARGET RULES
+#
+########################################
+
+#
+# Target that forces all of the objects to be rebuilt if the makefile changes
+#
+
+$(OBJS) : Makefile
+$(DEPS) : Makefile
+#
+# Targets that create the output object directory if it doesn't already exist
+#
+
+Makefile : $(OBJDIR) $(DEPDIR) $(LSTDIR)
+
+$(OBJDIR) :
+ $(MKDIR) $(OBJDIR)
+
+#
+# Targets that create the output dependency directory if it doesn't already exist
+#
+
+$(DEPDIR) :
+ $(MKDIR) $(DEPDIR)
+
+#
+# Targets that create the output list directory if it doesn't already exist
+#
+
+$(LSTDIR) :
+ $(MKDIR) $(LSTDIR)
+
+#
+# Generated Dependencie Files
+#
+-include $(wildcard $(DEPDIR)/*.d)
+
+
diff --git a/bin/mrsprite/mrsprite.sln b/bin/mrsprite/mrsprite.sln
new file mode 100644
index 0000000..fdc6252
--- /dev/null
+++ b/bin/mrsprite/mrsprite.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27428.2043
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mrsprite", "mrsprite.vcxproj", "{D5FCACC0-771C-4F8D-BD54-4E4725A6FF1A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D5FCACC0-771C-4F8D-BD54-4E4725A6FF1A}.Debug|x64.ActiveCfg = Debug|x64
+ {D5FCACC0-771C-4F8D-BD54-4E4725A6FF1A}.Debug|x64.Build.0 = Debug|x64
+ {D5FCACC0-771C-4F8D-BD54-4E4725A6FF1A}.Debug|x86.ActiveCfg = Debug|Win32
+ {D5FCACC0-771C-4F8D-BD54-4E4725A6FF1A}.Debug|x86.Build.0 = Debug|Win32
+ {D5FCACC0-771C-4F8D-BD54-4E4725A6FF1A}.Release|x64.ActiveCfg = Release|x64
+ {D5FCACC0-771C-4F8D-BD54-4E4725A6FF1A}.Release|x64.Build.0 = Release|x64
+ {D5FCACC0-771C-4F8D-BD54-4E4725A6FF1A}.Release|x86.ActiveCfg = Release|Win32
+ {D5FCACC0-771C-4F8D-BD54-4E4725A6FF1A}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {212A2123-E9D6-4288-A661-7041DA6D6E38}
+ EndGlobalSection
+EndGlobal
diff --git a/bin/mrsprite/mrsprite.vcxproj b/bin/mrsprite/mrsprite.vcxproj
new file mode 100644
index 0000000..ca02560
--- /dev/null
+++ b/bin/mrsprite/mrsprite.vcxproj
@@ -0,0 +1,168 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 15.0
+ {D5FCACC0-771C-4F8D-BD54-4E4725A6FF1A}
+ Win32Proj
+ mrsprite
+ 10.0.16299.0
+
+
+
+ Application
+ true
+ v141
+ Unicode
+
+
+ Application
+ false
+ v141
+ true
+ Unicode
+
+
+ Application
+ true
+ v141
+ Unicode
+
+
+ Application
+ false
+ v141
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+ false
+
+
+
+ NotUsing
+ Level3
+ Disabled
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS
+ true
+
+
+ Console
+ true
+
+
+
+
+ NotUsing
+ TurnOffAllWarnings
+ Disabled
+ true
+ WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS
+ true
+
+
+ Console
+ true
+
+
+
+
+ Use
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ NotUsing
+ TurnOffAllWarnings
+ MaxSpeed
+ true
+ true
+ true
+ WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS
+ true
+ C4267;C4101;C4267
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bin/mrsprite/mrsprite.vcxproj.filters b/bin/mrsprite/mrsprite.vcxproj.filters
new file mode 100644
index 0000000..b8a4a68
--- /dev/null
+++ b/bin/mrsprite/mrsprite.vcxproj.filters
@@ -0,0 +1,54 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/bin/mrsprite/source/Dc_Code.c b/bin/mrsprite/source/Dc_Code.c
new file mode 100644
index 0000000..8c00e64
--- /dev/null
+++ b/bin/mrsprite/source/Dc_Code.c
@@ -0,0 +1,1404 @@
+/********************************************************************
+ * *
+ * Dc_Code.c : Module de gestion des lignes de Code. *
+ * *
+ ********************************************************************
+ * Auteur : Olivier ZARDINI * Brutal Deluxe * Date : Jan 2013 *
+ ********************************************************************/
+
+#include
+#include
+#include
+#include
+
+#include "Dc_Shared.h"
+#include "Dc_Graphic.h"
+#include "Dc_Memory.h"
+#include "Dc_Gif.h"
+#include "Dc_Code.h"
+
+#define TYPE_LINE_EMPTY 0 /* Aucun point sur la ligne */
+#define TYPE_LINE_RED 1 /* Au moins 1 zone rouge de 4 Bytes */
+#define TYPE_LINE_LEFTRED 2 /* Au moins 1 zone rouge et rien à gauche de celle qui est la plus à gauche */
+#define TYPE_LINE_MISC 3 /* Autre type de ligne */
+
+#define SCREEN_WIDTH 160 /* Largeur en Byte de l'Ecran */
+
+void BuildCodeLineWithMask(struct picture_256 *,struct picture_256 *,struct pattern *,struct pattern *,struct pattern *,int,int,int);
+void BuildCodeLineWithStack(struct picture_256 *,struct picture_256 *,struct pattern *,struct pattern *,struct pattern *,int,int,int *,int *);
+int GetLineType(int,struct picture_256 *,int *);
+void AddOneLine(char *,char *,char *,char *,int,int);
+int AssembleOneLine(char *,unsigned char *);
+
+/**************************************************************/
+/* BuildCodeLine() : Création des lignes de code du sprite. */
+/**************************************************************/
+void BuildCodeLine(struct picture_256 *current_picture, struct picture_256 *byte_picture, int sprite_number)
+{
+ int i, y, stack_x, stack_y, nb_codeline, nb_total_cycle, nb_total_byte, offset_line, current_line_type, offset_red;
+ int max_length, delta_stack;
+// int result;
+ struct pattern *pattern_1 = NULL;
+ struct pattern *pattern_2 = NULL;
+ struct pattern *pattern_3 = NULL;
+ struct code_line *current_codeline;
+ char buffer_label[256];
+ char buffer_operand[256];
+ char buffer_comment[256];
+// char buffer[100];
+
+ /* Récupère les patterns les + utilisées */
+ i = 1;
+ my_Memory(MEMORY_GET_PATTERN,&i,&pattern_1);
+ if(pattern_1 != NULL)
+ pattern_2 = pattern_1->next;
+ if(pattern_2 != NULL)
+ pattern_3 = pattern_2->next;
+
+ /* Init Mémoire */
+ my_Memory(MEMORY_FREE_CODELINE,NULL,NULL);
+
+ /** On commence par les lignes standards **/
+ sprintf(buffer_label,"Spr_%03d",sprite_number);
+ AddOneLine(buffer_label,"CLC","","",1,2);
+ AddOneLine("","SEI","","; Disable Interrupts",1,2);
+ AddOneLine("","PHD","","; Backup Direct Page",1,4);
+ AddOneLine("","TSC","","; Backup Stack",1,2);
+ AddOneLine("","STA","StackAddress","",3,4);
+ AddOneLine("","LDAL","$E1C068","; Direct Page and Stack in Bank 01/",4,6);
+ AddOneLine("","ORA","#$0030","",3,3);
+ AddOneLine("","STAL","$E1C068","",4,6);
+
+ /* Adresse d'affichage du Sprite vers la Pile */
+ AddOneLine("","TYA","","; Y = Sprite Target Screen Address (upper left corner)",1,2);
+ AddOneLine("","TCS","","; New Stack address",1,2);
+ stack_x = 0; /* Adresse X.Y de la Pile dans le Sprite */
+ stack_y = 0;
+
+ /** On positionne X, Y et D avec les Pattern les + utilisées **/
+ if(pattern_1 != NULL)
+ {
+ sprintf(buffer_operand,"#$%04X",ExchangeByte(pattern_1->pattern_data));
+ sprintf(buffer_comment,"; Pattern #1 : %d",pattern_1->nb_found);
+ AddOneLine("","LDX",buffer_operand,buffer_comment,3,3);
+ }
+ if(pattern_2 != NULL)
+ {
+ sprintf(buffer_operand,"#$%04X",ExchangeByte(pattern_2->pattern_data));
+ sprintf(buffer_comment,"; Pattern #2 : %d",pattern_2->nb_found);
+ AddOneLine("","LDY",buffer_operand,buffer_comment,3,3);
+ }
+ if(pattern_3 != NULL)
+ {
+ sprintf(buffer_operand,"#$%04X",ExchangeByte(pattern_3->pattern_data));
+ sprintf(buffer_comment,"; Pattern #3 : %d",pattern_3->nb_found);
+ AddOneLine("","LDA",buffer_operand,buffer_comment,3,3);
+ AddOneLine("","TCD","","",1,2);
+ }
+ AddOneLine("*--","","","",0,0);
+
+ /************************************/
+ /*** Création du code du Sprite ***/
+ /************************************/
+ for(y=0; yheight; y++)
+ {
+ /* Début de la ligne */
+ offset_line = y*byte_picture->width;
+
+ /* Commentaire pour signaler la ligne traitée */
+ sprintf(buffer_comment,"; Line %d",y);
+ my_Memory(MEMORY_ADD_COMMENT,buffer_comment,NULL);
+
+ /** On va sauter au dessus de toutes les lignes vides **/
+ current_line_type = GetLineType(offset_line,byte_picture,&offset_red);
+ if(current_line_type == TYPE_LINE_EMPTY)
+ continue;
+
+ /*** On va devoir repositionner la Pile sur la ligne courante (au début ou directement à la fin de la 1ère zone rouge) ***/
+ if(stack_y != y)
+ {
+ /* On se postionne au début de la ligne x=0 de la ligne actuelle */
+ if(current_line_type == TYPE_LINE_MISC || current_line_type == TYPE_LINE_RED)
+ {
+ /* Nombre de bytes entre l'ancienne position et la nouvelle */
+ delta_stack = (0+y*SCREEN_WIDTH) - (stack_x+stack_y*SCREEN_WIDTH);
+
+ /* Conserve la nouvelle position de la stack */
+ stack_y = y;
+ stack_x = 0;
+ }
+ /* On se positionne à droite de la 1ère zone Rouge de la ligne actuelle */
+ else if(current_line_type == TYPE_LINE_LEFTRED)
+ {
+ /* Nombre de bytes entre l'ancienne position et la nouvelle */
+ delta_stack = (offset_red+y*SCREEN_WIDTH) - (stack_x+stack_y*SCREEN_WIDTH);
+
+ /* Conserve la nouvelle position de la stack */
+ stack_y = y;
+ stack_x = offset_red;
+ }
+
+ /** Code déplaçant le pointeur de pile **/
+ AddOneLine("","TSC","","",1,2);
+ sprintf(buffer_operand,"#$%04X",delta_stack);
+ AddOneLine("","ADC",buffer_operand,"",3,3);
+ AddOneLine("","TCS","","",1,2);
+ }
+
+ /*** Traitement des points en Orange (LDA/STA 16bit), Violet (LDA/AND/ORA/STA 16bit), Jaune (LDA/STA 8bit) et Bleu (LDA/AND/ORA/STA 8bit) ***/
+ max_length = (byte_picture->width - stack_x) + ((stack_y == (byte_picture->height-1)) ? 0 : byte_picture->width);
+ BuildCodeLineWithMask(current_picture,byte_picture,pattern_1,pattern_2,pattern_3,offset_line,stack_x,max_length);
+
+ /*sprintf(buffer,"c:\\Temp\\sprite_tmp_%03d_1.gif",y);
+ result = GIFWriteFileFrom256Color(buffer,byte_picture);
+ if(result)
+ printf(" - Error : Can't create Sprite BYTE temp file.\n");*/
+
+ /** A t'on du Rouge sur la ligne courante ? **/
+ current_line_type = GetLineType(offset_line,byte_picture,&offset_red);
+ if(current_line_type == TYPE_LINE_RED || current_line_type == TYPE_LINE_LEFTRED)
+ {
+ /*** Traitement des points en Rouge (PHA/PEA 16bit) de la ligne ***/
+ BuildCodeLineWithStack(current_picture,byte_picture,pattern_1,pattern_2,pattern_3,offset_line,y,&stack_x,&stack_y);
+
+ /*sprintf(buffer,"c:\\Temp\\sprite_tmp_%03d_2.gif",y);
+ result = GIFWriteFileFrom256Color(buffer,byte_picture);
+ if(result)
+ printf(" - Error : Can't create Sprite BYTE temp file.\n");*/
+ }
+ }
+
+ /* Efface le commentaire à venir */
+ strcpy(buffer_comment,"");
+ my_Memory(MEMORY_ADD_COMMENT,buffer_comment,NULL);
+
+ /** Fin du Code **/
+ AddOneLine("*--","","","",0,0);
+ AddOneLine("","LDAL","$E1C068","; Direct Page and Stack in Bank 00/",4,6);
+ AddOneLine("","AND","#$FFCF","",3,3);
+ AddOneLine("","STAL","$E1C068","",4,6);
+ AddOneLine("","LDA","StackAddress","; Restore Stack",3,5);
+ AddOneLine("","TCS","","",1,2);
+ AddOneLine("","PLD","","; Restore Direct Page",1,5);
+ AddOneLine("","CLI","","; Enable Interrupts",1,2);
+ AddOneLine("","RTL","","",1,6);
+ AddOneLine("","","","",0,0);
+ AddOneLine("*-----------------------------------","","","",0,0);
+
+ /** Détermine la taille du code et le nb de cycle **/
+ nb_total_cycle = 0;
+ nb_total_byte = 0;
+ my_Memory(MEMORY_GET_CODELINE_NB,&nb_codeline,NULL);
+ for(i=1; i<=nb_codeline; i++)
+ {
+ my_Memory(MEMORY_GET_CODELINE,&i,¤t_codeline);
+ nb_total_cycle += current_codeline->nb_cycle;
+ nb_total_byte += current_codeline->nb_byte;
+ }
+
+ /* Met ces valeurs en commentaire de la première ligne du code */
+ i = 1;
+ my_Memory(MEMORY_GET_CODELINE,&i,¤t_codeline);
+ sprintf(current_codeline->comment,"; %dx%d, %d bytes, %d cycles",current_picture->width,current_picture->height,nb_total_byte,nb_total_cycle);
+}
+
+
+/***************************************************************************/
+/* BuildCodeLineWithMask() : Création des lignes de code avec LDA / STA. */
+/***************************************************************************/
+void BuildCodeLineWithMask(struct picture_256 *current_picture, struct picture_256 *byte_picture,
+ struct pattern *pattern_1, struct pattern *pattern_2, struct pattern *pattern_3,
+ int offset_line, int stack_x, int max_length)
+{
+ int j, k, done, is_valid_register_a, is_valid_register_a_8bit, is_pattern_ora_f, nb_8bit_line;
+ WORD pattern, pattern_and, pattern_ora, register_a;
+ BYTE pattern_8bit, pattern_8bit_and, pattern_8bit_ora, register_a_8bit;
+ char buffer_operand_value[256];
+ char buffer_operand_address[256];
+ char buffer_operand_and[256];
+ char buffer_operand_ora[256];
+
+ /* On ne peut pas garantir le contenu de A */
+ is_valid_register_a = 0;
+ is_valid_register_a_8bit = 0;
+ register_a = 0x0000;
+ register_a_8bit = 0x00;
+
+ /***********************************/
+ /*** 16 bit : Orange (LDA/STA) ***/
+ /***********************************/
+ for(j=0; jdata[offset_line+stack_x+j] == 0x99)
+ {
+ /* Récupération des 4 points de l'image */
+ pattern = ((WORD) current_picture->data[2*(offset_line+stack_x+j)+0]) << 12 |
+ ((WORD) current_picture->data[2*(offset_line+stack_x+j)+1]) << 8 |
+ ((WORD) current_picture->data[2*(offset_line+stack_x+j)+2]) << 4 |
+ ((WORD) current_picture->data[2*(offset_line+stack_x+j)+3]);
+ done = 0;
+
+ /* Adresse relative à la pile (on gère le saut de ligne) */
+ if(j < (byte_picture->width - stack_x))
+ sprintf(buffer_operand_address,"$%02X,S",j);
+ else
+ sprintf(buffer_operand_address,"$%02X,S",SCREEN_WIDTH+(j-byte_picture->width));
+
+ /** A contient déjà la pattern **/
+ if(register_a == pattern && is_valid_register_a == 1)
+ {
+ AddOneLine("","STA",buffer_operand_address,"",2,5);
+ done = 1;
+ }
+
+ /*** On utilise une pattern connue X, Y ou D ***/
+ /* X */
+ if(pattern_1 != NULL && done == 0)
+ if(pattern == pattern_1->pattern_data)
+ {
+ AddOneLine("","TXA","","",1,2);
+ AddOneLine("","STA",buffer_operand_address,"",2,5);
+ done = 1;
+ }
+ /* Y */
+ if(pattern_2 != NULL && done == 0)
+ if(pattern == pattern_2->pattern_data)
+ {
+ AddOneLine("","TYA","","",1,2);
+ AddOneLine("","STA",buffer_operand_address,"",2,5);
+ done = 1;
+ }
+ /* D */
+ if(pattern_3 != NULL && done == 0)
+ if(pattern == pattern_3->pattern_data)
+ {
+ AddOneLine("","TDC","","",1,2);
+ AddOneLine("","STA",buffer_operand_address,"",2,5);
+ done = 1;
+ }
+
+ /** On va finalement devoir charger une constante **/
+ if(done == 0)
+ {
+ sprintf(buffer_operand_value,"#$%04X",ExchangeByte(pattern));
+ AddOneLine("","LDA",buffer_operand_value,"",3,3);
+ AddOneLine("","STA",buffer_operand_address,"",2,5);
+ done = 1;
+ }
+
+ /* A contient maintenant la Pattern */
+ register_a = pattern;
+ is_valid_register_a = 1;
+
+ /* Met du Fond à la place des points déjà traités */
+ byte_picture->data[offset_line+stack_x+j] = 0xFF;
+ byte_picture->data[offset_line+stack_x+j+1] = 0xFF;
+
+ /*** Maintenant qu'on a mis une pattern dans A, on regarde si on ne l'a pas un peu plus loin ***/
+ for(k=j+1; kdata[offset_line+stack_x+k] == 0x99)
+ {
+ /* Récupération des 4 points de l'image */
+ pattern = ((WORD) current_picture->data[2*(offset_line+stack_x+k)+0]) << 12 |
+ ((WORD) current_picture->data[2*(offset_line+stack_x+k)+1]) << 8 |
+ ((WORD) current_picture->data[2*(offset_line+stack_x+k)+2]) << 4 |
+ ((WORD) current_picture->data[2*(offset_line+stack_x+k)+3]);
+
+ /** A contient déjà la pattern **/
+ if(register_a == pattern)
+ {
+ /* Adresse relative à la pile (on gère le saut de ligne) */
+ if(k < (byte_picture->width - stack_x))
+ sprintf(buffer_operand_address,"$%02X,S",k);
+ else
+ sprintf(buffer_operand_address,"$%02X,S",SCREEN_WIDTH+(k-byte_picture->width));
+
+ /* STA */
+ AddOneLine("","STA",buffer_operand_address,"",2,5);
+
+ /* Met du Fond à la place des points déjà traités */
+ byte_picture->data[offset_line+stack_x+k] = 0xFF;
+ byte_picture->data[offset_line+stack_x+k+1] = 0xFF;
+ }
+ }
+ }
+
+ /*******************************************/
+ /*** 16 bit : Violet (LDA/AND/ORA/STA) ***/
+ /*******************************************/
+ for(j=0; jdata[offset_line+stack_x+j] == 0xDD)
+ {
+ /* Récupération du mask 16 bit (on repère les points du décor) */
+ pattern_and = (current_picture->data[2*(offset_line+stack_x+j)+0] == 0xFF ? 0xF000 : 0x0000) |
+ (current_picture->data[2*(offset_line+stack_x+j)+1] == 0xFF ? 0x0F00 : 0x0000) |
+ (current_picture->data[2*(offset_line+stack_x+j)+2] == 0xFF ? 0x00F0 : 0x0000) |
+ (current_picture->data[2*(offset_line+stack_x+j)+3] == 0xFF ? 0x000F : 0x0000);
+ sprintf(buffer_operand_and,"#$%04X",ExchangeByte(pattern_and));
+
+ /* Récupération des points 16 bit de l'image (on repère les points du décor) */
+ pattern_ora = (current_picture->data[2*(offset_line+stack_x+j)+0] == 0xFF ? 0x0000 : ((WORD) current_picture->data[2*(offset_line+stack_x+j)+0]) << 12) |
+ (current_picture->data[2*(offset_line+stack_x+j)+1] == 0xFF ? 0x0000 : ((WORD) current_picture->data[2*(offset_line+stack_x+j)+1]) << 8 ) |
+ (current_picture->data[2*(offset_line+stack_x+j)+2] == 0xFF ? 0x0000 : ((WORD) current_picture->data[2*(offset_line+stack_x+j)+2]) << 4 ) |
+ (current_picture->data[2*(offset_line+stack_x+j)+3] == 0xFF ? 0x0000 : ((WORD) current_picture->data[2*(offset_line+stack_x+j)+3]) << 0 );
+ sprintf(buffer_operand_ora,"#$%04X",ExchangeByte(pattern_ora));
+
+ /* Les points du sprite sont t'ils tous F ? */
+ if(pattern_ora == 0x0000)
+ is_pattern_ora_f = 0;
+ else
+ {
+ is_pattern_ora_f = 1;
+ if(((pattern_ora >> 12) & 0x000F) != 0x0000)
+ if(((pattern_ora >> 12) & 0x000F) != 0x000F)
+ is_pattern_ora_f = 0;
+ if(((pattern_ora >> 8) & 0x000F) != 0x0000)
+ if(((pattern_ora >> 8) & 0x000F) != 0x000F)
+ is_pattern_ora_f = 0;
+ if(((pattern_ora >> 4) & 0x000F) != 0x0000)
+ if(((pattern_ora >> 4) & 0x000F) != 0x000F)
+ is_pattern_ora_f = 0;
+ if(((pattern_ora >> 0) & 0x000F) != 0x0000)
+ if(((pattern_ora >> 0) & 0x000F) != 0x000F)
+ is_pattern_ora_f = 0;
+ }
+
+ /* Adresse relative à la pile (on gère le saut de ligne) */
+ if(j < (byte_picture->width - stack_x))
+ sprintf(buffer_operand_address,"$%02X,S",j);
+ else
+ sprintf(buffer_operand_address,"$%02X,S",SCREEN_WIDTH+(j-byte_picture->width));
+
+ /** LDA / AND / ORA / STA **/
+ AddOneLine("","LDA",buffer_operand_address,"",2,5);
+ if(is_pattern_ora_f != 1)
+ AddOneLine("","AND",buffer_operand_and,"",3,3); /* Petite Optimiation, la couleur F est mise par le ORA */
+ if(pattern_ora != 0x0000)
+ AddOneLine("","ORA",buffer_operand_ora,"",3,3); /* Petite Optimisation, la couleur 0 est mise par le AND */
+ AddOneLine("","STA",buffer_operand_address,"",2,5);
+
+ /* Met du Fond à la place des points déjà traités */
+ byte_picture->data[offset_line+stack_x+j] = 0xFF;
+ byte_picture->data[offset_line+stack_x+j+1] = 0xFF;
+
+ /* On a perdu le contenu de A */
+ is_valid_register_a = 0;
+ is_valid_register_a_8bit = 0;
+ }
+
+ /** On passe A en 8 bit (on laisse X et Y en 16 sinon on perd une partie du registre) **/
+ AddOneLine("","SEP","#$20","",2,3);
+ nb_8bit_line = 0;
+
+ /*********************************/
+ /*** 8 bit : Jaune (LDA/STA) ***/
+ /*********************************/
+ for(j=0; jdata[offset_line+stack_x+j] == 0xAA)
+ {
+ /* Récupération des points 8 bit de l'image */
+ pattern_8bit = (current_picture->data[2*(offset_line+stack_x+j)+0] << 4) | current_picture->data[2*(offset_line+stack_x+j)+1];
+ sprintf(buffer_operand_value,"#$%02X",pattern_8bit);
+
+ /* Adresse relative à la pile (on gère le saut de ligne) */
+ if(j < (byte_picture->width - stack_x))
+ sprintf(buffer_operand_address,"$%02X,S",j);
+ else
+ sprintf(buffer_operand_address,"$%02X,S",SCREEN_WIDTH+(j-byte_picture->width));
+
+ /** LDA / STA **/
+ if(register_a_8bit != pattern_8bit || is_valid_register_a_8bit == 0)
+ AddOneLine("","LDA",buffer_operand_value,"",2,2);
+ AddOneLine("","STA",buffer_operand_address,"",2,3);
+
+ /* A contient maintenant la valeur de la pattern */
+ register_a_8bit = pattern_8bit;
+ is_valid_register_a_8bit = 1;
+
+ /* Met du Fond à la place des points déjà traités */
+ byte_picture->data[offset_line+stack_x+j] = 0xFF;
+ nb_8bit_line++;
+
+ /*** Maintenant qu'on a mis une pattern dans A, on regarde s'il n'y en a pas d'autres identiques un peu plus loin ***/
+ for(k=j+1; kdata[offset_line+stack_x+k] == 0xAA)
+ {
+ /* Récupération des points 8 bit de l'image */
+ pattern_8bit = (current_picture->data[2*(offset_line+stack_x+k)+0] << 4) | current_picture->data[2*(offset_line+stack_x+k)+1];
+
+ /** On a la même valeur que dans A **/
+ if(register_a_8bit == pattern_8bit)
+ {
+ /* Adresse relative à la pile (on gère le saut de ligne) */
+ if(k < (byte_picture->width - stack_x))
+ sprintf(buffer_operand_address,"$%02X,S",k);
+ else
+ sprintf(buffer_operand_address,"$%02X,S",SCREEN_WIDTH+(k-byte_picture->width));
+
+ /* STA */
+ AddOneLine("","STA",buffer_operand_address,"",2,3);
+
+ /* Met du Fond à la place des points déjà traités */
+ byte_picture->data[offset_line+stack_x+k] = 0xFF;
+ }
+ }
+ }
+
+ /****************************************/
+ /*** 8 bit : Bleu (LDA/AND/ORA/STA) ***/
+ /****************************************/
+ for(j=0; jdata[offset_line+stack_x+j] == 0xBB)
+ {
+ /* Récupération du mask 8 bit (on repère les points du décor) */
+ pattern_8bit_and = (current_picture->data[2*(offset_line+stack_x+j)+0] == 0xFF ? 0xF0 : 0x00) |
+ (current_picture->data[2*(offset_line+stack_x+j)+1] == 0xFF ? 0x0F : 0x00);
+ sprintf(buffer_operand_and,"#$%02X",pattern_8bit_and);
+
+ /* Récupération des points 8 bit de l'image (on repère les points du décor) */
+ pattern_8bit_ora = (current_picture->data[2*(offset_line+stack_x+j)+0] == 0xFF ? 0x00 : current_picture->data[2*(offset_line+stack_x+j)+0] << 4) |
+ (current_picture->data[2*(offset_line+stack_x+j)+1] == 0xFF ? 0x00 : current_picture->data[2*(offset_line+stack_x+j)+1] );
+ sprintf(buffer_operand_ora,"#$%02X",pattern_8bit_ora);
+
+ /* Les points du sprite sont t'ils tous F ? */
+ if(pattern_8bit_ora == 0x00)
+ is_pattern_ora_f = 0;
+ else
+ {
+ is_pattern_ora_f = 1;
+ if(((pattern_8bit_ora & 0xF0) != 0x00) && ((pattern_8bit_ora & 0xF0) != 0xF0))
+ is_pattern_ora_f = 0;
+ if(((pattern_8bit_ora & 0x0F) != 0x00) && ((pattern_8bit_ora & 0x0F) != 0x0F))
+ is_pattern_ora_f = 0;
+ }
+
+ /* Adresse relative à la pile (on gère le saut de ligne) */
+ if(j < (byte_picture->width - stack_x))
+ sprintf(buffer_operand_address,"$%02X,S",j);
+ else
+ sprintf(buffer_operand_address,"$%02X,S",SCREEN_WIDTH+(j-byte_picture->width));
+
+ /** LDA / AND / ORA / STA **/
+ AddOneLine("","LDA",buffer_operand_address,"",2,4);
+ if(is_pattern_ora_f != 1)
+ AddOneLine("","AND",buffer_operand_and,"",2,2); /* Petite Optimiation, la couleur F est mise par le ORA */
+ if(pattern_8bit_ora != 0x00)
+ AddOneLine("","ORA",buffer_operand_ora,"",2,2); /* Petite Optimisation, la couleur 0 est mise par le AND */
+ AddOneLine("","STA",buffer_operand_address,"",2,4);
+
+ /* Met du Fond à la place des points déjà traités */
+ byte_picture->data[offset_line+stack_x+j] = 0xFF;
+ nb_8bit_line++;
+
+ /* On a perdu le contenu de A */
+ is_valid_register_a = 0;
+ is_valid_register_a_8bit = 0;
+ }
+
+ /** On re-passe en 16 bit (si besoin) **/
+ if(nb_8bit_line == 0)
+ my_Memory(MEMORY_DROP_CODELINE,NULL,NULL); /* On supprime la ligne faisant passer en 8 bit */
+ else
+ AddOneLine("","REP","#$30","",2,3);
+}
+
+
+/****************************************************************************/
+/* BuildCodeLineWithStack() : Création des lignes de code avec PHA / PEA. */
+/****************************************************************************/
+void BuildCodeLineWithStack(struct picture_256 *current_picture, struct picture_256 *byte_picture,
+ struct pattern *pattern_1, struct pattern *pattern_2, struct pattern *pattern_3,
+ int offset_line, int line_y, int *stack_x_rtn, int *stack_y_rtn)
+{
+ int i, j, length, stack_x, stack_y, delta_stack, done, is_valid_register_a;
+ WORD pattern;
+ WORD register_a = 0;
+ struct pattern *pattern_red;
+ char buffer_operand[256];
+
+ /* Init */
+ stack_x = *stack_x_rtn;
+ stack_y = *stack_y_rtn;
+ is_valid_register_a = 0;
+
+ /************************************************************************/
+ /*** Traite toutes les zones rouges de la ligne (de gauche à droite) ***/
+ for(i=0; iwidth; i++)
+ {
+ /** On a trouvé une zone rouge **/
+ if(byte_picture->data[i+offset_line] == 0xCC) /* Rouge */
+ {
+ /* Init */
+ is_valid_register_a = 0;
+
+ /* Recherche la fin */
+ for(j=i; jwidth; j++)
+ if(byte_picture->data[j+offset_line] != 0xCC)
+ break;
+ length = j-i;
+
+ /** Il faut peut être déplacer le pointeur de Pile à la fin de cette zone rouge **/
+ delta_stack = ((i+length-1)+line_y*SCREEN_WIDTH) - (stack_x+stack_y*SCREEN_WIDTH);
+ if(delta_stack > 0)
+ {
+ /* Code déplacant le pointeur de Pile */
+ AddOneLine("","TSC","","",1,2);
+ sprintf(buffer_operand,"#$%04X",delta_stack);
+ AddOneLine("","ADC",buffer_operand,"",3,3);
+ AddOneLine("","TCS","","",1,2);
+
+ /* Met à jour la variable */
+ stack_x += delta_stack;
+ }
+
+ /*** Recherche dans cette zone Rouge une pattern au moins répétée 3 fois et qui n'est pas déjà dans X, Y ou D ! ***/
+ my_Memory(MEMORY_FREE_REDPATTERN,NULL,NULL);
+ for(j=0; jdata[2*(offset_line+i+length-2-j)+0]) << 12 |
+ ((WORD) current_picture->data[2*(offset_line+i+length-2-j)+1]) << 8 |
+ ((WORD) current_picture->data[2*(offset_line+i+length-2-j)+2]) << 4 |
+ ((WORD) current_picture->data[2*(offset_line+i+length-2-j)+3]);
+
+ /* On ne veut pas celles déjà connues */
+ if(pattern_1 != NULL)
+ if(pattern == pattern_1->pattern_data)
+ continue;
+ if(pattern_2 != NULL)
+ if(pattern == pattern_2->pattern_data)
+ continue;
+ if(pattern_3 != NULL)
+ if(pattern == pattern_3->pattern_data)
+ continue;
+
+ /* Conserve dans une Table */
+ my_Memory(MEMORY_ADD_REDPATTERN,&pattern,NULL);
+ }
+ /* Tri le tableau */
+ my_Memory(MEMORY_SORT_REDPATTERN,NULL,NULL);
+
+ /** Le LDA/PHA n'est 'rentable' qui si on fait au moins 4 PHA dans la zone rouge (19 cycles / 20 cycles pour le PEA) ! **/
+ j = 1;
+ my_Memory(MEMORY_GET_REDPATTERN,&j,&pattern_red);
+ if(pattern_red != NULL)
+ if(pattern_red->nb_found >= 3) /* Si on l'a 3 fois, on ne gagne rien pour les cycles (15 partout) mais sur les bytes (6/9) */
+ {
+ sprintf(buffer_operand,"#$%04X",ExchangeByte(pattern_red->pattern_data));
+ AddOneLine("","LDA",buffer_operand,"",3,3);
+ register_a = pattern_red->pattern_data;
+ is_valid_register_a = 1;
+ }
+
+ /*** Génération du code pour cette zone (PHA, PHX, PHY, PHD et PEA) ***/
+ for(j=0; jdata[2*(offset_line+i+length-2-j)+0]) << 12 |
+ ((WORD) current_picture->data[2*(offset_line+i+length-2-j)+1]) << 8 |
+ ((WORD) current_picture->data[2*(offset_line+i+length-2-j)+2]) << 4 |
+ ((WORD) current_picture->data[2*(offset_line+i+length-2-j)+3]);
+ done = 0;
+
+ /*** On utilise une pattern connue X, Y ou D ***/
+ /* X */
+ if(pattern_1 != NULL && done == 0)
+ if(pattern == pattern_1->pattern_data)
+ {
+ AddOneLine("","PHX","","",1,4);
+ done = 1;
+ }
+ /* Y */
+ if(pattern_2 != NULL && done == 0)
+ if(pattern == pattern_2->pattern_data)
+ {
+ AddOneLine("","PHY","","",1,4);
+ done = 1;
+ }
+ /* D */
+ if(pattern_3 != NULL && done == 0)
+ if(pattern == pattern_3->pattern_data)
+ {
+ AddOneLine("","PHD","","",1,4);
+ done = 1;
+ }
+ /** A : Remplis tout au début via un LDA **/
+ if(pattern == register_a && is_valid_register_a == 1)
+ {
+ AddOneLine("","PHA","","",1,4);
+ done = 1;
+ }
+
+ /** On va finalement devoir charger une constante **/
+ if(done == 0)
+ {
+ /* PEA */
+ sprintf(buffer_operand,"$%04X",ExchangeByte(pattern));
+ AddOneLine("","PEA",buffer_operand,"",3,5);
+ }
+ }
+
+ /** Met à jour la position actuelle de la Pile **/
+ stack_x -= length;
+ stack_y = line_y;
+
+ /** Met du Background sur les points traités **/
+ for(j=0; jdata[i+j+offset_line] = 0xFF; /* Background */
+
+ /* On passe à la Zone suivante */
+ i += length -1; /* -1 Car i++ */
+ }
+ }
+
+ /** Renvoie la nouvelle position de la Pile **/
+ *stack_x_rtn = stack_x;
+ *stack_y_rtn = stack_y;
+}
+
+
+/*******************************************************************************/
+/* GetLineType() : Détermine le type de ligne (EMPTY, RED, LEFTRED ou MISC). */
+/*******************************************************************************/
+int GetLineType(int offset_line, struct picture_256 *byte_picture, int *offset_red_rtn)
+{
+ int i, j, has_red, has_misc;
+
+ /** Relève les points de la ligne **/
+ for(i=0,has_red=0,has_misc=0; iwidth; i++)
+ if(byte_picture->data[offset_line+i] == 0xFF) /* Background */
+ continue;
+ else if(byte_picture->data[offset_line+i] == 0xCC) /* Rouge */
+ has_red = 1;
+ else /* Autre */
+ has_misc = 1;
+
+ /** Renvoie le type de ligne **/
+ if(has_red == 1)
+ {
+ /* On renvoie le offset_red = le point à droite de la 1ère zone rouge = @ de la pile pour la série de PHA/PEA */
+ for(i=0; iwidth; i++)
+ if(byte_picture->data[offset_line+i] == 0xCC) /* Rouge */
+ {
+ for(j=i; jwidth; j++)
+ if(byte_picture->data[offset_line+j] != 0xCC)
+ break;
+ *offset_red_rtn = j-1;
+ break;
+ }
+
+ /* On doit trancher en RED et LEFTRED (rien à gauche de la 1ère zone rouge) */
+ for(i=0; iwidth; i++)
+ if(byte_picture->data[offset_line+i] == 0xFF) /* Background */
+ continue;
+ else if(byte_picture->data[offset_line+i] == 0xCC) /* Rouge */
+ return(TYPE_LINE_LEFTRED);
+ else /* Autre */
+ return(TYPE_LINE_RED);
+
+ /* Never here */
+ return(TYPE_LINE_RED);
+ }
+ else if(has_misc == 1)
+ return(TYPE_LINE_MISC);
+ else
+ return(TYPE_LINE_EMPTY);
+}
+
+
+/**********************************************************************/
+/* AddOneLine() : Création d'une ligne de code et ajout à la liste. */
+/**********************************************************************/
+void AddOneLine(char *label, char *opcode, char *operand, char *comment, int nb_byte, int nb_cycle)
+{
+ struct code_line *current_codeline;
+
+ /* Allocation mémoire */
+ current_codeline = (struct code_line *) calloc(1,sizeof(struct code_line));
+ if(current_codeline == NULL)
+ {
+ printf(" Error : Impossible to allocate memory for structure code_line.\n");
+ return;
+ }
+
+ /* Remplissage */
+ strcpy(current_codeline->label,label);
+ strcpy(current_codeline->opcode,opcode);
+ strcpy(current_codeline->operand,operand);
+ strcpy(current_codeline->comment,comment);
+ current_codeline->nb_byte = nb_byte;
+ current_codeline->nb_cycle = nb_cycle;
+
+ /* Déclaration */
+ my_Memory(MEMORY_ADD_CODELINE,current_codeline,NULL);
+}
+
+
+/********************************************************************/
+/* LoadSpriteCode() : Chargement/Compilation d'un fichier source. */
+/********************************************************************/
+int LoadSpriteCode(char *file_path)
+{
+ int i, index, nb_line, found, object_size;
+ char **tab_line;
+ struct code_file *current_codefile;
+ char *next_sep;
+ char buffer[1024];
+ unsigned char object[256];
+
+ /** Isole le numero du Sprite dans le nom **/
+ for(i=strlen(file_path),found=0; i>=0; i--)
+ if(file_path[i] == '_')
+ {
+ strcpy(buffer,&file_path[i+1]);
+ next_sep = strchr(buffer,'.');
+ if(next_sep != NULL)
+ *next_sep = '\0';
+ else
+ break;
+ index = atoi(buffer);
+ if(index < 0)
+ break;
+ found = 1;
+ break;
+ }
+ if(found == 0)
+ {
+ printf(" Error : Impossible to extract Sprite Index number from Source file name '%s'.\n",file_path);
+ return(1);
+ }
+
+ /** Chargement en mémoire du fichier Source **/
+ tab_line = BuildListFromFile(file_path,&nb_line);
+ if(tab_line == NULL)
+ {
+ printf(" Error : Impossible to load Source file '%s'.\n",file_path);
+ return(1);
+ }
+
+ /* Allocation mémoire */
+ current_codefile = (struct code_file *) calloc(1,sizeof(struct code_file));
+ if(current_codefile == NULL)
+ {
+ mem_free_list(nb_line,tab_line);
+ printf(" Error : Impossible to load Source file '%s'.\n",file_path);
+ return(1);
+ }
+ current_codefile->index = index;
+
+ /** Assemblage des lignes en code objet **/
+ for(i=0; iobject[current_codefile->size],&object[0],object_size);
+ current_codefile->size += object_size;
+ }
+
+ /* Libération mémoire du Source */
+ mem_free_list(nb_line,tab_line);
+
+ /* Déclaration de la structure */
+ my_Memory(MEMORY_ADD_CODEFILE,current_codefile,NULL);
+
+ /* OK */
+ return(0);
+}
+
+
+/*******************************************************/
+/* AssembleOneLine() : Assemble une ligne du Source. */
+/*******************************************************/
+int AssembleOneLine(char *one_line, unsigned char *object)
+{
+ WORD one_word;
+ DWORD one_dword;
+ char *next_sep;
+ char opcode[256] = "";
+ char operand[256] = "";
+
+ /* Ligne vide */
+ if(strlen(one_line) < 3)
+ return(0);
+
+ /* Ligne commentaire */
+ if(one_line[0] == '*')
+ return(0);
+
+ /* Saute le premier \t pour tomber sur l'Opcode */
+ if(one_line[0] != '\t')
+ return(0);
+ next_sep = strchr(&one_line[1],'\t');
+ if(next_sep == NULL)
+ strcpy(opcode,&one_line[1]);
+ else
+ {
+ memcpy(opcode,&one_line[1],next_sep-&one_line[1]);
+ opcode[next_sep-&one_line[1]] = '\0';
+ }
+
+ /* Isole l'Operand */
+ if(next_sep)
+ {
+ next_sep++;
+ strcpy(operand,next_sep);
+ next_sep = strchr(operand,'\t');
+ if(next_sep)
+ *next_sep = '\0';
+ }
+
+ /****************************/
+ /*** Assemblage du code ***/
+ /****************************/
+ /** 1 Byte **/
+ if(!my_stricmp(opcode,"CLC"))
+ {
+ object[0] = 0x18;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"RTL"))
+ {
+ object[0] = 0x6B;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"CLI"))
+ {
+ object[0] = 0x58;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"SEI"))
+ {
+ object[0] = 0x78;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"TSC"))
+ {
+ object[0] = 0x3B;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"TCS"))
+ {
+ object[0] = 0x1B;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"TXA"))
+ {
+ object[0] = 0x8A;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"TYA"))
+ {
+ object[0] = 0x98;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"TCD"))
+ {
+ object[0] = 0x5B;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"TDC"))
+ {
+ object[0] = 0x7B;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"PHA"))
+ {
+ object[0] = 0x48;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"PHD"))
+ {
+ object[0] = 0x0B;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"PHX"))
+ {
+ object[0] = 0xDA;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"PHY"))
+ {
+ object[0] = 0x5A;
+ return(1);
+ }
+ else if(!my_stricmp(opcode,"PLD"))
+ {
+ object[0] = 0x2B;
+ return(1);
+ }
+ /** SEP / REP **/
+ else if(!my_stricmp(opcode,"SEP"))
+ {
+ object[0] = 0xE2;
+ object[1] = GetOneByte(operand);
+ return(2);
+ }
+ else if(!my_stricmp(opcode,"REP"))
+ {
+ object[0] = 0xC2;
+ object[1] = GetOneByte(operand);
+ return(2);
+ }
+ /** PEA **/
+ else if(!my_stricmp(opcode,"PEA"))
+ {
+ if(strlen(operand) == 5)
+ {
+ object[0] = 0xF4;
+ one_word = GetOneWord(operand);
+ object[1] = (unsigned char) (one_word & 0x00FF);
+ object[2] = (unsigned char) ((one_word & 0xFF00) >> 8);
+ return(3);
+ }
+ }
+ /** ADC **/
+ else if(!my_stricmp(opcode,"ADC"))
+ {
+ if(strlen(operand) == 6)
+ {
+ object[0] = 0x69;
+ one_word = GetOneWord(operand);
+ object[1] = (unsigned char) (one_word & 0x00FF);
+ object[2] = (unsigned char) ((one_word & 0xFF00) >> 8);
+ return(3);
+ }
+ }
+ /** LDX **/
+ else if(!my_stricmp(opcode,"LDX"))
+ {
+ if(operand[0] == '#' && operand[1] == '$' && strlen(operand) == 6) /* Constante 16 bit */
+ {
+ object[0] = 0xA2;
+ one_word = GetOneWord(operand);
+ object[1] = (unsigned char) (one_word & 0x00FF);
+ object[2] = (unsigned char) ((one_word & 0xFF00) >> 8);
+ return(3);
+ }
+ }
+ /** LDY **/
+ else if(!my_stricmp(opcode,"LDY"))
+ {
+ if(operand[0] == '#' && operand[1] == '$' && strlen(operand) == 6) /* Constante 16 bit */
+ {
+ object[0] = 0xA0;
+ one_word = GetOneWord(operand);
+ object[1] = (unsigned char) (one_word & 0x00FF);
+ object[2] = (unsigned char) ((one_word & 0xFF00) >> 8);
+ return(3);
+ }
+ }
+ /** LDA **/
+ else if(!my_stricmp(opcode,"LDA"))
+ {
+ if(operand[0] == '#' && operand[1] == '$' && strlen(operand) == 4) /* Constante 8 bit */
+ {
+ object[0] = 0xA9;
+ object[1] = GetOneByte(operand);
+ return(2);
+ }
+ else if(operand[0] == '#' && operand[1] == '$' && strlen(operand) == 6) /* Constante 16 bit */
+ {
+ object[0] = 0xA9;
+ one_word = GetOneWord(operand);
+ object[1] = (unsigned char) (one_word & 0x00FF);
+ object[2] = (unsigned char) ((one_word & 0xFF00) >> 8);
+ return(3);
+ }
+ else if(strlen(operand) == 5 && !my_stricmp(&operand[3],",S")) /* Stack Relative $XX,S */
+ {
+ object[0] = 0xA3;
+ object[1] = GetOneByte(operand);
+ return(2);
+ }
+ else if(!my_stricmp(operand,"StackAddress")) /* Stack Address */
+ {
+ object[0] = 0xAD;
+ object[1] = 0x07; /* Adresse où on stocke l'adresse de la Pile */
+ object[2] = 0x00;
+ return(3);
+ }
+ }
+ /** LDAL **/
+ else if(!my_stricmp(opcode,"LDAL") && strlen(operand) == 7)
+ {
+ object[0] = 0xAF;
+ one_dword = Get24Bit(operand);
+ object[1] = (unsigned char) (one_dword & 0x000000FF);
+ object[2] = (unsigned char) ((one_dword & 0x0000FF00) >> 8);
+ object[3] = (unsigned char) ((one_dword & 0x00FF0000) >> 16);
+ return(4);
+ }
+ /** STA **/
+ else if(!my_stricmp(opcode,"STA"))
+ {
+ if(strlen(operand) == 5 && !my_stricmp(&operand[3],",S")) /* Stack Relative $XX,S */
+ {
+ object[0] = 0x83;
+ object[1] = GetOneByte(operand);
+ return(2);
+ }
+ else if(!my_stricmp(operand,"StackAddress")) /* Stack Address */
+ {
+ object[0] = 0x8D;
+ object[1] = 0x07; /* Adresse où on stocke l'adresse de la Pile */
+ object[2] = 0x00;
+ return(3);
+ }
+ }
+ /** STAL **/
+ else if(!my_stricmp(opcode,"STAL") && strlen(operand) == 7)
+ {
+ object[0] = 0x8F;
+ one_dword = Get24Bit(operand);
+ object[1] = (unsigned char) (one_dword & 0x000000FF);
+ object[2] = (unsigned char) ((one_dword & 0x0000FF00) >> 8);
+ object[3] = (unsigned char) ((one_dword & 0x00FF0000) >> 16);
+ return(4);
+ }
+ /** AND **/
+ else if(!my_stricmp(opcode,"AND"))
+ {
+ if(strlen(operand) == 4)
+ {
+ object[0] = 0x29;
+ object[1] = GetOneByte(operand);
+ return(2);
+ }
+ else if(strlen(operand) == 6)
+ {
+ object[0] = 0x29;
+ one_word = GetOneWord(operand);
+ object[1] = (unsigned char) (one_word & 0x00FF);
+ object[2] = (unsigned char) ((one_word & 0xFF00) >> 8);
+ return(3);
+ }
+ }
+ /** ORA **/
+ else if(!my_stricmp(opcode,"ORA"))
+ {
+ if(strlen(operand) == 4)
+ {
+ object[0] = 0x09;
+ object[1] = GetOneByte(operand);
+ return(2);
+ }
+ else if(strlen(operand) == 6)
+ {
+ object[0] = 0x09;
+ one_word = GetOneWord(operand);
+ object[1] = (unsigned char) (one_word & 0x00FF);
+ object[2] = (unsigned char) ((one_word & 0xFF00) >> 8);
+ return(3);
+ }
+ }
+
+ /* Never Here */
+ printf(" Error : Unknown Source Code Line '%s'.\n",one_line);
+ return(0);
+}
+
+
+/*******************************************************/
+/* BuildCodeBank() : Construction des fichiers Bank. */
+/*******************************************************/
+int BuildCodeBank(char *file_folder_path, char *bank_name, int *nb_bank_rtn)
+{
+ int i, j, k, nb_codefile, total_size, nb_bank, bank_free_size, offset, bank_size, nb_store;
+ WORD code_offset;
+ FILE *fd;
+ struct code_file *current_codefile;
+ unsigned char **tab_bank;
+ char file_bank_path[1024];
+ unsigned char header_code[] = {0x4B,0xAB,0x0A,0xAA,0x7C,0x09,0x00,0x00,0x00};
+
+ /* On fait le total */
+ nb_store = 0;
+ my_Memory(MEMORY_GET_CODEFILE_NB,&nb_codefile,NULL);
+ for(i=1,total_size=0; i<=nb_codefile; i++)
+ {
+ my_Memory(MEMORY_GET_CODEFILE,&i,¤t_codefile);
+ total_size += current_codefile->size;
+ current_codefile->bank_number = -1;
+ }
+
+ /* Nombre de bank nécessaires */
+ nb_bank = (total_size / BANK_TOTAL_SIZE) + 1;
+
+ /** Allocation mémoire (on réserve 1 bank en plus) **/
+ tab_bank = (unsigned char **) calloc(nb_bank+1,sizeof(unsigned char *));
+ if(tab_bank == NULL)
+ {
+ printf(" Error : Impossible to allocate memory for Bank.\n");
+ return(1);
+ }
+ for(i=0; ibank_number == -1)
+ if(bank_free_size-2 > current_codefile->size)
+ {
+ /* Copie le code dans le banc */
+ offset -= current_codefile->size;
+ memcpy(&tab_bank[i][offset],current_codefile->object,current_codefile->size);
+
+ /* Place le pointeur vers le début pour le JMP ,X */
+ code_offset = (WORD) offset;
+ memcpy(&tab_bank[i][BANK_HEADER_SIZE+k*sizeof(WORD)],&code_offset,sizeof(WORD));
+ k++;
+
+ /* Met à jour la taille restante du banc */
+ bank_free_size -= (sizeof(WORD) + current_codefile->size);
+
+ /* Ce code a été placé dans ce Bank */
+ current_codefile->bank_number = i;
+ current_codefile->index_bank = k-1;
+ nb_store++;
+ }
+ }
+
+ /** On va compacter ce bank = faire remonter le code **/
+ if(bank_free_size > 0)
+ {
+ /* On remonte */
+ memmove(&tab_bank[i][BANK_HEADER_SIZE+k*sizeof(WORD)],&tab_bank[i][BANK_HEADER_SIZE+k*sizeof(WORD)+bank_free_size],BANK_TOTAL_SIZE-(BANK_HEADER_SIZE+k*sizeof(WORD)+bank_free_size));
+
+ /* On recalcule les offset */
+ for(j=0; j=0; j--)
+ if(file_bank_path[j] == FOLDER_SEPARATOR_CHAR) /* \ or / */
+ {
+ file_bank_path[j+1] = '\0';
+ break;
+ }
+ sprintf(&file_bank_path[strlen(file_bank_path)],"%s%02d.bin",bank_name,i);
+ fd = fopen(file_bank_path,"wb");
+ if(fd == NULL)
+ printf(" Error : Impossible to create Bank file '%s'.\n",file_bank_path);
+ else
+ {
+ fwrite(tab_bank[i],bank_size,1,fd);
+ fclose(fd);
+ }
+ }
+
+ /* Nombre de banc utilisés */
+ *nb_bank_rtn = nb_bank;
+
+ /**************************************************/
+ /** Cas particulier, il reste encore des données **/
+ /**************************************************/
+ if(nb_store < nb_codefile)
+ {
+ /** On utilise le dernier Banc réservé exprès au cas où **/
+ /* Init */
+ bank_free_size = BANK_TOTAL_SIZE - BANK_HEADER_SIZE;
+ offset = BANK_TOTAL_SIZE;
+
+ /** On place le code d'entête **/
+ memcpy(&tab_bank[nb_bank][0],header_code,BANK_HEADER_SIZE);
+
+ /** On ajoute tous les Codes possibles dans ce Bank **/
+ for(k=0,j=1; j<=nb_codefile; j++)
+ {
+ my_Memory(MEMORY_GET_CODEFILE,&j,¤t_codefile);
+ if(current_codefile->bank_number == -1)
+ if(bank_free_size-2 > current_codefile->size)
+ {
+ /* Copie le code dans le banc */
+ offset -= current_codefile->size;
+ memcpy(&tab_bank[nb_bank][offset],current_codefile->object,current_codefile->size);
+
+ /* Place le pointeur vers le début pour le JMP ,X */
+ code_offset = (WORD) offset;
+ memcpy(&tab_bank[nb_bank][BANK_HEADER_SIZE+k*sizeof(WORD)],&code_offset,sizeof(WORD));
+ k++;
+
+ /* Met à jour la taille restante du banc */
+ bank_free_size -= (sizeof(WORD) + current_codefile->size);
+
+ /* Ce code a été placé dans ce Bank */
+ current_codefile->bank_number = nb_bank;
+ current_codefile->index_bank = k-1;
+ nb_store++;
+ }
+ }
+
+ /** On va compacter ce bank = faire remonter le code **/
+ if(bank_free_size > 0)
+ {
+ /* On remonte */
+ memmove(&tab_bank[nb_bank][BANK_HEADER_SIZE+k*sizeof(WORD)],&tab_bank[nb_bank][BANK_HEADER_SIZE+k*sizeof(WORD)+bank_free_size],BANK_TOTAL_SIZE-(BANK_HEADER_SIZE+k*sizeof(WORD)+bank_free_size));
+
+ /* On recalcule les offset */
+ for(j=0; j=0; j--)
+ if(file_bank_path[j] == FOLDER_SEPARATOR_CHAR) /* \ or / */
+ {
+ file_bank_path[j+1] = '\0';
+ break;
+ }
+ sprintf(&file_bank_path[strlen(file_bank_path)],"%s%02d.bin",bank_name,nb_bank);
+ fd = fopen(file_bank_path,"wb");
+ if(fd == NULL)
+ printf(" Error : Impossible to create Bank file '%s'.\n",file_bank_path);
+ else
+ {
+ fwrite(tab_bank[i],bank_size,1,fd);
+ fclose(fd);
+ }
+
+ /* Nombre de banc utilisés */
+ *nb_bank_rtn = nb_bank+1;
+ }
+
+ /* Libération mémoire des Bank */
+ for(i=0; i=0; i--)
+ if(file_source_path[i] == FOLDER_SEPARATOR_CHAR) /* \ or / */
+ {
+ file_source_path[i+1] = '\0';
+ break;
+ }
+ sprintf(&file_source_path[strlen(file_source_path)],"%sSrc.txt",bank_name);
+ fd = fopen(file_source_path,"w");
+ if(fd == NULL)
+ printf(" Error : Impossible to create Source file '%s'.\n",file_source_path);
+
+ /* Nombre de Sprites */
+ my_Memory(MEMORY_GET_CODEFILE_NB,&nb_codefile,NULL);
+
+ /* Début du Source */
+ fprintf(fd,"Draw%s\tASL\t\t; A=Sprite Number ($0000-$%04X)\n",bank_name,nb_codefile-1);
+ fprintf(fd,"\tTAX\t\t; Y=Target Screen Address ($2000-$9D00)\n");
+ fprintf(fd,"\tLDA\t%sNum,X\t; Relative Sprite Number Table\n",bank_name);
+ fprintf(fd,"\tJMP\t(%sBank,X)\t; Bank Number Table\n",bank_name);
+ fprintf(fd,"\n");
+
+ /** Table des Numéros Relatifs des Sprite dans leur Banc **/
+ fprintf(fd,"%sNum\tHEX\t",bank_name);
+ for(i=1,j=0; i<=nb_codefile; i++)
+ {
+ if(j == 8)
+ {
+ j = 0;
+ fprintf(fd,"\n\tHEX\t");
+ }
+ my_Memory(MEMORY_GET_CODEFILE,&i,¤t_codefile);
+ fprintf(fd,"%s%04X",(j==0 || i==1)?"":",",(unsigned int)ExchangeByte((WORD)current_codefile->index_bank));
+ j++;
+ }
+ fprintf(fd,"\n");
+ fprintf(fd,"\n");
+
+ /** Table des Numéros de Banc des Sprites **/
+ fprintf(fd,"%sBank\tDA\t",bank_name);
+ for(i=1,j=0; i<=nb_codefile; i++)
+ {
+ if(j == 8)
+ {
+ j = 0;
+ fprintf(fd,"\n\tDA\t");
+ }
+ my_Memory(MEMORY_GET_CODEFILE,&i,¤t_codefile);
+ fprintf(fd,"%s%sBank%02d",(j==0 || i==1)?"":",",bank_name,current_codefile->bank_number);
+ j++;
+ }
+ fprintf(fd,"\n");
+ fprintf(fd,"\n");
+
+ /** Saut vers les bancs **/
+ for(i=0; i
+
+#include
+#include
+#include
+//#include
+#include
+
+#include "Dc_Shared.h"
+#include "Dc_Graphic.h"
+#include "Dc_Gif.h"
+
+#define MAXCOLORMAPSIZE 256
+#define CM_RED 0
+#define CM_GREEN 1
+#define CM_BLUE 2
+#define MAX_LZW_BITS 12
+
+#define INTERLACE 0x40
+#define LOCALCOLORMAP 0x80
+#define BitSet(byte,bit) (((byte) & (bit))==(bit))
+#define LM_to_uint(a,b) (((b)<<8)|(a))
+
+#define BITS 12
+#define HSIZE 5003 /* 80% occupancy */
+
+#define HashTabOf(i) global->htab[i]
+#define CodeTabOf(i) global->codetab[i]
+#define MAXCODE(n_bits) (((code_int) 1 << (global->n_bits)) - 1)
+
+typedef unsigned char char_type;
+typedef short int code_int; /* was int */
+typedef long int count_int;
+typedef unsigned char pixval;
+
+struct global_gif
+{
+ int n_bits; /* number of bits/code */
+ int maxbits; /* user settable max # bits/code */
+ code_int maxcode; /* maximum code, given n_bits */
+ code_int maxmaxcode; /* should NEVER generate this code */
+ count_int htab [HSIZE];
+ unsigned short codetab [HSIZE];
+ code_int free_ent; /* first unused entry */
+ int Width, Height;
+ int curx, cury;
+ long CountDown;
+ unsigned long cur_accum;
+ int cur_bits;
+
+ unsigned char *buffer;
+ int g_init_bits;
+ FILE* g_outfile;
+
+ int clear_flg;
+
+ int ClearCode;
+ int EOFCode;
+
+ int a_count;
+ char accum[256];
+};
+
+static unsigned long masks[] =
+{
+ 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
+};
+
+#define TRUE 1
+#define FALSE 0
+
+struct
+{
+ unsigned int Width;
+ unsigned int Height;
+ unsigned char ColorMap[3][MAXCOLORMAPSIZE];
+ unsigned int BitPixel;
+ unsigned int ColorResolution;
+ unsigned int BackGround;
+ unsigned int AspectRatio;
+} GifScreen;
+
+struct
+{
+ int transparent;
+ int delayTime;
+ int inputFlag;
+ int disposal;
+} Gif89={-1,-1,-1,0};
+
+int ZeroDataBlock=FALSE;
+
+static int ReadColorMap(FILE *, int,unsigned char [3][MAXCOLORMAPSIZE]);
+static int DoExtension(FILE *,int);
+static int GetDataBlock(FILE *,unsigned char *);
+static int GetCode(FILE *,int,int);
+static int LZWReadByte(FILE *,int,int);
+static int ReadImage(FILE *,unsigned char *,int,int,unsigned char [3][MAXCOLORMAPSIZE],int);
+static void Putword(int,FILE *);
+static void compress(int,FILE *,struct global_gif *);
+static void cl_hash(register count_int,struct global_gif *);
+static void output(code_int,struct global_gif *);
+static void cl_block(struct global_gif *);
+static void flush_char(struct global_gif *);
+
+/**************************************************************************/
+/* GIFWriteFileFrom256Color() : Création d'une image GIF 256 couleurs. */
+/**************************************************************************/
+int GIFWriteFileFrom256Color(char *file_path, struct picture_256 *current_picture_256)
+{
+ FILE *fp;
+ int B;
+ int RWidth, RHeight;
+ int LeftOfs, TopOfs;
+ int Resolution;
+ int ColorMapSize;
+ int InitCodeSize;
+ int i;
+ int BitsPerPixel = 8;
+ struct global_gif global;
+
+ /* Init des variables 'globales' */
+ memset(&global,0,sizeof(struct global_gif));
+ global.maxbits = BITS;
+ global.maxmaxcode = (code_int)1 << BITS;
+
+ /* Création du fichier */
+ fp = fopen(file_path,"wb");
+ if(fp == NULL)
+ {
+ return(1);
+ }
+
+ /* Valeurs de l'entête */
+ ColorMapSize = 1 << BitsPerPixel;
+ global.buffer = current_picture_256->data;
+ RWidth = global.Width = current_picture_256->width;
+ RHeight = global.Height = current_picture_256->height;
+ LeftOfs = TopOfs = 0;
+ global.cur_accum = 0;
+ global.cur_bits = 0;
+ Resolution = BitsPerPixel;
+ global.CountDown = (long)global.Width * (long)global.Height;
+ InitCodeSize = (BitsPerPixel <= 1) ? 2 : BitsPerPixel;
+ global.curx = global.cury = 0;
+
+ /* Ecriture de l'entête */
+ fwrite("GIF87a",1,6,fp);
+ Putword(RWidth,fp);
+ Putword(RHeight,fp);
+
+ B=0x80;
+ B |=(Resolution -1) << 5;
+ B |=(BitsPerPixel - 1);
+ fputc(B,fp);
+
+ /* Couleur de fond = 0 */
+ fputc(0,fp);
+ fputc(0,fp);
+ for(i=0; ipalette_red[i],fp);
+ fputc(current_picture_256->palette_green[i],fp);
+ fputc(current_picture_256->palette_blue[i],fp);
+ }
+
+ fputc(',',fp);
+ Putword(LeftOfs,fp);
+ Putword(TopOfs,fp);
+ Putword(global.Width,fp);
+ Putword(global.Height,fp);
+ fputc(0x00,fp);
+
+ /* Taille des données initale */
+ fputc(InitCodeSize,fp);
+
+ /* Compression des données */
+ compress(InitCodeSize+1,fp,&global);
+
+ /* Un zéro pour finir la série */
+ fputc(0,fp);
+
+ /* On place le terminateur */
+ fputc(';',fp);
+
+ /* Fermeture du fichier */
+ fclose(fp);
+
+ return(0);
+}
+
+
+/***************************************************************************/
+/* GIFReadFileToRGB() : Ouverture / Décompression d'une image GIF -> RGB. */
+/***************************************************************************/
+struct picture_true *GIFReadFileToRGB(char *path)
+{
+ int error;
+ unsigned char *bigBuf;
+ unsigned char buffer[16];
+ unsigned char c;
+ unsigned char localColorMap[3][MAXCOLORMAPSIZE];
+ int useGlobalColormap;
+ int bitPixel;
+// int imageCount=0;
+ char version[4];
+ FILE *fd;
+ int nb_read;
+ int width=0;
+ int height=0;
+ long bufsize;
+ struct picture_true *current_picture;
+
+ /* Ouverture du fichier GIF */
+ fd=fopen(path,"rb");
+ if(fd == NULL)
+ return(NULL);
+
+ /** Lecture de la signature "GIF" **/
+ nb_read = fread(buffer,1,6,fd);
+ if(nb_read != 6)
+ {
+ fclose(fd);
+ return(NULL);
+ }
+ if(strncmp((char *)buffer,"GIF",3))
+ {
+ fclose(fd);
+ return(NULL);
+ }
+
+ /** Analyse de la version (87a/89a) **/
+ strncpy(version,(char *)&buffer[3],3);
+ version[3]='\0';
+ if(strcmp(version,"87a") && strcmp(version,"89a"))
+ {
+ fclose(fd);
+ return(NULL);
+ }
+
+ /* Récupération des valeurs de l'entête */
+ nb_read = fread(buffer,1,7,fd);
+ if(nb_read != 7)
+ {
+ fclose(fd);
+ return(NULL);
+ }
+ GifScreen.Width = LM_to_uint(buffer[0],buffer[1]);
+ GifScreen.Height = LM_to_uint(buffer[2],buffer[3]);
+ GifScreen.BitPixel = 2 << (buffer[4] & 0x07);
+ GifScreen.ColorResolution = (((buffer[4] & 0x70) >> 3) + 1);
+ GifScreen.BackGround = buffer[5];
+ GifScreen.AspectRatio = buffer[6];
+
+ /* Récupération de la palette (si elle est présente) */
+ if(BitSet(buffer[4],LOCALCOLORMAP))
+ {
+ error = ReadColorMap(fd,GifScreen.BitPixel,GifScreen.ColorMap);
+ if(error)
+ {
+ fclose(fd);
+ return(NULL);
+ }
+ }
+
+ /** On ne traite que la première des images du fichier **/
+ for(;;)
+ {
+ /* Lecture du TAG */
+ nb_read = fread(&c,1,1,fd);
+ if(nb_read != 1)
+ {
+ fclose(fd);
+ return(NULL);
+ }
+
+ if(c == '!')
+ {
+ nb_read = fread(&c,1,1,fd);
+ if(nb_read != 1)
+ {
+ fclose(fd);
+ return(NULL);
+ }
+ DoExtension(fd,c);
+ continue;
+ }
+
+ if(c != ',')
+ continue;
+
+ /* read image header */
+ nb_read = fread(buffer,1,9,fd);
+ if(nb_read != 9)
+ {
+ fclose(fd);
+ return(NULL);
+ }
+
+ useGlobalColormap = !BitSet(buffer[8],LOCALCOLORMAP);
+ bitPixel = 1<<((buffer[8]&0x07)+1);
+
+ /** On récupère la taille de l'image **/
+ width = LM_to_uint(buffer[4],buffer[5]);
+ height = LM_to_uint(buffer[6],buffer[7]);
+ if(width <= 0 || height <= 0)
+ {
+ fclose(fd);
+ return(NULL);
+ }
+
+ /* Allocation mémoire */
+ bufsize = width*height*3;
+ bigBuf = (unsigned char *) calloc(bufsize,1);
+ if(bigBuf == NULL)
+ {
+ fclose(fd);
+ return(NULL);
+ }
+
+ /** Utilisation d'une palette locale ? **/
+ if(!useGlobalColormap)
+ {
+ /* Lecture de la palette locale */
+ error = ReadColorMap(fd,bitPixel,localColorMap);
+ if(error)
+ {
+ free(bigBuf);
+ fclose(fd);
+ return(NULL);
+ }
+
+ /* Lecture des points */
+ error = ReadImage(fd,bigBuf,width,height,localColorMap,BitSet(buffer[8],INTERLACE));
+ if(error)
+ {
+ free(bigBuf);
+ fclose(fd);
+ return(NULL);
+ }
+ }
+ else
+ {
+ /* Lecture des points */
+ error = ReadImage(fd,bigBuf,width,height,GifScreen.ColorMap,BitSet(buffer[8],INTERLACE));
+ if(error)
+ {
+ free(bigBuf);
+ fclose(fd);
+ return(NULL);
+ }
+ }
+ break;
+ }
+
+ /* Fermeture du fichier */
+ fclose(fd);
+
+ /** On retourne l'image dans une structure **/
+ current_picture = (struct picture_true *) calloc(1,sizeof(struct picture_true));
+ if(current_picture == NULL)
+ {
+ free(bigBuf);
+ return(NULL);
+ }
+ current_picture->height = height;
+ current_picture->width = width;
+ current_picture->data = bigBuf;
+
+ /* OK */
+ return(current_picture);
+}
+
+
+/************************************************************************************/
+/* GIFReadFileToRGB() : Ouverture / Décompression d'une image GIF -> 256 couleurs. */
+/************************************************************************************/
+struct picture_256 *GIFReadFileTo256Color(char *file_path)
+{
+ struct picture_true *current_picture_true;
+ struct picture_256 *current_picture_256;
+
+ /** Chargement de l'image en True Color **/
+ current_picture_true = GIFReadFileToRGB(file_path);
+ if(current_picture_true == NULL)
+ return(NULL);
+
+ /** Conversion en 256 Couleurs **/
+ current_picture_256 = ConvertTrueColorTo256(current_picture_true);
+
+ /* Libération mémoire */
+ mem_free_picture_true(current_picture_true);
+
+ /* Renvoie l'image */
+ return(current_picture_256);
+}
+
+
+/************************************************************************/
+/* ReadColorMap() */
+/************************************************************************/
+static int ReadColorMap(FILE *fd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE])
+{
+ int i;
+ int nb_read;
+ unsigned char rgb[3*MAXCOLORMAPSIZE];
+
+ /* Lecture de la palette */
+ nb_read = fread(rgb,3,number,fd);
+ if(nb_read != number)
+ return(1);
+
+ /* On place les compasantes RVB */
+ for(i=0; i>2)&0x7;
+ Gif89.inputFlag = (buffer[0]>>1)&0x1;
+ Gif89.delayTime = LM_to_uint(buffer[1],buffer[2]);
+ if((buffer[0]&0x1)!=0)
+ Gif89.transparent=buffer[3];
+
+ while(GetDataBlock(fd,(unsigned char *)buffer)!=0);
+ return(FALSE);
+ break;
+ default :
+ sprintf(buffer,"UNKNOWN (0x%02x)",label);
+ break;
+ }
+
+ while(GetDataBlock(fd,(unsigned char *)buffer)!=0);
+
+ return(FALSE);
+}
+
+
+/*************************************************************/
+/* */
+/*************************************************************/
+static int GetDataBlock(FILE *fd, unsigned char *buffer)
+{
+ int nb_read;
+ unsigned char count;
+
+ nb_read = fread(&count,1,1,fd);
+ if(nb_read != 1)
+ return(-1);
+
+ ZeroDataBlock=count==0;
+
+ if((count != 0) && (fread(buffer,1,count,fd) != count))
+ return(-1);
+
+ return(count);
+}
+
+
+/*********************************************************************/
+/* */
+/*********************************************************************/
+static int GetCode(FILE *fd, int code_size, int flag)
+{
+ static unsigned char buf[280];
+ static int curbit, lastbit, done, last_byte;
+ int i,j,ret;
+ unsigned char count;
+
+ if(flag)
+ {
+ curbit=0;
+ lastbit=0;
+ done=FALSE;
+ return(0);
+ }
+
+ if((curbit+code_size) >=lastbit)
+ {
+ if(done)
+ {
+ if(curbit >=lastbit)
+ return(0);
+ return(-1);
+ }
+ buf[0]=buf[last_byte-2];
+ buf[1]=buf[last_byte-1];
+
+ if((count=GetDataBlock(fd,&buf[2]))==0)
+ done=TRUE;
+
+ last_byte = 2+count;
+
+ curbit = (curbit - lastbit) + 16;
+
+ lastbit = (2+count)*8;
+ }
+ ret=0;
+ for(i=curbit,j=0; j=0)
+ {
+ curidx= (xpos + ypos*width)*3;
+
+ *(bigMemBuf+curidx) = cmap[0][color];
+ *(bigMemBuf+curidx+1) = cmap[1][color];
+ *(bigMemBuf+curidx+2) = cmap[2][color];
+
+ xpos++;
+ if(xpos==width)
+ {
+ xpos=0;
+ if(interlace)
+ {
+ switch(pass)
+ {
+ case 0:
+ case 1:
+ ypos += 8;
+ break;
+ case 2:
+ ypos += 4;
+ break;
+ case 3:
+ ypos += 2;
+ break;
+ }
+
+ if(ypos>=height)
+ {
+ pass++;
+ switch(pass)
+ {
+ case 1:
+ ypos=4;
+ break;
+ case 2:
+ ypos=2;
+ break;
+ case 3:
+ ypos=1;
+ break;
+ default :
+ LZWReadByte(fd,FALSE,c);
+ return(0);
+ }
+ }
+ }
+ else
+ ypos++;
+ }
+
+ if(ypos >= height)
+ break;
+ }
+
+ LZWReadByte(fd,FALSE,c);
+ return(0);
+}
+
+
+/*********************************************************************/
+/* LZWReadByte() */
+/*********************************************************************/
+static int LZWReadByte(FILE *fd, int flag, int input_code_size)
+{
+ static int fresh=FALSE;
+ int code, incode;
+ static int code_size, set_code_size;
+ static int max_code, max_code_size;
+ static int firstcode, oldcode;
+ static int clear_code, end_code;
+
+ static unsigned short next[1< stack)
+ return(*--sp);
+
+ while((code= GetCode(fd,code_size,FALSE)) >=0)
+ {
+ if(code==clear_code)
+ {
+ for(i=0; i0);
+ if(count!=0)
+ return(-2);
+ }
+
+ incode = code;
+
+ if(code >= max_code)
+ {
+ *sp++=firstcode;
+ code=oldcode;
+ }
+
+ while(code >= clear_code)
+ {
+ *sp++=vals[code];
+ if(code==(int)next[code])
+ return(-1);
+ code=next[code];
+ }
+
+ *sp++ = firstcode=vals[code];
+
+ if((code=max_code) < (1<= max_code_size) &&
+ (max_code_size < (1< stack)
+ return *--sp;
+ }
+ return(code);
+}
+
+static void Putword(int w, FILE *fp)
+{
+ fputc(w & 0xff,fp);
+ fputc((w / 256) & 0xff,fp);
+}
+
+
+static void compress(int init_bits, FILE *outfile, struct global_gif *global)
+{
+ register long fcode;
+ register code_int i /* = 0 */;
+ register int c;
+ register code_int ent;
+ register code_int disp;
+ register int hshift;
+
+ /*
+ * Set up the globals: g_init_bits - initial number of bits
+ * g_outfile - pointer to output file
+ */
+ global->g_init_bits = init_bits;
+ global->g_outfile = outfile;
+
+ /* Set up the necessary values */
+ global->clear_flg = 0;
+ global->maxcode = MAXCODE(n_bits = global->g_init_bits);
+
+ global->ClearCode = (1 << (init_bits - 1));
+ global->EOFCode = global->ClearCode + 1;
+ global->free_ent = global->ClearCode + 2;
+
+ /* Char Init */
+ global->a_count=0;
+
+ /** Next Pixel **/
+ if(global->CountDown == 0)
+ ent = EOF;
+ else
+ {
+ global->CountDown--;
+ ent = *(global->buffer + global->curx + global->cury*global->Width);
+
+ /* Bump the current X position */
+ global->curx++;
+ if(global->curx == global->Width)
+ {
+ global->curx = 0;
+ global->cury++;
+ }
+ }
+
+ hshift = 0;
+ for(fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L)
+ ++hshift;
+ hshift = 8 - hshift; /* set hash code range bound */
+
+ cl_hash((count_int) HSIZE,global); /* clear hash table */
+
+ output((code_int)global->ClearCode,global);
+
+ while(1)
+ {
+ /** Next Pixel **/
+ if(global->CountDown == 0)
+ break;
+ else
+ {
+ global->CountDown--;
+ c = *(global->buffer + global->curx + global->cury*global->Width);
+
+ /* Bump the current X position */
+ global->curx++;
+ if(global->curx == global->Width)
+ {
+ global->curx = 0;
+ global->cury++;
+ }
+ }
+
+ fcode = (long) (((long) c << global->maxbits) + ent);
+ i = (((code_int)c << hshift) ^ ent); /* xor hashing */
+
+ if(HashTabOf(i) == fcode)
+ {
+ ent = CodeTabOf(i);
+ continue;
+ }
+ else if((long)HashTabOf (i) < 0) /* empty slot */
+ goto nomatch;
+ disp = HSIZE - i; /* secondary hash (after G. Knott) */
+ if(i == 0)
+ disp = 1;
+probe:
+ if((i -= disp) < 0)
+ i += HSIZE;
+
+ if(HashTabOf(i) == fcode)
+ {
+ ent = CodeTabOf(i);
+ continue;
+ }
+ if((long)HashTabOf(i) > 0)
+ goto probe;
+nomatch:
+ /**************/
+ /** Output **/
+ global->cur_accum &= masks[global->cur_bits];
+
+ if(global->cur_bits > 0)
+ global->cur_accum |= ((long)((code_int)ent) << global->cur_bits);
+ else
+ global->cur_accum = (code_int) ent;
+ global->cur_bits += global->n_bits;
+
+ while(global->cur_bits >= 8)
+ {
+ /* Char Out */
+ global->accum[global->a_count++] = (unsigned int)(global->cur_accum & 0xff);
+ if(global->a_count >=254)
+ flush_char(global);
+
+ global->cur_accum >>= 8;
+ global->cur_bits -= 8;
+ }
+
+ /* If the next entry is going to be too big for the code size, */
+ /* then increase it, if possible. */
+ if(global->free_ent > global->maxcode || global->clear_flg)
+ {
+ if(global->clear_flg)
+ {
+ global->maxcode = MAXCODE (n_bits = global->g_init_bits);
+ global->clear_flg = 0;
+ }
+ else
+ {
+ ++global->n_bits;
+ if(global->n_bits == global->maxbits)
+ global->maxcode = global->maxmaxcode;
+ else
+ global->maxcode = MAXCODE(n_bits);
+ }
+ }
+
+ if(((code_int) ent) == global->EOFCode)
+ {
+ /* At EOF, write the rest of the buffer. */
+ while(global->cur_bits > 0)
+ {
+ /* Char Out */
+ global->accum[global->a_count++] = (unsigned int)(global->cur_accum & 0xff);
+ if(global->a_count >=254)
+ flush_char(global);
+
+ global->cur_accum >>= 8;
+ global->cur_bits -= 8;
+ }
+
+ flush_char(global);
+ fflush(global->g_outfile);
+ }
+
+ ent = c;
+ if(global->free_ent < global->maxmaxcode)
+ {
+ CodeTabOf(i) = global->free_ent++; /* code -> hashtable */
+ HashTabOf(i) = fcode;
+ }
+ else
+ cl_block(global);
+ }
+
+ /* Put out the final code. */
+ output((code_int)ent,global);
+ output((code_int)global->EOFCode,global);
+}
+
+
+static void output(code_int code, struct global_gif *global)
+{
+ global->cur_accum &= masks[ global->cur_bits ];
+
+ if(global->cur_bits > 0)
+ global->cur_accum |= ((long)code << global->cur_bits);
+ else
+ global->cur_accum = code;
+
+ global->cur_bits += global->n_bits;
+
+ while(global->cur_bits >= 8)
+ {
+ /* Char Out */
+ global->accum[global->a_count++] = (unsigned int)(global->cur_accum & 0xff);
+ if(global->a_count >=254)
+ flush_char(global);
+
+ global->cur_accum >>= 8;
+ global->cur_bits -= 8;
+ }
+
+ /*
+ * If the next entry is going to be too big for the code size,
+ * then increase it, if possible.
+ */
+ if(global->free_ent > global->maxcode || global->clear_flg)
+ {
+ if(global->clear_flg)
+ {
+ global->maxcode = MAXCODE (n_bits = global->g_init_bits);
+ global->clear_flg = 0;
+ }
+ else
+ {
+ ++global->n_bits;
+ if(global->n_bits == global->maxbits)
+ global->maxcode = global->maxmaxcode;
+ else
+ global->maxcode = MAXCODE(n_bits);
+ }
+ }
+
+ if(code == global->EOFCode)
+ {
+ /* At EOF, write the rest of the buffer. */
+ while(global->cur_bits > 0)
+ {
+ /* Char Out */
+ global->accum[global->a_count++] = (unsigned int)(global->cur_accum & 0xff);
+ if(global->a_count >=254)
+ flush_char(global);
+
+ global->cur_accum >>= 8;
+ global->cur_bits -= 8;
+ }
+
+ flush_char(global);
+ fflush(global->g_outfile);
+ }
+}
+
+
+static void cl_block(struct global_gif *global)
+{
+ cl_hash((count_int)HSIZE,global);
+ global->free_ent=global->ClearCode+2;
+ global->clear_flg=1;
+
+ output((code_int)global->ClearCode,global);
+}
+
+
+static void cl_hash(register count_int hsize, struct global_gif *global)
+{
+ register count_int *htab_p = global->htab+hsize;
+
+ register long i;
+ register long m1 = -1L;
+
+ i = hsize - 16;
+
+ do{
+ *(htab_p-16) = m1;
+ *(htab_p-15) = m1;
+ *(htab_p-14) = m1;
+ *(htab_p-13) = m1;
+ *(htab_p-12) = m1;
+ *(htab_p-11) = m1;
+ *(htab_p-10) = m1;
+ *(htab_p-9) = m1;
+ *(htab_p-8) = m1;
+ *(htab_p-7) = m1;
+ *(htab_p-6) = m1;
+ *(htab_p-5) = m1;
+ *(htab_p-4) = m1;
+ *(htab_p-3) = m1;
+ *(htab_p-2) = m1;
+ *(htab_p-1) = m1;
+
+ htab_p-=16;
+ } while((i-=16) >=0);
+
+ for(i+=16; i>0; i--)
+ *--htab_p=m1;
+}
+
+
+static void flush_char(struct global_gif *global)
+{
+ if(global->a_count > 0)
+ {
+ fputc(global->a_count,global->g_outfile);
+ fwrite(global->accum,1,global->a_count,global->g_outfile);
+ global->a_count=0;
+ }
+}
+
+/**************************************************************************/
diff --git a/bin/mrsprite/source/Dc_Gif.h b/bin/mrsprite/source/Dc_Gif.h
new file mode 100644
index 0000000..ba8beac
--- /dev/null
+++ b/bin/mrsprite/source/Dc_Gif.h
@@ -0,0 +1,18 @@
+/*****************************************************************
+ * *
+ * Dc_Gif.h : Header de gestion des fichiers GIF. *
+ * *
+ *****************************************************************
+ * Auteur : Olivier ZARDINI * CooperTeam * Date : Jui 2005 *
+ *****************************************************************/
+
+#define GR_ERR_NOERROR 0
+#define GR_ERR_MEMORY (-100)
+#define GR_ERR_BADFORMAT (-160)
+#define GR_ERR_OPENFILE (-210)
+
+struct picture_true *GIFReadFileToRGB(char *);
+struct picture_256 *GIFReadFileTo256Color(char *);
+int GIFWriteFileFrom256Color(char *,struct picture_256 *);
+
+/****************************************************************/
\ No newline at end of file
diff --git a/bin/mrsprite/source/Dc_Graphic.c b/bin/mrsprite/source/Dc_Graphic.c
new file mode 100644
index 0000000..99a8245
--- /dev/null
+++ b/bin/mrsprite/source/Dc_Graphic.c
@@ -0,0 +1,2337 @@
+/********************************************************************
+ * *
+ * Dc_Graphic.c : Module de gestion des fichiers Graphiques. *
+ * *
+ ********************************************************************
+ * Auteur : Olivier ZARDINI * Brutal Deluxe * Date : Nov 2012 *
+ ********************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+
+#include "Dc_Gif.h"
+#include "Dc_Shared.h"
+#include "Dc_Memory.h"
+#include "Dc_Code.h"
+#include "Dc_Graphic.h"
+
+struct picture_256 *BuildSpritePicture(int,int,int,int,int,unsigned char,struct picture_256 *);
+struct picture_256 *BuildByteImage(struct picture_256 *,char *,int);
+int IsEmptyRow(int,int,int,int,struct picture_256 *);
+int IsEmptyColumn(int,int,int,int,struct picture_256 *);
+int ComputeDensity(struct picture_256 *,int,int,int);
+int IsSpriteAdjacent(int,int,int *,int,int);
+
+/*****************************************************************/
+/* DecodeRGBColor() : Conversion d'une couleur Texte en DWORD. */
+/*****************************************************************/
+DWORD DecodeRGBColor(char *color_text)
+{
+ int i;
+ DWORD color;
+
+ /* Vérification */
+ if(strlen(color_text) != strlen("FF00FF"))
+ return(0xFFFFFFFF);
+ for(i=0; i<(int)strlen("FF00FF"); i++)
+ if(!((color_text[i] >= '0' && color_text[i] <= '9') || (toupper(color_text[i]) >= 'A' && toupper(color_text[i]) <= 'F')))
+ return(0xFFFFFFFF);
+
+ /* Conversion */
+ sscanf(color_text,"%06X",&color);
+
+ /* Renvoi la couleur */
+ return(color);
+}
+
+
+/*************************************************************/
+/* ExtractAllSprite() : Extrait les Sprites de la planche. */
+/*************************************************************/
+int ExtractAllSprite(char *file_path, DWORD bg_color, DWORD frame_color)
+{
+ int i, j, x, y, nb, result, bg_index, frame_index, found;
+ int uleft_x, uleft_y, lright_x, lright_y;
+ int sprite_width, sprite_height, sprite_index;
+ int frame_width, frame_height, frame_uleft_x, frame_uleft_y;
+ DWORD color;
+ struct picture_256 *current_picture;
+ struct picture_256 *work_picture;
+ struct picture_256 *sprite_picture;
+ char sprite_file_path[1024];
+
+ /** Charge l'image Gif en mémoire **/
+ current_picture = GIFReadFileTo256Color(file_path);
+ if(current_picture == NULL)
+ {
+ printf(" Error : Can't load GIF file '%s'.\n",file_path);
+ return(1);
+ }
+ work_picture = GIFReadFileTo256Color(file_path);
+ if(current_picture == NULL)
+ {
+ printf(" Error : Can't load GIF file '%s'.\n",file_path);
+ mem_free_picture_256(current_picture);
+ return(1);
+ }
+
+ /** Recherche l'indice de la couleur de fond / couleur de bordure **/
+ for(i=0,bg_index=-1,frame_index=-1; inb_color; i++)
+ {
+ color = current_picture->palette_red[i]<<16 | current_picture->palette_green[i]<<8 | current_picture->palette_blue[i];
+ if(color == bg_color)
+ bg_index = i;
+ if(color == frame_color)
+ frame_index = i;
+ }
+
+ /* Erreur */
+ if(bg_index == -1)
+ {
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't find background color %06X in palette.\n",bg_color);
+ return(2);
+ }
+
+ /* Couleur de Bordure */
+ if(frame_index == -1)
+ {
+ /* Ajoute la couleur de la bordure à la table des couleurs */
+ frame_index = current_picture->nb_color;
+ current_picture->palette_red[current_picture->nb_color] = (frame_color>>16) & 0xFF;
+ current_picture->palette_green[current_picture->nb_color] = (frame_color>>8) & 0xFF;
+ current_picture->palette_blue[current_picture->nb_color] = (frame_color) & 0xFF;
+ current_picture->nb_color++;
+ }
+
+ /******************************************************/
+ /*** Recherche des Sprites entourés par une Frame ***/
+ /******************************************************/
+ /*** On efface les points Frame de l'image Current ***/
+ for(j=0; jheight; j++)
+ for(i=0; iwidth; i++)
+ if(current_picture->data[i+j*current_picture->width] == frame_index)
+ current_picture->data[i+j*current_picture->width] = bg_index;
+
+ /*** Recherche des Sprites Frame ***/
+ for(sprite_index=0; ; sprite_index++)
+ {
+ /** Recherche un point de l'image qui est du Frame **/
+ found = 0;
+ for(j=0; jheight; j++)
+ {
+ for(i=0; iwidth; i++)
+ if(work_picture->data[i+j*work_picture->width] == frame_index)
+ {
+ found = 1;
+ break;
+ }
+ if(found == 1)
+ break;
+ }
+ /* Il n'y a plus de Sprite Frame dans l'image Work */
+ if(found == 0)
+ break;
+
+ /** Zone rectangulaire Frame **/
+ frame_uleft_x = i;
+ frame_uleft_y = j;
+ /* Largeur */
+ for(i=frame_uleft_x; iwidth; i++)
+ if(work_picture->data[i+frame_uleft_y*work_picture->width] != frame_index)
+ break;
+ frame_width = i - frame_uleft_x;
+ /* Hauteur */
+ for(j=frame_uleft_y; jheight; j++)
+ if(work_picture->data[frame_uleft_x+j*work_picture->width] != frame_index)
+ break;
+ frame_height = j - frame_uleft_y;
+
+ /*** Réduction de la zone du Sprite ***/
+ uleft_x = frame_uleft_x + 1;
+ uleft_y = frame_uleft_y + 1;
+ lright_x = frame_uleft_x + frame_width - 2;
+ lright_y = frame_uleft_y + frame_height - 2;
+
+#if 0
+ /** Descend **/
+ for(y=uleft_y,nb=0; ydata[x+y*work_picture->width] != bg_index)
+ {
+ found = 1;
+ break;
+ }
+ if(found == 1)
+ break;
+ nb++;
+ }
+ uleft_y += nb;
+
+ /** Monte **/
+ for(y=lright_y,nb=0; y>uleft_y; y--)
+ {
+ /* Que du fond sur la ligne ? */
+ for(x=uleft_x,found=0; xdata[x+y*work_picture->width] != bg_index)
+ {
+ found = 1;
+ break;
+ }
+ if(found == 1)
+ break;
+ nb++;
+ }
+ lright_y -= nb;
+
+ /** -> Droite **/
+ for(x=uleft_x,nb=0; xdata[x+y*work_picture->width] != bg_index)
+ {
+ found = 1;
+ break;
+ }
+ if(found == 1)
+ break;
+ nb++;
+ }
+ uleft_x += nb;
+
+ /** <- Gauche **/
+ for(x=lright_x,nb=0; x>uleft_x; x--)
+ {
+ /* Que du fond sur la colonne ? */
+ for(y=uleft_y,found=0; ydata[x+y*work_picture->width] != bg_index)
+ {
+ found = 1;
+ break;
+ }
+ if(found == 1)
+ break;
+ nb++;
+ }
+ lright_x -= nb;
+#endif
+
+ /** On aligne la largeur du Sprite sur 4 points **/
+ sprite_width = lright_x - uleft_x + 1;
+ if(sprite_width % 4 != 0)
+ sprite_width += (4 - sprite_width%4);
+ sprite_height = lright_y - uleft_y + 1;
+
+ /** Création du Sprite sur le Disque **/
+ strcpy(sprite_file_path,file_path);
+ sprintf(&sprite_file_path[strlen(sprite_file_path)-4],"_spr_%03d.gif",sprite_index);
+ sprite_picture = BuildSpritePicture(uleft_x,uleft_y,lright_x-uleft_x+1,sprite_height,sprite_width,(unsigned char)bg_index,work_picture);
+ if(sprite_picture == NULL)
+ {
+ mem_free_picture_256(work_picture);
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't build sprite picture.\n");
+ return(5);
+ }
+ result = GIFWriteFileFrom256Color(sprite_file_path,sprite_picture);
+ if(result)
+ {
+ mem_free_picture_256(work_picture);
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't create sprite picture '%s'.\n",sprite_file_path);
+ return(5);
+ }
+ mem_free_picture_256(sprite_picture);
+
+ /** On efface le Sprite de l'image Work **/
+ for(j=0; jdata[i+frame_uleft_x+(j+frame_uleft_y)*work_picture->width] = bg_index;
+
+ /** On dessine le cadre autour du Sprite sur l'image Current **/
+ for(i=0; i= 0 && (uleft_x-1+i) < current_picture->width && (uleft_y-1) >= 0)
+ current_picture->data[uleft_x-1+i + (uleft_y-1)*current_picture->width] = (unsigned char) frame_index;
+ if((uleft_x-1+i) >= 0 && (uleft_x-1+i) < current_picture->width && (lright_y+1) < current_picture->height)
+ current_picture->data[uleft_x-1+i + (lright_y+1)*current_picture->width] = (unsigned char) frame_index;
+ }
+ for(i=0; i= 0 && (uleft_y-1+i) < current_picture->height && (uleft_x-1) >= 0)
+ current_picture->data[uleft_x-1 + (uleft_y-1+i)*current_picture->width] = (unsigned char) frame_index;
+ if((uleft_y-1+i) >= 0 && (uleft_y-1+i) < current_picture->height && (uleft_x+sprite_width) < current_picture->width)
+ current_picture->data[uleft_x+sprite_width + (uleft_y-1+i)*current_picture->width] = (unsigned char) frame_index;
+ }
+ }
+
+ /********************************************/
+ /*** Recherche des Sprites dans l'image ***/
+ /********************************************/
+ for(; ; sprite_index++)
+ {
+ /** Recherche un point de l'image qui n'est pas du fond **/
+ found = 0;
+ for(j=0; jheight; j++)
+ {
+ for(i=0; iwidth; i++)
+ if(work_picture->data[i+j*work_picture->width] != bg_index)
+ {
+ found = 1;
+ break;
+ }
+ if(found == 1)
+ break;
+ }
+ /* Il n'y a plus de Sprite dans l'image Work */
+ if(found == 0)
+ break;
+
+ /* On va étendre le rectangle du Sprite */
+ uleft_x = i;
+ uleft_y = j;
+ lright_x = i;
+ lright_y = j;
+
+ /*** On part du rectangle de référence et on trace un rectangle englobant ***/
+ while(1)
+ {
+ found = 0;
+
+ /* Haut */
+ if(uleft_y > 0)
+ {
+ for(i=(uleft_x==0)?0:uleft_x-1; i<((lright_x+1)>work_picture->width?work_picture->width:lright_x+1); i++)
+ if(work_picture->data[i+(uleft_y-1)*work_picture->width] != bg_index)
+ {
+ found = 1;
+ uleft_y--;
+ break;
+ }
+ }
+
+ /* Bas */
+ if(lright_y < work_picture->height-1)
+ {
+ for(i=(uleft_x==0)?0:uleft_x-1; i<((lright_x+1)>work_picture->width?work_picture->width:lright_x+1); i++)
+ if(work_picture->data[i+(lright_y+1)*work_picture->width] != bg_index)
+ {
+ found = 1;
+ lright_y++;
+ break;
+ }
+ }
+
+ /* Gauche */
+ if(uleft_x > 0)
+ {
+ for(j=(uleft_y==0)?0:uleft_y-1; j<((lright_y+1)>work_picture->height?work_picture->height:lright_y+1); j++)
+ if(work_picture->data[(uleft_x-1)+j*work_picture->width] != bg_index)
+ {
+ found = 1;
+ uleft_x--;
+ break;
+ }
+ }
+
+ /* Droite */
+ if(lright_x < work_picture->width-1)
+ {
+ for(j=(uleft_x==0)?0:uleft_y-1; j<((lright_y+1)>work_picture->height?work_picture->height:lright_y+1); j++)
+ if(work_picture->data[(lright_x+1)+j*work_picture->width] != bg_index)
+ {
+ found = 1;
+ lright_x++;
+ break;
+ }
+ }
+
+ /* On a que du décor autour du sprite */
+ if(found == 0)
+ break;
+ }
+
+ /** On aligne la largeur du Sprite sur 4 points **/
+ sprite_width = lright_x - uleft_x + 1;
+ if(sprite_width % 4 != 0)
+ sprite_width += (4 - sprite_width%4);
+ sprite_height = lright_y - uleft_y + 1;
+
+ /** Création du Sprite sur le Disque **/
+ strcpy(sprite_file_path,file_path);
+ sprintf(&sprite_file_path[strlen(sprite_file_path)-4],"_spr_%03d.gif",sprite_index);
+ sprite_picture = BuildSpritePicture(uleft_x,uleft_y,lright_x-uleft_x+1,sprite_height,sprite_width,(unsigned char)bg_index,work_picture);
+ if(sprite_picture == NULL)
+ {
+ mem_free_picture_256(work_picture);
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't build sprite picture.\n");
+ return(5);
+ }
+ result = GIFWriteFileFrom256Color(sprite_file_path,sprite_picture);
+ if(result)
+ {
+ mem_free_picture_256(work_picture);
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't create sprite picture '%s'.\n",sprite_file_path);
+ return(5);
+ }
+ mem_free_picture_256(sprite_picture);
+
+ /** On efface le Sprite de l'image Work **/
+ for(j=0; jdata[i+uleft_x+(j+uleft_y)*work_picture->width] = bg_index;
+
+ /** On dessine le cadre autour du Sprite sur l'image Current **/
+ for(i=0; i= 0 && (uleft_x-1+i) < current_picture->width && (uleft_y-1) >= 0)
+ current_picture->data[uleft_x-1+i + (uleft_y-1)*current_picture->width] = (unsigned char) frame_index;
+ if((uleft_x-1+i) >= 0 && (uleft_x-1+i) < current_picture->width && (lright_y+1) < current_picture->height)
+ current_picture->data[uleft_x-1+i + (lright_y+1)*current_picture->width] = (unsigned char) frame_index;
+ }
+ for(i=0; i= 0 && (uleft_y-1+i) < current_picture->height && (uleft_x-1) >= 0)
+ current_picture->data[uleft_x-1 + (uleft_y-1+i)*current_picture->width] = (unsigned char) frame_index;
+ if((uleft_y-1+i) >= 0 && (uleft_y-1+i) < current_picture->height && (uleft_x+sprite_width) < current_picture->width)
+ current_picture->data[uleft_x+sprite_width + (uleft_y-1+i)*current_picture->width] = (unsigned char) frame_index;
+ }
+ }
+
+ /* Libération de l'image de travail */
+ mem_free_picture_256(work_picture);
+
+ /** Enregistre l'image avec les frames **/
+ strcpy(sprite_file_path,file_path);
+ strcpy(&sprite_file_path[strlen(sprite_file_path)-4],"_frame.gif");
+ result = GIFWriteFileFrom256Color(sprite_file_path,current_picture);
+ if(result)
+ {
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't create frame picture '%s'.\n",sprite_file_path);
+ return(5);
+ }
+
+ /* Libération mémoire */
+ mem_free_picture_256(current_picture);
+
+ /* OK */
+ return(0);
+}
+
+
+/*******************************************************************/
+/* BuildSpritePicture() : Construit l'image avec juste le sprite. */
+/*******************************************************************/
+struct picture_256 *BuildSpritePicture(int x, int y, int sprite_width, int sprite_height, int picture_width, unsigned char bg_index, struct picture_256 *current_picture)
+{
+ int i, j;
+ struct picture_256 *sprite_picture;
+
+ /* Allocation structure */
+ sprite_picture = (struct picture_256 *) calloc(1,sizeof(struct picture_256));
+ if(sprite_picture == NULL)
+ return(NULL);
+ sprite_picture->data = (unsigned char *) calloc(picture_width*sprite_height,sizeof(unsigned char));
+ if(sprite_picture->data == NULL)
+ {
+ free(sprite_picture);
+ return(NULL);
+ }
+ memset(sprite_picture->data,bg_index,picture_width*sprite_height);
+
+ /* Initialisation */
+ sprite_picture->width = picture_width;
+ sprite_picture->height = sprite_height;
+
+ /** On place les points **/
+ for(i=0; idata[i+j*sprite_picture->width] = (unsigned char) current_picture->data[x+i+(j+y)*current_picture->width];
+
+ /* On place les couleurs */
+ sprite_picture->nb_color = current_picture->nb_color;
+ memcpy(&sprite_picture->palette_red[0],¤t_picture->palette_red[0],256*sizeof(int));
+ memcpy(&sprite_picture->palette_green[0],¤t_picture->palette_green[0],256*sizeof(int));
+ memcpy(&sprite_picture->palette_blue[0],¤t_picture->palette_blue[0],256*sizeof(int));
+
+ /* Renvoi l'image */
+ return(sprite_picture);
+}
+
+
+/**********************************************************/
+/* CreateMirrorPicture() : Création de l'image mirroir. */
+/**********************************************************/
+int CreateMirrorPicture(char *file_path, DWORD bg_color)
+{
+ int i, j, x, c, result, bg_index, found;
+ DWORD color;
+ struct picture_256 *current_picture;
+ struct picture_256 *mirror_picture;
+ char sprite_file_path[1024];
+
+ /** Charge l'image Gif en mémoire **/
+ current_picture = GIFReadFileTo256Color(file_path);
+ if(current_picture == NULL)
+ {
+ printf(" Error : Can't load GIF file '%s'.\n",file_path);
+ return(1);
+ }
+
+ /** Recherche l'indice de la couleur de fond **/
+ for(i=0,bg_index=-1; inb_color; i++)
+ {
+ color = current_picture->palette_red[i]<<16 | current_picture->palette_green[i]<<8 | current_picture->palette_blue[i];
+ if(color == bg_color)
+ bg_index = i;
+ }
+
+ /* Erreur */
+ if(bg_index == -1)
+ {
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't find background color %06X in palette.\n",bg_color);
+ return(2);
+ }
+
+ /** On recherche la colonne la + à droite ayant des points **/
+ found = 0;
+ for(x=current_picture->width-1; x>=0; x--)
+ {
+ for(j=0; jheight; j++)
+ if(current_picture->data[x+j*current_picture->width] != (unsigned char) bg_index)
+ {
+ found = 1;
+ break;
+ }
+ if(found == 1)
+ break;
+ }
+ if(found == 0)
+ {
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't create mirror for empty picture.\n");
+ return(3);
+ }
+
+ /** Création de l'image mirroir **/
+ mirror_picture = CreateEmptyPicture(current_picture->width,current_picture->height,current_picture->nb_color,¤t_picture->palette_red[0],¤t_picture->palette_green[0],¤t_picture->palette_blue[0],(unsigned char)bg_index);
+ if(mirror_picture == NULL)
+ {
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't allocate memory for mirror picture.\n");
+ return(4);
+ }
+
+ /*** On transfert les pixels en mode mirroir ***/
+ for(i=x,c=0; i>=0; i--,c++)
+ for(j=0; jheight; j++)
+ mirror_picture->data[c+j*current_picture->width] = current_picture->data[i+j*current_picture->width];
+
+ /* Libération de l'image d'origine */
+ mem_free_picture_256(current_picture);
+
+ /** Enregistre l'image mirroir **/
+ strcpy(sprite_file_path,file_path);
+ strcpy(&sprite_file_path[strlen(sprite_file_path)-4],"m.gif");
+ result = GIFWriteFileFrom256Color(sprite_file_path,mirror_picture);
+ if(result)
+ {
+ mem_free_picture_256(mirror_picture);
+ printf(" Error : Can't create mirror picture '%s'.\n",sprite_file_path);
+ return(5);
+ }
+
+ /* Libération mémoire */
+ mem_free_picture_256(mirror_picture);
+
+ /* OK */
+ return(0);
+}
+
+
+/*********************************************************/
+/* CreateFlipPicture() : Création de l'image inversée. */
+/*********************************************************/
+int CreateFlipPicture(char *file_path, DWORD bg_color)
+{
+ int i, j, result, bg_index;
+ DWORD color;
+ struct picture_256 *current_picture;
+ struct picture_256 *flip_picture;
+ char sprite_file_path[1024];
+
+ /** Charge l'image Gif en mémoire **/
+ current_picture = GIFReadFileTo256Color(file_path);
+ if(current_picture == NULL)
+ {
+ printf(" Error : Can't load GIF file '%s'.\n",file_path);
+ return(1);
+ }
+
+ /** Recherche l'indice de la couleur de fond **/
+ for(i=0,bg_index=-1; inb_color; i++)
+ {
+ color = current_picture->palette_red[i]<<16 | current_picture->palette_green[i]<<8 | current_picture->palette_blue[i];
+ if(color == bg_color)
+ bg_index = i;
+ }
+
+ /* Erreur */
+ if(bg_index == -1)
+ {
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't find background color %06X in palette.\n",bg_color);
+ return(2);
+ }
+
+ /** Création de l'image mirroir **/
+ flip_picture = CreateEmptyPicture(current_picture->width,current_picture->height,current_picture->nb_color,¤t_picture->palette_red[0],¤t_picture->palette_green[0],¤t_picture->palette_blue[0],(unsigned char)bg_index);
+ if(flip_picture == NULL)
+ {
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't allocate memory for flip picture.\n");
+ return(4);
+ }
+
+ /*** On transfert les pixels en mode inversé ***/
+ for(j=0; jheight; j++)
+ for(i=0; iwidth; i++)
+ flip_picture->data[i+(current_picture->height-j-1)*current_picture->width] = current_picture->data[i+j*current_picture->width];
+
+ /* Libération de l'image d'origine */
+ mem_free_picture_256(current_picture);
+
+ /** Enregistre l'image inversée **/
+ strcpy(sprite_file_path,file_path);
+ strcpy(&sprite_file_path[strlen(sprite_file_path)-4],"f.gif");
+ result = GIFWriteFileFrom256Color(sprite_file_path,flip_picture);
+ if(result)
+ {
+ mem_free_picture_256(flip_picture);
+ printf(" Error : Can't create flip picture '%s'.\n",sprite_file_path);
+ return(5);
+ }
+
+ /* Libération mémoire */
+ mem_free_picture_256(flip_picture);
+
+ /* OK */
+ return(0);
+}
+
+
+/*******************************************************/
+/* CreateOddPicture() : Création de l'image impaire. */
+/*******************************************************/
+int CreateOddPicture(char *file_path, DWORD bg_color)
+{
+ int i, j, result, bg_index, found;
+ DWORD color;
+ struct picture_256 *current_picture;
+ struct picture_256 *odd_picture;
+ char sprite_file_path[1024];
+
+ /** Charge l'image Gif en mémoire **/
+ current_picture = GIFReadFileTo256Color(file_path);
+ if(current_picture == NULL)
+ {
+ printf(" Error : Can't load GIF file '%s'.\n",file_path);
+ return(1);
+ }
+
+ /** Recherche l'indice de la couleur de fond **/
+ for(i=0,bg_index=-1; inb_color; i++)
+ {
+ color = current_picture->palette_red[i]<<16 | current_picture->palette_green[i]<<8 | current_picture->palette_blue[i];
+ if(color == bg_color)
+ bg_index = i;
+ }
+
+ /* Erreur */
+ if(bg_index == -1)
+ {
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't find background color %06X in palette.\n",bg_color);
+ return(2);
+ }
+
+ /** Détermine la taille de l'image : Doit on ajouter 4 points de plus ? **/
+ found = 0;
+ for(j=0; jheight; j++)
+ if(current_picture->data[current_picture->width-1+j*current_picture->width] != (unsigned char) bg_index)
+ {
+ found = 1;
+ break;
+ }
+
+ /** Création de l'image mirroir **/
+ odd_picture = CreateEmptyPicture(current_picture->width+4*found,current_picture->height,current_picture->nb_color,¤t_picture->palette_red[0],¤t_picture->palette_green[0],¤t_picture->palette_blue[0],(unsigned char)bg_index);
+ if(odd_picture == NULL)
+ {
+ mem_free_picture_256(current_picture);
+ printf(" Error : Can't allocate memory for odd picture.\n");
+ return(4);
+ }
+
+ /*** On transfert les pixels en mode impaire ***/
+ for(j=0; jheight; j++)
+ for(i=0; iwidth-1+found; i++)
+ odd_picture->data[i+1+j*odd_picture->width] = current_picture->data[i+j*current_picture->width];
+
+ /* Libération de l'image d'origine */
+ mem_free_picture_256(current_picture);
+
+ /** Enregistre l'image inversée **/
+ strcpy(sprite_file_path,file_path);
+ strcpy(&sprite_file_path[strlen(sprite_file_path)-4],"o.gif");
+ result = GIFWriteFileFrom256Color(sprite_file_path,odd_picture);
+ if(result)
+ {
+ mem_free_picture_256(odd_picture);
+ printf(" Error : Can't create odd picture '%s'.\n",sprite_file_path);
+ return(5);
+ }
+
+ /* Libération mémoire */
+ mem_free_picture_256(odd_picture);
+
+ /* OK */
+ return(0);
+}
+
+
+/********************************************************/
+/* CreateEmptyPicture() : Création d'une image vide. */
+/********************************************************/
+struct picture_256 *CreateEmptyPicture(int width, int height, int nb_color, int *palette_red, int *palette_green, int *palette_blue, unsigned char bg_index)
+{
+ struct picture_256 *current_picture;
+
+ /** Allocation mémoire **/
+ current_picture = (struct picture_256 *) calloc(1,sizeof(struct picture_256));
+ if(current_picture == NULL)
+ return(NULL);
+ current_picture->width = width;
+ current_picture->height = height;
+ current_picture->data = (unsigned char *) calloc(current_picture->width*current_picture->height,sizeof(unsigned char));
+ if(current_picture->data == NULL)
+ {
+ free(current_picture);
+ return(NULL);
+ }
+ memset(current_picture->data,bg_index,current_picture->width*current_picture->height);
+
+ /** Copie les couleurs **/
+ current_picture->nb_color = nb_color;
+ memcpy(¤t_picture->palette_red[0],palette_red,256*sizeof(int));
+ memcpy(¤t_picture->palette_green[0],palette_green,256*sizeof(int));
+ memcpy(¤t_picture->palette_blue[0],palette_blue,256*sizeof(int));
+
+ /* Renvoie l'image */
+ return(current_picture);
+}
+
+
+/*************************************************************************/
+/* IsEmptyRow() : Vérifie si une ligne est composée de pixels du fond. */
+/*************************************************************************/
+int IsEmptyRow(int x, int y, int length, int bg_index, struct picture_256 *current_picture)
+{
+ int i;
+
+ /* Passe en revue tous les points de la ligne */
+ for(i=0; iwidth) && y < current_picture->height)
+ if(current_picture->data[x+i + y*current_picture->width] != (unsigned char) bg_index)
+ return(0);
+
+ /* OK */
+ return(1);
+}
+
+
+/******************************************************************************/
+/* IsEmptyColumn() : Vérifie si une colonne est composée de pixels du fond. */
+/******************************************************************************/
+int IsEmptyColumn(int x, int y, int length, int bg_index, struct picture_256 *current_picture)
+{
+ int j;
+
+ /* Passe en revue tous les points de la colonne */
+ for(j=0; jwidth) && y+j < current_picture->height)
+ if(current_picture->data[x + (y+j)*current_picture->width] != (unsigned char) bg_index)
+ return(0);
+
+ /* OK */
+ return(1);
+}
+
+
+/*********************************************************************************************************/
+/* IsSpriteAdjacent() : Regarde si les cases autour ont déjà été marquées comme appartenant au sprite. */
+/*********************************************************************************************************/
+int IsSpriteAdjacent(int width, int height, int *density_tab, int tab_width, int tab_height)
+{
+ /** On regarde les 4 cases autour **/
+ /* A gauche */
+ if(width > 0)
+ if(density_tab[(width-1)+height*tab_width] == -1)
+ return(1);
+
+ /* A droite */
+ if(width < (tab_width-1))
+ if(density_tab[(width+1)+height*tab_width] == -1)
+ return(1);
+
+ /* En haut */
+ if(height > 0)
+ if(density_tab[width+(height-1)*tab_width] == -1)
+ return(1);
+
+ /* En bas */
+ if(height < (tab_height-1))
+ if(density_tab[width+(height+1)*tab_width] == -1)
+ return(1);
+
+ /* Non */
+ return(0);
+}
+
+/*****************************************************************************/
+/* ComputeDensity() : Calcule le nombre de point qui ne sont pas du foond. */
+/*****************************************************************************/
+int ComputeDensity(struct picture_256 *current_picture, int width, int height, int bg_index)
+{
+ int i, j, density;
+
+ /* Init */
+ density = 0;
+
+ /** Calcule la densité de point **/
+ for(i=0; i<16; i++)
+ for(j=0; j<16; j++)
+ if((16*width + i < current_picture->width) && (16*height + j < current_picture->height))
+ if(current_picture->data[16*width + i + (height*16+j)*current_picture->width] != (unsigned char) bg_index)
+ density++;
+
+ /* Renvoi la densité */
+ return(density);
+}
+
+
+/******************************************************************/
+/* RemoveDuplicatedPictures() : Supprime les images en doubles. */
+/******************************************************************/
+int RemoveDuplicatedPictures(int nb_file, char **tab_file)
+{
+ int i, j, result;
+ struct picture_true **picture_tab;
+
+ /* Allocation mémoire */
+ picture_tab = (struct picture_true **) calloc(nb_file,sizeof(struct picture_true *));
+ if(picture_tab == NULL)
+ {
+ printf(" Error : Can't allocate memory for table picture_tab.\n");
+ return(1);
+ }
+
+ /** Charge tous les fichiers **/
+ for(i=0; iwidth == picture_tab[j]->width && picture_tab[i]->height == picture_tab[j]->height)
+ {
+ result = memcmp(picture_tab[i]->data,picture_tab[j]->data,picture_tab[i]->width*picture_tab[i]->height*3);
+ if(result == 0)
+ {
+ /* On peut supprimer j */
+ mem_free_picture_true(picture_tab[j]);
+ picture_tab[j] = NULL;
+ printf(" - Delete duplicated file '%s'.\n",tab_file[j]);
+ remove(tab_file[j]);
+ }
+ }
+ }
+
+ /* Libération mémoire */
+ for(i=0; i> 16));
+ bg_green = (unsigned char) (0x000000FF & (color_bg >> 8));
+ bg_blue = (unsigned char) (0x000000FF & color_bg);
+
+ /* Couleur de frame */
+ frame_red = (unsigned char) (0x000000FF & (color_frame >> 16));
+ frame_green = (unsigned char) (0x000000FF & (color_frame >> 8));
+ frame_blue = (unsigned char) (0x000000FF & color_frame);
+
+ /* Allocation mémoire */
+ picture_tab = (struct picture_true **) calloc(nb_file,sizeof(struct picture_true *));
+ if(picture_tab == NULL)
+ {
+ printf(" Error : Can't allocate memory for table picture_tab.\n");
+ return(1);
+ }
+
+ /** Charge tous les fichiers **/
+ max_width = 0;
+ max_height = 0;
+ nb_picture = 0;
+ for(i=0; iwidth > max_width)
+ max_width = picture_tab[i]->width;
+ if(picture_tab[i]->height > max_height)
+ max_height = picture_tab[i]->height;
+
+ /* Nombre d'image */
+ nb_picture++;
+ }
+
+ /* Nombre d'image sur une ligne / Nombre de ligne d'image */
+ nb_picture_per_line = 10;
+ if(max_width*20 < 1024)
+ nb_picture_per_line = 20;
+ nb_line = nb_picture / nb_picture_per_line;
+ if(nb_line*nb_picture_per_line < nb_picture)
+ nb_line++;
+
+ /** Allocation de l'image Wall **/
+ wall_picture = (struct picture_true *) calloc(1,sizeof(struct picture_true));
+ if(wall_picture == NULL)
+ {
+ printf(" Error : Can't allocate memory for picture wall_picture.\n");
+ for(i=0; iwidth = nb_picture_per_line*(max_width + 4);
+ wall_picture->height = nb_line*(max_height+4+9);
+ wall_picture->data = (unsigned char *) calloc(1,3*wall_picture->width*wall_picture->height);
+ if(wall_picture->data == NULL)
+ {
+ printf(" Error : Can't allocate memory for picture wall_picture.\n");
+ free(wall_picture);
+ for(i=0; iwidth*wall_picture->height; i++)
+ {
+ wall_picture->data[3*i+0] = bg_red;
+ wall_picture->data[3*i+1] = bg_green;
+ wall_picture->data[3*i+2] = bg_blue;
+ }
+ box_width = max_width+2;
+ box_height = max_height+2+9;
+
+ /*** Création du contenu de l'image ***/
+ nb_picture = 0;
+ for(j=0; j= nb_file)
+ break;
+ }
+
+ /* Coin en haut à gauche de la box */
+ box_uleft_x = 2 + i*box_width;
+ box_uleft_y = 2 + j*box_height;
+
+ /* Coin en haut à gauche de l'image dans la box */
+ pict_uleft_x = (max_width - picture_tab[nb_picture]->width)/2; /* On centre l'image dans la Box */
+ pict_uleft_y = max_height - picture_tab[nb_picture]->height; /* On place l'image en bas de la box */
+
+ /** Copie l'image dans la box **/
+ for(k=0; kheight; k++)
+ memcpy(&wall_picture->data[3*(box_uleft_x+pict_uleft_x + (box_uleft_y+pict_uleft_y+k)*wall_picture->width)],&picture_tab[nb_picture]->data[3*k*picture_tab[nb_picture]->width],3*picture_tab[nb_picture]->width);
+
+ /** Trace les contours de la Frame **/
+ for(k=0; k<2+picture_tab[nb_picture]->width; k++)
+ {
+ PlotTrueColor(box_uleft_x+pict_uleft_x-1+k,box_uleft_y+pict_uleft_y-1,frame_red,frame_green,frame_blue,wall_picture);
+ PlotTrueColor(box_uleft_x+pict_uleft_x-1+k,box_uleft_y+pict_uleft_y+picture_tab[nb_picture]->height,frame_red,frame_green,frame_blue,wall_picture);
+ }
+ for(k=0; k<2+picture_tab[nb_picture]->height; k++)
+ {
+ PlotTrueColor(box_uleft_x+pict_uleft_x-1,box_uleft_y+pict_uleft_y-1+k,frame_red,frame_green,frame_blue,wall_picture);
+ PlotTrueColor(box_uleft_x+pict_uleft_x+picture_tab[nb_picture]->width,box_uleft_y+pict_uleft_y-1+k,frame_red,frame_green,frame_blue,wall_picture);
+ }
+
+ /** Place le numéro de l'image en dessous **/
+ sprite_number = 0;
+ strcpy(file_path,tab_file[nb_picture]);
+ file_path[strlen(file_path)-4] = '\0';
+ for(k=strlen(file_path); k>=0; k--)
+ if(file_path[k] == '_')
+ {
+ sprite_number = atoi(&file_path[k+1]);
+ break;
+ }
+ if(nb_picture >= 100)
+ {
+ /* 3 chiffres */
+ offset = PlotNumber(sprite_number/100,box_uleft_x+box_width/2-8,box_uleft_y+box_height-8,frame_red,frame_green,frame_blue,wall_picture);
+ offset += PlotNumber(sprite_number/10-10*(sprite_number/100),box_uleft_x+box_width/2-8+offset+1,box_uleft_y+box_height-8,frame_red,frame_green,frame_blue,wall_picture);
+ offset += PlotNumber(sprite_number-10*(sprite_number/10),box_uleft_x+box_width/2-8+offset+2,box_uleft_y+box_height-8,frame_red,frame_green,frame_blue,wall_picture);
+ }
+ else if(nb_picture >= 10)
+ {
+ /* 2 chiffres */
+ offset = PlotNumber(sprite_number/10,box_uleft_x+box_width/2-5,box_uleft_y+box_height-8,frame_red,frame_green,frame_blue,wall_picture);
+ offset += PlotNumber(sprite_number-10*(sprite_number/10),box_uleft_x+box_width/2-5+offset+1,box_uleft_y+box_height-8,frame_red,frame_green,frame_blue,wall_picture);
+ }
+ else
+ {
+ /* 1 chiffre */
+ offset = PlotNumber(sprite_number,box_uleft_x+box_width/2-2,box_uleft_y+box_height-8,frame_red,frame_green,frame_blue,wall_picture);
+ }
+
+ /* Image suivante */
+ nb_picture++;
+ if(nb_picture == nb_file)
+ break;
+ }
+
+ /* Fin */
+ if(nb_picture == nb_file)
+ break;
+ }
+
+ /** Conversion True Color -> 256 Couleurs **/
+ current_picture = ConvertTrueColorTo256(wall_picture);
+ if(current_picture == NULL)
+ {
+ printf(" - Error : Can't convert Wall picture to 256 colors.\n");
+ mem_free_picture_true(wall_picture);
+ for(i=0; i=0; i--)
+ if(file_path[i] == FOLDER_SEPARATOR_CHAR) /* \ or / */
+ {
+ for(; i<(int)strlen(file_path); i++)
+ if(file_path[i] == '_')
+ {
+ strcpy(&file_path[i],"_Wall.gif");
+ found = 1;
+ break;
+ }
+ break;
+ }
+ if(found == 0)
+ strcpy(&file_path[strlen(file_path)-4],"_Wall.gif");
+ result = GIFWriteFileFrom256Color(file_path,current_picture);
+ if(result)
+ printf(" - Error : Can't create Wall picture '%s'.\n",file_path);
+
+ /* Libération mémoire */
+ mem_free_picture_256(current_picture);
+ mem_free_picture_true(wall_picture);
+ for(i=0; i=0; i--)
+ if(file_path[i] == '_')
+ {
+ strcpy(buffer,&file_path[i+1]);
+ for(i=0; i<(int)strlen(buffer); i++)
+ if(buffer[i] == '.')
+ {
+ buffer[i] = '\0';
+ break;
+ }
+ for(i=0; i<(int)strlen(buffer); i++)
+ if(buffer[i] != '0')
+ {
+ sprite_number = atoi(&buffer[i]);
+ break;
+ }
+ break;
+ }
+
+ /** Charge l'image Gif en mémoire **/
+ current_picture = GIFReadFileTo256Color(file_path);
+ if(current_picture == NULL)
+ {
+ printf(" Error : Can't load GIF file '%s'.\n",file_path);
+ return(1);
+ }
+
+ /* Init */
+ for(i=0; i<256; i++)
+ index_map[i] = 0xAA;
+
+ /** Remappage de la palette avec les couleurs 0x00-0x0F et la couleur de fond en 0xFF **/
+ for(i=0; inb_color; i++)
+ {
+ color = ((DWORD)current_picture->palette_red[i]) << 16 | ((DWORD)current_picture->palette_green[i]) << 8 | ((DWORD)current_picture->palette_blue[i]);
+ if(color == color_bg)
+ {
+ index_map[i] = 0xFF;
+ continue;
+ }
+ for(j=0; jpalette_red[0xFF] = (unsigned char) (color_bg>>16);
+ current_picture->palette_green[0xFF] = (unsigned char) (color_bg>>8);
+ current_picture->palette_blue[0xFF] = (unsigned char) (color_bg);
+
+ /** Remappage de l'image avec les couleurs 0x00-0x0F et la couleur de fond en 0xFF **/
+ for(i=0; iwidth*current_picture->height; i++)
+ if(index_map[current_picture->data[i]] == 0xAA)
+ {
+ printf(" Error : Picture color %02X%02X%02X is unknown.\n",current_picture->palette_red[current_picture->data[i]],current_picture->palette_green[current_picture->data[i]],current_picture->palette_blue[current_picture->data[i]]);
+ mem_free_picture_256(current_picture);
+ return(1);
+ }
+ else
+ current_picture->data[i] = index_map[current_picture->data[i]];
+
+ /*** Construit l'image simplifiée BYTE du sprite ***/
+ byte_picture = BuildByteImage(current_picture,file_path,verbose);
+ if(byte_picture == NULL)
+ {
+ printf(" Error : Imposible to create BYTE Picture.\n");
+ mem_free_picture_256(current_picture);
+ return(1);
+ }
+
+ /*** Création des lignes de code ***/
+ BuildCodeLine(current_picture,byte_picture,sprite_number);
+
+ /** Création du fichier contenant le code **/
+ strcpy(code_file_path,file_path);
+ strcpy(&code_file_path[strlen(code_file_path)-4],".txt");
+ fd = fopen(code_file_path,"w");
+ if(fd == NULL)
+ {
+ printf(" Error : Can't create Code file '%s'.\n",code_file_path);
+ mem_free_picture_256(current_picture);
+ return(1);
+ }
+
+ /** Ecriture des lignes de code dans le fichier Source **/
+ nb_bytes = 0;
+ nb_cycles = 0;
+ my_Memory(MEMORY_GET_CODELINE_NB,&nb_codeline,NULL);
+ for(i=1; i<=nb_codeline; i++)
+ {
+ my_Memory(MEMORY_GET_CODELINE,&i,¤t_codeline);
+ fprintf(fd,"%s\t%s\t%s%s%s\n",current_codeline->label,current_codeline->opcode,current_codeline->operand,
+ strlen(current_codeline->comment)>0?"\t":"",strlen(current_codeline->comment)>0?current_codeline->comment:"");
+ nb_bytes += current_codeline->nb_byte;
+ nb_cycles += current_codeline->nb_cycle;
+ }
+
+ /* Fermeture du fichier */
+ fclose(fd);
+
+ /* Statistiques */
+ nb_max_cycles = 5 + byte_picture->height*(3+(byte_picture->width/2)*31-1+41) - 1;
+ printf(" => %d*%d pixels, %d bytes (%d), %d cycles (%d).\n",2*byte_picture->width,byte_picture->height,nb_bytes,2*byte_picture->width*byte_picture->height,nb_cycles,nb_max_cycles);
+
+ /* Libération mémoire */
+ mem_free_picture_256(byte_picture);
+ mem_free_picture_256(current_picture);
+
+ /* OK */
+ return(0);
+}
+
+
+/***************************************************************/
+/* BuildByteImage() : Construit une version BYTE de l'image. */
+/***************************************************************/
+struct picture_256 *BuildByteImage(struct picture_256 *current_picture, char *sprite_path, int verbose)
+{
+ int x, y, i, j, next_x, is_full_red, is_full_red_left, is_full_red_right, is_full_red_around, is_full_blue;
+ int total, nb_ff, nb_bb, nb_cc, nb_99, nb_aa, nb_dd, nb_pattern, nb_red, nb_blue, nb_modif;
+ int pattern_coef_1, pattern_coef_2, score;
+ int length, result;
+ struct picture_256 *byte_picture;
+ struct pattern *current_pattern;
+ char file_path[1024];
+ WORD pattern;
+
+ /* Init */
+ nb_ff = 0;
+ nb_bb = 0;
+ nb_cc = 0;
+
+ /* Allocation mémoire */
+ byte_picture = (struct picture_256 *) calloc(1,sizeof(struct picture_256));
+ if(byte_picture == NULL)
+ return(NULL);
+ byte_picture->height = current_picture->height;
+ byte_picture->width = current_picture->width/2;
+ byte_picture->data = (unsigned char *) calloc(byte_picture->width*byte_picture->height,sizeof(unsigned char));
+ if(byte_picture->data == NULL)
+ {
+ free(byte_picture);
+ return(NULL);
+ }
+
+ /** Couleurs **/
+ byte_picture->nb_color = 256;
+ /* 0xFF : Background (Byte contenant 2 points de fond) */
+ byte_picture->palette_red[0xFF] = current_picture->palette_red[0xFF];
+ byte_picture->palette_green[0xFF] = current_picture->palette_green[0xFF];
+ byte_picture->palette_blue[0xFF] = current_picture->palette_blue[0xFF];
+ /* 0xBB : Blue (Byte contenant 1 point du décor et 1 point du sprite) */
+ byte_picture->palette_red[0xBB] = 0x00;
+ byte_picture->palette_green[0xBB] = 0x00;
+ byte_picture->palette_blue[0xBB] = 0xFF;
+ /* 0xCC : Red (Byte contenant 2 points de sprite) */
+ byte_picture->palette_red[0xCC] = 0xFF;
+ byte_picture->palette_green[0xCC] = 0x00;
+ byte_picture->palette_blue[0xCC] = 0x00;
+ /* 0xAA : Yellow (Byte contenant 2 points de sprite mais en 8 bit) */
+ byte_picture->palette_red[0xAA] = 0xFF;
+ byte_picture->palette_green[0xAA] = 0xFF;
+ byte_picture->palette_blue[0xAA] = 0x00;
+ /* 0xDD : Violet= fusion Rouge+Bleu ou Bleu+Bleu (2 Bytes consécutifs contenant 3 points de sprite et 1 point de décor OU Bleu+Bleu => LDA / AND / ORA / STA sur 16 bits) */
+ byte_picture->palette_red[0xDD] = 0xFF;
+ byte_picture->palette_green[0xDD] = 0x00;
+ byte_picture->palette_blue[0xDD] = 0xFF;
+ /* 0x99 : Orange (4 points rouges seuls deviennent 4 Orange, car ce n'est pas assez intéressant pour la Pile) */
+ byte_picture->palette_red[0x99] = 0xFF;
+ byte_picture->palette_green[0x99] = 0x7F;
+ byte_picture->palette_blue[0x99] = 0x00;
+ /* 0xEE : VertFluo= Erreur pour les rouges CC */
+ byte_picture->palette_red[0xEE] = 0x00;
+ byte_picture->palette_green[0xEE] = 0xFF;
+ byte_picture->palette_blue[0xEE] = 0x00;
+
+ /*** On va remapper les points (FF:Background, BB:Blue, CC:Red) ***/
+ for(y=0; yheight; y++)
+ for(x=0; xwidth; x++)
+ {
+ if(current_picture->data[2*x+y*current_picture->width] == 0xFF && current_picture->data[2*x+1+y*current_picture->width] == 0xFF)
+ {
+ byte_picture->data[x+y*byte_picture->width] = 0xFF;
+ nb_ff++;
+ }
+ else if((current_picture->data[2*x+y*current_picture->width] == 0xFF && current_picture->data[2*x+1+y*current_picture->width] != 0xFF) ||
+ (current_picture->data[2*x+y*current_picture->width] != 0xFF && current_picture->data[2*x+1+y*current_picture->width] == 0xFF))
+ {
+ byte_picture->data[x+y*byte_picture->width] = 0xBB;
+ nb_bb++;
+ }
+ else
+ {
+ byte_picture->data[x+y*byte_picture->width] = 0xCC;
+ nb_cc++;
+ }
+ }
+
+ /** Création de l'image BYTE Red / Blue **/
+ if(verbose)
+ {
+ strcpy(file_path,sprite_path);
+ strcpy(&file_path[strlen(file_path)-4],"_B_rb.gif");
+ result = GIFWriteFileFrom256Color(file_path,byte_picture);
+ if(result)
+ printf(" - Error : Can't create Sprite BYTE rb file '%s'.\n",file_path);
+ total = nb_ff+nb_bb+nb_cc;
+ printf(" - Sprite BYTE rb : %dx%d Total=%d, Red=%d (%d%%), Blue=%d (%d%%), Background=%d (%d%%).\n",byte_picture->width,byte_picture->height,total,nb_cc,(nb_cc*100)/total,nb_bb,(nb_bb*100)/total,nb_ff,(nb_ff*100)/total);
+ }
+
+ /*** On va établir les statistiques sur les fréquences d'utilisation des zones rouges 16 bit (2 BYTES, 4 points) ***/
+ my_Memory(MEMORY_FREE_PATTERN,NULL,NULL);
+ for(y=0; yheight; y++)
+ for(x=0; xwidth; x++)
+ {
+ /* Début d'un bloc rouge */
+ if(byte_picture->data[x+y*byte_picture->width] == 0xCC)
+ {
+ /* Longueur du bloc rouge */
+ for(i=x,length=0; iwidth; i++)
+ if(byte_picture->data[i+y*byte_picture->width] == 0xCC)
+ length++;
+ else
+ break;
+
+ /** Il faut au moins 2 BYTES **/
+ if(length >= 2)
+ {
+ /* Si la longueur est paire : 1 passage */
+ if(length%2 == 0)
+ {
+ for(j=0; jdata[2*(x+j)+0+y*current_picture->width] << 12) |
+ ((WORD) current_picture->data[2*(x+j)+1+y*current_picture->width] << 8) |
+ ((WORD) current_picture->data[2*(x+j)+2+y*current_picture->width] << 4) |
+ ((WORD) current_picture->data[2*(x+j)+3+y*current_picture->width]);
+ my_Memory(MEMORY_ADD_PATTERN,&pattern,NULL);
+ my_Memory(MEMORY_ADD_PATTERN,&pattern,NULL);
+ }
+ }
+ else
+ {
+ /** Deux passages, on sacrifie 1 BYTE à chaque fois (le premier et le dernier) **/
+ for(j=1; jdata[2*(x+j)+0+y*current_picture->width] << 12) |
+ ((WORD) current_picture->data[2*(x+j)+1+y*current_picture->width] << 8) |
+ ((WORD) current_picture->data[2*(x+j)+2+y*current_picture->width] << 4) |
+ ((WORD) current_picture->data[2*(x+j)+3+y*current_picture->width]);
+ my_Memory(MEMORY_ADD_PATTERN,&pattern,NULL);
+ }
+ for(j=0; jdata[2*(x+j)+0+y*current_picture->width] << 12) |
+ ((WORD) current_picture->data[2*(x+j)+1+y*current_picture->width] << 8) |
+ ((WORD) current_picture->data[2*(x+j)+2+y*current_picture->width] << 4) |
+ ((WORD) current_picture->data[2*(x+j)+3+y*current_picture->width]);
+ my_Memory(MEMORY_ADD_PATTERN,&pattern,NULL);
+ }
+ }
+ }
+
+ /* Bloc suivant */
+ x+=length-1; /* car x++ */
+ }
+ }
+ my_Memory(MEMORY_SORT_PATTERN,NULL,NULL);
+
+ /* Affiche les statistiques Pattern */
+ my_Memory(MEMORY_GET_PATTERN_NB,&nb_pattern,NULL);
+ if(verbose)
+ printf(" - Nb Pattern : %d\n",nb_pattern);
+ for(i=1; i<=nb_pattern; i++)
+ {
+ my_Memory(MEMORY_GET_PATTERN,&i,¤t_pattern);
+ if(i < 5)
+ if(verbose)
+ printf(" - Pattern[%d] : %04X (%d)\n",i-1,current_pattern->pattern_data,current_pattern->nb_found/2);
+ }
+
+ /*** On va remapper les points pour ajouter Yellow (Rouge BYTE tout seul no combinablme avec un autre Rouge) et Violet (Fusion d'un Rouge tout seul et d'un bleu tout seul) ***/
+ for(y=0; yheight; y++)
+ {
+ /** On analyse chaque ligne séparément les unes des autres. On parcours de Droite à gauche **/
+ for(x=byte_picture->width-1; x>=0; x--)
+ {
+ /** On travaille sur un bloc continue de pixels, de droite à gauche [i|.|.|.|.|x] **/
+ if(byte_picture->data[x+y*byte_picture->width] != 0xFF)
+ {
+ /* Cherche la fin du bloc */
+ for(i=x; i>=0; i--)
+ if(byte_picture->data[i+y*byte_picture->width] == 0xFF)
+ break;
+ length = x-i;
+ i++;
+ next_x = i;
+
+ /**************************************************/
+ /*** On va simplifier le bloc en le re-taillant ***/
+ nb_modif = 1;
+ while(nb_modif && length > 1)
+ {
+ nb_modif = 0;
+
+ /** Le bloc a deux Bleu à gauche **/
+ if(byte_picture->data[i+y*byte_picture->width] == 0xBB && byte_picture->data[i+1+y*byte_picture->width] == 0xBB)
+ {
+ /* Transforme les 2 bleus BB en 2 violet DD */
+ byte_picture->data[i+y*byte_picture->width] = 0xDD;
+ byte_picture->data[i+1+y*byte_picture->width] = 0xDD;
+
+ /* Retaille le bloc */
+ i += 2;
+ length -= 2;
+ nb_modif = 1;
+ continue;
+ }
+
+ /** Le bloc a deux Bleu à droite **/
+ if(byte_picture->data[x+y*byte_picture->width] == 0xBB && byte_picture->data[x-1+y*byte_picture->width] == 0xBB)
+ {
+ /* Transforme les 2 bleus BB en 2 violet DD */
+ byte_picture->data[x+y*byte_picture->width] = 0xDD;
+ byte_picture->data[x-1+y*byte_picture->width] = 0xDD;
+
+ /* Retaille le bloc */
+ x -= 2;
+ length -= 2;
+ nb_modif = 1;
+ continue;
+ }
+ }
+ if(length == 0)
+ {
+ x = next_x;
+ continue;
+ }
+
+ /**********************************/
+ /***** Bloc de faible taille ******/
+ /* On ne fait rien avec les blocs bleu de taille 1 (les rouges eux passent en Yellow) */
+ if(length == 1 && byte_picture->data[x+y*byte_picture->width] == 0xBB)
+ {
+ x = next_x;
+ continue;
+ }
+
+ /* Bloc de Taille 2 Blue/Red ou Red/Blue => Violet DD */
+ if(length == 2 && byte_picture->data[i+y*byte_picture->width] != byte_picture->data[i+1+y*byte_picture->width])
+ {
+ byte_picture->data[i+y*byte_picture->width] = 0xDD;
+ byte_picture->data[i+1+y*byte_picture->width] = 0xDD;
+ x = next_x;
+ continue;
+ }
+
+ /*********************************************/
+ /*** On recherche des compositions connues ***/
+
+ /* Regarde la composition du bloc : que du rouge CC ? */
+ for(is_full_red=1,nb_red=0,j=0; jdata[i+j+y*byte_picture->width] != 0xCC)
+ {
+ is_full_red = 0;
+ break;
+ }
+ else
+ nb_red++;
+ }
+ if(nb_red == 0)
+ is_full_red = 0;
+
+ /* Regarde la composition du bloc : que du rouge CC avec un seul bleu BB à Gauche ? */
+ is_full_red_left = 0;
+ if(byte_picture->data[i+y*byte_picture->width] == 0xBB)
+ {
+ for(is_full_red_left=1,nb_red=0,j=1; jdata[i+j+y*byte_picture->width] != 0xCC)
+ {
+ is_full_red_left = 0;
+ break;
+ }
+ else
+ nb_red++;
+ }
+ if(nb_red == 0)
+ is_full_red_left = 0;
+ }
+ /* Regarde la composition du bloc : que du rouge CC avec un seul bleu BB à Droite ? */
+ is_full_red_right = 0;
+ if(byte_picture->data[i+length-1+y*byte_picture->width] == 0xBB)
+ {
+ for(is_full_red_right=1,nb_red=0,j=0; jdata[i+j+y*byte_picture->width] != 0xCC)
+ {
+ is_full_red_right = 0;
+ break;
+ }
+ else
+ nb_red++;
+ }
+ if(nb_red == 0)
+ is_full_red_right = 0;
+ }
+ /* Regarde la composition du bloc : que du rouge CC avec un bleu BB à Gauche et un bleu BB à Droite ? */
+ is_full_red_around = 0;
+ if(byte_picture->data[i+y*byte_picture->width] == 0xBB && byte_picture->data[i+length-1+y*byte_picture->width] == 0xBB)
+ {
+ for(is_full_red_around=1,nb_red=0,j=1; jdata[i+j+y*byte_picture->width] != 0xCC)
+ {
+ is_full_red_around = 0;
+ break;
+ }
+ else
+ nb_red++;
+ }
+ if(nb_red == 0)
+ is_full_red_around = 0;
+ }
+
+ /* Regarde la composition du bloc : que du bleu BB ? */
+ for(is_full_blue=1,nb_blue=0,j=0; jdata[i+j+y*byte_picture->width] != 0xBB)
+ {
+ is_full_blue = 0;
+ break;
+ }
+ else
+ nb_blue++;
+ }
+ if(nb_blue == 0)
+ is_full_blue = 0;
+
+ /** Cas 1 : Que du rouge et une longueur paire **/
+ if(is_full_red == 1 && length%2 == 0)
+ {
+ /* Rien à faire le bloc FullRed est validé */
+ }
+ /** Cas 2 : Que du Rouge mais une longueur = 1 => il faut mettre du jaune à la place du rouge **/
+ else if(is_full_red == 1 && length == 1)
+ {
+ byte_picture->data[x+y*byte_picture->width] = 0xAA;
+ }
+ /** Cas 3 : Que du Rouge mais une longueur impaire > 1 => il faut mettre du jaune soit au début, soit à la fin **/
+ else if(is_full_red == 1 && length%2 != 0)
+ {
+ /** On calcule les 2 possibilités en tenant compte des stats des pattern **/
+ /* Passage 1 : On ne prend pas le premier */
+ for(pattern_coef_1=0,j=1; jdata[2*(i+j)+0+y*current_picture->width] << 12) |
+ ((WORD) current_picture->data[2*(i+j)+1+y*current_picture->width] << 8) |
+ ((WORD) current_picture->data[2*(i+j)+2+y*current_picture->width] << 4) |
+ ((WORD) current_picture->data[2*(i+j)+3+y*current_picture->width]);
+ my_Memory(MEMORY_GET_PATTERN_SCORE,&pattern,&score);
+ pattern_coef_1 += score;
+ }
+ /* Passage 2 : On ne prend pas le dernier */
+ for(pattern_coef_2=0,j=0; jdata[2*(i+j)+0+y*current_picture->width] << 12) |
+ ((WORD) current_picture->data[2*(i+j)+1+y*current_picture->width] << 8) |
+ ((WORD) current_picture->data[2*(i+j)+2+y*current_picture->width] << 4) |
+ ((WORD) current_picture->data[2*(i+j)+3+y*current_picture->width]);
+ my_Memory(MEMORY_GET_PATTERN_SCORE,&pattern,&score);
+ pattern_coef_2 += score;
+ }
+ /** On met en jaune AA celui qui permet d'utiliser les pattern les plus utilisées **/
+ if(pattern_coef_1 > pattern_coef_2)
+ byte_picture->data[i+y*byte_picture->width] = 0xAA; /* AA à Gauche */
+ else
+ byte_picture->data[x+y*byte_picture->width] = 0xAA; /* AA à Droite */
+ }
+ /** Cas 4 : Que du Rouge + un Bleu à gauche **/
+ else if(is_full_red_left == 1)
+ {
+ /* Longueur Impaire => il faut fusionner à gauche (le bleu BB + rouge CC passe en violet DD) */
+ if(nb_red%2 == 1)
+ {
+ byte_picture->data[i+y*byte_picture->width] = 0xDD; /* DD à Gauche */
+ byte_picture->data[i+1+y*byte_picture->width] = 0xDD; /* DD à Gauche */
+ }
+ else
+ ; /* Rien à faire */
+ }
+ /** Cas 5 : Que du Rouge avec + un Bleu à droite **/
+ else if(is_full_red_right == 1)
+ {
+ /* Longueur Impaire => il faut fusionner à droite (le rouge CC +le bleu BB passe en violet DD) */
+ if(nb_red%2 == 1)
+ {
+ byte_picture->data[i+length-1+y*byte_picture->width] = 0xDD; /* DD à Droite */
+ byte_picture->data[i+length-2+y*byte_picture->width] = 0xDD; /* DD à Droite */
+ }
+ else
+ ; /* Rien à faire */
+ }
+ /** Cas 6 : Bleu à gauche + du Rouge + un Bleu à droite => il faut peut être fusionner (le rouge CC +le bleu BB passe en violet DD) **/
+ else if(is_full_red_around == 1)
+ {
+ /* Cas particulier 1 : Blue-Red-Blue */
+ if(nb_red == 1)
+ {
+ byte_picture->data[i+y*byte_picture->width] = 0xDD; /* BB à gauche devient DD */
+ byte_picture->data[i+1+y*byte_picture->width] = 0xDD; /* CC au milieu devient DD */
+ }
+ /* Cas particulier 2 : Blue-Red-Red-Blue ou Blue-Nb Pair de Red-Blue */
+ else if(nb_red%2 == 0)
+ {
+ byte_picture->data[i+y*byte_picture->width] = 0xDD; /* BB à gauche devient DD */
+ byte_picture->data[i+1+y*byte_picture->width] = 0xDD; /* CC à gauche devient DD */
+ byte_picture->data[x-1+y*byte_picture->width] = 0xDD; /* CC à droite devient DD */
+ byte_picture->data[x+y*byte_picture->width] = 0xDD; /* BB à droite devient DD */
+ }
+ /* Nombre impair de Red => On ne sacrifie qu'un seul côté */
+ else
+ {
+ /** On calcule les 2 possibilités en tenant compte des stats des pattern **/
+ /* Passage 1 : On ne prend pas le premier */
+ for(pattern_coef_1=0,j=2; jdata[2*(i+j)+0+y*current_picture->width] << 12) |
+ ((WORD) current_picture->data[2*(i+j)+1+y*current_picture->width] << 8) |
+ ((WORD) current_picture->data[2*(i+j)+2+y*current_picture->width] << 4) |
+ ((WORD) current_picture->data[2*(i+j)+3+y*current_picture->width]);
+ my_Memory(MEMORY_GET_PATTERN_SCORE,&pattern,&score);
+ pattern_coef_1 += score;
+ }
+ /* Passage 2 : On ne prend pas le dernier */
+ for(pattern_coef_2=0,j=1; jdata[2*(i+j)+0+y*current_picture->width] << 12) |
+ ((WORD) current_picture->data[2*(i+j)+1+y*current_picture->width] << 8) |
+ ((WORD) current_picture->data[2*(i+j)+2+y*current_picture->width] << 4) |
+ ((WORD) current_picture->data[2*(i+j)+3+y*current_picture->width]);
+ my_Memory(MEMORY_GET_PATTERN_SCORE,&pattern,&score);
+ pattern_coef_2 += score;
+ }
+ /** On met en violet DD celui qui permet d'utiliser les pattern les plus utilisées **/
+ if(pattern_coef_1 > pattern_coef_2)
+ {
+ byte_picture->data[i+y*byte_picture->width] = 0xDD; /* BB à Gauche devient DD */
+ byte_picture->data[i+1+y*byte_picture->width] = 0xDD; /* CC à Gauche devient DD */
+ }
+ else
+ {
+ byte_picture->data[x+y*byte_picture->width] = 0xDD; /* BB à Droite devient DD */
+ byte_picture->data[x-1+y*byte_picture->width] = 0xDD; /* CC à Droite devient DD */
+ }
+ }
+ }
+ /** Cas 7 : Que du bleu **/
+ else if(is_full_blue == 1 && length > 1)
+ {
+ /* On va regrouper les bleus BB par 2 pour faire du violet DD : on les traitera en 16 bit */
+ for(j=(length%2==0)?0:1; jdata[i+j+y*byte_picture->width] = 0xDD; /* Si le nb de BB est impair, on ne groupe pas le + à gauche (convention) */
+ }
+ /** Cas 8 : Mixure de Bleu et de Rouge (du bleu au milieu de rouge) dont la longueur >= 3 **/
+ else
+ {
+ /* On parcours de droite à gauche */
+ for(j=x; j>=i; j--)
+ {
+ /** Avant-Avant dernier (il reste 3 BYTE) = 8 cas possibles **/
+ if(j == i+2)
+ {
+ /* 3 Red (on passe le + à gauche en Yellow AA ) */
+ if(byte_picture->data[j-2+y*byte_picture->width] == 0xCC && byte_picture->data[j-1+y*byte_picture->width] == 0xCC && byte_picture->data[j+y*byte_picture->width] == 0xCC)
+ {
+ byte_picture->data[j-2+y*byte_picture->width] = 0xAA;
+ j-=2; /* On avance de 3 */
+ }
+ /* 3 Blue (on passe les 2 à droite en violet DD) */
+ else if(byte_picture->data[j-2+y*byte_picture->width] == 0xBB && byte_picture->data[j-1+y*byte_picture->width] == 0xBB && byte_picture->data[j+y*byte_picture->width] == 0xBB)
+ {
+ byte_picture->data[j-1+y*byte_picture->width] = 0xDD;
+ byte_picture->data[j+y*byte_picture->width] = 0xDD;
+ j-=2; /* On avance de 3 */
+ }
+ /* RBR ou RBB (on passe le + à gauche en Yellow AA et les 2 à droite en violet DD) */
+ else if((byte_picture->data[j-2+y*byte_picture->width] == 0xCC && byte_picture->data[j-1+y*byte_picture->width] == 0xBB && byte_picture->data[j+y*byte_picture->width] == 0xCC) ||
+ (byte_picture->data[j-2+y*byte_picture->width] == 0xCC && byte_picture->data[j-1+y*byte_picture->width] == 0xBB && byte_picture->data[j+y*byte_picture->width] == 0xCC))
+ {
+ byte_picture->data[j-2+y*byte_picture->width] = 0xAA;
+ byte_picture->data[j-1+y*byte_picture->width] = 0xDD;
+ byte_picture->data[j+y*byte_picture->width] = 0xDD;
+ j-=2; /* On avance de 3 */
+ }
+ /* BRB (on passe les 2 à droite en violet DD) */
+ else if(byte_picture->data[j-2+y*byte_picture->width] == 0xBB && byte_picture->data[j-1+y*byte_picture->width] == 0xCC && byte_picture->data[j+y*byte_picture->width] == 0xBB)
+ {
+ byte_picture->data[j-1+y*byte_picture->width] = 0xDD;
+ byte_picture->data[j+y*byte_picture->width] = 0xDD;
+ j-=2; /* On avance de 3 */
+ }
+ /* BBR (on passe les 2 à gauche en violet DD et celui à droite en Yellow AA) */
+ else if(byte_picture->data[j-2+y*byte_picture->width] == 0xBB && byte_picture->data[j-1+y*byte_picture->width] == 0xBB && byte_picture->data[j+y*byte_picture->width] == 0xCC)
+ {
+ byte_picture->data[j-2+y*byte_picture->width] = 0xDD;
+ byte_picture->data[j-1+y*byte_picture->width] = 0xDD;
+ byte_picture->data[j+y*byte_picture->width] = 0xAA;
+ j-=2; /* On avance de 3 */
+ }
+ /* RRB et BRR = On ne fait rien */
+ else
+ j-=2; /* On avance de 3 */
+ }
+ /** Avant dernier (il reste 2 BYTE) **/
+ else if(j == i+1)
+ {
+ /* 2 Blue => Violet DD */
+ if(byte_picture->data[j+y*byte_picture->width] == 0xBB && byte_picture->data[j-1+y*byte_picture->width] == 0xBB)
+ {
+ byte_picture->data[j+y*byte_picture->width] = 0xDD;
+ byte_picture->data[j-1+y*byte_picture->width] = 0xDD;
+ j--; /* On avance de 2 */
+ }
+ /* 2 Red => Rien à faire */
+ else if(byte_picture->data[j+y*byte_picture->width] == 0xCC && byte_picture->data[j-1+y*byte_picture->width] == 0xCC)
+ {
+ j--; /* On avance de 2 */
+ }
+ /* 1 Red / 1 Blue (ou inverse) => Violet DD */
+ else if(byte_picture->data[j+y*byte_picture->width] != byte_picture->data[j-1+y*byte_picture->width])
+ {
+ byte_picture->data[j+y*byte_picture->width] = 0xDD;
+ byte_picture->data[j-1+y*byte_picture->width] = 0xDD;
+ j--; /* On avance de 2 */
+ }
+ }
+ /** Dernier (il reste 1 BYTE) **/
+ else if(j == i)
+ {
+ /* Blue (on ne fait rien) */
+ if(byte_picture->data[j+y*byte_picture->width] == 0xBB)
+ ;
+ /* Red (On passe en Jaune AA) */
+ else if(byte_picture->data[j+y*byte_picture->width] == 0xCC)
+ byte_picture->data[j+y*byte_picture->width] = 0xAA;
+ }
+ else /* Il reste au moins 4 BYTE */
+ {
+ /* BB on fusionne en VV */
+ if(byte_picture->data[j-1+y*byte_picture->width] == 0xBB && byte_picture->data[j+y*byte_picture->width] == 0xBB)
+ {
+ byte_picture->data[j-1+y*byte_picture->width] = 0xDD;
+ byte_picture->data[j+y*byte_picture->width] = 0xDD;
+ j--; /* On avance de 2 */
+ }
+ /* RR : On ne fait rien */
+ else if(byte_picture->data[j-1+y*byte_picture->width] == 0xCC && byte_picture->data[j+y*byte_picture->width] == 0xCC)
+ j--; /* On avance de 2 */
+ /* RB : Ca va dépendre de celui encore à gauche */
+ else if(byte_picture->data[j-1+y*byte_picture->width] == 0xCC && byte_picture->data[j+y*byte_picture->width] == 0xBB)
+ {
+ /* R[RB] : On isole le Bleu tout seul pour groupper les 2 R */
+ if(byte_picture->data[j-2+y*byte_picture->width] == 0xCC)
+ {
+ ; /* On avance de 1 */
+ }
+ /* B[RB] : On fusionne le RB en VV */
+ else if(byte_picture->data[j-2+y*byte_picture->width] == 0xBB)
+ {
+ /* Les 2 passent en violet DD */
+ byte_picture->data[j-1+y*byte_picture->width] = 0xDD;
+ byte_picture->data[j+y*byte_picture->width] = 0xDD;
+ j--; /* On avance de 2 */
+ }
+ }
+ /* BR : Ca va dépendre de celui encore à gauche */
+ else if(byte_picture->data[j-1+y*byte_picture->width] == 0xBB && byte_picture->data[j+y*byte_picture->width] == 0xCC)
+ {
+ /* R[BR] : On passe le BR en VV */
+ if(byte_picture->data[j-2+y*byte_picture->width] == 0xCC)
+ {
+ /* Les 2 passent en violet DD */
+ byte_picture->data[j-1+y*byte_picture->width] = 0xDD;
+ byte_picture->data[j+y*byte_picture->width] = 0xDD;
+ j--; /* On avance de 2 */
+ }
+ /* B[BR] : On fusionne le BB en VV et on passe le R en A */
+ else if(byte_picture->data[j-2+y*byte_picture->width] == 0xBB)
+ {
+ /* Le R passe en AA */
+ byte_picture->data[j+y*byte_picture->width] = 0xAA;
+
+ /* Les 2 B passent en violet DD */
+ byte_picture->data[j-1+y*byte_picture->width] = 0xDD;
+ byte_picture->data[j-2+y*byte_picture->width] = 0xDD;
+ j-=2; /* On avance de 3 */
+ }
+ }
+ }
+ }
+ }
+
+ /* Bloc suivant */
+ x = next_x;
+ }
+ }
+ }
+
+ /*** On va refaire les statistiques sur les fréquences d'utilisation des zones rouges CC 16 bit (2 BYTES, 4 points) ***/
+ my_Memory(MEMORY_FREE_PATTERN,NULL,NULL);
+ for(y=0; yheight; y++)
+ for(x=0; xwidth-1; x++)
+ {
+ /* Début d'un WORD rouge-rouge */
+ if(byte_picture->data[x+y*byte_picture->width] == 0xCC && byte_picture->data[x+1+y*byte_picture->width] == 0xCC)
+ {
+ pattern = ((WORD) current_picture->data[2*x+0+y*current_picture->width] << 12) |
+ ((WORD) current_picture->data[2*x+1+y*current_picture->width] << 8) |
+ ((WORD) current_picture->data[2*x+2+y*current_picture->width] << 4) |
+ ((WORD) current_picture->data[2*x+3+y*current_picture->width]);
+ my_Memory(MEMORY_ADD_PATTERN,&pattern,NULL);
+ }
+ }
+ my_Memory(MEMORY_SORT_PATTERN,NULL,NULL);
+
+ /*** On va recherche les CC (Rouge) qui vont en paire et on va les convertir en 99 (Orange), pas assez long pour la pile ***/
+ for(y=0; yheight; y++)
+ for(x=0; xwidth; x++)
+ if(byte_picture->data[x+y*byte_picture->width] == 0xCC)
+ {
+ /* Longueur de la partie rouge */
+ for(length=0,i=x; iwidth; i++)
+ if(byte_picture->data[i+y*byte_picture->width] == 0xCC)
+ length++;
+ else
+ break;
+
+ /* Si la longueur est 2 => Conversion en Orange 99 */
+ if(length == 2)
+ {
+ byte_picture->data[x+y*byte_picture->width+0] = 0x99;
+ byte_picture->data[x+y*byte_picture->width+1] = 0x99;
+ x += (2-1); /* -1 car x++ */
+ }
+ else
+ x += (length-1); /* -1 car x++ */
+ }
+
+ /** Statistiques sur l'image ROBYP **/
+ nb_cc = 0; /* Red */
+ nb_99 = 0; /* Orange */
+ nb_bb = 0; /* Blue */
+ nb_aa = 0; /* Yellow */
+ nb_dd = 0; /* Purple */
+ nb_ff = 0; /* Background */
+ total = byte_picture->width*byte_picture->height;
+ for(i=0; idata[i] == 0xFF)
+ nb_ff++;
+ else if(byte_picture->data[i] == 0x99)
+ nb_99++;
+ else if(byte_picture->data[i] == 0xCC)
+ nb_cc++;
+ else if(byte_picture->data[i] == 0xBB)
+ nb_bb++;
+ else if(byte_picture->data[i] == 0xAA)
+ nb_aa++;
+ else if(byte_picture->data[i] == 0xDD)
+ nb_dd++;
+ if(verbose)
+ printf(" - Sprite BYTE ropyb : %dx%d Total=%d, Red=%d (%d%%), Orange=%d (%d%%), Purple=%d (%d%%), Yellow=%d (%d%%), Blue=%d (%d%%), Background=%d (%d%%).\n",
+ byte_picture->width,byte_picture->height,total,nb_cc,(nb_cc*100)/total,nb_99,(nb_99*100)/total,nb_dd,(nb_dd*100)/total,nb_aa,(nb_aa*100)/total,nb_bb,(nb_bb*100)/total,nb_ff,(nb_ff*100)/total);
+
+ /* Affiche les statistiques Pattern */
+ my_Memory(MEMORY_GET_PATTERN_NB,&nb_pattern,NULL);
+ if(verbose)
+ printf(" - Nb Pattern : %d\n",nb_pattern);
+ for(i=1; i<=nb_pattern; i++)
+ {
+ my_Memory(MEMORY_GET_PATTERN,&i,¤t_pattern);
+ if(i < 5)
+ if(verbose)
+ printf(" - Pattern[%d] : %04X (%d)\n",i-1,current_pattern->pattern_data,current_pattern->nb_found/2);
+ }
+
+ /** Création de l'image BYTE Red / Orange / Blue / Yellow / Purple **/
+ if(verbose)
+ {
+ strcpy(file_path,sprite_path);
+ strcpy(&file_path[strlen(file_path)-4],"_B_ropyb.gif");
+ result = GIFWriteFileFrom256Color(file_path,byte_picture);
+ if(result)
+ printf(" - Error : Can't create Sprite BYTE ropyb file '%s'.\n",file_path);
+ }
+
+ /* Renvoie la structure BYTE */
+ return(byte_picture);
+}
+
+
+/**********************************************************/
+/* Compute8BitColors() : Compte les couleurs de l'image. */
+/**********************************************************/
+int Compute8BitColors(int nb_byte, int height, int width, unsigned char *windows_bitmap_data, int *palette_ind)
+{
+ unsigned char red, green, blue;
+ int i, j, first, last, x, color_ind, window_height, window_width, nb_real_color, offset;
+
+ /* Init */
+ memset(palette_ind,0,257*sizeof(int));
+ window_height = height;
+ window_width = width;
+ nb_real_color = 0;
+
+ /** Passe tous les points en revue **/
+ for(j=0; j=first;)
+ {
+ x = (first+last)/2;
+ if(color_ind < palette_ind[x])
+ last = x - 1;
+ else
+ first = x + 1;
+
+ if(color_ind == palette_ind[x])
+ break;
+ }
+
+ /* A t'on trouvé la couleur ou doit on l'ajouter */
+ if(color_ind != palette_ind[x])
+ {
+ /* Décalage du tableau */
+ if(x < nb_real_color)
+ if(palette_ind[x] < color_ind)
+ x++;
+ memmove(&palette_ind[x+1],&palette_ind[x],(nb_real_color-x)*sizeof(int));
+ palette_ind[x] = color_ind;
+ nb_real_color++;
+ }
+ }
+ }
+
+ /* Renvoi le nombre de couleurs */
+ return(nb_real_color);
+}
+
+
+/****************************************************************************/
+/* ConvertTrueColorTo256() : Conversion du true color en 256 couleurs GIF. */
+/****************************************************************************/
+struct picture_256 *ConvertTrueColorTo256(struct picture_true *current_picture_true)
+{
+ int i,j;
+ int offset, nb_real_color;
+ int first, last, x, color_ind;
+ int palette_ind[256];
+ unsigned char red, green, blue;
+ struct picture_256 *current_picture_256;
+
+ /* Allocation mémoire */
+ current_picture_256 = (struct picture_256 *) calloc(1,sizeof(struct picture_256));
+ if(current_picture_256 == NULL)
+ return(NULL);
+ current_picture_256->width = current_picture_true->width;
+ current_picture_256->height = current_picture_true->height;
+
+ /* Init Palette */
+ memset(¤t_picture_256->palette_red[0],0,256*sizeof(int));
+ memset(¤t_picture_256->palette_green[0],0,256*sizeof(int));
+ memset(¤t_picture_256->palette_blue[0],0,256*sizeof(int));
+
+ /** Création de la palette **/
+ nb_real_color = 0;
+ for(j=0; jheight; j++)
+ for(i=0; iwidth; i++)
+ {
+ /* Couleur du point */
+ offset = (i+j*current_picture_true->width)*3;
+ red = current_picture_true->data[offset];
+ green = current_picture_true->data[offset+1];
+ blue = current_picture_true->data[offset+2];
+ color_ind = 65536*red + 256*green + blue;
+
+ /** On insert/recherche la couleur (dichotomie) **/
+ if(i == 0 && j == 0)
+ {
+ palette_ind[0] = color_ind;
+ nb_real_color = 1;
+ }
+ else
+ {
+ for(first=0,last=nb_real_color; last>=first;)
+ {
+ x = (first+last)/2;
+ if(color_ind < palette_ind[x])
+ last = x - 1;
+ else
+ first = x + 1;
+
+ if(color_ind == palette_ind[x])
+ break;
+ }
+
+ /* A t'on trouvé la couleur ou doit on l'ajouter */
+ if(color_ind != palette_ind[x])
+ {
+ /* Gestion des images > 256 couleurs */
+ if(nb_real_color == 256)
+ return(NULL);
+
+ /* Décalage du tableau */
+ if(x < nb_real_color)
+ if(palette_ind[x] < color_ind)
+ x++;
+ memmove(&palette_ind[x+1],&palette_ind[x],(nb_real_color-x)*sizeof(int));
+ palette_ind[x] = color_ind;
+ nb_real_color++;
+ }
+ }
+ }
+ /* Palette séparée RGB */
+ for(i=0; ipalette_red[i] = (palette_ind[i]&0x00FF0000)>>16;
+ current_picture_256->palette_green[i] = (palette_ind[i]&0x0000FF00)>>8;
+ current_picture_256->palette_blue[i] = (palette_ind[i]&0x000000FF);
+ }
+ current_picture_256->nb_color = nb_real_color;
+
+ /* Allocation mémoire de l'image en 256 couleurs */
+ current_picture_256->data = (unsigned char *) calloc(1,current_picture_true->height*current_picture_true->width);
+ if(current_picture_256->data == NULL)
+ return(NULL);
+
+ /** Points **/
+ for(j=0; jheight; j++)
+ for(i=0; iwidth; i++)
+ {
+ offset = (i+j*current_picture_true->width)*3;
+ red = current_picture_true->data[offset];
+ green = current_picture_true->data[offset+1];
+ blue = current_picture_true->data[offset+2];
+ color_ind = 65536*red + 256*green + blue;
+
+ /** Recherche dichotomique de la valeur **/
+ for(first=0,last=nb_real_color; last>=first;)
+ {
+ x = (first+last)/2;
+ if(color_ind < palette_ind[x])
+ last = x - 1;
+ else
+ first = x + 1;
+
+ if(color_ind == palette_ind[x])
+ break;
+ }
+
+ /* Création du point */
+ current_picture_256->data[i+j*current_picture_true->width] = (unsigned char) x;
+ }
+
+ /** Renvoi l'image 256 **/
+ return(current_picture_256);
+}
+
+
+/****************************************************************/
+/* PlotTrueColor() : Place un point sur une image True Color. */
+/****************************************************************/
+void PlotTrueColor(int x, int y, unsigned char red, unsigned char green, unsigned char blue, struct picture_true *current_picture)
+{
+ current_picture->data[(y*current_picture->width+x)*3+0] = red;
+ current_picture->data[(y*current_picture->width+x)*3+1] = green;
+ current_picture->data[(y*current_picture->width+x)*3+2] = blue;
+}
+
+/*
+ 000 0 0000 0000 0 0 00000 000 00000 000 000
+0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 000 00 0000 0000 0000 0 000 0000
+0 0 0 0 0 0 0 0 0 0 0 0 0
+ 000 0 00000 0000 0 0000 000 0 000 000
+*/
+
+/***************************************************************/
+/* PlotNumber() : Place un chiffre sur une image True Color. */
+/***************************************************************/
+int PlotNumber(int number, int x, int y, unsigned char red, unsigned char green, unsigned char blue, struct picture_true *current_picture)
+{
+ /* Vérification */
+ if(number > 9)
+ return(0);
+
+ /* 0 */
+ if(number == 0)
+ {
+ PlotTrueColor(x+1,y,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y,red,green,blue,current_picture);
+ PlotTrueColor(x,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+4,red,green,blue,current_picture);
+ return(5);
+ }
+ else if(number == 1)
+ {
+ PlotTrueColor(x,y,red,green,blue,current_picture);
+ PlotTrueColor(x,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x,y+4,red,green,blue,current_picture);
+ return(1);
+ }
+ else if(number == 2)
+ {
+ PlotTrueColor(x,y,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+4,red,green,blue,current_picture);
+ return(5);
+ }
+ else if(number == 3)
+ {
+ PlotTrueColor(x,y,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+4,red,green,blue,current_picture);
+ return(5);
+ }
+ else if(number == 4)
+ {
+ PlotTrueColor(x,y,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y,red,green,blue,current_picture);
+ PlotTrueColor(x,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+4,red,green,blue,current_picture);
+ return(5);
+ }
+ else if(number == 5)
+ {
+ PlotTrueColor(x,y,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y,red,green,blue,current_picture);
+ PlotTrueColor(x,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+4,red,green,blue,current_picture);
+ return(5);
+ }
+ else if(number == 6)
+ {
+ PlotTrueColor(x+1,y,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y,red,green,blue,current_picture);
+ PlotTrueColor(x,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+4,red,green,blue,current_picture);
+ return(5);
+ }
+ else if(number == 7)
+ {
+ PlotTrueColor(x,y,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+4,red,green,blue,current_picture);
+ return(5);
+ }
+ else if(number == 8)
+ {
+ PlotTrueColor(x+1,y,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y,red,green,blue,current_picture);
+ PlotTrueColor(x,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+4,red,green,blue,current_picture);
+ return(5);
+ }
+ else if(number == 9)
+ {
+ PlotTrueColor(x+1,y,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y,red,green,blue,current_picture);
+ PlotTrueColor(x,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+1,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+2,red,green,blue,current_picture);
+ PlotTrueColor(x+4,y+3,red,green,blue,current_picture);
+ PlotTrueColor(x+1,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+2,y+4,red,green,blue,current_picture);
+ PlotTrueColor(x+3,y+4,red,green,blue,current_picture);
+ return(5);
+ }
+
+ /* Never here */
+ return(0);
+}
+
+
+/******************************************************************************/
+/* mem_free_picture_256() : Libération mémoire de la structure picture_256. */
+/******************************************************************************/
+void mem_free_picture_256(struct picture_256 *current_picture)
+{
+ if(current_picture == NULL)
+ return;
+
+ if(current_picture->data)
+ free(current_picture->data);
+
+ if(current_picture->tab_nb_color)
+ free(current_picture->tab_nb_color);
+
+ if(current_picture->tab_color_line)
+ free(current_picture->tab_color_line);
+
+ free(current_picture);
+}
+
+/********************************************************************************/
+/* mem_free_picture_true() : Libération mémoire de la structure picture_true. */
+/********************************************************************************/
+void mem_free_picture_true(struct picture_true *current_picture)
+{
+ if(current_picture == NULL)
+ return;
+
+ if(current_picture->data)
+ free(current_picture->data);
+
+ free(current_picture);
+}
+
+/**************************************************************************/
diff --git a/bin/mrsprite/source/Dc_Graphic.h b/bin/mrsprite/source/Dc_Graphic.h
new file mode 100644
index 0000000..fcafa88
--- /dev/null
+++ b/bin/mrsprite/source/Dc_Graphic.h
@@ -0,0 +1,56 @@
+/********************************************************************
+ * *
+ * Dc_Graphic.h : Header de gestion des fichiers Graphiques. *
+ * *
+ ********************************************************************
+ * Auteur : Olivier ZARDINI * Brutal Deluxe * Date : Nov 2012 *
+ ********************************************************************/
+
+#define TOO_MANY_COLOR 1
+#define ERR_GRAPHIC_FOPEN 2
+#define ERR_ALLOC 3
+#define ERR_GRAPHIC_BADFORMAT 4
+#define ERR_GRAPHIC_WRITEFILE 5
+
+struct picture_256
+{
+ int width;
+ int height;
+
+ int nb_color;
+ int palette_red[256];
+ int palette_green[256];
+ int palette_blue[256];
+
+ unsigned char *data;
+
+ /* Stat */
+ int *tab_nb_color; /* Nombre de couleur sur la ligne */
+ int *tab_color_line; /* Nombre de points utilisant chaque couleur */
+};
+
+struct picture_true
+{
+ int width;
+ int height;
+
+ unsigned char *data;
+};
+
+DWORD DecodeRGBColor(char *);
+int ExtractAllSprite(char *,DWORD,DWORD);
+int CreateMirrorPicture(char *,DWORD);
+int CreateFlipPicture(char *,DWORD);
+int CreateOddPicture(char *,DWORD);
+int RemoveDuplicatedPictures(int,char **);
+int CreateWallPaper(int,char **,DWORD,DWORD);
+int CreateSpriteCode(char *,DWORD,int,DWORD *,int);
+int Compute8BitColors(int,int,int,unsigned char *,int *);
+struct picture_256 *ConvertTrueColorTo256(struct picture_true *);
+void PlotTrueColor(int,int,unsigned char,unsigned char,unsigned char,struct picture_true *);
+int PlotNumber(int,int,int,unsigned char,unsigned char,unsigned char,struct picture_true *);
+struct picture_256 *CreateEmptyPicture(int,int,int,int *,int *,int *,unsigned char);
+void mem_free_picture_256(struct picture_256 *);
+void mem_free_picture_true(struct picture_true *);
+
+/********************************************************************/
diff --git a/bin/mrsprite/source/Dc_Memory.c b/bin/mrsprite/source/Dc_Memory.c
new file mode 100644
index 0000000..85168b7
--- /dev/null
+++ b/bin/mrsprite/source/Dc_Memory.c
@@ -0,0 +1,510 @@
+/*****************************************************************
+ * *
+ * Dc_Memory.c : Module de gestion des ressources memoires. *
+ * *
+ *****************************************************************
+ * Auteur : Olivier ZARDINI * CooperTeam * Date : Jan 2013 *
+ *****************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+
+#include "Dc_Code.h"
+#include "Dc_Shared.h"
+#include "Dc_Memory.h"
+
+int compare_pattern(const void *,const void *);
+
+/******************************************************/
+/* my_Memory() : Fonction de gestion de la mémoire. */
+/******************************************************/
+void my_Memory(int code, void *data, void *value)
+{
+ int i, index;
+ WORD pattern_data;
+ static int nb_pattern; /* Pattern */
+ static struct pattern *first_pattern;
+ static struct pattern *last_pattern;
+ struct pattern *current_pattern;
+ struct pattern *next_pattern;
+ struct pattern **tab_pattern;
+ static int nb_redpattern; /* Red Pattern */
+ static struct pattern *first_redpattern;
+ static struct pattern *last_redpattern;
+ struct pattern *current_redpattern;
+ struct pattern *next_redpattern;
+ struct pattern **tab_redpattern;
+ static int nb_codeline; /* Ligne de Code */
+ static struct code_line *first_codeline;
+ static struct code_line *last_codeline;
+ struct code_line *current_codeline;
+ struct code_line *next_codeline;
+ static char buffer_comment[512]; /* Commentaire */
+ static int nb_codefile; /* Fichier de Code */
+ static struct code_file *first_codefile;
+ static struct code_file *last_codefile;
+ struct code_file *current_codefile;
+ struct code_file *next_codefile;
+ struct code_file **tab_codefile;
+
+ switch(code)
+ {
+ case MEMORY_INIT :
+ nb_pattern = 0;
+ first_pattern = NULL;
+ last_pattern = NULL;
+ nb_redpattern = 0;
+ first_redpattern = NULL;
+ last_redpattern = NULL;
+ nb_codeline = 0;
+ first_codeline = NULL;
+ last_codeline = NULL;
+ strcpy(buffer_comment,"");
+ nb_codefile = 0;
+ first_codefile = NULL;
+ last_codefile = NULL;
+ break;
+
+ case MEMORY_FREE :
+ my_Memory(MEMORY_FREE_PATTERN,NULL,NULL);
+ my_Memory(MEMORY_FREE_REDPATTERN,NULL,NULL);
+ my_Memory(MEMORY_FREE_CODELINE,NULL,NULL);
+ my_Memory(MEMORY_FREE_CODEFILE,NULL,NULL);
+ break;
+
+ /*************************/
+ /* Gestion des Pattern */
+ /*************************/
+ case MEMORY_ADD_PATTERN :
+ pattern_data = *((WORD *) data);
+
+ /* A t'on déjà cette pattern */
+ for(current_pattern=first_pattern; current_pattern; current_pattern=current_pattern->next)
+ if(current_pattern->pattern_data == pattern_data)
+ {
+ current_pattern->nb_found++;
+ return;
+ }
+
+ /* Création d'une nouvelle */
+ current_pattern = (struct pattern *) calloc(1,sizeof(struct pattern));
+ if(current_pattern == NULL)
+ return;
+ current_pattern->pattern_data = pattern_data;
+ current_pattern->nb_found = 1;
+
+ /* Attachement à la liste */
+ if(first_pattern == NULL)
+ first_pattern = current_pattern;
+ else
+ last_pattern->next = current_pattern;
+ last_pattern = current_pattern;
+ nb_pattern++;
+ break;
+
+ case MEMORY_GET_PATTERN_NB :
+ *((int *) data) = nb_pattern;
+ break;
+
+ case MEMORY_GET_PATTERN :
+ index = *((int *)data);
+ *((struct pattern **) value) = NULL;
+ if(index <= 0 || index > nb_pattern)
+ break;
+
+ for(i=1,current_pattern=first_pattern; i<=nb_pattern; i++,current_pattern=current_pattern->next)
+ if(i == index)
+ {
+ *((struct pattern **) value) = current_pattern;
+ break;
+ }
+ break;
+
+ case MEMORY_GET_PATTERN_SCORE :
+ pattern_data = *((WORD *) data);
+ for(i=0,current_pattern=first_pattern; current_pattern; current_pattern=current_pattern->next,i++)
+ {
+ if(i > 2) /* On ne prend en compte que les 3 premiers Pattern stockées dans les registres 16 bits X, Y et D */
+ break;
+ else if(current_pattern->pattern_data == pattern_data)
+ {
+ *((int *) value) = current_pattern->nb_found;
+ return;
+ }
+ }
+
+ /* Pas trouvé */
+ *((int *) value) = 0;
+ break;
+
+ case MEMORY_SORT_PATTERN :
+ if(nb_pattern == 0 || nb_pattern == 1)
+ break;
+
+ /* Allocation */
+ tab_pattern = (struct pattern **) calloc(nb_pattern,sizeof(struct pattern *));
+ if(tab_pattern == NULL)
+ return;
+
+ /* Remplissage */
+ for(i=0, current_pattern = first_pattern; current_pattern; current_pattern = current_pattern->next,i++)
+ tab_pattern[i] = current_pattern;
+
+ /* Tri */
+ qsort(tab_pattern,nb_pattern,sizeof(struct pattern *),compare_pattern);
+
+ /* Recablage */
+ first_pattern = tab_pattern[0];
+ last_pattern = tab_pattern[nb_pattern-1];
+ last_pattern->next = NULL;
+ for(i=0; inext = tab_pattern[i+1];
+
+ /* Libération */
+ free(tab_pattern);
+ break;
+
+ case MEMORY_FREE_PATTERN :
+ for(current_pattern=first_pattern; current_pattern; )
+ {
+ next_pattern = current_pattern->next;
+ free(current_pattern);
+ current_pattern = next_pattern;
+ }
+ nb_pattern = 0;
+ first_pattern = NULL;
+ last_pattern = NULL;
+ break;
+
+
+ /*****************************/
+ /* Gestion des Red Pattern */
+ /*****************************/
+ case MEMORY_ADD_REDPATTERN :
+ pattern_data = *((WORD *) data);
+
+ /* A t'on déjà cette pattern */
+ for(current_redpattern=first_redpattern; current_redpattern; current_redpattern=current_redpattern->next)
+ if(current_redpattern->pattern_data == pattern_data)
+ {
+ current_redpattern->nb_found++;
+ return;
+ }
+
+ /* Création d'une nouvelle */
+ current_redpattern = (struct pattern *) calloc(1,sizeof(struct pattern));
+ if(current_redpattern == NULL)
+ return;
+ current_redpattern->pattern_data = pattern_data;
+ current_redpattern->nb_found = 1;
+
+ /* Attachement à la liste */
+ if(first_redpattern == NULL)
+ first_redpattern = current_redpattern;
+ else
+ last_redpattern->next = current_redpattern;
+ last_redpattern = current_redpattern;
+ nb_redpattern++;
+ break;
+
+ case MEMORY_GET_REDPATTERN :
+ index = *((int *) data);
+ *((struct pattern **) value) = NULL;
+ if(index <= 0 || index > nb_redpattern)
+ break;
+
+ for(i=1,current_redpattern=first_redpattern; i<=nb_redpattern; i++,current_redpattern=current_redpattern->next)
+ if(i == index)
+ {
+ *((struct pattern **) value) = current_redpattern;
+ break;
+ }
+ break;
+
+ case MEMORY_SORT_REDPATTERN :
+ if(nb_redpattern == 0 || nb_redpattern == 1)
+ break;
+
+ /* Allocation */
+ tab_redpattern = (struct pattern **) calloc(nb_redpattern,sizeof(struct pattern *));
+ if(tab_redpattern == NULL)
+ return;
+
+ /* Remplissage */
+ for(i=0, current_redpattern = first_redpattern; current_redpattern; current_redpattern = current_redpattern->next,i++)
+ tab_redpattern[i] = current_redpattern;
+
+ /* Tri */
+ qsort(tab_redpattern,nb_redpattern,sizeof(struct pattern *),compare_pattern);
+
+ /* Recablage */
+ first_redpattern = tab_redpattern[0];
+ last_redpattern = tab_redpattern[nb_redpattern-1];
+ last_redpattern->next = NULL;
+ for(i=0; inext = tab_redpattern[i+1];
+
+ /* Libération */
+ free(tab_redpattern);
+ break;
+
+ case MEMORY_FREE_REDPATTERN :
+ for(current_redpattern=first_redpattern; current_redpattern; )
+ {
+ next_redpattern = current_redpattern->next;
+ free(current_redpattern);
+ current_redpattern = next_redpattern;
+ }
+ nb_redpattern = 0;
+ first_redpattern = NULL;
+ last_redpattern = NULL;
+ break;
+
+
+ /********************************/
+ /* Gestion des Lignes de Code */
+ /********************************/
+ case MEMORY_ADD_CODELINE :
+ current_codeline = (struct code_line *) data;
+
+ /* Attachement à la liste */
+ if(first_codeline == NULL)
+ first_codeline = current_codeline;
+ else
+ last_codeline->next = current_codeline;
+ last_codeline = current_codeline;
+ nb_codeline++;
+
+ /* Met le commentaire */
+ if(strlen(buffer_comment) > 0 && strlen(current_codeline->comment) == 0)
+ strcpy(current_codeline->comment,buffer_comment);
+
+ /* Vide le commentaire */
+ strcpy(buffer_comment,"");
+ break;
+
+ case MEMORY_GET_CODELINE_NB :
+ *((int *) data) = nb_codeline;
+ break;
+
+ case MEMORY_GET_CODELINE :
+ index = *((int *) data);
+ *((struct code_line **) value) = NULL;
+ if(index <= 0 || index > nb_codeline)
+ break;
+
+ for(i=1,current_codeline=first_codeline; i<=nb_codeline; i++,current_codeline=current_codeline->next)
+ if(i == index)
+ {
+ *((struct code_line **) value) = current_codeline;
+ break;
+ }
+ break;
+
+ case MEMORY_DROP_CODELINE :
+ /** Supprime la dernière ligne ajoutée **/
+ if(last_codeline == NULL)
+ return;
+ if(nb_codeline == 1)
+ {
+ free(first_codeline);
+ nb_codeline = 0;
+ first_codeline = NULL;
+ last_codeline = NULL;
+ }
+ else
+ {
+ /* Cas général */
+ for(current_codeline=first_codeline; current_codeline; current_codeline=current_codeline->next)
+ if(current_codeline->next == last_codeline)
+ break;
+ free(last_codeline);
+ nb_codeline--;
+ last_codeline = current_codeline;
+ current_codeline->next = NULL;
+ }
+ break;
+
+ case MEMORY_FREE_CODELINE :
+ for(current_codeline=first_codeline; current_codeline; )
+ {
+ next_codeline = current_codeline->next;
+ free(current_codeline);
+ current_codeline = next_codeline;
+ }
+ nb_codeline = 0;
+ first_codeline = NULL;
+ last_codeline = NULL;
+ break;
+
+ /*******************************************************/
+ /* Commentaire à ajouter à la ligne de code suivante */
+ /*******************************************************/
+ case MEMORY_ADD_COMMENT :
+ strcpy(buffer_comment,(char *)data);
+ break;
+
+ /*******************************/
+ /* Liste des fichiers Source */
+ /*******************************/
+ case MEMORY_ADD_CODEFILE :
+ current_codefile = (struct code_file *) data;
+
+ /* Attachement à la liste */
+ if(first_codefile == NULL)
+ first_codefile = current_codefile;
+ else
+ last_codefile->next = current_codefile;
+ last_codefile = current_codefile;
+ nb_codefile++;
+ break;
+
+ case MEMORY_GET_CODEFILE_NB :
+ *((int *) data) = nb_codefile;
+ break;
+
+ case MEMORY_GET_CODEFILE :
+ index = *((int *) data);
+ *((struct code_file **) value) = NULL;
+ if(index <= 0 || index > nb_codefile)
+ break;
+
+ for(i=1,current_codefile=first_codefile; i<=nb_codefile; i++,current_codefile=current_codefile->next)
+ if(i == index)
+ {
+ *((struct code_file **) value) = current_codefile;
+ break;
+ }
+ break;
+
+ case MEMORY_SORT_CODEFILE :
+ if(nb_codefile == 0 || nb_codefile == 1)
+ break;
+
+ /* Allocation */
+ tab_codefile = (struct code_file **) calloc(nb_codefile,sizeof(struct code_file *));
+ if(tab_codefile == NULL)
+ return;
+
+ /* Remplissage */
+ for(i=0, current_codefile = first_codefile; current_codefile; current_codefile = current_codefile->next,i++)
+ tab_codefile[i] = current_codefile;
+
+ /* Tri */
+ qsort(tab_codefile,nb_codefile,sizeof(struct code_file *),(int (*)(const void *,const void *))data);
+
+ /* Recablage */
+ first_codefile = tab_codefile[0];
+ last_codefile = tab_codefile[nb_codefile-1];
+ last_codefile->next = NULL;
+ for(i=0; inext = tab_codefile[i+1];
+
+ /* Libération */
+ free(tab_codefile);
+ break;
+
+ case MEMORY_FREE_CODEFILE :
+ for(current_codefile=first_codefile; current_codefile; )
+ {
+ next_codefile = current_codefile->next;
+ free(current_codefile);
+ current_codefile = next_codefile;
+ }
+ nb_codefile = 0;
+ first_codefile = NULL;
+ last_codefile = NULL;
+ break;
+
+ default :
+ break;
+ }
+}
+
+
+/**************************************************************/
+/* compare_pattern() : Fonction de comparaison des pattern. */
+/**************************************************************/
+int compare_pattern(const void *data_1, const void *data_2)
+{
+ struct pattern *pattern_1;
+ struct pattern *pattern_2;
+
+ /* Récupère les structures */
+ pattern_1 = *((struct pattern **) data_1);
+ pattern_2 = *((struct pattern **) data_2);
+
+ /* Comparaison du nb */
+ if(pattern_1->nb_found < pattern_2->nb_found)
+ return(1);
+ else if(pattern_1->nb_found == pattern_2->nb_found)
+ return(0);
+ else
+ return(-1);
+}
+
+
+/**********************************************************************/
+/* compare_codefile_size() : Fonction de comparaison des code_file. */
+/**********************************************************************/
+int compare_codefile_size(const void *data_1, const void *data_2)
+{
+ struct code_file *codefile_1;
+ struct code_file *codefile_2;
+
+ /* Récupère les structures */
+ codefile_1 = *((struct code_file **) data_1);
+ codefile_2 = *((struct code_file **) data_2);
+
+ /* Comparaison de la taille de l'objet */
+ if(codefile_1->size < codefile_2->size)
+ return(1);
+ else if(codefile_1->size == codefile_2->size)
+ return(0);
+ else
+ return(-1);
+}
+
+
+/*********************************************************************/
+/* compare_codefile_num() : Fonction de comparaison des code_file. */
+/*********************************************************************/
+int compare_codefile_num(const void *data_1, const void *data_2)
+{
+ struct code_file *codefile_1;
+ struct code_file *codefile_2;
+
+ /* Récupère les structures */
+ codefile_1 = *((struct code_file **) data_1);
+ codefile_2 = *((struct code_file **) data_2);
+
+ /* Comparaison du numéro de l'objet */
+ if(codefile_1->index > codefile_2->index)
+ return(1);
+ else if(codefile_1->index == codefile_2->index)
+ return(0);
+ else
+ return(-1);
+}
+
+
+/***************************************************************/
+/* compare_filepath() : Fonction de comparaison des chemins. */
+/***************************************************************/
+int compare_filepath(const void *data_1, const void *data_2)
+{
+ char *filepath_1;
+ char *filepath_2;
+
+ /* Récupère les structures */
+ filepath_1 = *((char **) data_1);
+ filepath_2 = *((char **) data_2);
+
+ /* Comparaison des noms */
+ return(my_stricmp(filepath_1,filepath_2));
+}
+
+/*****************************************************************/
diff --git a/bin/mrsprite/source/Dc_Memory.h b/bin/mrsprite/source/Dc_Memory.h
new file mode 100644
index 0000000..e47f640
--- /dev/null
+++ b/bin/mrsprite/source/Dc_Memory.h
@@ -0,0 +1,51 @@
+/*****************************************************************
+ * *
+ * Dc_Memory.h : Header de gestion des ressources memoires. *
+ * *
+ *****************************************************************
+ * Auteur : Olivier ZARDINI * CooperTeam * Date : Jan 2013 *
+ *****************************************************************/
+
+#define MEMORY_INIT 1
+#define MEMORY_FREE 2
+
+#define MEMORY_ADD_PATTERN 10
+#define MEMORY_GET_PATTERN_NB 11
+#define MEMORY_GET_PATTERN 12
+#define MEMORY_GET_PATTERN_SCORE 13
+#define MEMORY_SORT_PATTERN 14
+#define MEMORY_FREE_PATTERN 15
+
+#define MEMORY_ADD_CODELINE 20
+#define MEMORY_GET_CODELINE_NB 21
+#define MEMORY_GET_CODELINE 22
+#define MEMORY_DROP_CODELINE 23
+#define MEMORY_FREE_CODELINE 25
+
+#define MEMORY_ADD_REDPATTERN 30
+#define MEMORY_GET_REDPATTERN 32
+#define MEMORY_SORT_REDPATTERN 34
+#define MEMORY_FREE_REDPATTERN 35
+
+#define MEMORY_ADD_COMMENT 40
+
+#define MEMORY_ADD_CODEFILE 50
+#define MEMORY_GET_CODEFILE_NB 51
+#define MEMORY_GET_CODEFILE 52
+#define MEMORY_SORT_CODEFILE 53
+#define MEMORY_FREE_CODEFILE 54
+
+struct pattern
+{
+ WORD pattern_data;
+ int nb_found;
+
+ struct pattern *next;
+};
+
+void my_Memory(int,void *,void *);
+int compare_filepath(const void *,const void *);
+int compare_codefile_size(const void *,const void *);
+int compare_codefile_num(const void *,const void *);
+
+/*****************************************************************/
diff --git a/bin/mrsprite/source/Dc_Shared.c b/bin/mrsprite/source/Dc_Shared.c
new file mode 100644
index 0000000..828fe53
--- /dev/null
+++ b/bin/mrsprite/source/Dc_Shared.c
@@ -0,0 +1,705 @@
+/**********************************************************************
+ * *
+ * Dc_Shared.c : Module de la bibliothèque de fonctions génériques. *
+ * *
+ **********************************************************************
+ * Auteur : Olivier ZARDINI * Brutal Deluxe * Date : Jan 2013 *
+ **********************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifndef WIN32
+//#include
+#endif
+#include
+#include
+
+#include "Dc_Shared.h"
+
+struct one_file
+{
+ char *file_path;
+
+ struct one_file *next;
+};
+
+struct one_file *LoadListFiles(char *);
+void mem_free_onefile_list(struct one_file *);
+int compare_file(const void *,const void *);
+char *my_strstr(char *,char *);
+int myq_stricmp(char *,char *);
+int myq_strnicmp(char *,char *,int);
+
+/********************************************************************/
+/* BuildFileTab() : Construit un tableau de la liste de fichiers. */
+/********************************************************************/
+char **BuildFileTab(char *file_path, int *nb_file_rtn)
+{
+ int i, nb_file;
+ char **tab_file;
+ struct one_file *first_file = NULL;
+ struct one_file *current_file;
+
+ /** Cas particulier : un seul fichier **/
+ if(strchr(file_path,'*') == NULL)
+ {
+ nb_file = 1;
+ tab_file = (char **) calloc(1,sizeof(char *));
+ if(tab_file == NULL)
+ return(NULL);
+ tab_file[0] = _strdup(file_path);
+ if(tab_file[0] == NULL)
+ {
+ free(tab_file);
+ return(NULL);
+ }
+ *nb_file_rtn = nb_file;
+ return(tab_file);
+ }
+
+ /*** Il faut récupérer la liste des fichiers ***/
+ /* Charge tous les fichier en mémoire */
+ first_file = LoadListFiles(file_path);
+ if(first_file == NULL)
+ return(NULL);
+
+ /* Compte le nombre de fichiers */
+ for(nb_file=0,current_file = first_file; current_file; current_file = current_file->next)
+ nb_file++;
+
+ /* Création du tableau d'accès rapide */
+ tab_file = (char **) calloc(nb_file,sizeof(char *));
+ if(tab_file == NULL)
+ return(NULL);
+ for(i=0,current_file = first_file; current_file; current_file = current_file->next,i++)
+ {
+ tab_file[i] = current_file->file_path;
+ current_file->file_path = NULL;
+ }
+
+ /* Libération de la liste */
+ mem_free_onefile_list(first_file);
+
+ /* Tri les fichiers par ordre alphabétique */
+ qsort(tab_file,nb_file,sizeof(char *),compare_file);
+
+ /* Renvoie le tableau */
+ *nb_file_rtn = nb_file;
+ return(tab_file);
+}
+
+
+/*********************************************************************/
+/* LoadListFiles() : Charge tous les fichiers binaires en mémoire. */
+/*********************************************************************/
+struct one_file *LoadListFiles(char *source_file_path)
+{
+#if defined(WIN32) || defined(WIN64)
+ int i, rc;
+ long hFile;
+ int first_time = 1;
+ struct _finddata_t c_file;
+ char folder_path[1024];
+ char buffer_file_path[1024];
+ struct one_file *first_file = NULL;
+ struct one_file *last_file = NULL;
+ struct one_file *new_file;
+
+ /* Extrait le nom du répertoire */
+ strcpy(folder_path,source_file_path);
+ for(i=strlen(folder_path); i>=0; i--)
+ if(folder_path[i] == FOLDER_SEPARATOR_CHAR) /* \ or / */
+ {
+ folder_path[i+1] = '\0';
+ break;
+ }
+
+ /** On boucle sur tous les fichiers présents **/
+ while(1)
+ {
+ if(first_time == 1)
+ {
+ hFile = _findfirst(source_file_path,&c_file);
+ rc = (int) hFile;
+ }
+ else
+ rc = _findnext(hFile,&c_file);
+
+ /* On analyse le résultat */
+ if(rc == -1)
+ break; /* no more files */
+ first_time++;
+
+ /* On ne traite pas les dossiers **/
+ if((c_file.attrib & _A_SUBDIR) == _A_SUBDIR)
+ continue;
+
+ /** On traite cette entrée **/
+ /* Chemin du fichier */
+ sprintf(buffer_file_path,"%s%s",folder_path,c_file.name);
+
+ /** Conserve le chemin du fichier **/
+ new_file = (struct one_file *) calloc(1,sizeof(struct one_file));
+ if(new_file == NULL)
+ {
+ mem_free_onefile_list(first_file);
+ _findclose(hFile);
+ return(NULL);
+ }
+ new_file->file_path = _strdup(buffer_file_path);
+ if(new_file->file_path == NULL)
+ {
+ free(new_file);
+ mem_free_onefile_list(first_file);
+ _findclose(hFile);
+ return(NULL);
+ }
+
+ /* Rattache à la liste chainée */
+ if(first_file == NULL)
+ first_file = new_file;
+ else
+ last_file->next = new_file;
+ last_file = new_file;
+ }
+
+ /* On ferme */
+ _findclose(hFile);
+
+ return(first_file);
+#else
+ DIR *dir;
+ struct dirent *d;
+ struct stat st;
+ char folder_path[1024];
+ char buffer_file_path[1024];
+ struct one_file *first_file = NULL;
+ struct one_file *last_file = NULL;
+ struct one_file *new_file;
+
+ /* Extrait le nom du répertoire */
+ strcpy(folder_path,source_file_path);
+ for(int i=strlen(folder_path); i>=0; i--)
+ if(folder_path[i] == FOLDER_SEPARATOR_CHAR) /* \ or / */
+ {
+ folder_path[i+1] = '\0';
+ break;
+ }
+
+ /* Ouverture du répertoire */
+ dir = opendir(folder_path);
+ if(dir == NULL)
+ return(NULL);
+
+ /* Passe toutes les entrées en revue */
+ while((d = readdir(dir)))
+ {
+ /* On ignore . et .. */
+ if(!strcmp(d->d_name,".") || !strcmp(d->d_name,".."))
+ continue;
+
+ /* Nom complet */
+ sprintf(buffer_file_path,"%s%c%s",folder_path,FOLDER_SEPARATOR_CHAR,d->d_name);
+
+ /* On ignore les dossier */
+ stat(buffer_file_path,&st);
+ if(S_ISDIR(st.st_mode))
+ continue;
+
+ /* Le fichier fait t'il partie de la sélection */
+ if(MatchHierarchy(buffer_file_path,source_file_path) == 0)
+ continue;
+
+ /** Conserve le chemin du fichier **/
+ new_file = (struct one_file *) calloc(1,sizeof(struct one_file));
+ if(new_file == NULL)
+ {
+ mem_free_onefile_list(first_file);
+ closedir(dir);
+ return(NULL);
+ }
+ new_file->file_path = strdup(buffer_file_path);
+ if(new_file->file_path == NULL)
+ {
+ free(new_file);
+ mem_free_onefile_list(first_file);
+ closedir(dir);
+ return(NULL);
+ }
+
+ /* Rattache à la liste chainée */
+ if(first_file == NULL)
+ first_file = new_file;
+ else
+ last_file->next = new_file;
+ last_file = new_file;
+ }
+
+ /* Fermeture du répertoire */
+ closedir(dir);
+
+ /* Renvoie la liste de fichier */
+ return(first_file);
+#endif
+}
+
+
+/******************************************************/
+/* ExchangeByte() : Echange les 2 octets d'un WORD. */
+/******************************************************/
+WORD ExchangeByte(WORD pattern)
+{
+ WORD new_pattern;
+
+ new_pattern = (pattern >> 8) | (pattern << 8);
+
+ return(new_pattern);
+}
+
+
+/******************************************************************************/
+/* mem_free_onefile_list() : Libération d'une liste de structures one_file. */
+/******************************************************************************/
+void mem_free_onefile_list(struct one_file *first_file)
+{
+ struct one_file *current_file;
+ struct one_file *next_file;
+
+ for(current_file=first_file; current_file; )
+ {
+ next_file = current_file->next;
+ if(current_file->file_path)
+ free(current_file->file_path);
+ free(current_file);
+ current_file = next_file;
+ }
+}
+
+
+/*****************************************************/
+/* compare_file() : On tri par ordre alphabétique. */
+/*****************************************************/
+int compare_file(const void *arg1, const void *arg2)
+{
+ char *file_path1 = *((char **)arg1);
+ char *file_path2 = *((char **)arg2);
+
+ /* On compare les deux chemin */
+ return(my_stricmp(file_path1,file_path2));
+}
+
+
+/******************************************************/
+/* mem_free_list() : Libération mémoire du tableau. */
+/******************************************************/
+void mem_free_list(int nb_values, char **values)
+{
+ int i;
+
+ /* On libère le tableau */
+ if(values)
+ {
+ for(i=0; i=0; i--)
+ if(folder_path[i] == FOLDER_SEPARATOR_CHAR) /* \ or / */
+ {
+ folder_path[i+1] = '\0';
+ break;
+ }
+
+ /** Traite tous les fichiers**/
+ for(i=0; i0); s1++, s2++, length--)
+ if(((tolower)(*s1)) != ((tolower)((*s2))))
+ return(((tolower)(*s1)) - ((tolower)(*s2)));
+
+ if(length == 0)
+ return(0);
+ else
+ return(1);
+#endif
+}
+
+
+/**********************************************************************/
+/* MatchHierarchy() : Indique si un nom appartient à une hiérarchie. */
+/**********************************************************************/
+int MatchHierarchy(char *name, char *hierarchie)
+{
+ int i,j,k;
+ int length;
+ char *hier_ptr;
+ char *name_ptr;
+ int result;
+ int count;
+ size_t offset;
+ char buffer[2048];
+
+ /*** On parcours les deux chaînes ***/
+ for(i=0,j=0; i<(int)strlen(hierarchie); i++)
+ {
+ if(hierarchie[i] != '*')
+ {
+ if(toupper(hierarchie[i]) != toupper(name[j]) &&
+ !(hierarchie[i] == '/' && name[j] == '\\') &&
+ !(hierarchie[i] == '\\' && name[j] == '/'))
+ return(0);
+ j++;
+ }
+ else if(hierarchie[i] == '?')
+ j++;
+ else
+ {
+ /* Si '*' dernier caractère de la chaîne => OK */
+ if(hierarchie[i+1] == '\0')
+ return(1);
+
+ /** S'il ne reste pas d'autre '*' : On compare la fin **/
+ hier_ptr = strchr(&hierarchie[i+1],'*');
+ if(hier_ptr == NULL)
+ {
+ length = (int)strlen(&hierarchie[i+1]);
+ if((int)strlen(&name[j]) < length)
+ return(0);
+ if(!myq_stricmp(&name[strlen(name)-length],&hierarchie[i+1]))
+ return(1);
+ else
+ return(0);
+ }
+
+ /** On compte le nb d'occurences de la partie entre les deux '*' dans name **/
+ strncpy(buffer,&hierarchie[i+1],hier_ptr-&hierarchie[i+1]);
+ buffer[hier_ptr-&hierarchie[i+1]] = '\0';
+ length = (int)strlen(buffer);
+ for(count = 0,offset = j;;count++)
+ {
+ name_ptr = my_strstr(&name[offset],buffer);
+ if(name_ptr == NULL)
+ break;
+ offset = (name_ptr - name) + 1;
+ }
+ /* Si aucune occurence => pas de matching */
+ if(count == 0)
+ return(0);
+
+ /** On lance la récursivité sur toutes les occurences trouvées **/
+ for(k=0,offset=j; k
+#include
+#include
+
+#include "Dc_Shared.h"
+#include "Dc_Graphic.h"
+#include "Dc_Code.h"
+#include "Dc_Gif.h"
+#include "Dc_Memory.h"
+
+/****************************************************/
+/* Main() : Fonction principale de l'application. */
+/****************************************************/
+int main(int argc, char *argv[])
+{
+ int i, result, nb_file, verbose, nb_bank;
+ char **tab_file;
+ char file_extension[256];
+ DWORD color_bg, color_frame;
+ DWORD palette_16[16] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
+
+ /* Information */
+ printf("MrSprite v1.0 (c) Brutal Deluxe 2012-2013.\n");
+
+ /* Init */
+ verbose = 0;
+ my_Memory(MEMORY_INIT,NULL,NULL);
+
+ /* Vérification des paramètres */
+ if(argc < 3)
+ {
+ printf(" Usage : %s COMMAND ...\n",argv[0]);
+ printf(" %s EXTRACT .\n",argv[0]);
+ printf(" ----\n");
+ printf(" %s MIRROR .\n",argv[0]);
+ printf(" %s FLIP .\n",argv[0]);
+ printf(" %s ODD .\n",argv[0]);
+ printf(" ----\n");
+ printf(" %s UNIQUE .\n",argv[0]);
+ printf(" %s RENAME .\n",argv[0]);
+ printf(" %s WALLPAPER .\n",argv[0]);
+ printf(" ----\n");
+ printf(" %s CODE [-V] ...\n",argv[0]);
+ printf(" %s BANK .\n",argv[0]);
+ printf(" ----\n");
+ return(1);
+ }
+
+ /**********************************************************************************/
+ /** EXTRACT : Extrait tous les sprites d'une planche et les entoure d'un cadre **/
+ /**********************************************************************************/
+ if(argc == 5 && !my_stricmp(argv[1],"EXTRACT"))
+ {
+ /* Vérifie les paramètres */
+ color_bg = DecodeRGBColor(argv[3]);
+ color_frame = DecodeRGBColor(argv[4]);
+ if(color_bg == 0xFFFFFFFF || color_frame == 0xFFFFFFFF)
+ {
+ printf(" Error : Can't convert color into a valid 0xRRGGBB format.\n");
+ return(1);
+ }
+
+ /* Récupère la liste des fichiers */
+ tab_file = BuildFileTab(argv[2],&nb_file);
+ if(tab_file == NULL)
+ {
+ printf(" Error : Can't build file list from '%s'.\n",argv[2]);
+ return(2);
+ }
+
+ /** Modifie l'image pour ajouter un cadre autour du Sprite + Création de l'image Sprite **/
+ for(i=0; i=0; i++)
+ if(tab_file[0][i] == '.')
+ {
+ strcpy(file_extension,&tab_file[0][i+1]);
+ break;
+ }
+
+ /** Renomme les fichiers de facon incrémentale **/
+ result = RenameAllFiles(nb_file,tab_file,argv[3],file_extension);
+
+ /* Libération mémoire */
+ mem_free_list(nb_file,tab_file);
+ }
+
+
+ /***************************************************************/
+ /** WALLPAPER : Crée une grande image avec tous les Sprites **/
+ /***************************************************************/
+ if(argc == 5 && !my_stricmp(argv[1],"WALLPAPER"))
+ {
+ /* Vérifie les paramètres */
+ color_bg = DecodeRGBColor(argv[3]);
+ color_frame = DecodeRGBColor(argv[4]);
+ if(color_bg == 0xFFFFFFFF || color_frame == 0xFFFFFFFF)
+ {
+ printf(" Error : Can't convert color into a valid 0xRRGGBB format.\n");
+ return(1);
+ }
+
+ /* Récupère la liste des fichiers */
+ tab_file = BuildFileTab(argv[2],&nb_file);
+ if(tab_file == NULL)
+ {
+ printf(" Error : Can't build file list from '%s'.\n",argv[2]);
+ return(2);
+ }
+
+ /** Création de l'image complète **/
+ result = CreateWallPaper(nb_file,tab_file,color_bg,color_frame);
+
+ /* Libération mémoire */
+ mem_free_list(nb_file,tab_file);
+ }
+
+ //C:\svn_devzing\MrSprite\Debug>MrSprite.exe CODE D:\Project\StreetFighter\adon_spr_*.gif BAFECA 000000 443344 550000 555555 664400 777777 990000 996644 AA7700 BBBBBB CC4400 CC8866 CCAA00 DDAA88 DDCCAA
+ /************************************************/
+ /** CODE : Création du code pour les Sprites **/
+ /************************************************/
+ if(argc > 4 && !my_stricmp(argv[1],"CODE"))
+ {
+ /* Verbose */
+ if(!my_stricmp(argv[2],"-V"))
+ verbose = 1;
+
+ /* Décodage des 16 couleurs du sprite */
+ color_bg = DecodeRGBColor(argv[verbose+3]);
+ if(color_bg == 0xFFFFFFFF)
+ {
+ printf(" Error : Can't convert color '%s' into a valid 0xRRGGBB format.\n",argv[verbose+3]);
+ return(1);
+ }
+ for(i=0; i