#include  <stdio.h>
#include  <string.h>
#include  "bbc.h"
#include  "sprite.h"

#include  "general.h"
#include  "Externals.h"

/* Ecran texte Apple */
#define MODE_APPLE 9
#define MODE_APPLE80 12

static BOOL Page2 = FALSE;
static u_int owner = 0;

static u_int adbase[24] =
	{
	0x400,0x480,0x500,0x580,0x600,0x680,0x700,0x780,
	0x428,0x4a8,0x528,0x5a8,0x628,0x6a8,0x728,0x7a8,
	0x450,0x4d0,0x550,0x5d0,0x650,0x6d0,0x750,0x7d0
	};

static const u_int adbase1[24] =
	{
	0x400,0x480,0x500,0x580,0x600,0x680,0x700,0x780,
	0x428,0x4a8,0x528,0x5a8,0x628,0x6a8,0x728,0x7a8,
	0x450,0x4d0,0x550,0x5d0,0x650,0x6d0,0x750,0x7d0
	};

static const u_int adbase2[24] =
	{
	0x800,0x880,0x900,0x980,0xa00,0xa80,0xb00,0xb80,
	0x828,0x8a8,0x928,0x9a8,0xa28,0xaa8,0xb28,0xba8,
	0x850,0x8d0,0x950,0x9d0,0xa50,0xad0,0xb50,0xbd0
	};

u_char oldcol0 = 0xff;
u_char oldcol1 = 0xff;
BOOL (*EmuWrite[SIZE_CODE>>8])(u_int ax, u_char vx);
void (*RafEcr48)(void);
void RafEcrAC40T(void);
void (*RafEcrAC40)(void) = RafEcrAC40T;
void RafEcrAC80T(void);
void (*RafEcrAC80)(void) = RafEcrAC80T;

BOOL UpdScreen40T(u_int ax, u_char vx);
BOOL (*UpdScreen40)(u_int ax, u_char vx) = UpdScreen40T;
BOOL UpdScreen80mT(u_int ax, u_char vx);
BOOL (*UpdScreen80m)(u_int ax, u_char vx) = UpdScreen80mT;
BOOL UpdScreen80aT(u_int ax, u_char vx);
BOOL (*UpdScreen80a)(u_int ax, u_char vx) = UpdScreen80aT;

/*  Softswitches materiels de l'Apple //e */
extern BOOL RdC3ROM, RdCxROM, Rd80store, RdPage2, RdHires, RdRAMRd, RdRAMWrt;
extern BOOL RdAltChar, Rd80vid, RdLCRAM, RdBNK2, RdAltZP;

extern BOOL WrLCRAM;
extern BOOL RdText, RdMixed;

extern u_char Vkbd;

static u_char (*cs[24])(u_char vx);

u_char primarycsT(u_char vx);
u_char (*vprimarycs)(u_char vx) = primarycsT;
u_char alternatecsT(u_char vx);
u_char (*valternatecs)(u_char vx) = alternatecsT;
u_char lorescsT(u_char vx);
u_char (*vlorescs)(u_char vx) = lorescsT;

/*static*/ u_char (*current_graphcs)(u_char vx);
u_char (*current_textcs)(u_char vx);

extern void sprite_plot(u_char vx, u_char ix, u_char cv);
	       
static u_char cvmax = 24;

u_char primarycsT(u_char vx)
{
u_char colour0;
static const signed char offset[8] =
	{
	0x40, 0, 0, -0x40,
	-0x40,-0x80,-0x80, -0x80
	};

if((colour0= vx<0x80 ? 143 : 15) != oldcol0)
	bbc_colour(oldcol0=colour0);
if((colour0= vx<0x80 ? 0 : 128) != oldcol1)
	bbc_colour(oldcol1=colour0);
return(vx + (vx == 0xff ? 0 : offset[vx>>5]));
}

u_char primarycsS(u_char vx)
{
extern sprite_pixtrans mpixtrans[2];
static const signed char offset[8] =
	{
	0x40, 0, 0, -0x40,
	-0x40,-0x80,-0x80, -0x80
	};
mpixtrans[vx<0x80 ? 0 : 1] = 15;
mpixtrans[vx<0x80 ? 1 : 0] = 0;
return(vx + offset[vx>>5]);
}

