/** ADAMEm: Coleco ADAM emulator ********************************************/ /** **/ /** Common.h **/ /** **/ /** This file contains the system-independent part of the screen refresh **/ /** drivers and general modem drivers **/ /** **/ /** Copyright (C) Marcel de Kogel 1996,1997,1998,1999 **/ /** You are not allowed to distribute this software commercially **/ /** Please, notify me, if you make any changes to this file **/ /****************************************************************************/ /****************************************************************************/ /* Uncomment any of these if you don't want to use a particular driver */ /****************************************************************************/ /* #define NO_COMMON_SCREEN_REFRESH_DRIVERS */ /* #define NO_COMMON_MODEM_DRIVERS */ #ifndef NO_COMMON_SCREEN_REFRESH_DRIVERS /****************************************************************************/ /* Uncomment this if you want to use lookup tables for the screen refresh */ /* Using lookup tables greatly increases the emulation speed, but is only */ /* compatible with 32-bit machines */ /****************************************************************************/ /* #define USE_LOOKUP_TABLE */ /****************************************************************************/ /* Uncomment this if you're using an 8 bbp video device */ /****************************************************************************/ /* #define _8BPP */ #ifdef _8BPP #define PutPixel(P,C) DisplayBuf[P]=C #endif /****************************************************************************/ /** Refresh sprites **/ /****************************************************************************/ #define BigPixel(P,C) {\ PutPixel (P,C); \ PutPixel (P+1,C); \ PutPixel (P+WIDTH,C); \ PutPixel (P+WIDTH+1,C);} #define BigPixelClipped(X,Y,P,C) { \ if (X>=0 && X<256 && Y>=0 && Y<192) PutPixel(P,C); \ if (X+1>=0 && X+1<256 && Y>=0 && Y<192) PutPixel(P+1,C); \ if (X>=0 && X<256 && Y+1>=0 && Y+1<192) PutPixel(P+WIDTH,C); \ if (X+1>=0 && X+1<256 && Y+1>=0 && Y+1<192) PutPixel(P+WIDTH+1,C); } #define PixelClipped(X,P,C) { \ if (X>=0 && X<256) PutPixel(P,C); } static void BigSprite (int X,int Y,int P,int J,int C) { if (J) { if (J) if (X>=0 && X<242 && Y>=0 && Y<191) { if(J&0x80) BigPixel (P,C); if(J&0x40) BigPixel (P+2,C); if(J&0x20) BigPixel (P+4,C); if(J&0x10) BigPixel (P+6,C); if(J&0x08) BigPixel (P+8,C); if(J&0x04) BigPixel (P+10,C); if(J&0x02) BigPixel (P+12,C); if(J&0x01) BigPixel (P+14,C); } else if (X>=-1 && X<256 && Y>=-1 && Y<192) { if(J&0x80) BigPixelClipped (X,Y,P,C); if(J&0x40) BigPixelClipped (X+2,Y,P+2,C); if(J&0x20) BigPixelClipped (X+4,Y,P+4,C); if(J&0x10) BigPixelClipped (X+6,Y,P+6,C); if(J&0x08) BigPixelClipped (X+8,Y,P+8,C); if(J&0x04) BigPixelClipped (X+10,Y,P+10,C); if(J&0x02) BigPixelClipped (X+12,Y,P+12,C); if(J&0x01) BigPixelClipped (X+14,Y,P+14,C); } } } static void Sprite (int X,int Y,int P,int J,int C) { if (Y>=0 && Y<192 && J) if (X>=0 && X<248) { if (J&0x80) PutPixel (P+0,C); if (J&0x40) PutPixel (P+1,C); if (J&0x20) PutPixel (P+2,C); if (J&0x10) PutPixel (P+3,C); if (J&0x08) PutPixel (P+4,C); if (J&0x04) PutPixel (P+5,C); if (J&0x02) PutPixel (P+6,C); if (J&0x01) PutPixel (P+7,C); } else if (X>-8 && X<256) { if (J&0x80) PixelClipped (X+0,P+0,C); if (J&0x40) PixelClipped (X+1,P+1,C); if (J&0x20) PixelClipped (X+2,P+2,C); if (J&0x10) PixelClipped (X+3,P+3,C); if (J&0x08) PixelClipped (X+4,P+4,C); if (J&0x04) PixelClipped (X+5,P+5,C); if (J&0x02) PixelClipped (X+6,P+6,C); if (J&0x01) PixelClipped (X+7,P+7,C); } } static void RefreshSprites(void) { byte *T,*S; byte *SprGen; int SpriteSize,X,Y,C,N,P,y; SpriteSize=((Sprites16x16)? 16:8)*((BigSprites)? 2:1); SprGen=VDP.VRAM+(((VDP.Reg[6]&7)*2048)&VDP.VRAMSize); /* Get pointer to first sprite */ S=VDP.VRAM+(((VDP.Reg[5]&127)*128)&VDP.VRAMSize); for(N=0;(N<32)&&(S[0]!=208);N++,S+=4); S-=4; N--; for (;N>=0;N--,S-=4) { C=S[3]&15; Y=S[0]; if (Y>=234) Y=Y-255; else ++Y; X=S[1]; if (S[3]&0x80) X-=32; if (X>-SpriteSize && X<256 && Y>-SpriteSize && Y<192 && C) { P=WIDTH*(HEIGHT-192)/2+(WIDTH-256)/2+X+Y*WIDTH; C=PalBuf[C]; if (Sprites16x16) { T=SprGen+(S[2]&0xFC)*8; if (BigSprites) { for(y=16;y;y--,Y+=2,T++,P+=WIDTH*2) { if (LastSprite[Y&255]>=N) { BigSprite (X,Y,P,T[0],C); BigSprite (X+16,Y,P+16,T[16],C); } } } else { for(y=16;y;y--,Y++,T++,P+=WIDTH) { if (LastSprite[Y&255]>=N) { Sprite (X,Y,P,T[0],C); Sprite (X+8,Y,P+8,T[16],C); } } } } else { T=SprGen+S[2]*8; if (BigSprites) for (y=8;y;y--,Y+=2,T++,P+=WIDTH*2) { if (LastSprite[Y&255]>=N) { BigSprite (X,Y,P,T[0],C); } } else for (y=8;y;y--,Y++,T++,P+=WIDTH) { if (LastSprite[Y&255]>=N) { Sprite (X,Y,P,T[0],C); } } } } } } /****************************************************************************/ /** Refresh background **/ /****************************************************************************/ static void RefreshScreen0 (void) { byte *S,*T,*PGT; int P,N,X,Y,J,K,BC,FC; P=WIDTH*(HEIGHT-192)/2+(WIDTH-240)/2; BC=PalBuf[VDP.BGColour]; FC=PalBuf[VDP.FGColour]; PGT=VDP.VRAM+(((VDP.Reg[4]&((VDP.Reg[0]&2)?4:7))*2048)&VDP.VRAMSize); T=VDP.VRAM+(((VDP.Reg[2]&15)*1024)&VDP.VRAMSize); for (N=0;N<3;++N) { for(Y=8;Y;Y--) { for (J=0;J<8;++J) { PutPixel(P-8,BC);PutPixel(P-7,BC); PutPixel(P-6,BC);PutPixel(P-5,BC); PutPixel(P-4,BC);PutPixel(P-3,BC); PutPixel(P-2,BC);PutPixel(P-1,BC); PutPixel(P+240,BC);PutPixel(P+241,BC); PutPixel(P+242,BC);PutPixel(P+243,BC); PutPixel(P+244,BC);PutPixel(P+245,BC); PutPixel(P+246,BC);PutPixel(P+247,BC); P+=WIDTH; } P-=8*WIDTH; for (X=40;X;X--) { S=PGT+T[0]*8; for (J=0;J<8;J++) { K=*S++; PutPixel (P+0,(K&0x80)? FC:BC); PutPixel (P+1,(K&0x40)? FC:BC); PutPixel (P+2,(K&0x20)? FC:BC); PutPixel (P+3,(K&0x10)? FC:BC); PutPixel (P+4,(K&0x08)? FC:BC); PutPixel (P+5,(K&0x04)? FC:BC); P+=WIDTH; } P+=6-WIDTH*8; T++; } P+=WIDTH*8-6*40; } if (VDP.Reg[0]&2) { if (N==0 && (VDP.Reg[4]&2)) PGT+=0x800; if (N==1) { switch (VDP.Reg[4]&3) { case 0: break; case 1: PGT+=0x1000; break; case 2: PGT-=0x800; break; case 3: PGT+=0x800; break; } } } } } #ifdef USE_LOOKUP_TABLE static void RefreshScreen1 (void) { int X,Y,K; byte *P,*S,*T,*PGT,*CLT; unsigned *s; P=DisplayBuf+WIDTH*(HEIGHT-192)/2+(WIDTH-256)/2; PGT=VDP.VRAM+(((VDP.Reg[4]&((VDP.Reg[0]&2)?4:7))*2048)&VDP.VRAMSize); CLT=VDP.VRAM+(((VDP.Reg[3]&((VDP.Reg[0]&2)?128:255))*64)&VDP.VRAMSize); T=VDP.VRAM+(((VDP.Reg[2]&15)*1024)&VDP.VRAMSize); for(Y=24;Y;Y--,P+=WIDTH*8-8*32) for(X=32;X;X--) { S=PGT+T[0]*8; s=font2screen+CLT[T[0]>>3]*16; K=S[0]; *(unsigned*)(P+0+WIDTH*0)=s[K>>4]; *(unsigned*)(P+4+WIDTH*0)=s[K&0x0F]; K=S[1]; *(unsigned*)(P+0+WIDTH*1)=s[K>>4]; *(unsigned*)(P+4+WIDTH*1)=s[K&0x0F]; K=S[2]; *(unsigned*)(P+0+WIDTH*2)=s[K>>4]; *(unsigned*)(P+4+WIDTH*2)=s[K&0x0F]; K=S[3]; *(unsigned*)(P+0+WIDTH*3)=s[K>>4]; *(unsigned*)(P+4+WIDTH*3)=s[K&0x0F]; K=S[4]; *(unsigned*)(P+0+WIDTH*4)=s[K>>4]; *(unsigned*)(P+4+WIDTH*4)=s[K&0x0F]; K=S[5]; *(unsigned*)(P+0+WIDTH*5)=s[K>>4]; *(unsigned*)(P+4+WIDTH*5)=s[K&0x0F]; K=S[6]; *(unsigned*)(P+0+WIDTH*6)=s[K>>4]; *(unsigned*)(P+4+WIDTH*6)=s[K&0x0F]; K=S[7]; *(unsigned*)(P+0+WIDTH*7)=s[K>>4]; *(unsigned*)(P+4+WIDTH*7)=s[K&0x0F]; P+=8; T++; } } static void RefreshScreen2 (void) { int X,Y,K,N; byte *P,*S,*T,*PGT,*CLT,*C; unsigned *s; P=DisplayBuf+WIDTH*(HEIGHT-192)/2+(WIDTH-256)/2; PGT=VDP.VRAM+(((VDP.Reg[4]&((VDP.Reg[0]&2)?4:7))*2048)&VDP.VRAMSize); CLT=VDP.VRAM+(((VDP.Reg[3]&((VDP.Reg[0]&2)?128:255))*64)&VDP.VRAMSize); T=VDP.VRAM+(((VDP.Reg[2]&15)*1024)&VDP.VRAMSize); for(N=0;N<3;N++) { for(Y=8;Y;Y--) { for(X=32;X;X--) { S=PGT+T[0]*8;C=CLT+T[0]*8; K=S[0]; s=font2screen+C[0]*16; *(unsigned*)(P+0+WIDTH*0)=s[K>>4]; *(unsigned*)(P+4+WIDTH*0)=s[K&0x0F]; K=S[1]; s=font2screen+C[1]*16; *(unsigned*)(P+0+WIDTH*1)=s[K>>4]; *(unsigned*)(P+4+WIDTH*1)=s[K&0x0F]; K=S[2]; s=font2screen+C[2]*16; *(unsigned*)(P+0+WIDTH*2)=s[K>>4]; *(unsigned*)(P+4+WIDTH*2)=s[K&0x0F]; K=S[3]; s=font2screen+C[3]*16; *(unsigned*)(P+0+WIDTH*3)=s[K>>4]; *(unsigned*)(P+4+WIDTH*3)=s[K&0x0F]; K=S[4]; s=font2screen+C[4]*16; *(unsigned*)(P+0+WIDTH*4)=s[K>>4]; *(unsigned*)(P+4+WIDTH*4)=s[K&0x0F]; K=S[5]; s=font2screen+C[5]*16; *(unsigned*)(P+0+WIDTH*5)=s[K>>4]; *(unsigned*)(P+4+WIDTH*5)=s[K&0x0F]; K=S[6]; s=font2screen+C[6]*16; *(unsigned*)(P+0+WIDTH*6)=s[K>>4]; *(unsigned*)(P+4+WIDTH*6)=s[K&0x0F]; K=S[7]; s=font2screen+C[7]*16; *(unsigned*)(P+0+WIDTH*7)=s[K>>4]; *(unsigned*)(P+4+WIDTH*7)=s[K&0x0F]; P+=8; T++; } P+=WIDTH*8-8*32; } switch (N) { case 0: if (VDP.Reg[4]&2) PGT+=0x800; if (VDP.Reg[3]&0x40) CLT+=0x800; break; case 1: switch (VDP.Reg[4]&3) { case 0: break; case 1: PGT+=0x1000; break; case 2: PGT-=0x800; break; case 3: PGT+=0x800; break; } switch (VDP.Reg[3]&0x60) { case 0: break; case 0x20: CLT+=0x1000; break; case 0x40: CLT-=0x800; break; case 0x60: CLT+=0x800; break; } break; } } } static void RefreshScreen3 (void) { byte *P,*T,*C,*PGT; int N,X,Y,C1,C2; P=DisplayBuf+WIDTH*(HEIGHT-192)/2+(WIDTH-256)/2; PGT=VDP.VRAM+(((VDP.Reg[4]&((VDP.Reg[0]&2)?4:7))*2048)&VDP.VRAMSize); T=VDP.VRAM+(((VDP.Reg[2]&15)*1024)&VDP.VRAMSize); for (N=0;N<3;++N) { for(Y=0;Y<8;Y++) { for(X=32;X;X--) { C=PGT+T[0]*8+((Y&3)<<1); C1=PalBuf[C[0]>>4] *0x01010101L; C2=PalBuf[C[0]&0x0F]*0x01010101L; *(unsigned*)P=C1;P+=4;*(unsigned*)P=C2;P+=WIDTH-4; *(unsigned*)P=C1;P+=4;*(unsigned*)P=C2;P+=WIDTH-4; *(unsigned*)P=C1;P+=4;*(unsigned*)P=C2;P+=WIDTH-4; *(unsigned*)P=C1;P+=4;*(unsigned*)P=C2;P+=WIDTH-4; C1=PalBuf[C[1]>>4] *0x01010101L; C2=PalBuf[C[1]&0x0F]*0x01010101L; *(unsigned*)P=C1;P+=4;*(unsigned*)P=C2;P+=WIDTH-4; *(unsigned*)P=C1;P+=4;*(unsigned*)P=C2;P+=WIDTH-4; *(unsigned*)P=C1;P+=4;*(unsigned*)P=C2;P+=WIDTH-4; *(unsigned*)P=C1;P+=4;*(unsigned*)P=C2; T++; P+=4-7*WIDTH; } P+=WIDTH*8-8*32; } if (VDP.Reg[0]&2) { if (N==0 && (VDP.Reg[4]&2)) PGT+=0x800; if (N==1) { switch (VDP.Reg[4]&3) { case 0: break; case 1: PGT+=0x1000; break; case 2: PGT-=0x800; break; case 3: PGT+=0x800; break; } } } } } #else static void RefreshScreen1 (void) { int X,Y,K,I,BC,FC,P; byte *S,*T,*PGT,*CLT; P=WIDTH*(HEIGHT-192)/2+(WIDTH-256)/2; PGT=VDP.VRAM+(((VDP.Reg[4]&((VDP.Reg[0]&2)?4:7))*2048)&VDP.VRAMSize); CLT=VDP.VRAM+(((VDP.Reg[3]&((VDP.Reg[0]&2)?128:255))*64)&VDP.VRAMSize); T=VDP.VRAM+(((VDP.Reg[2]&15)*1024)&VDP.VRAMSize); for(Y=24;Y;Y--) { for(X=32;X;X--) { S=PGT+T[0]*8; BC=CLT[T[0]>>3]; FC=PalBuf[BC>>4]; BC=PalBuf[BC&0x0F]; for(I=0;I<8;I++,P+=WIDTH) { K=*S++; PutPixel (P+0,(K&0x80)? FC:BC); PutPixel (P+1,(K&0x40)? FC:BC); PutPixel (P+2,(K&0x20)? FC:BC); PutPixel (P+3,(K&0x10)? FC:BC); PutPixel (P+4,(K&0x08)? FC:BC); PutPixel (P+5,(K&0x04)? FC:BC); PutPixel (P+6,(K&0x02)? FC:BC); PutPixel (P+7,(K&0x01)? FC:BC); } T++; P+=8-WIDTH*8; } P+=WIDTH*8-8*32; } } static void RefreshScreen2 (void) { int X,Y,K,I,N,FC,BC,P; byte *S,*T,*PGT,*CLT,*C; P=WIDTH*(HEIGHT-192)/2+(WIDTH-256)/2; PGT=VDP.VRAM+(((VDP.Reg[4]&((VDP.Reg[0]&2)?4:7))*2048)&VDP.VRAMSize); CLT=VDP.VRAM+(((VDP.Reg[3]&((VDP.Reg[0]&2)?128:255))*64)&VDP.VRAMSize); T=VDP.VRAM+(((VDP.Reg[2]&15)*1024)&VDP.VRAMSize); for(N=0;N<3;N++) { for(Y=8;Y;Y--) { for(X=32;X;X--) { S=PGT+T[0]*8; C=CLT+T[0]*8; for(I=0;I<8;I++) { BC=PalBuf[C[0]&0x0F]; FC=PalBuf[C[0]>>4]; ++C; K=*S++; PutPixel (P+0,(K&0x80)? FC:BC); PutPixel (P+1,(K&0x40)? FC:BC); PutPixel (P+2,(K&0x20)? FC:BC); PutPixel (P+3,(K&0x10)? FC:BC); PutPixel (P+4,(K&0x08)? FC:BC); PutPixel (P+5,(K&0x04)? FC:BC); PutPixel (P+6,(K&0x02)? FC:BC); PutPixel (P+7,(K&0x01)? FC:BC); P+=WIDTH; } T++; P+=8-WIDTH*8; } P+=WIDTH*8-8*32; } if (N==0 && (VDP.Reg[4]&2)) PGT+=0x800; if (N==0 && (VDP.Reg[3]&0x40)) CLT+=0x800; if (N==1) { switch (VDP.Reg[4]&3) { case 0: break; case 1: PGT+=0x1000; break; case 2: PGT-=0x800; break; case 3: PGT+=0x800; break; } switch (VDP.Reg[3]&0x60) { case 0: break; case 0x20: CLT+=0x1000; break; case 0x40: CLT-=0x800; break; case 0x60: CLT+=0x800; break; } } } } static void RefreshScreen3 (void) { byte *T,*C,*PGT; int X,Y,C1,C2,N,P; P=WIDTH*(HEIGHT-192)/2+(WIDTH-256)/2; PGT=VDP.VRAM+(((VDP.Reg[4]&((VDP.Reg[0]&2)?4:7))*2048)&VDP.VRAMSize); T=VDP.VRAM+(((VDP.Reg[2]&15)*1024)&VDP.VRAMSize); for (N=0;N<3;++N) { for(Y=0;Y<8;Y++) { for(X=32;X;X--) { C=PGT+T[0]*8+((Y&3)<<1); C1=PalBuf[C[0]>>4]; C2=PalBuf[C[0]&0x0F]; PutPixel(P+0,C1); PutPixel(P+1,C1); PutPixel(P+2,C1); PutPixel(P+3,C1); PutPixel(P+4,C2); PutPixel(P+5,C2); PutPixel(P+6,C2); PutPixel(P+7,C2); P+=WIDTH; PutPixel(P+0,C1); PutPixel(P+1,C1); PutPixel(P+2,C1); PutPixel(P+3,C1); PutPixel(P+4,C2); PutPixel(P+5,C2); PutPixel(P+6,C2); PutPixel(P+7,C2); P+=WIDTH; PutPixel(P+0,C1); PutPixel(P+1,C1); PutPixel(P+2,C1); PutPixel(P+3,C1); PutPixel(P+4,C2); PutPixel(P+5,C2); PutPixel(P+6,C2); PutPixel(P+7,C2); P+=WIDTH; PutPixel(P+0,C1); PutPixel(P+1,C1); PutPixel(P+2,C1); PutPixel(P+3,C1); PutPixel(P+4,C2); PutPixel(P+5,C2); PutPixel(P+6,C2); PutPixel(P+7,C2); P+=WIDTH; C1=PalBuf[C[1]>>4]; C2=PalBuf[C[1]&0x0F]; PutPixel(P+0,C1); PutPixel(P+1,C1); PutPixel(P+2,C1); PutPixel(P+3,C1); PutPixel(P+4,C2); PutPixel(P+5,C2); PutPixel(P+6,C2); PutPixel(P+7,C2); P+=WIDTH; PutPixel(P+0,C1); PutPixel(P+1,C1); PutPixel(P+2,C1); PutPixel(P+3,C1); PutPixel(P+4,C2); PutPixel(P+5,C2); PutPixel(P+6,C2); PutPixel(P+7,C2); P+=WIDTH; PutPixel(P+0,C1); PutPixel(P+1,C1); PutPixel(P+2,C1); PutPixel(P+3,C1); PutPixel(P+4,C2); PutPixel(P+5,C2); PutPixel(P+6,C2); PutPixel(P+7,C2); P+=WIDTH; PutPixel(P+0,C1); PutPixel(P+1,C1); PutPixel(P+2,C1); PutPixel(P+3,C1); PutPixel(P+4,C2); PutPixel(P+5,C2); PutPixel(P+6,C2); PutPixel(P+7,C2); T++; P+=8-7*WIDTH; } P+=WIDTH*8-8*32; } if (VDP.Reg[0]&2) { if (N==0 && (VDP.Reg[4]&2)) PGT+=0x800; if (N==1) { switch (VDP.Reg[4]&3) { case 0: break; case 1: PGT+=0x1000; break; case 2: PGT-=0x800; break; case 3: PGT+=0x800; break; } } } } } #endif static void RefreshScreenConflict (void) { int X,Y,BC,FC,P; P=WIDTH*(HEIGHT-192)/2+(WIDTH-256)/2; FC=PalBuf[VDP.FGColour]; BC=PalBuf[VDP.BGColour]; for(Y=192;Y;Y--,P+=WIDTH) { for(X=16;X;X--) { PutPixel(P+0,FC); PutPixel(P+1,FC); PutPixel(P+2,FC); PutPixel(P+3,FC); PutPixel(P+4,FC); PutPixel(P+5,FC); PutPixel(P+6,FC); PutPixel(P+7,FC); P+=8; PutPixel(P+0,BC); PutPixel(P+1,BC); PutPixel(P+2,BC); PutPixel(P+3,BC); PutPixel(P+4,BC); PutPixel(P+5,BC); PutPixel(P+6,BC); PutPixel(P+7,BC); P+=8; } } } #ifdef TEXT80 static int CheckTDOS (void) /* Return offset of screenbuffer */ { int addr; addr=RAM[0x01]+RAM[0x02]*256+0x6D-3; /* Read block buffer routine */ addr=RAM[addr]+RAM[addr+1]*256; /* Get the address */ if (RAM[addr+0]==0xF5 && /* Check routine code */ RAM[addr+1]==0xC5 && RAM[addr+2]==0xD5 && RAM[addr+3]==0xCD && RAM[addr+6]==0x30 && RAM[addr+8]==0xE1 && RAM[addr+9]==0x11 && RAM[addr+12]==0x01 && RAM[addr+13]==0x00 && RAM[addr+14]==0x04 && RAM[addr+15]==0xED && RAM[addr+16]==0xB0 && (VDP.Reg[0]&0x02)==0x00 && /* Check video mode */ (VDP.Reg[1]&0x18)==0x10) return RAM[addr+10]+RAM[addr+11]*256+0x400; return 0; } #endif void RefreshScreen (int ScreenChanged) { int i; if (ScreenON) { #ifdef TEXT80 int addr; addr=CheckTDOS (); if (AutoText80) /* Switch to/from Text80 mode if */ { /* necessary */ if (addr) { if (!Text80) InitText80(); } else { if (Text80) ResetText80(); } } if (Text80) { int num_lines; i=RAM[0x01]+RAM[0x02]*256+0x64-3; /* Get number of lines */ i=RAM[i]+RAM[i+1]*256; /* ... to display */ i=RAM[i+3]+RAM[i+4]*256; num_lines=RAM[i]+1; if (num_lines>24) num_lines=24; /* Just in case ... */ memcpy(DisplayBuf,RAM+addr,num_lines*80); /* Copy offscreen buffer */ addr=((VDP.Reg[2]&15)*1024)&VDP.VRAMSize; for (i=num_lines;i<24;++i) { memcpy(DisplayBuf+i*80,VDP.VRAM+addr+i*40,40); /* Copy smartkey display */ memset(DisplayBuf+i*80+40,' ',40); /* Clear rest of buffer */ } Text80Colour=VDP.FGColour; } else #endif { if (!ScreenChanged) return; switch((VDP.Reg[0]&0x02)|(VDP.Reg[1]&0x18)) { case 0x12: case 0x10: RefreshScreen0(); break; case 0x00: RefreshScreen1(); RefreshSprites(); break; case 0x02: RefreshScreen2(); RefreshSprites(); break; case 0x0A: case 0x08: RefreshScreen3(); RefreshSprites(); break; default: RefreshScreenConflict(); break; } } } else { #ifdef TEXT80 if (Text80) { for (i=0;i<80*24;++i) DisplayBuf[i]=' '; } else #endif for (i=0;i