dosbox-wii/src/dos/dev_con.h

394 lines
12 KiB
C
Raw Normal View History

2009-05-02 23:03:37 +02:00
/*
2009-05-02 23:35:44 +02:00
* Copyright (C) 2002-2003 The DOSBox Team
2009-05-02 23:03:37 +02:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
2009-05-02 23:43:00 +02:00
/* $Id: dev_con.h,v 1.14 2003/09/08 18:06:44 qbix79 Exp $ */
2009-05-02 23:27:47 +02:00
#include "dos_inc.h"
#include "../ints/int10.h"
2009-05-02 23:43:00 +02:00
#include <string.h>
2009-05-02 23:27:47 +02:00
#define NUMBER_ANSI_DATA 10
2009-05-02 23:03:37 +02:00
class device_CON : public DOS_Device {
public:
device_CON();
bool Read(Bit8u * data,Bit16u * size);
bool Write(Bit8u * data,Bit16u * size);
bool Seek(Bit32u * pos,Bit32u type);
bool Close();
2009-05-02 23:27:47 +02:00
void ClearAnsi(void);
2009-05-02 23:03:37 +02:00
Bit16u GetInformation(void);
private:
Bit8u cache;
2009-05-02 23:27:47 +02:00
struct ansi { /* should create a constructor which fills them with the appriorate values */
bool esc;
bool sci;
2009-05-02 23:43:00 +02:00
bool enabled;
2009-05-02 23:27:47 +02:00
Bit8u attr;
Bit8u data[NUMBER_ANSI_DATA];
Bit8u numberofarg;
Bit16u nrows;
Bit16u ncols;
Bit8s savecol;
Bit8s saverow;
} ansi;
2009-05-02 23:03:37 +02:00
};
bool device_CON::Read(Bit8u * data,Bit16u * size) {
Bit16u oldax=reg_ax;
Bit16u count=0;
if ((cache) && (*size)) {
data[count++]=cache;
2009-05-02 23:27:47 +02:00
if(dos.echo) {
2009-05-02 23:43:00 +02:00
INT10_TeletypeOutput(cache,7,false);
2009-05-02 23:27:47 +02:00
}
cache=0;
2009-05-02 23:03:37 +02:00
}
while (*size>count) {
reg_ah=0;
CALLBACK_RunRealInt(0x16);
switch(reg_al) {
case 13:
data[count++]=0x0D;
2009-05-02 23:27:47 +02:00
if (*size>count) data[count++]=0x0A; // it's only expanded if there is room for it. (NO cache)
*size=count;
2009-05-02 23:03:37 +02:00
reg_ax=oldax;
2009-05-02 23:27:47 +02:00
if(dos.echo) {
2009-05-02 23:43:00 +02:00
INT10_TeletypeOutput(13,7,false); //maybe don't do this ( no need for it actually ) (but it's compatible)
INT10_TeletypeOutput(10,7,false);
2009-05-02 23:27:47 +02:00
}
2009-05-02 23:03:37 +02:00
return true;
2009-05-02 23:27:47 +02:00
break;
case 8:
if(*size==1) data[count++]=reg_al; //one char at the time so give back that BS
else if(count) { //Remove data if it exists (extended keys don't go right)
data[count--]=0;
2009-05-02 23:43:00 +02:00
INT10_TeletypeOutput(8,7,false);
INT10_TeletypeOutput(' ',7,false);
2009-05-02 23:27:47 +02:00
} else {
continue; //no data read yet so restart whileloop.
}
break;
2009-05-02 23:03:37 +02:00
default:
data[count++]=reg_al;
break;
case 0:
data[count++]=reg_al;
if (*size>count) data[count++]=reg_ah;
else cache=reg_ah;
break;
2009-05-02 23:27:47 +02:00
}
if(dos.echo) { //what to do if *size==1 and character is BS ?????
2009-05-02 23:43:00 +02:00
INT10_TeletypeOutput(reg_al,7,false);
2009-05-02 23:27:47 +02:00
}
2009-05-02 23:03:37 +02:00
}
*size=count;
reg_ax=oldax;
return true;
}
2009-05-02 23:27:47 +02:00
2009-05-02 23:03:37 +02:00
bool device_CON::Write(Bit8u * data,Bit16u * size) {
Bit16u count=0;
2009-05-02 23:27:47 +02:00
Bitu i;
2009-05-02 23:43:00 +02:00
Bit8u col,row;
Bit8u tempdata;
2009-05-02 23:27:47 +02:00
while (*size>count) {
if (!ansi.esc){
if(data[count]=='\033') {
/*clear the datastructure */
ClearAnsi();
/* start the sequence */
ansi.esc=true;
count++;
continue;
2009-05-02 23:12:18 +02:00
2009-05-02 23:27:47 +02:00
} else {
2009-05-02 23:43:00 +02:00
// pass attribute only if ansi is enabled
INT10_TeletypeOutput(data[count],ansi.attr,ansi.enabled);
count++;
continue;
2009-05-02 23:27:47 +02:00
};
};
2009-05-02 23:43:00 +02:00
2009-05-02 23:27:47 +02:00
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:
2009-05-02 23:43:00 +02:00
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unknown char %c after a esc",data[count]); /*prob () */
2009-05-02 23:27:47 +02:00
ClearAnsi();
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++){
2009-05-02 23:43:00 +02:00
ansi.enabled=true;
2009-05-02 23:27:47 +02:00
switch(ansi.data[i]){
case 0: /* normal */
ansi.attr=0x7;
2009-05-02 23:43:00 +02:00
ansi.enabled=false;
2009-05-02 23:27:47 +02:00
break;
case 1: /* bold mode on*/
ansi.attr|=0x8;
break;
case 4: /* underline */
2009-05-02 23:43:00 +02:00
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for underline yet");
2009-05-02 23:27:47 +02:00
break;
case 5: /* blinking */
2009-05-02 23:43:00 +02:00
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for blinking yet");
2009-05-02 23:27:47 +02:00
break;
case 7: /* reverse */
2009-05-02 23:43:00 +02:00
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for reverse yet");
2009-05-02 23:27:47 +02:00
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;
2009-05-02 23:43:00 +02:00
/* cursor up down and forward and backward only change the row or the col not both */
2009-05-02 23:27:47 +02:00
case 'A': /* cursor up*/
col=CURSOR_POS_COL(0) ;
2009-05-02 23:43:00 +02:00
row=CURSOR_POS_ROW(0) ;
tempdata = (ansi.data[0]? ansi.data[0] : 1);
if(tempdata > row)
{ row=0; }
else
{ row-=tempdata;}
INT10_SetCursorPos(row,col,0);
2009-05-02 23:27:47 +02:00
ClearAnsi();
break;
2009-05-02 23:43:00 +02:00
case 'B': /*cursor Down */
col=CURSOR_POS_COL(0) ;
row=CURSOR_POS_ROW(0) ;
tempdata = (ansi.data[0]? ansi.data[0] : 1);
if(tempdata + static_cast<Bitu>(row) >= ansi.nrows)
{ row = ansi.nrows - 1;}
else
{ row += tempdata; }
INT10_SetCursorPos(row,col,0);
ClearAnsi();
break;
2009-05-02 23:27:47 +02:00
case 'C': /*cursor forward */
2009-05-02 23:43:00 +02:00
col=CURSOR_POS_COL(0);
row=CURSOR_POS_ROW(0);
tempdata=(ansi.data[0]? ansi.data[0] : 1);
if(tempdata + static_cast<Bitu>(col) >= ansi.ncols)
{ col = ansi.ncols - 1;}
else
{ col += tempdata;}
INT10_SetCursorPos(row,col,0);
ClearAnsi();
break;
case 'D': /*Cursor Backward */
col=CURSOR_POS_COL(0);
2009-05-02 23:27:47 +02:00
row=CURSOR_POS_ROW(0);
2009-05-02 23:43:00 +02:00
tempdata=(ansi.data[0]? ansi.data[0] : 1);
if(tempdata > col)
{col = 0;}
else
{ col -= tempdata;}
2009-05-02 23:27:47 +02:00
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) */
2009-05-02 23:43:00 +02:00
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: esc[%dJ called : not supported",ansi.data[0]);
2009-05-02 23:27:47 +02:00
break;
}
2009-05-02 23:43:00 +02:00
for(i=0;i<(Bitu)ansi.ncols*ansi.nrows;i++) INT10_TeletypeOutput(' ',ansi.attr,true);
2009-05-02 23:27:47 +02:00
ClearAnsi();
INT10_SetCursorPos(0,0,0);
break;
case 'h': /* set MODE (if code =7 enable linewrap) */
case 'I': /*RESET MODE */
2009-05-02 23:43:00 +02:00
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: set/reset mode called(not supported)");
2009-05-02 23:27:47 +02:00
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;
2009-05-02 23:43:00 +02:00
case 'K':/* erase till end of line */
for(i = CURSOR_POS_COL(0);i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutput(' ',ansi.attr,true);
ClearAnsi(); /* maybe set cursor back to starting place ???? */
break;
2009-05-02 23:27:47 +02:00
case 'l':/* (if code =7) disable linewrap */
case 'p':/* reassign keys (needs strings) */
case 'i':/* printer stuff */
default:
2009-05-02 23:43:00 +02:00
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unhandled char %c in esc[",data[count]);
2009-05-02 23:27:47 +02:00
ClearAnsi();
break;
}
count++;
2009-05-02 23:03:37 +02:00
}
*size=count;
return true;
}
bool device_CON::Seek(Bit32u * pos,Bit32u type) {
2009-05-02 23:27:47 +02:00
// seek is valid
*pos = 0;
return true;
2009-05-02 23:03:37 +02:00
}
bool device_CON::Close() {
return false;
}
Bit16u device_CON::GetInformation(void) {
Bit16u head=mem_readw(BIOS_KEYBOARD_BUFFER_HEAD);
Bit16u tail=mem_readw(BIOS_KEYBOARD_BUFFER_TAIL);
if ((head==tail) && !cache) return 0x80D3; /* No Key Available */
return 0x8093; /* Key Available */
};
device_CON::device_CON() {
name="CON";
cache=0;
2009-05-02 23:27:47 +02:00
ansi.esc=false;
ansi.sci=false;
2009-05-02 23:43:00 +02:00
ansi.enabled=false;
2009-05-02 23:27:47 +02:00
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
2009-05-02 23:43:00 +02:00
ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1;
2009-05-02 23:27:47 +02:00
ansi.saverow=0;
ansi.savecol=0;
2009-05-02 23:43:00 +02:00
ClearAnsi();
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:27:47 +02:00
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;
}