u_char alternatecsT(u_char vx)
{
u_char colour0;
static const signed int offset[8] =
	{
	0x40, 0, 0x80, 0,
	-0x40, -0x80, -0x80, -0x80
	};
static const u_char forecolor[8] =
	{
	143,143,15,143,
	15,15,15,15
	};
static const u_char backcolor[8] =
	{
	0,0,128,0,
	128,128,128,128
	};
if((colour0= forecolor[vx>>5]) != oldcol0)
	bbc_colour(oldcol0=colour0);
if((colour0= backcolor[vx>>5]) != oldcol1)
	bbc_colour(oldcol1=colour0);
return(vx + (vx == 0xff ? 0 : (vx == 0x7f ? 0x80 : offset[vx>>5])));
}

u_char alternatecsS(u_char vx)
{
extern sprite_pixtrans mpixtrans[2];
static const signed char offset[8] =
	{
	0x40, 0, -0x40, 0,
	-0x40, -0x80, -0x80, -0x80
	};
static u_char forecolor[8] =
	{
	 0,  0, 15,  0,
	15, 15, 15, 15
	};
static u_char backcolor[8] =
	{
	15, 15, 0, 15,
	 0,  0, 0,  0
	};
mpixtrans[0]= backcolor[vx>>5];
mpixtrans[1]= forecolor[vx>>5];
return(vx+offset[vx>>5]);
}

u_char lorescsT(u_char vx)
{
u_char colour0;
if((vx>>4) != oldcol0)
	bbc_colour(oldcol0=(vx>>4));
if((colour0= (vx & 0x0f) | 0x80) != oldcol1)
	bbc_colour(oldcol1=colour0);
return(0xfe);
}

u_char lorescsS(u_char vx)
{
extern sprite_pixtrans mpixtrans[2];

mpixtrans[0]= vx & 0x0f;
mpixtrans[1]= vx>>4;
return(0x80);
}

static u_char getcv17(u_int ad)
{

if(ad>0x6ff && ad<0x728) return(6);
else if(ad>0x77f && ad<0x7a8) return(7);
else if(ad>0x727 && ad<0x750) return(14);
else if(ad>0x7a7 && ad<0x7d0) return(15);
else if(ad>0x74f && ad<0x778) return(22);
else if(ad>0x7cf && ad<0x7f8) return(23);
else return(0xff);
}

static u_char getcv16(u_int ad)
{

if(ad>0x5ff && ad<0x628) return(4);
else if(ad>0x67f && ad<0x6a8) return(5);
else if(ad>0x627 && ad<0x650) return(12);
else if(ad>0x6a7 && ad<0x6d0) return(13);
else if(ad>0x64f && ad<0x678) return(20);
else if(ad>0x6cf && ad<0x6f8) return(21);
else return(0xff);
}

static u_char getcv15(u_int ad)
{

if(ad>0x4ff && ad<0x528) return(2);
else if(ad>0x57f && ad<0x5a8) return(3);
else if(ad>0x527 && ad<0x550) return(10);
else if(ad>0x5a7 && ad<0x5d0) return(11);
else if(ad>0x54f && ad<0x578) return(18);
else if(ad>0x5cf && ad<0x5f8) return(19);
else return(0xff);
}

static u_char getcv14(u_int ad)
{
if(ad>0x3ff && ad<0x428) return(0);
else if(ad>0x47f && ad<0x4a8) return(1);
else if(ad>0x427 && ad<0x450) return(8);
else if(ad>0x4a7 && ad<0x4d0) return(9);
else if(ad>0x44f && ad<0x478) return(16);
else if(ad>0x4cf && ad<0x4f8) return(17);
else return(0xff);
}

static u_char getcv20(u_int ad); /* Prototype */

static u_char (*vgetcv[12])(u_int ad) =
	{
	0, 0, 0, 0,
	getcv14, getcv15, getcv16, getcv17,
	getcv20, getcv20, getcv20, getcv20
	};

static u_char getcv20(u_int ad)
{
return((*vgetcv[(ad-0x400)>>8])(ad-0x400));
}

BOOL UpdScreen40T(u_int ad, u_char vx)
{
u_char cv;
if((cv= (*vgetcv[ad>>8])(ad)) != 0xff)
	if(cs[cv])
		{
		bbc_tab(ad-adbase[cv],cv);
		bbc_vdu((*cs[cv])(vx));
		}
return(FALSE);
}

BOOL UpdScreen80mT(u_int ad,u_char vx)
{
u_char cv;

if((cv= (*vgetcv[ad>>8])(ad)) != 0xff)
	if(cs[cv])
		{
		bbc_tab(1+((ad-adbase[cv])<<1),cv);
		bbc_vdu((*cs[cv])(vx));
		}
return(FALSE);
}

BOOL UpdScreen80aT(u_int ad,u_char vx)
{
u_char cv;
u_int ax = ad-OFFBANK;

if((cv= (*vgetcv[ax>>8])(ax)) != 0xff)
	if(cs[cv])
		{
		bbc_tab((ax-adbase[cv])<<1,cv);
		bbc_vdu((*cs[cv])(vx));
		}
return(FALSE);
}

void RafEcrAC40T()
{
u_char cv;
u_int p;
u_char (*csp)(u_char c);

for(cv=0; cv<24; cv++)
	if((csp=cs[cv])!= NULL)
		{
		bbc_tab(0,cv);
		for(p=adbase[cv]; p<adbase[cv]+40; p++)
			bbc_vdu((*csp)(AppleCode->bytes[p]));
		}
}

void RafEcrAC80T()
{
u_char cv;
u_int p;
u_char (*csp)(u_char c);

for(cv=0; cv<24; cv++)
	if((csp=cs[cv])!= NULL)
		{
		bbc_tab(0,cv);
		for(p=adbase[cv]; p<adbase[cv]+40; p++)
			{
			bbc_vdu((*csp)(AppleCode->bytes[p+OFFBANK]));
			bbc_vdu((*csp)(AppleCode->bytes[p]));
			}
		}
}

BOOL UpdScreen40S(u_int ad, u_char vx)
{
u_char cv;

if((cv= (*vgetcv[ad>>8])(ad)) != 0xff)
	if(cs[cv]) sprite_plot((*cs[cv])(vx),ad-adbase[cv],cv);
return(FALSE);
}

BOOL UpdScreen80mS(u_int ad,u_char vx)
{
u_char cv;

if((cv= (*vgetcv[ad>>8])(ad)) != 0xff)
	if(cs[cv]) sprite_plot((*cs[cv])(vx),1+((ad-adbase[cv])<<1),cv);
return(FALSE);
}

BOOL UpdScreen80aS(u_int ad,u_char vx)
{
u_char cv;
u_int ax = ad-OFFBANK;

if((cv= (*vgetcv[ax>>8])(ax)) != 0xff)
	if(cs[cv]) sprite_plot((*cs[cv])(vx),(ax-adbase[cv])<<1,cv);
return(FALSE);
}

void RafEcrAC40S()
{
u_char ix, cv;
u_int p;
u_char (*csp)(u_char c);

for(cv=0; cv<24; cv++)
	if((csp=cs[cv])!= NULL)
		for(ix=0, p=adbase[cv]; p<adbase[cv]+40; ix++,p++)
			sprite_plot((*csp)(AppleCode->bytes[p]),ix,cv);
}

void RafEcrAC80S()
{
u_char ix, cv;
u_int p;
u_char (*csp)(u_char c);

for(cv=0; cv<24; cv++)
	if((csp=cs[cv])!= NULL)
		for(ix=0, p=adbase[cv]; p<adbase[cv]+40; p++)
			{
			sprite_plot((*csp)(AppleCode->bytes[p+OFFBANK]),ix++,cv);
			sprite_plot((*csp)(AppleCode->bytes[p]),ix++,cv);
			}
}

void SRdCxROMFalse()
{
u_char i;
for(i=0xc1; i<0xc8; i++)
	if(i != 0xc3) offread[i]= OFFBANK;
for(; i<0xd0; i++)
	offread[i]= owner;
RdCxROM=FALSE;
}

