Skip to content

Commit

Permalink
Merge pull request #4700 from nanshiki/pc98conout
Browse files Browse the repository at this point in the history
Fixed PC-98 console output
  • Loading branch information
joncampbell123 authored Dec 22, 2023
2 parents 51ab9fc + 8ce0645 commit b58da28
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 38 deletions.
168 changes: 130 additions & 38 deletions src/dos/dev_con.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ uint16_t last_int16_code = 0;

static size_t dev_con_pos=0,dev_con_max=0;
static unsigned char dev_con_readbuf[64];
static bool pc98_column_over;
extern bool CheckHat(uint8_t code);
extern bool isDBCSCP();
extern bool inshell;
Expand Down Expand Up @@ -210,6 +211,83 @@ class device_CON : public DOS_Device {
ClearAnsi();
}

// ESC [ J
void ESC_BRACKET_J() {
uint8_t page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
if(IS_PC98_ARCH) {
uint8_t col = CURSOR_POS_COL(page);
uint8_t row = CURSOR_POS_ROW(page);
if(ansi.data[0] == 0) {
INT10_ScrollWindow(row, col, row, (uint8_t)ansi.ncols, 0, ansi.attr, page);
INT10_ScrollWindow(row + 1, 0, (uint8_t)ansi.nrows, (uint8_t)ansi.ncols, 0, ansi.attr, page);
} else if(ansi.data[0] == 1) {
INT10_ScrollWindow(0, 0, row - 1, (uint8_t)ansi.ncols, 0, ansi.attr, page);
INT10_ScrollWindow(row, 0, row, col, 0, ansi.attr, page);
} else if(ansi.data[0] == 2) {
INT10_ScrollWindow(0, 0, (uint8_t)ansi.nrows, (uint8_t)ansi.ncols, 0, ansi.attr,page);
Real_INT10_SetCursorPos(0, 0, page);
}
ClearAnsi();
} else {
if(ansi.data[0]==0) ansi.data[0]=2;
if(ansi.data[0]!=2) {/* every version behaves like type 2 */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: esc[%dJ called : not supported handling as 2",ansi.data[0]);
}
INT10_ScrollWindow(0,0,255,255,0,ansi.attr,page);
ClearAnsi();
Real_INT10_SetCursorPos(0,0,page);
}
}

// ESC [ K
void ESC_BRACKET_K() {
uint8_t page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
uint8_t col = CURSOR_POS_COL(page);
uint8_t row = CURSOR_POS_ROW(page);
if(IS_PC98_ARCH) {
if(ansi.data[0] == 0) {
INT10_WriteChar(' ', ansi.attr, page, ansi.ncols - col, true);
} else if(ansi.data[0] == 1) {
Real_INT10_SetCursorPos(row, 0, page);
INT10_WriteChar(' ', ansi.attr, page, col + 1, true);
} else if(ansi.data[0] == 2) {
Real_INT10_SetCursorPos(row, 0, page);
INT10_WriteChar(' ', ansi.attr, page, ansi.ncols, true);
}
} else {
ansi.ncols = real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
INT10_WriteChar(' ',ansi.attr,page,ansi.ncols-col,true);
}
Real_INT10_SetCursorPos(row,col,page);
ClearAnsi();
}

// ESC [ L
void ESC_BRACKET_L() {
uint8_t page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
uint8_t row = CURSOR_POS_ROW(page);
if(!IS_PC98_ARCH) {
ansi.ncols = real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
ansi.nrows = IS_EGAVGA_ARCH ? (real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1) : 25;
}
INT10_ScrollWindow(row,0,ansi.nrows-1,ansi.ncols-1,ansi.data[0]? ansi.data[0] : 1,ansi.attr,0xFF);
ClearAnsi();
Real_INT10_SetCursorPos(row, 0, page);
}

// ESC [ M
void ESC_BRACKET_M() {
uint8_t page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
uint8_t row = CURSOR_POS_ROW(page);
if(!IS_PC98_ARCH) {
ansi.ncols = real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
ansi.nrows = IS_EGAVGA_ARCH ? (real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1) : 25;
}
INT10_ScrollWindow(row,0,ansi.nrows-1,ansi.ncols-1,ansi.data[0]? -ansi.data[0] : -1,ansi.attr,0xFF);
ClearAnsi();
Real_INT10_SetCursorPos(row, 0, page);
}

// ESC = Y X
void ESC_EQU_cursor_pos(void) {
uint8_t page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
Expand Down Expand Up @@ -248,9 +326,10 @@ class device_CON : public DOS_Device {
* better emulates the actual platform. The purpose of this
* hack is to allow our code to call into INT 10h without
* setting up an INT 10h vector */
if (IS_PC98_ARCH)
if (IS_PC98_ARCH) {
INT10_Handler();
else
if(pc98_column_over && CURSOR_POS_COL(page) != 80 - 1) pc98_column_over = false;
} else
CALLBACK_RunRealInt(0x10);

reg_ax=oldax;
Expand Down Expand Up @@ -518,12 +597,17 @@ class device_CON : public DOS_Device {
//Need a new line?
if(cur_col==ncols)
{
cur_col=0;
cur_row++;

if (!IS_PC98_ARCH)
Real_INT10_TeletypeOutput('\r',defattr);
}
if (!IS_PC98_ARCH) {
cur_col=0;
cur_row++;
Real_INT10_TeletypeOutput('\r',defattr);
} else {
if(!pc98_column_over) {
pc98_column_over = true;
cur_col--;
}
}
} else pc98_column_over = false;

//Reached the bottom?
if(cur_row==nrows)
Expand Down Expand Up @@ -583,12 +667,18 @@ class device_CON : public DOS_Device {
BIOS_NCOLS;
unsigned char cw = con_sjis.doublewide ? 2 : 1;

/* FIXME: I'm not sure what NEC's ANSI driver does if a doublewide character is printed at column 79 */
if ((cur_col+cw) > ncols) {
cur_col = (uint8_t)ncols;
AdjustCursorPosition(cur_col,cur_row);
if(pc98_column_over || (cw == 2 && (cur_col+cw) > ncols)) {
BIOS_NROWS;
auto defattr = DefaultANSIAttr();
pc98_column_over = false;
cur_col=0;
cur_row++;
if(cur_row==nrows) {
INT10_ScrollWindow(0,0,(uint8_t)(nrows-1),(uint8_t)(ncols-1),-1,defattr,0);
cur_row--;
}
Real_INT10_SetCursorPos(cur_row,cur_col,page);
}

/* JIS conversion to WORD value appropriate for text RAM */
if (con_sjis.b2 != 0) con_sjis.b1 -= 0x20;

Expand Down Expand Up @@ -653,6 +743,26 @@ class device_CON : public DOS_Device {
ESC_BRACKET_D();
}

void INTDC_CL10h_AH0Ah(uint16_t pattern) {
ansi.data[0] = (uint8_t)pattern;
ESC_BRACKET_J();
}

void INTDC_CL10h_AH0Bh(uint16_t pattern) {
ansi.data[0] = (uint8_t)pattern;
ESC_BRACKET_K();
}

void INTDC_CL10h_AH0Ch(uint16_t count) {
ansi.data[0] = (uint8_t)count;
ESC_BRACKET_L();
}

void INTDC_CL10h_AH0Dh(uint16_t count) {
ansi.data[0] = (uint8_t)count;
ESC_BRACKET_M();
}

};

// NEC-PC98 keyboard input notes
Expand Down Expand Up @@ -1277,13 +1387,7 @@ bool device_CON::Write(const uint8_t * data,uint16_t * size) {
ESC_BRACKET_D();
break;
case 'J': /*erase screen and move cursor home*/
if(ansi.data[0]==0) ansi.data[0]=2;
if(ansi.data[0]!=2) {/* every version behaves like type 2 */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: esc[%dJ called : not supported handling as 2",ansi.data[0]);
}
INT10_ScrollWindow(0,0,255,255,0,ansi.attr,page);
ClearAnsi();
Real_INT10_SetCursorPos(0,0,page);
ESC_BRACKET_J();
break;
case 'h': /* SET MODE (if code =7 enable linewrap) */
case 'I': /* RESET MODE */
Expand All @@ -1300,25 +1404,13 @@ bool device_CON::Write(const uint8_t * data,uint16_t * size) {
ClearAnsi();
break;
case 'K': /* erase till end of line (don't touch cursor) */
col = CURSOR_POS_COL(page);
row = CURSOR_POS_ROW(page);
if (!IS_PC98_ARCH) {
ansi.ncols = real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
}
INT10_WriteChar(' ',ansi.attr,page,ansi.ncols-col,true); //Real_WriteChar(ansi.ncols-col,row,page,' ',ansi.attr,true);

//for(i = col;i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true);
Real_INT10_SetCursorPos(row,col,page);
ClearAnsi();
ESC_BRACKET_K();
break;
case 'M': /* delete line (NANSI) */
row = CURSOR_POS_ROW(page);
if (!IS_PC98_ARCH) {
ansi.ncols = real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
ansi.nrows = IS_EGAVGA_ARCH ? (real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1) : 25;
}
INT10_ScrollWindow(row,0,ansi.nrows-1,ansi.ncols-1,ansi.data[0]? -ansi.data[0] : -1,ansi.attr,0xFF);
ClearAnsi();
case 'L': /* insert line (PC-98) */
ESC_BRACKET_L();
break;
case 'M': /* delete line (NANSI,PC-98) */
ESC_BRACKET_M();
break;
case '>':/* proprietary NEC PC-98 MS-DOS codes (??) */
if (IS_PC98_ARCH) {
Expand Down
20 changes: 20 additions & 0 deletions src/dos/dos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3634,6 +3634,26 @@ static Bitu DOS_29Handler(void)
col--;
}
} else {
if(isDBCSCP() && isKanji1(reg_al) && col == ncols - 1) {
col = 0;
if(row < nrows) {
row++;
} else {
uint8_t tmp_al = reg_al;
reg_bh = 0x07;
reg_ax = 0x0601;
reg_cx = 0x0000;
reg_dl = (uint8_t)(ncols - 1);
reg_dh = (uint8_t)nrows;
CALLBACK_RunRealInt(0x10);
reg_al = tmp_al;
}
reg_ah = 0x02;
reg_bh = page;
reg_dl = col;
reg_dh = row;
CALLBACK_RunRealInt(0x10);
}
reg_ah = 0x09;
reg_bh = page;
reg_bl = int29h_data.ansi.attr;
Expand Down
20 changes: 20 additions & 0 deletions src/dos/dos_devices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,26 @@ void INTDC_CL10h_AH09h(uint16_t count) {
DOS_CON->INTDC_CL10h_AH09h(count);
}

void INTDC_CL10h_AH0Ah(uint16_t pattern) {
if (DOS_CON != NULL)
DOS_CON->INTDC_CL10h_AH0Ah(pattern);
}

void INTDC_CL10h_AH0Bh(uint16_t pattern) {
if (DOS_CON != NULL)
DOS_CON->INTDC_CL10h_AH0Bh(pattern);
}

void INTDC_CL10h_AH0Ch(uint16_t count) {
if (DOS_CON != NULL)
DOS_CON->INTDC_CL10h_AH0Ch(count);
}

void INTDC_CL10h_AH0Dh(uint16_t count) {
if (DOS_CON != NULL)
DOS_CON->INTDC_CL10h_AH0Dh(count);
}

/* The CB_INT28 handler calls this callback then executes STI+HLT.
* This works great when called from the CON device because on return,
* when IRQ1 keyboard input breaks the HLT and returns to CON, this
Expand Down
25 changes: 25 additions & 0 deletions src/ints/bios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5503,6 +5503,31 @@ static Bitu INTDC_PC98_Handler(void) {
else if (reg_ah == 0x09) { /* CL=0x10 AH=0x09 DX=count Move cursor left multiple lines */
void INTDC_CL10h_AH09h(uint16_t count);
INTDC_CL10h_AH09h(reg_dx);
goto done;
}
else if (reg_ah == 0x0a) { /* CL=0x10 AH=0x0A DL=pattern Erase screen */
void INTDC_CL10h_AH0Ah(uint16_t pattern);
INTDC_CL10h_AH0Ah(reg_dx);
goto done;
}
else if (reg_ah == 0x0b) { /* CL=0x10 AH=0x0B DL=pattern Erase lines */
void INTDC_CL10h_AH0Bh(uint16_t pattern);
INTDC_CL10h_AH0Bh(reg_dx);
goto done;
}
else if (reg_ah == 0x0c) { /* CL=0x10 AH=0x0C DL=count Insert lines */
void INTDC_CL10h_AH0Ch(uint16_t count);
INTDC_CL10h_AH0Ch(reg_dx);
goto done;
}
else if (reg_ah == 0x0d) { /* CL=0x10 AH=0x0D DL=count Erase lines */
void INTDC_CL10h_AH0Dh(uint16_t count);
INTDC_CL10h_AH0Dh(reg_dx);
goto done;
}
else if (reg_ah == 0x0E) { /* CL=0x10 AH=0x0E DL=mode Change character mode */
void pc98_set_char_mode(bool mode);
pc98_set_char_mode(reg_dl == 0);
goto done;
}
goto unknown;
Expand Down

0 comments on commit b58da28

Please sign in to comment.