mirror of
https://github.com/dwsJason/xrick2gs.git
synced 2024-06-14 18:29:29 +00:00
1405 lines
50 KiB
C
1405 lines
50 KiB
C
/********************************************************************
|
|
* *
|
|
* Dc_Code.c : Module de gestion des lignes de Code. *
|
|
* *
|
|
********************************************************************
|
|
* Auteur : Olivier ZARDINI * Brutal Deluxe * Date : Jan 2013 *
|
|
********************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <malloc.h>
|
|
|
|
#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; y<byte_picture->height; 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; j<max_length; j++)
|
|
if(byte_picture->data[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; k<max_length; k++)
|
|
if(byte_picture->data[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; j<max_length; j++)
|
|
if(byte_picture->data[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; j<max_length; j++)
|
|
if(byte_picture->data[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; k<max_length; k++)
|
|
if(byte_picture->data[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; j<max_length; j++)
|
|
if(byte_picture->data[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; i<byte_picture->width; 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; j<byte_picture->width; 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; j<length; j+=2)
|
|
{
|
|
/* Récupération des 4 points de l'image */
|
|
pattern = ((WORD) current_picture->data[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; j<length; j+=2)
|
|
{
|
|
/* Récupération des 4 points de l'image */
|
|
pattern = ((WORD) current_picture->data[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; j<length; j++)
|
|
byte_picture->data[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; i<byte_picture->width; 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; i<byte_picture->width; i++)
|
|
if(byte_picture->data[offset_line+i] == 0xCC) /* Rouge */
|
|
{
|
|
for(j=i; j<byte_picture->width; 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; i<byte_picture->width; 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; i<nb_line; i++)
|
|
{
|
|
/* Assemble 1 ligne */
|
|
object_size = AssembleOneLine(tab_line[i],object);
|
|
if(object_size == 0)
|
|
continue;
|
|
|
|
/* Stocke le code objet */
|
|
memcpy(¤t_codefile->object[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; i<nb_bank+1; i++)
|
|
{
|
|
tab_bank[i] = (unsigned char *) calloc(BANK_TOTAL_SIZE,sizeof(unsigned char));
|
|
if(tab_bank[i] == NULL)
|
|
{
|
|
for(j=0; j<i; j++)
|
|
free(tab_bank[j]);
|
|
free(tab_bank);
|
|
printf(" Error : Impossible to allocate memory for Bank.\n");
|
|
return(2);
|
|
}
|
|
}
|
|
|
|
/***********************************/
|
|
/** Remplissage des Banks prévus **/
|
|
/***********************************/
|
|
for(i=0; i<nb_bank; i++)
|
|
{
|
|
/* Init */
|
|
bank_free_size = BANK_TOTAL_SIZE - BANK_HEADER_SIZE;
|
|
offset = BANK_TOTAL_SIZE;
|
|
|
|
/** On place le code d'entête **/
|
|
memcpy(&tab_bank[i][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[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<k; j++)
|
|
{
|
|
memcpy(&code_offset,&tab_bank[i][BANK_HEADER_SIZE+j*sizeof(WORD)],sizeof(WORD));
|
|
code_offset -= (WORD) bank_free_size;
|
|
memcpy(&tab_bank[i][BANK_HEADER_SIZE+j*sizeof(WORD)],&code_offset,sizeof(WORD));
|
|
}
|
|
|
|
/* Taille utilisée */
|
|
bank_size = BANK_TOTAL_SIZE - bank_free_size;
|
|
}
|
|
else
|
|
bank_size = BANK_TOTAL_SIZE;
|
|
|
|
/** Création du fichier Bank **/
|
|
strcpy(file_bank_path,file_folder_path);
|
|
for(j=strlen(file_bank_path); 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<k; j++)
|
|
{
|
|
memcpy(&code_offset,&tab_bank[nb_bank][BANK_HEADER_SIZE+j*sizeof(WORD)],sizeof(WORD));
|
|
code_offset -= (WORD) bank_free_size;
|
|
memcpy(&tab_bank[nb_bank][BANK_HEADER_SIZE+j*sizeof(WORD)],&code_offset,sizeof(WORD));
|
|
}
|
|
|
|
/* Taille utilisée */
|
|
bank_size = BANK_TOTAL_SIZE - bank_free_size;
|
|
}
|
|
else
|
|
bank_size = BANK_TOTAL_SIZE;
|
|
|
|
/** Création du fichier Bank **/
|
|
strcpy(file_bank_path,file_folder_path);
|
|
for(j=strlen(file_bank_path); 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<nb_bank+1; i++)
|
|
free(tab_bank[i]);
|
|
free(tab_bank);
|
|
|
|
/* OK */
|
|
return(0);
|
|
}
|
|
|
|
|
|
/****************************************************/
|
|
/* CreateMainCode() : Création du Code principal. */
|
|
/****************************************************/
|
|
int CreateMainCode(char *file_folder_path, char *bank_name, int nb_bank)
|
|
{
|
|
int i, j, nb_codefile;
|
|
FILE *fd;
|
|
struct code_file *current_codefile;
|
|
char file_source_path[1024];
|
|
|
|
/** Création du fichier Source **/
|
|
strcpy(file_source_path,file_folder_path);
|
|
for(i=strlen(file_source_path); 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<nb_bank; i++)
|
|
{
|
|
fprintf(fd,"%sBank%02d\tJSL\t$AA0000\n",bank_name,i);
|
|
fprintf(fd,"\tPHK\n");
|
|
fprintf(fd,"\tPLB\n");
|
|
fprintf(fd,"\tRTS\n\n");
|
|
}
|
|
|
|
fprintf(fd,"*------------------------------------------------\n");
|
|
|
|
/* Fermeture du fichier */
|
|
fclose(fd);
|
|
|
|
/* OK */
|
|
return(0);
|
|
}
|
|
|
|
/********************************************************************/
|