void SRdRAMRdTrue()
{
u_char i;

offread[0x02] = offread[0x03] = OFFBANK;
for(i= Rd80store ? 0x08 :0x04; i<0x20; i++) offread[i]= OFFBANK;
for(i = Rd80store && RdHires ? 0x40 : 0x20; i<0xc0; i++)
	offread[i] = OFFBANK;
RdRAMRd = TRUE;
}

void SRdRAMRdFalse()
{
u_char i;

offread[0x02] = offread[0x03] = 0;
for(i= Rd80store ? 0x08 : 0x04; i<0x20; i++) offread[i]= 0;
for(i = Rd80store && RdHires ? 0x40 : 0x20; i<0xc0; i++)
	offread[i] = 0;
RdRAMRd = FALSE;
}

void SRdRAMWrtTrue()
{
u_char i;

offwrite[0x02] = offwrite[0x03] = OFFBANK;
for(i= Rd80store ? 0x08 : 0x04; i<0x20; i++) offwrite[i]= OFFBANK;
for(i = Rd80store && RdHires ? 0x40 : 0x20; i<0xc0; i++)
	offwrite[i] = OFFBANK;
RdRAMWrt = TRUE;
}

void SRdRAMWrtFalse()
{
u_char i;

offwrite[0x02] = offwrite[0x03] = 0;
for(i= Rd80store ? 0x08 :0x04; i<0x20; i++) offwrite[i]= 0;
for(i = Rd80store && RdHires ? 0x40 : 0x20; i<0xc0; i++)
	offwrite[i] = 0;
RdRAMWrt = FALSE;
}

void SRdAltZPTrue()
{
u_int p;

offread[0] = offwrite[0] =
	offread[1] = offwrite[1] = OFFBANK;
if(RdLCRAM)
	for(p=0xd0; p<0x100; p++) offread[p] += OFFBANK;
if(WrLCRAM)
	for(p=0xd0; p<0x100; p++) offwrite[p] += OFFBANK;
RdAltZP= TRUE;
}

void SRdAltZPFalse()
{
u_int p;

offread[0] = offwrite[0] =
	offread[1] = offwrite[1] = 0;
if(RdLCRAM)
	for(p=0xd0; p<0x100; p++) offread[p] -= OFFBANK;
if(WrLCRAM)
	for(p=0xd0; p<0x100; p++) offwrite[p] -= OFFBANK;
RdAltZP= FALSE;
}

void SRdPage2True()
{
if(Rd80store)
	{
	u_char i;
	for(i=0x04; i<0x08; i++)
		offread[i]=offwrite[i]= OFFBANK;
	if(RdHires)
		for(i=0x20; i<0x40; i++)
			offread[i]=offwrite[i]= OFFBANK;
	}
else	{
	memcpy((void *) adbase, (void *) adbase2, sizeof(adbase));
	Page2= TRUE;
	EmuWrite[0x08] = EmuWrite[0x09] =
		EmuWrite[0x0a] = EmuWrite[0x0b] = Rd80vid ? UpdScreen80m :
			UpdScreen40;
	EmuWrite[0x08+(OFFBANK>>8)] = EmuWrite[0x09+(OFFBANK>>8)] =
		EmuWrite[0x0a+(OFFBANK>>8)] = EmuWrite[0x0b+(OFFBANK>>8)] =
			Rd80vid ? UpdScreen80a : 0;
	EmuWrite[0x04] = EmuWrite[0x05] =
		EmuWrite[0x06] = EmuWrite[0x07] =
		EmuWrite[0x04+(OFFBANK>>8)] = EmuWrite[0x05+(OFFBANK>>8)] =
		EmuWrite[0x06+(OFFBANK>>8)] = EmuWrite[0x07+(OFFBANK>>8)] = 0;
	(*RafEcr48)();
	}
RdPage2=TRUE;
}

