From 54eae24600b02fdf321b9cfd02ae117a2985b58e Mon Sep 17 00:00:00 2001 From: dwsJason Date: Thu, 16 Aug 2018 21:36:49 -0400 Subject: [PATCH] import: Mr Sprite hacked up for the sprites in this project --- .gitignore | 10 + bin/mrsprite/Makefile | 159 ++ bin/mrsprite/mrsprite.sln | 31 + bin/mrsprite/mrsprite.vcxproj | 168 ++ bin/mrsprite/mrsprite.vcxproj.filters | 54 + bin/mrsprite/source/Dc_Code.c | 1404 +++++++++++++++ bin/mrsprite/source/Dc_Code.h | 57 + bin/mrsprite/source/Dc_Gif.c | 1046 +++++++++++ bin/mrsprite/source/Dc_Gif.h | 18 + bin/mrsprite/source/Dc_Graphic.c | 2337 +++++++++++++++++++++++++ bin/mrsprite/source/Dc_Graphic.h | 56 + bin/mrsprite/source/Dc_Memory.c | 510 ++++++ bin/mrsprite/source/Dc_Memory.h | 51 + bin/mrsprite/source/Dc_Shared.c | 705 ++++++++ bin/mrsprite/source/Dc_Shared.h | 31 + bin/mrsprite/source/Main.c | 363 ++++ 16 files changed, 7000 insertions(+) create mode 100644 bin/mrsprite/Makefile create mode 100644 bin/mrsprite/mrsprite.sln create mode 100644 bin/mrsprite/mrsprite.vcxproj create mode 100644 bin/mrsprite/mrsprite.vcxproj.filters create mode 100644 bin/mrsprite/source/Dc_Code.c create mode 100644 bin/mrsprite/source/Dc_Code.h create mode 100644 bin/mrsprite/source/Dc_Gif.c create mode 100644 bin/mrsprite/source/Dc_Gif.h create mode 100644 bin/mrsprite/source/Dc_Graphic.c create mode 100644 bin/mrsprite/source/Dc_Graphic.h create mode 100644 bin/mrsprite/source/Dc_Memory.c create mode 100644 bin/mrsprite/source/Dc_Memory.h create mode 100644 bin/mrsprite/source/Dc_Shared.c create mode 100644 bin/mrsprite/source/Dc_Shared.h create mode 100644 bin/mrsprite/source/Main.c 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