added support for ansi terminal graphics.
outputted the 0xD 0xA when they appear in the Read function Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@568
This commit is contained in:
parent
ce851095e0
commit
8ae271bf19
1 changed files with 252 additions and 4 deletions
|
@ -17,6 +17,9 @@
|
|||
*/
|
||||
|
||||
#include "dos_inc.h"
|
||||
#include "../ints/int10.h"
|
||||
|
||||
#define NUMBER_ANSI_DATA 10
|
||||
|
||||
class device_CON : public DOS_Device {
|
||||
public:
|
||||
|
@ -25,11 +28,25 @@ public:
|
|||
bool Write(Bit8u * data,Bit16u * size);
|
||||
bool Seek(Bit32u * pos,Bit32u type);
|
||||
bool Close();
|
||||
void ClearAnsi(void);
|
||||
Bit16u GetInformation(void);
|
||||
private:
|
||||
Bit8u cache;
|
||||
struct ansi { /* should create a constructor which fills them with the appriorate values */
|
||||
bool esc;
|
||||
bool sci;
|
||||
Bit8u attr;
|
||||
Bit8u data[NUMBER_ANSI_DATA];
|
||||
Bit8u numberofarg;
|
||||
Bit16u nrows;
|
||||
Bit16u ncols;
|
||||
Bit8s savecol;
|
||||
Bit8s saverow;
|
||||
} ansi;
|
||||
|
||||
};
|
||||
void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page);
|
||||
void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page);
|
||||
|
||||
bool device_CON::Read(Bit8u * data,Bit16u * size) {
|
||||
Bit16u oldax=reg_ax;
|
||||
|
@ -51,6 +68,10 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
|
|||
if (*size>count) data[count++]=0x0A; // it's only expanded if there is room for it. (NO cache)
|
||||
*size=count;
|
||||
reg_ax=oldax;
|
||||
if(dos.echo) {
|
||||
INT10_TeletypeOutput(13,7,false,0); //maybe don't do this ( no need for it actually ) (but it's compatible)
|
||||
INT10_TeletypeOutput(10,7,false,0);
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case 8:
|
||||
|
@ -86,10 +107,223 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
|
|||
|
||||
bool device_CON::Write(Bit8u * data,Bit16u * size) {
|
||||
Bit16u count=0;
|
||||
while (*size>count) {
|
||||
Bitu i;
|
||||
Bit8s col,row;
|
||||
static bool ansiwarned=false;
|
||||
|
||||
INT10_TeletypeOutput(data[count],7,false,0);
|
||||
count++;
|
||||
while (*size>count) {
|
||||
if (!ansi.esc){
|
||||
if(data[count]=='\033') {
|
||||
/*clear the datastructure */
|
||||
ClearAnsi();
|
||||
/* start the sequence */
|
||||
ansi.esc=true;
|
||||
count++;
|
||||
if(!ansiwarned) {
|
||||
LOG_WARN("ANSI sequences detected. enabling ansi support"); /* maybe LOG_MSG */
|
||||
ansiwarned=true;
|
||||
}
|
||||
continue;
|
||||
|
||||
} else {
|
||||
INT10_TeletypeOutput(data[count],ansi.attr,true,0);
|
||||
count++;
|
||||
continue;
|
||||
};
|
||||
};
|
||||
/* ansi.esc=true */
|
||||
if(!ansi.sci){
|
||||
|
||||
switch(data[count]){
|
||||
case '[':
|
||||
ansi.sci=true;
|
||||
break;
|
||||
case '7': /* save cursor pos +attr */
|
||||
case '8': /* restore this (Wonder if this is actually used) */
|
||||
case 'D':/* scrolling DOWN*/
|
||||
case 'M':/* scrolling UP*/
|
||||
default:
|
||||
LOG_DEBUG("ANSI: unknown char %c after a esc",data[count]); /*prob () */
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
continue;
|
||||
|
||||
}
|
||||
/*ansi.esc and ansi.sci are true */
|
||||
switch(data[count]){
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
ansi.data[ansi.numberofarg]=10*ansi.data[ansi.numberofarg]+(data[count]-'0');
|
||||
break;
|
||||
case ';': /* till a max of NUMBER_ANSI_DATA */
|
||||
ansi.numberofarg++;
|
||||
break;
|
||||
case 'm': /* SGR */
|
||||
for(i=0;i<=ansi.numberofarg;i++){
|
||||
|
||||
switch(ansi.data[i]){
|
||||
case 0: /* normal */
|
||||
ansi.attr=0x7;
|
||||
break;
|
||||
case 1: /* bold mode on*/
|
||||
ansi.attr|=0x8;
|
||||
break;
|
||||
case 4: /* underline */
|
||||
LOG_DEBUG("ANSI:no support for underline yet");
|
||||
break;
|
||||
case 5: /* blinking */
|
||||
LOG_DEBUG("ANSI:no support for blinking yet");
|
||||
break;
|
||||
case 7: /* reverse */
|
||||
LOG_DEBUG("ANSI:no support for reverse yet");
|
||||
break;
|
||||
case 30: /* fg color black */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x0;
|
||||
break;
|
||||
case 31: /* fg color red */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x4;
|
||||
break;
|
||||
case 32: /* fg color green */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x2;
|
||||
break;
|
||||
case 33: /* fg color yellow */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x6;
|
||||
break;
|
||||
case 34: /* fg color blue */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x1;
|
||||
break;
|
||||
case 35: /* fg color magenta */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x5;
|
||||
break;
|
||||
case 36: /* fg color cyan */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x3;
|
||||
break;
|
||||
case 37: /* fg color white */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x7;
|
||||
break;
|
||||
case 40:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x0;
|
||||
break;
|
||||
case 41:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x40;
|
||||
break;
|
||||
case 42:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x20;
|
||||
break;
|
||||
case 43:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x60;
|
||||
break;
|
||||
case 44:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x10;
|
||||
break;
|
||||
case 45:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x50;
|
||||
break;
|
||||
case 46:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x30;
|
||||
break;
|
||||
case 47:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x70;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'f':
|
||||
case 'H':/* Cursor Pos*/
|
||||
if(ansi.data[0]==0) ansi.data[0]=1;
|
||||
if(ansi.data[1]==0) ansi.data[1]=1;
|
||||
INT10_SetCursorPos(--(ansi.data[0]),--(ansi.data[1]),0); /*ansi=1 based, int10 is 0 based */
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'A': /* cursor up*/
|
||||
col=CURSOR_POS_COL(0) ;
|
||||
row=CURSOR_POS_ROW(0) - (ansi.data[0]? ansi.data[0] : 1);
|
||||
INT10_SetCursorPos(row,col,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'C': /*cursor forward */
|
||||
col=CURSOR_POS_COL(0) + (ansi.data[0]? ansi.data[0] : 1);
|
||||
row=CURSOR_POS_ROW(0);
|
||||
while(col>=ansi.ncols) {
|
||||
row++;
|
||||
col = col - ansi.ncols; // should depend on linebrake mode
|
||||
}
|
||||
INT10_SetCursorPos(row,col,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'J': /*erase screen and move cursor home*/
|
||||
if(ansi.data[0]==0) ansi.data[0]=2;
|
||||
if(ansi.data[0]!=2) {/* only number 2 (the standard one supported) */
|
||||
LOG_DEBUG("ANSI: esc[%dJ called : not supported",ansi.data[0]);
|
||||
break;
|
||||
}
|
||||
for(i=0;i<(Bitu)ansi.ncols*ansi.nrows;i++) INT10_TeletypeOutput(' ',ansi.attr,true,0);
|
||||
ClearAnsi();
|
||||
INT10_SetCursorPos(0,0,0);
|
||||
break;
|
||||
case 'h': /* set MODE (if code =7 enable linewrap) */
|
||||
case 'I': /*RESET MODE */
|
||||
LOG_DEBUG("ANSI: set/reset mode called(not supported)");
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'D': /*Cursor Backward */
|
||||
col=CURSOR_POS_COL(0) - (ansi.data[0]? ansi.data[0] : 1);
|
||||
row=CURSOR_POS_ROW(0);
|
||||
while(col<0) {
|
||||
row--;
|
||||
col = col + ansi.ncols ; // should depend on linebrake mode
|
||||
}
|
||||
INT10_SetCursorPos(row,col,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'u': /* Restore Cursor Pos */
|
||||
INT10_SetCursorPos(ansi.saverow,ansi.savecol,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 's': /* SAVE CURSOR POS */
|
||||
ansi.savecol=CURSOR_POS_COL(0);
|
||||
ansi.saverow=CURSOR_POS_ROW(0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'K':/* erase till end of line */
|
||||
case 'l':/* (if code =7) disable linewrap */
|
||||
case 'p':/* reassign keys (needs strings) */
|
||||
case 'i':/* printer stuff */
|
||||
default:
|
||||
LOG_DEBUG("ANSI: unhandled char %c in esc[",data[count]);
|
||||
ClearAnsi();
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
*size=count;
|
||||
return true;
|
||||
|
@ -113,9 +347,23 @@ Bit16u device_CON::GetInformation(void) {
|
|||
return 0x8093; /* Key Available */
|
||||
};
|
||||
|
||||
|
||||
device_CON::device_CON() {
|
||||
name="CON";
|
||||
cache=0;
|
||||
ansi.esc=false;
|
||||
ansi.sci=false;
|
||||
ansi.attr=0x7;
|
||||
ansi.numberofarg=0;
|
||||
for(Bit8u i=0; i<NUMBER_ANSI_DATA;i++) ansi.data[i]=0;
|
||||
ansi.ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); //should be updated once set/reset mode is implemented
|
||||
ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS);
|
||||
ansi.saverow=0;
|
||||
ansi.savecol=0;
|
||||
}
|
||||
|
||||
void device_CON::ClearAnsi(void){
|
||||
for(Bit8u i=0; i<NUMBER_ANSI_DATA;i++) ansi.data[i]=0;
|
||||
ansi.esc=false;
|
||||
ansi.sci=false;
|
||||
ansi.numberofarg=0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue