#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  <signal.h>
#include  <setjmp.h>

#include  "kernel.h"
#include  "bbc.h"
#include  "sprite.h"

#include "general.h"

extern void (*RafEcr3264)(void);

/* Ecran texte Apple */
#define MODE_TRS	0

EightBitCode *TRSCode;

u_int rPC0;

jmp_buf reprisepoint;

/* Anciennes valeurs pour le comportement des sequences de touche Break
   et des touches d'edition curseur */
int oldbreak, oldedit;

BOOL amode= FALSE; /* Mode Apple en vigueur */

TypGlb Glob;
u_int  Reg_PC;

extern BOOL (*EmulOp[SIZE_CODE>>8])(u_char pfx);
extern BOOL (*EmuWrite[SIZE_CODE>>8])(u_int ax, u_char vx);
extern void (*ModOp[])();
extern FILE *k7file[2], *diskfile;

void French_bbc_mode(u_char mode)
{
bbc_mode(mode);
bbc_cursor(0);
}
 
void Areset(int px)
{
u_int p;

/* Teste si la touche ESC ou Break est enfoncee */
p=_kernel_osbyte(122,0,0);
switch(p)
	{
	case 112: /* Code interne de Esc */
/*		signal(SIGINT,Areset);
		return; */
	case 44: /* Code interne Break */
		/* Touche Shift pressee? */
		if(_kernel_osbyte(121,0 ^ 0x80,0))
			{
			if(diskfile) fclose(diskfile);
			if(k7file[0]) fclose(k7file[0]);
			if(k7file[1]) fclose(k7file[1]);
			/* Libere l'espace memoire */
			free(TRSCode);
			/* Acknowledge escape condition */
			_kernel_osbyte(126,0,0);
			/* Restaure l'edition au clavier */
			_kernel_osbyte(4,oldedit,0);
			putchar('\n'); /* Instruction TRES importante. Don't remove */
			/* et l'effet de la touche Break */
			_kernel_osbyte(247,oldbreak,0);
			/* Redefinit les caracteres initiaux */
			bbc_vdu(bbc_RestoreLogical);
			/* Et notre curseur Archimedien reapparait */
			bbc_cursor(1);
			/* Textes et background en normal
			bbc_colour(7);
			bbc_colour(128); */
			raise(SIGINT); /* Touche pressee: Reset Archimedes */
			}
		else	/* Touche Shift relachee: Reset TRS80 */
			longjmp(reprisepoint,FROMRESET);
	}
}

int main()
{
FILE *dummy;
extern BOOL UpdWInter(u_int ad, u_char vx);
extern BOOL UpdScreen64(u_int ad, u_char vx);
extern void (*RafEcrAC64)(void);
#ifdef NMI
extern void FetchI(void);
#else
static void (*VFetch)(void);
#endif

/* Reservation de la memoire Apple */
if((TRSCode = (EightBitCode *) malloc(sizeof(EightBitCode))) == NULL)
	{
	puts("Erreur allocation memoire");
	exit(0);
	}

/* Chargement du fichier ROML2 en memoire */
if((dummy=fopen("<Trash80$Dir>.ROML2", "rb")) == NULL)
	{
	puts("Error opening ROML2");
	exit(1);
	}
puts("ROML2 successfully opened");

memset(TRSCode,0,sizeof(EightBitCode)); /* tout a zero */
if(fread((void *) TRSCode,0x3000,1,
	dummy) != 1)
	{
	puts("Error while reading ROML2");
	exit(2);
	}
fclose(dummy);
puts("ROML2 successfully read");

/* Ouverture d'un fichier k7file */
if((k7file[0]=fopen("<Trash80$Dir>.K71", "rb+")) == NULL)
	puts("Error opening first K7 file");
else	puts("First K7 file successfully opened");
if((k7file[1]=fopen("<Trash80$Dir>.K72", "rb+")) == NULL)
	puts("Error opening second K7 file");
else	puts("Second K7 file successfully opened");

/* Ouverture d'un fichier diskfile */
if((diskfile=fopen("<Trash80$Dir>.disk","rb+")) == NULL)
	puts("Error opening disk file");
else	puts("Diskfile opened with success");
/*
(void) getchar();
*/
RafEcr3264 = RafEcrAC64;

/* Initialisation du tableau EmuWrite */
memset(EmuWrite,0,sizeof(EmuWrite));
EmuWrite[0x37] = &UpdWInter;
EmuWrite[0x3c] = EmuWrite[0x3d] = EmuWrite[0x3e] =
	EmuWrite[0x3f] =  &UpdScreen64;

/* Inhibe l'edition au clavier */
oldedit = _kernel_osbyte(4,1,0) & 0xff;
/* Change l'effet de la touche Break
   0x5a: %01.01.10.10 */
oldbreak = _kernel_osbyte(247,0x5a,0) & 0xff;

/* Mode ecran Apple */
French_bbc_mode(MODE_TRS);
amode= TRUE;

/* Mode DEBUG
TRSCode->bytes[0x3840]= 4; Mode DEBUG */
rPC0= 0xffff; /*
scanf("%4x",&rPC0); (void) getchar();
*/

/* Memorisation du point a reprendre en cas de RESET */
switch(setjmp(reprisepoint))
	{
	extern void Traitk7(char *s);
#if defined(IM0) || defined(IM1) || defined(IM2)
	extern u_char mode_inter;
#endif
#ifndef NMI
	extern void Fetch(void), FetchI(void);
#endif
	case 0:
	case FROMRESET:
		signal(SIGINT, Areset); /* Redirection du Reset */
#if defined(IM0) || defined(IM1) || defined(IM2)
		mode_inter= 0;
#endif
		Traitk7("10");
		Traitk7("20");
		Reg_PC= 0;
		signal(SIGINT, Areset);
#ifndef NMI
	case FROMDI:
		VFetch= Fetch;
		break;
	case FROMEI:
		VFetch= FetchI;
#endif
	}
#ifdef NMI
FetchI();
#else
(*VFetch)();
#endif
}