void SRdPage2False()
{
if(Rd80store)
	{
	u_char i;
	for(i=0x04; i<0x08; i++)
		offread[i]= offwrite[i]= 0;
	if(RdHires)
		for(i=0x20; i<0x40; i++)
			offread[i]= offwrite[i]= 0;
	}
else	{
	memcpy((void *) adbase, (void *) adbase1, sizeof(adbase));
	Page2= FALSE;
	EmuWrite[0x04] = EmuWrite[0x05] =
		EmuWrite[0x06] = EmuWrite[0x07] = Rd80vid ? UpdScreen80m :
			UpdScreen40;
	EmuWrite[0x04+(OFFBANK>>8)] = EmuWrite[0x05+(OFFBANK>>8)] =
		EmuWrite[0x06+(OFFBANK>>8)] = EmuWrite[0x07+(OFFBANK>>8)] =
			Rd80vid ? UpdScreen80a : 0;
	EmuWrite[0x08] = EmuWrite[0x09] =
		EmuWrite[0x0a] = EmuWrite[0x0b] =
		EmuWrite[0x08+(OFFBANK>>8)] = EmuWrite[0x09+(OFFBANK>>8)] =
		EmuWrite[0x0a+(OFFBANK>>8)] = EmuWrite[0x0b+(OFFBANK>>8)] = 0;
	(*RafEcr48)();
	}
RdPage2=FALSE;
}

void SRdHiresTrue()
{
u_char cv;

if(Rd80store)
	{
	u_char i;
	if(RdPage2)
		for(i=0x20; i<0x40; i++)
			offread[i]= offwrite[i]= OFFBANK;
	}
current_graphcs= NULL;
if(!RdText)
	for(cv=0; cv<cvmax; cv++) cs[cv]= current_graphcs;
RdHires=TRUE;
}

void SRdHiresFalse()
{

if(Rd80store)
	{
	u_char i;
	u_int offset1 = RdRAMRd ? OFFBANK : 0;
	u_int offset2 = RdRAMWrt ? OFFBANK : 0;
	for(i=0x20; i<0x40; i++)
		{
		offread[i]=offset1;
		offwrite[i]=offset2;
		}
	}
current_graphcs= vlorescs;
if(!RdText)
	{
	u_char cv;
	for(cv=0; cv<cvmax; cv++) cs[cv]= current_graphcs;
	(*RafEcr48)();
	}
RdHires=FALSE;
}

void SRd80storeTrue()
{
if (Page2)
	{
	SRdPage2False();
	Rd80store= TRUE;
	SRdPage2True();
	}
else	{
	Rd80store= TRUE;
	SRdPage2False();
	}
}

void SRd80storeFalse()
{
u_char i;
u_int offset1= RdRAMRd ? OFFBANK : 0;
u_int offset2= RdRAMWrt ? OFFBANK : 0;
for(i=0x04; i<0x08; i++)
	{
	offread[i]=offset1;
	offwrite[i]=offset2;
	}
for(i=0x20; i<0x40; i++)
	{
	offread[i]=offset1;
	offwrite[i]=offset2;
	}
Rd80store= FALSE;
if(RdPage2) SRdPage2True();
}

void SRd80vidTrue()
{
u_int offset;
extern void French_bbc_mode(u_char mode);

French_bbc_mode(MODE_APPLE80);
Rd80vid= TRUE;
RafEcr48= RafEcrAC80;
offset= Page2 ? 4 : 0;
EmuWrite[0x04+offset] = EmuWrite[0x05+offset] =
	EmuWrite[0x06+offset] = EmuWrite[0x07+offset] = UpdScreen80m;
EmuWrite[0x04+(OFFBANK>>8)+offset] = EmuWrite[0x05+(OFFBANK>>8)+offset] =
	EmuWrite[0x06+(OFFBANK>>8)+offset] = EmuWrite[0x07+(OFFBANK>>8)+offset] =
		UpdScreen80a;
(*RafEcr48)();
}

void SRd80vidFalse()
{
u_int offset;
extern void French_bbc_mode(u_char mode);

French_bbc_mode(MODE_APPLE);
Rd80vid= FALSE;
RafEcr48= RafEcrAC40;
offset= Page2 ? 4 : 0;
EmuWrite[0x04+offset] = EmuWrite[0x05+offset] =
	EmuWrite[0x06+offset] = EmuWrite[0x07+offset] = UpdScreen40;
EmuWrite[0x04+(OFFBANK>>8)+offset] = EmuWrite[0x05+(OFFBANK>>8)+offset] =
	EmuWrite[0x06+(OFFBANK>>8)+offset] = EmuWrite[0x07+(OFFBANK>>8)+offset] =
		0;
(*RafEcr48)();
}

