Implemented last-chance recovery that saves the current and spare page. (issue 97)
Tested OK on Windows when crashing Contour (issue 119) Doesn't handle frozen states (when killed in task manager), I'll have to look further. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@628 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
parent
546dc6011f
commit
d704c4f425
59
init.c
59
init.c
@ -22,6 +22,11 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
// Signal handler: I activate it for the two platforms who certainly
|
||||
// support them. Feel free to check with others.
|
||||
#if defined(__WIN32__) || defined(__linux__)
|
||||
#define GRAFX2_CATCHES_SIGNALS
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
@ -36,10 +41,12 @@
|
||||
#if defined(__WIN32__)
|
||||
#include <windows.h> // GetLogicalDrives(), GetDriveType(), DRIVE_*
|
||||
#endif
|
||||
|
||||
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__)
|
||||
#include <proto/exec.h>
|
||||
#include <proto/dos.h>
|
||||
#include <proto/exec.h>
|
||||
#include <proto/dos.h>
|
||||
#endif
|
||||
#ifdef GRAFX2_CATCHES_SIGNALS
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "const.h"
|
||||
@ -60,6 +67,7 @@
|
||||
#include "windows.h"
|
||||
#include "sdlscreen.h"
|
||||
#include "mountlist.h" // read_file_system_list
|
||||
#include "loadsave.h" // Image_emergency_backup
|
||||
|
||||
// Ajouter un lecteur à la liste de lecteurs
|
||||
void Ajouter_lecteur(char Lettre, byte Type, char *Chemin)
|
||||
@ -72,7 +80,6 @@ void Ajouter_lecteur(char Lettre, byte Type, char *Chemin)
|
||||
Nb_drives++;
|
||||
}
|
||||
|
||||
|
||||
// Rechercher la liste et le type des lecteurs de la machine
|
||||
|
||||
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__)
|
||||
@ -2364,3 +2371,47 @@ void Config_par_defaut(void)
|
||||
Snap_Decalage_X=Snap_Decalage_Y=0;
|
||||
|
||||
}
|
||||
|
||||
#ifdef GRAFX2_CATCHES_SIGNALS
|
||||
|
||||
// Memorize the signal handlers of SDL
|
||||
__p_sig_fn_t Handler_TERM=SIG_DFL;
|
||||
__p_sig_fn_t Handler_INT=SIG_DFL;
|
||||
__p_sig_fn_t Handler_ABRT=SIG_DFL;
|
||||
__p_sig_fn_t Handler_SEGV=SIG_DFL;
|
||||
__p_sig_fn_t Handler_FPE=SIG_DFL;
|
||||
|
||||
void sig_handler(int sig)
|
||||
{
|
||||
// Restore default behaviour
|
||||
signal(SIGTERM, Handler_TERM);
|
||||
signal(SIGINT, Handler_INT);
|
||||
signal(SIGABRT, Handler_ABRT);
|
||||
signal(SIGSEGV, Handler_SEGV);
|
||||
signal(SIGFPE, Handler_FPE);
|
||||
|
||||
switch(sig)
|
||||
{
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
case SIGABRT:
|
||||
case SIGSEGV:
|
||||
Image_emergency_backup();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Initialiser_sighandler(void)
|
||||
{
|
||||
#ifdef GRAFX2_CATCHES_SIGNALS
|
||||
Handler_TERM=signal(SIGTERM,sig_handler);
|
||||
Handler_INT =signal(SIGINT,sig_handler);
|
||||
Handler_ABRT=signal(SIGABRT,sig_handler);
|
||||
Handler_SEGV=signal(SIGSEGV,sig_handler);
|
||||
Handler_FPE =signal(SIGFPE,sig_handler);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
1
init.h
1
init.h
@ -28,3 +28,4 @@ void Initialiser_les_tables_de_multiplication(void);
|
||||
void Definition_des_modes_video(void);
|
||||
int ActiverLecteur(int);
|
||||
void Config_par_defaut(void);
|
||||
void Initialiser_sighandler(void);
|
||||
|
||||
55
loadsave.c
55
loadsave.c
@ -5864,3 +5864,58 @@ void Save_PNG(void)
|
||||
row_pointers=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Saves an image.
|
||||
// This routine will only be called when all hope is lost, memory thrashed, etc
|
||||
// It's the last chance to save anything, but the code has to be extremely careful,
|
||||
// anything could happen.
|
||||
// The chosen format is IMG since it's extremely simple, difficult to make it create an unusable image.
|
||||
void Emergency_backup(const char *Fname, byte *Source, int Largeur, int Hauteur, T_Palette *Palette)
|
||||
{
|
||||
char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
|
||||
FILE *Fichier;
|
||||
short Pos_X,Pos_Y;
|
||||
T_Header_IMG IMG_Header;
|
||||
|
||||
strcpy(Nom_du_fichier,Repertoire_de_configuration);
|
||||
strcat(Nom_du_fichier,Fname);
|
||||
|
||||
// Ouverture du fichier
|
||||
Fichier=fopen(Nom_du_fichier,"wb");
|
||||
if (!Fichier)
|
||||
return;
|
||||
|
||||
memcpy(IMG_Header.Filler1,"\x01\x00\x47\x12\x6D\xB0",6);
|
||||
memset(IMG_Header.Filler2,0,118);
|
||||
IMG_Header.Filler2[4]=0xFF;
|
||||
IMG_Header.Filler2[22]=64; // Lo(Longueur de la signature)
|
||||
IMG_Header.Filler2[23]=0; // Hi(Longueur de la signature)
|
||||
memcpy(IMG_Header.Filler2+23,"GRAFX2 by SunsetDesign (IMG format taken from PV (c)W.Wiedmann)",64);
|
||||
|
||||
if (!write_bytes(Fichier,IMG_Header.Filler1,6) ||
|
||||
!write_word_le(Fichier,Largeur) ||
|
||||
!write_word_le(Fichier,Hauteur) ||
|
||||
!write_bytes(Fichier,IMG_Header.Filler2,118) ||
|
||||
!write_bytes(Fichier,Palette,sizeof(T_Palette)))
|
||||
{
|
||||
fclose(Fichier);
|
||||
return;
|
||||
}
|
||||
|
||||
for (Pos_Y=0; ((Pos_Y<Hauteur) && (!Erreur_fichier)); Pos_Y++)
|
||||
for (Pos_X=0; Pos_X<Largeur; Pos_X++)
|
||||
if (!write_byte(Fichier,*(Source+Pos_Y*Largeur+Pos_X)))
|
||||
{
|
||||
fclose(Fichier);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ouf, sauvé
|
||||
fclose(Fichier);
|
||||
}
|
||||
|
||||
void Image_emergency_backup()
|
||||
{
|
||||
Emergency_backup("phoenix.img",Principal_Ecran, Principal_Largeur_image, Principal_Hauteur_image, &Principal_Palette);
|
||||
Emergency_backup("phoenix2.img",Brouillon_Ecran, Brouillon_Largeur_image, Brouillon_Hauteur_image, &Brouillon_Palette);
|
||||
}
|
||||
|
||||
@ -40,3 +40,5 @@ typedef struct {
|
||||
// Tableau des formats connus
|
||||
extern T_Format FormatFichier[NB_FORMATS_CONNUS];
|
||||
|
||||
// Fonction de sauvegarde en cas de probleme
|
||||
void Image_emergency_backup(void);
|
||||
|
||||
58
main.c
58
main.c
@ -536,7 +536,6 @@ void Initialisation_du_programme(int argc,char * argv[])
|
||||
Pinceau_Hauteur=1;
|
||||
|
||||
Analyse_de_la_ligne_de_commande(argc,argv);
|
||||
|
||||
Mode_dans_lequel_on_demarre=Resolution_actuelle;
|
||||
Buffer_de_ligne_horizontale=NULL;
|
||||
Resolution_actuelle=-1; // On n'était pas dans un mode graphique
|
||||
@ -584,6 +583,9 @@ void Initialisation_du_programme(int argc,char * argv[])
|
||||
Brouillon_Image_modifiee=0;
|
||||
Principal_Image_modifiee=0;
|
||||
|
||||
// Gestionnaire de signaux, quand il ne reste plus aucun espoir
|
||||
Initialiser_sighandler();
|
||||
|
||||
// Le programme débute en mode de dessin à la main
|
||||
Enclencher_bouton(BOUTON_DESSIN,A_GAUCHE);
|
||||
|
||||
@ -635,18 +637,58 @@ void Fermeture_du_programme(void)
|
||||
// -------------------------- Procédure principale ---------------------------
|
||||
int main(int argc,char * argv[])
|
||||
{
|
||||
int PhoenixTrouve=0;
|
||||
int Phoenix2Trouve=0;
|
||||
char Nom_du_fichier_Phoenix[TAILLE_CHEMIN_FICHIER];
|
||||
char Nom_du_fichier_Phoenix2[TAILLE_CHEMIN_FICHIER];
|
||||
|
||||
Initialisation_du_programme(argc,argv);
|
||||
|
||||
if (Config.Opening_message && (!Un_fichier_a_ete_passe_en_parametre))
|
||||
Bouton_Message_initial();
|
||||
//free(Logo_GrafX2); // Utilisé dans le About
|
||||
|
||||
if (Un_fichier_a_ete_passe_en_parametre)
|
||||
// Test de recuperation de fichiers sauvés
|
||||
strcpy(Nom_du_fichier_Phoenix,Repertoire_de_configuration);
|
||||
strcat(Nom_du_fichier_Phoenix,"phoenix.img");
|
||||
strcpy(Nom_du_fichier_Phoenix2,Repertoire_de_configuration);
|
||||
strcat(Nom_du_fichier_Phoenix2,"phoenix2.img");
|
||||
if (Fichier_existe(Nom_du_fichier_Phoenix))
|
||||
PhoenixTrouve=1;
|
||||
if (Fichier_existe(Nom_du_fichier_Phoenix2))
|
||||
Phoenix2Trouve=1;
|
||||
if (PhoenixTrouve || Phoenix2Trouve)
|
||||
{
|
||||
Bouton_Reload();
|
||||
Une_resolution_a_ete_passee_en_parametre=0;
|
||||
if (Phoenix2Trouve)
|
||||
{
|
||||
strcpy(Principal_Repertoire_fichier,Repertoire_de_configuration);
|
||||
strcpy(Principal_Nom_fichier,"phoenix2.img");
|
||||
chdir(Principal_Repertoire_fichier);
|
||||
Bouton_Reload();
|
||||
Warning_message("Spare page recovered");
|
||||
// I don't really like this, but...
|
||||
remove(Nom_du_fichier_Phoenix2);
|
||||
Bouton_Page();
|
||||
}
|
||||
if (PhoenixTrouve)
|
||||
{
|
||||
strcpy(Principal_Repertoire_fichier,Repertoire_de_configuration);
|
||||
strcpy(Principal_Nom_fichier,"phoenix.img");
|
||||
chdir(Principal_Repertoire_fichier);
|
||||
Bouton_Reload();
|
||||
Warning_message("Main page recovered");
|
||||
// I don't really like this, but...
|
||||
remove(Nom_du_fichier_Phoenix);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Config.Opening_message && (!Un_fichier_a_ete_passe_en_parametre))
|
||||
Bouton_Message_initial();
|
||||
//free(Logo_GrafX2); // Utilisé dans le About
|
||||
|
||||
if (Un_fichier_a_ete_passe_en_parametre)
|
||||
{
|
||||
Bouton_Reload();
|
||||
Une_resolution_a_ete_passee_en_parametre=0;
|
||||
}
|
||||
}
|
||||
Gestion_principale();
|
||||
|
||||
Fermeture_du_programme();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user