void SRdAltCharTrue()
{
u_char cv;

RdAltChar= TRUE;
current_textcs= valternatecs;
for(cv=0; cv<24; cv++) if (cs[cv]==vprimarycs) cs[cv]= current_textcs;
(*RafEcr48)();
}

void SRdAltCharFalse()
{
u_char cv;

RdAltChar= FALSE;
current_textcs= vprimarycs;
for(cv=0; cv<24; cv++) if (cs[cv]==valternatecs) cs[cv]= current_textcs;
(*RafEcr48)();
}

void SRdTextFalse()
{
u_char cv;

RdText=FALSE;
for(cv=0; cv<cvmax; cv++) cs[cv]= current_graphcs;
(*RafEcr48)();
}

void SRdTextTrue()
{
u_char cv;
for(cv=0; cv<24; cv++) cs[cv]= current_textcs;
RdText=TRUE;
(*RafEcr48)();
}

void SRdMixedTrue()
{
u_char cv;

cvmax= 20;
RdMixed= TRUE;
if(!RdText)
	{
	for(cv=cvmax; cv<24; cv++) cs[cv]= current_textcs;
	(*RafEcr48)();
	}
}

void SRdMixedFalse()
{
u_char cv;

cvmax= 24;
RdMixed= FALSE;
if(!RdText)
	{
	for(cv=0; cv<cvmax; cv++) cs[cv]= current_graphcs;
	(*RafEcr48)();
	}
}

BOOL EmuWc0(u_int ad, u_char v1)
{
extern void RegleLCSW(u_char ad);

switch(ad & 0xff)
	{
	case 0x03:
		if(!RdRAMRd) SRdRAMRdTrue();
		break;
	case 0x02:
		if(RdRAMRd) SRdRAMRdFalse();
		break;
	case 0x05:
		if(!RdRAMWrt) SRdRAMWrtTrue();
		break;
	case 0x04:
		if(RdRAMWrt) SRdRAMWrtFalse();
		break;
	case 0x07:
		if(!RdCxROM)
			{
			u_char i;
			for(i=0xc1; i<0xd0; i++)
				offread[i]= 0;
			RdCxROM=TRUE;
			}
	case 0x0a:
		offread[0xc3]=0;
		RdC3ROM=FALSE;
		break;
	case 0x06:
		if(RdCxROM) SRdCxROMFalse();
		break;
	case 0x0b:
		offread[0xc3]= OFFBANK;
		RdC3ROM=TRUE;
		break;
	case 0x09:
		if(!RdAltZP) SRdAltZPTrue();
		break;
	case 0x08:
		if(RdAltZP) SRdAltZPFalse();
		break;
	case 0x01:
		if(!Rd80store) SRd80storeTrue();
		break;
	case 0x00:
		if(Rd80store) SRd80storeFalse();
		break;
	case 0x0f:
		if(!RdAltChar) SRdAltCharTrue();
		break;
	case 0x0e:
		if(RdAltChar) SRdAltCharFalse();
		break;
	case 0x0d:
		if(!Rd80vid) SRd80vidTrue();
		break;
	case 0x0c:
		if(Rd80vid) SRd80vidFalse();
		break;
	case 0x55:
		if(!RdPage2) SRdPage2True();
		break;
	case 0x54:
		if(RdPage2) SRdPage2False();
		break;
	case 0x51:
		if(!RdText) SRdTextTrue();
		break;
	case 0x50:
		if(RdText) SRdTextFalse();
		break;
	case 0x53:
		if(!RdMixed) SRdMixedTrue();
		break;
	case 0x52:
		if(RdMixed) SRdMixedFalse();
		break;
	case 0x57:
		if(!RdHires) SRdHiresTrue();
		break;
	case 0x56:
		if(RdHires) SRdHiresFalse();
		break;
	case 0x80:
	case 0x81:
	case 0x82:
	case 0x83:
	case 0x88:
	case 0x89:
	case 0x8a:
	case 0x8b:
		RegleLCSW(ad & 0x0f);
		break;
	case 0x10:
		Vkbd &= 0x7f;
	}
return(TRUE);
}

BOOL EmuWCF(u_int ax, u_char vx)
{
owner= 0;
switch(ax & 0xff)
	{
	u_char p;
	case 0xff:
		if(!RdCxROM)
			{
			p= ((Reg_PC>>8) & 0x0f) - 1;
			if((Reg_PC>>12) == 0x0c && p>= 0x00 && p <0x07)
				owner= OFFBANK+(p<<11);
			}
	case 0xfe:
		for(p=0xc8; p<0xd0; p++)
			offread[p]= owner;
		return(TRUE);
	}
return(FALSE);
}

void PtoText(void)
{
u_char index;

RafEcrAC40 = RafEcrAC40T;
RafEcrAC80 = RafEcrAC80T;
RafEcr48 = (RafEcr48 == RafEcrAC40S) ? RafEcrAC40T : RafEcrAC80T;

UpdScreen40 = UpdScreen40T;
UpdScreen80m = UpdScreen80mT;
UpdScreen80a = UpdScreen80aT;

for(index=0x04; index<0x0c; index++)
	{
	if(EmuWrite[index] == UpdScreen40S)
		EmuWrite[index]= UpdScreen40T;
	else
		if(EmuWrite[index] == UpdScreen80mS)
			EmuWrite[index]= UpdScreen80mT;
	if(EmuWrite[index+(OFFBANK>>8)] == UpdScreen80aS)
		EmuWrite[index+(OFFBANK>>8)]= UpdScreen80aT;
	}

vprimarycs = primarycsT;
valternatecs = alternatecsT;
vlorescs = lorescsT;

current_textcs = (current_textcs == primarycsS) ? primarycsT : alternatecsT;
if(current_graphcs == lorescsS) current_graphcs = lorescsT;

for(index=0; index<24; index++)
	if(cs[index] == primarycsS)
		cs[index]= primarycsT;
	else
		if(cs[index] == alternatecsS)
			cs[index]= alternatecsT;
		else
			if(cs[index] == lorescsS)
				cs[index]= lorescsT;
}

void PtoSprite(void)
{
u_char index;

RafEcrAC40 = RafEcrAC40S;
RafEcrAC80 = RafEcrAC80S;
RafEcr48 = (RafEcr48 == RafEcrAC40T) ? RafEcrAC40S : RafEcrAC80S;

UpdScreen40 = UpdScreen40S;
UpdScreen80m = UpdScreen80mS;
UpdScreen80a = UpdScreen80aS;

for(index=0x04; index<0x0c; index++)
	{
	if(EmuWrite[index] == UpdScreen40T)
		EmuWrite[index]= UpdScreen40S;
	else
		if(EmuWrite[index] == UpdScreen80mT)
			EmuWrite[index]= UpdScreen80mS;
	if(EmuWrite[index+(OFFBANK>>8)] == UpdScreen80aT)
		EmuWrite[index+(OFFBANK>>8)]= UpdScreen80aS;
	}

vprimarycs = primarycsS;
valternatecs = alternatecsS;
vlorescs = lorescsS;

current_textcs = (current_textcs == primarycsT) ? primarycsS : alternatecsS;
if(current_graphcs == lorescsT) current_graphcs = lorescsS;

for(index=0; index<24; index++)
	if(cs[index] == primarycsT)
		cs[index]= primarycsS;
	else
		if(cs[index] == alternatecsT)
			cs[index]= alternatecsS;
		else
			if(cs[index] == lorescsT)
				cs[index]= lorescsS;

/* efface le trop plein a droite de l'ecran */
bbc_colour(128); /* Couleur de fond a zero */
(void) bbc_plot(bbc_Point+7,1120,0);
(void) bbc_plot(bbc_RectangleFill+7,1279,1023);
}

u_int xvtabz(rA,wndlft)
u_char rA, wndlft;
{
u_char basl;
basl= (adbase1[rA] & 0xff) + (Rd80vid ? (wndlft>>1) : wndlft);
return((adbase1[rA] & 0xff00) | basl);
}

BOOL Xscroll(void)
{
BOOL Direction= (Reg_Y != 0);
u_char wndlft= Lire_Code(0x20);
u_char wndwdth= Lire_Code(0x21);
u_char wndtop= Lire_Code(0x22);
u_char wndbtm= Lire_Code(0x23);

if(Rd80vid)
	{
	BOOL LeftEdgeOdd= ((wndlft & 1) != 0);
	BOOL RightEdgeEven= (((wndlft + wndwdth) & 1) != 0);
	u_char xwndwdth= wndwdth>>1;
	if((!LeftEdgeOdd) && (!RightEdgeEven)) xwndwdth--;
	if(Direction)
		{
		u_int bas, bas2;
		u_char rX= wndtop;
		bas= xvtabz(rX,wndlft);
		while((bas2=bas), (++rX <wndbtm))
			{
			u_char rY;
			bas= xvtabz(rX,wndlft);
				for(rY= xwndwdth; rY>0; rY--)
					AppleCode->bytes[bas2+rY+OFFBANK]=
						AppleCode->bytes[bas+rY+OFFBANK];
			if(!LeftEdgeOdd)
				AppleCode->bytes[bas2+OFFBANK]=
					AppleCode->bytes[bas+OFFBANK];
			for(rY= xwndwdth - (RightEdgeEven ? 1 : 0); rY <128; rY--)
				AppleCode->bytes[bas2+rY]= AppleCode->bytes[bas+rY];
			}					
		}
	else
		{
		u_int bas, bas2;
		u_char rX= wndbtm-1;
		bas= xvtabz(rX, wndlft);
		while((bas2=bas), ((--rX - wndtop) < 128))
			{
			u_char rY;
			bas= xvtabz(rX,wndlft);
			for(rY= xwndwdth; rY>0; rY--)
				AppleCode->bytes[bas2+rY+OFFBANK]=
					AppleCode->bytes[bas+rY+OFFBANK];
			if(!LeftEdgeOdd)
				AppleCode->bytes[bas2+OFFBANK]=
					AppleCode->bytes[bas+OFFBANK];
			for(rY= xwndwdth - (RightEdgeEven ? 1 : 0); rY <128; rY--)
				AppleCode->bytes[bas2+rY]= AppleCode->bytes[bas+rY];
			}
		}   
	}
else
	{
	if(Direction)
		{
		u_int bas, bas2;
		u_char rX= wndtop;
		bas= xvtabz(rX,wndlft);
		while((bas2=bas), (++rX <wndbtm))
			{
			u_char rY;
			bas= xvtabz(rX,wndlft);
			rY= wndwdth;
			if (rY--)
				for(;rY<128;rY--) AppleCode->bytes[bas2+rY]=
					AppleCode->bytes[bas+rY];  
			}
		}
	else
		{
		u_int bas, bas2;
		u_char rX= wndbtm-1;
		bas= xvtabz(rX, wndlft);
		while((bas2=bas), ((--rX - wndtop) < 128))
			{
			u_char rY;
			bas= xvtabz(rX,wndlft);
			rY= wndwdth;
			if (rY--)
				for(;rY<128;rY--) AppleCode->bytes[bas2+rY]=
					AppleCode->bytes[bas+rY];  
			}
		}
	}
if(	wndwdth!= 0 &&
	(wndlft+wndwdth)<= (Rd80vid ? 80 : 40) &&
	wndbtm<=24 && wndtop<wndbtm)
	{
	BOOL Isprite= (vprimarycs == primarycsS);
	extern u_int x_offset[80];
	extern u_char scale_x;
	u_int xscreen, yscreen;
	if(wndtop+1 == wndbtm) return(TRUE);
	xscreen= (Isprite ? x_offset[wndlft + wndwdth] : (wndlft+wndwdth)<<3)-1;
	yscreen= 255-(wndtop<<3); if (Direction) yscreen-= 8;
	bbc_move(xscreen<<scale_x,yscreen<<2);
	xscreen= Isprite ? x_offset[wndlft] : wndlft<<3;
	yscreen= 255-(wndbtm<<3)+1; if(!Direction) yscreen+= 8;
	bbc_move(xscreen<<scale_x,yscreen<<2);
	bbc_plot(0xba,0,(Direction ? 32 : -32));
	}
else
	(*RafEcr48)(); 
return(TRUE);
}
