support for Japanese EGA mode

This commit is contained in:
Wengier 2021-06-04 08:47:15 -04:00
parent 8171f0090b
commit a28c26512e
18 changed files with 1010 additions and 51 deletions

View File

@ -1,5 +1,8 @@
0.83.15
-
- Added support for Japanese EGA mode (machine=jega)
by adopting code from DOSVax. You can optionally
set SBCS and DBCS fonts with jfontsbcs & jfontdbcs
config options in [render] section. (Wengier)
0.83.14
- Added support for directories on the Z drive, so
there is no need to put all files/programs on the

View File

@ -160,6 +160,7 @@ void DOSBOX_SetNormalLoop();
/* machine tests for use with if() statements */
#define IS_TANDY_ARCH ((machine==MCH_TANDY) || (machine==MCH_PCJR))
#define IS_EGAVGA_ARCH ((machine==MCH_EGA) || (machine==MCH_VGA))
#define IS_JEGA_ARCH (machine==MCH_EGA && jp_ega)
#define IS_EGA_ARCH (machine==MCH_EGA)
#define IS_VGA_ARCH (machine==MCH_VGA)
#define IS_PC98_ARCH (machine==MCH_PC98)

View File

@ -59,6 +59,8 @@ enum KBD_KEYS {
KBD_jp_muhenkan, /* Muhenkan (No conversion from kana to kanji) */
KBD_jp_henkan, /* Henkan/zenkouho (Conversion from kana to kanji, shifted: previous candidate, alt: all candidates) */
KBD_jp_hiragana, /* Hiragana/Katakana (Hiragana, shifted: Katakana, alt: romaji) */
KBD_yen, KBD_underscore, /* JP layout */
KBD_ax,KBD_conv,KBD_nconv, /* for AX */
/* Korean */
KBD_kor_hancha, /* Hancha */

View File

@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "dosbox.h"
#include "dos_inc.h"
@ -39,6 +40,7 @@
#include "serialport.h"
#include "dos_network.h"
#include "render.h"
#include "jega.h"
#if defined(WIN32)
#include "../dos/cdrom.h"
#include <shellapi.h>
@ -2921,8 +2923,6 @@ void DOS_GetMemory_reset();
void DOS_GetMemory_Choose();
Bitu MEM_PageMask(void);
#include <assert.h>
extern bool dos_con_use_int16_to_detect_input;
extern bool dbg_zero_on_dos_allocmem;
extern bool log_dev_con, addovl;
@ -3405,6 +3405,11 @@ public:
DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetDrive(25); /* Else the next call gives a warning. */
DOS_SetDefaultDrive(25);
if (IS_JEGA_ARCH) {
INT10_AX_SetCRTBIOSMode(0x51);
INT16_AX_SetKBDBIOSMode(0x51);
}
const char *keepstr = section->Get_string("keep private area on boot");
if (!strcasecmp(keepstr, "true")||!strcasecmp(keepstr, "1")) keep_private_area_on_boot = 1;
else if (!strcasecmp(keepstr, "false")||!strcasecmp(keepstr, "0")) keep_private_area_on_boot = 0;

View File

@ -32,6 +32,8 @@
#include "render.h"
#include "dos_codepages.h"
#include "dos_keyboard_layout_data.h"
#define INCJFONT 1
#include "jega.h"
#if defined (WIN32)
#include <windows.h>
@ -714,6 +716,142 @@ uint16_t keyboard_layout::extract_codepage(const char* keyboard_file_name) {
return (IS_PC98_ARCH ? 932 : 437);
}
#define ID_LEN 6
#define NAME_LEN 8
#define SBCS19_LEN 256 * 19
#define DBCS16_LEN 65536 * 32
uint8_t jfont_sbcs_19[SBCS19_LEN];//256 * 19( * 8)
uint8_t jfont_dbcs_16[DBCS16_LEN];//65536 * 16 * 2 (* 8)
typedef struct {
char id[ID_LEN];
char name[NAME_LEN];
unsigned char width;
unsigned char height;
unsigned char type;
} fontx_h;
typedef struct {
Bit16u start;
Bit16u end;
} fontxTbl;
Bitu getfontx2header(FILE *fp, fontx_h *header)
{
fread(header->id, ID_LEN, 1, fp);
if (strncmp(header->id, "FONTX2", ID_LEN) != 0) {
return 1;
}
fread(header->name, NAME_LEN, 1, fp);
header->width = (uint8_t)getc(fp);
header->height = (uint8_t)getc(fp);
header->type = (uint8_t)getc(fp);
return 0;
}
uint16_t chrtosht(FILE *fp)
{
Bit16u i, j;
i = (uint8_t)getc(fp);
j = (uint8_t)getc(fp) << 8;
return(i | j);
}
void readfontxtbl(fontxTbl *table, Bitu size, FILE *fp)
{
while (size > 0) {
table->start = chrtosht(fp);
table->end = chrtosht(fp);
++table;
--size;
}
}
static void LoadFontxFile(const char * fname, int opt) {
fontxTbl *table;
uint8_t size;
Bitu code;
if (opt==1) {
memcpy(jfont_sbcs_19, JPNHN19X+NAME_LEN+ID_LEN+3, SBCS19_LEN * sizeof(uint8_t));
return;
} else if (opt==2) {
int p=NAME_LEN+ID_LEN+3;
size = JPNZN16X[p++];
table = (fontxTbl *)calloc(size, sizeof(fontxTbl));
Bitu i=0;
while (i < size) {
table[i].start = (JPNZN16X[p] | (JPNZN16X[p+1] << 8));
table[i].end = (JPNZN16X[p+2] | (JPNZN16X[p+3] << 8));
i++;
p+=4;
}
for (i = 0; i < size; i++)
for (code = table[i].start; code <= table[i].end; code++) {
memcpy(&jfont_dbcs_16[code*32], JPNZN16X+p, 32*sizeof(uint8_t));
p+=32*sizeof(uint8_t);
}
return;
}
fontx_h head;
if (!fname) return;
if(*fname=='\0') return;
FILE * mfile=fopen(fname,"rb");
if (!mfile) {
LOG_MSG("MSG: Can't open FONTX2 file: %s",fname);
return;
}
if (getfontx2header(mfile, &head) != 0) {
fclose(mfile);
LOG_MSG("MSG: FONTX2 header is incorrect\n");
return;
}
// switch whether the font is DBCS or not
if (head.type == 1) {
if (head.width == 16 && head.height == 16) {
size = getc(mfile);
table = (fontxTbl *)calloc(size, sizeof(fontxTbl));
readfontxtbl(table, size, mfile);
for (Bitu i = 0; i < size; i++)
for (code = table[i].start; code <= table[i].end; code++)
fread(&jfont_dbcs_16[code*32], sizeof(uint8_t), 32, mfile);
}
else {
fclose(mfile);
LOG_MSG("MSG: FONTX2 DBCS font size is not correct\n");
return;
}
}
else {
if (head.width == 8 && head.height == 19)
fread(jfont_sbcs_19, sizeof(uint8_t), SBCS19_LEN, mfile);
else {
fclose(mfile);
LOG_MSG("MSG: FONTX2 SBCS font size is not correct\n");
return;
}
}
fclose(mfile);
}
void ResolvePath(std::string& in);
void JFONT_Init() {
std::string file_name;
Section_prop *section = static_cast<Section_prop *>(control->GetSection("render"));
Prop_path* pathprop = section->Get_path("jfontsbcs");
if (pathprop && pathprop->realpath!="") {
std::string path=pathprop->realpath;
ResolvePath(path);
LoadFontxFile(path.c_str(), 0);
} else LoadFontxFile(NULL, 1);
pathprop = section->Get_path("jfontdbcs");
if(pathprop && pathprop->realpath!="") {
std::string path=pathprop->realpath;
ResolvePath(path);
LoadFontxFile(path.c_str(), 0);
} else LoadFontxFile(NULL, 2);
}
extern int eurAscii;
extern uint8_t euro_08[8], euro_14[14], euro_16[16];
bool font_14_init=false, font_16_init=false;

View File

@ -117,7 +117,7 @@ static void CheckX86ExtensionsSupport()
/*=============================================================================*/
extern void GFX_SetTitle(int32_t cycles, int frameskip, Bits timing, bool paused);
extern void AddSaveStateMapper();
extern void AddSaveStateMapper(), JFONT_Init();
extern bool force_nocachedir;
extern bool wpcolon;
extern bool lockmount;
@ -142,7 +142,7 @@ extern unsigned int page;
uint32_t guest_msdos_LoL = 0;
uint16_t guest_msdos_mcb_chain = 0;
int boothax = BOOTHAX_NONE;
bool jp_ega = false;
bool want_fm_towns = false;
bool dos_con_use_int16_to_detect_input = true;
@ -988,6 +988,7 @@ void DOSBOX_RealInit() {
svgaCard = SVGA_None;
s3Card = S3_Generic;
machine = MCH_VGA;
jp_ega = false;
int10.vesa_nolfb = false;
int10.vesa_oldvbe = false;
if (mtype == "cga") { machine = MCH_CGA; mono_cga = false; }
@ -1001,6 +1002,7 @@ void DOSBOX_RealInit() {
else if (mtype == "hercules") { machine = MCH_HERC; }
else if (mtype == "mda") { machine = MCH_MDA; }
else if (mtype == "ega") { machine = MCH_EGA; }
else if (mtype == "jega") { machine = MCH_EGA; jp_ega = true;}
else if (mtype == "svga_s3") { svgaCard = SVGA_S3Trio; s3Card = S3_Trio64; } /* DOSBox SVN behavior */
else if (mtype == "svga_s386c928") { svgaCard = SVGA_S3Trio; s3Card = S3_86C928; }
else if (mtype == "svga_s3vision864"){svgaCard= SVGA_S3Trio; s3Card = S3_Vision864; }
@ -1023,8 +1025,9 @@ void DOSBOX_RealInit() {
else if (mtype == "fm_towns") { machine = MCH_VGA; want_fm_towns = true; /*machine = MCH_FM_TOWNS;*/ }
else E_Exit("DOSBOX:Unknown machine type %s",mtype.c_str());
else E_Exit("DOSBOX-X:Unknown machine type %s",mtype.c_str());
if (IS_JEGA_ARCH) JFONT_Init(); // Load DBCS fonts for JEGA
#if defined(USE_TTF)
if (IS_PC98_ARCH) ttf.cols = 80; // The number of columns on the screen is apparently fixed to 80 in PC-98 mode at this time
#endif
@ -1186,7 +1189,7 @@ void DOSBOX_SetupConfigSections(void) {
/* Setup all the different modules making up DOSBox-X */
const char* machines[] = {
"hercules", "cga", "cga_mono", "cga_rgb", "cga_composite", "cga_composite2", "tandy", "pcjr", "ega",
"hercules", "cga", "cga_mono", "cga_rgb", "cga_composite", "cga_composite2", "tandy", "pcjr", "ega", "jega",
"vgaonly", "svga_s3", "svga_s386c928", "svga_s3vision864", "svga_s3vision868", "svga_s3trio32", "svga_s3trio64", "svga_s3trio64v+", "svga_s3virge", "svga_s3virgevx", "svga_et3000", "svga_et4000",
"svga_paradise", "vesa_nolfb", "vesa_oldvbe", "amstrad", "pc98", "pc9801", "pc9821",
@ -2294,6 +2297,12 @@ void DOSBOX_SetupConfigSections(void) {
const char* bright[] = { "", "bright", 0 };
Pstring->Set_values(bright);
Pstring = secprop->Add_path("jfontsbcs",Property::Changeable::OnlyAtStart,"");
Pstring->Set_help("FONTX2 file used to rendering SBCS characters (8x19) in JEGA mode. If not specified, the default one will be used.");
Pstring = secprop->Add_path("jfontdbcs",Property::Changeable::OnlyAtStart,"");
Pstring->Set_help("FONTX2 file used to rendering DBCS characters (16x16) in JEGA mode. If not specified, the default one will be used.");
Pstring = secprop->Add_string("ttf.font", Property::Changeable::Always, "");
Pstring->Set_help("Specifies a TrueType font to use for the TTF output. If not specified, the built-in TrueType font will be used.\n"
"Either a font name or full font path can be specified. If file ends with the .TTF extension then the extension can be omitted.\n"

View File

@ -4765,7 +4765,7 @@ void MAPPER_CheckKeyboardLayout() {
#if defined(WIN32)
WORD cur_kb_layout = LOWORD(GetKeyboardLayout(0));
isJPkeyboard = false;
isJPkeyboard = true;
if (cur_kb_layout == 1041/*JP106*/) {
isJPkeyboard = true;

View File

@ -4656,7 +4656,7 @@ void GFX_EndTextLines(bool force=false) {
if (!force) justChanged = false;
// NTS: Additional fix is needed for the cursor in PC-98 mode; also expect further cleanup
bcount++;
if (vga.draw.cursor.enabled && vga.draw.cursor.sline <= vga.draw.cursor.eline && vga.draw.cursor.sline < 16 && blinkCursor) { // Draw cursor?
if (vga.draw.cursor.enabled && vga.draw.cursor.sline <= vga.draw.cursor.eline && vga.draw.cursor.sline <= 16 && blinkCursor) { // Draw cursor?
int newPos = (int)(vga.draw.cursor.address>>1);
if (newPos >= 0 && newPos < ttf.cols*ttf.lins) { // If on screen
int y = newPos/ttf.cols;
@ -4715,7 +4715,7 @@ void GFX_EndTextLines(bool force=false) {
if ((vga.draw.cursor.blinkon || blinkCursor<0)) {
// second reverse lower lines
textSurface = TTF_RenderUNICODE_Shaded(ttf.SDL_font, unimap, ttf_bgColor, ttf_fgColor, ttf.width*(dw?2:1));
ttf_textClip.y = (ttf.height*vga.draw.cursor.sline)>>4;
ttf_textClip.y = (ttf.height*(vga.draw.cursor.sline>15?15:vga.draw.cursor.sline))>>4;
ttf_textClip.h = ttf.height - ttf_textClip.y; // for now, cursor to bottom
ttf_textRect.y = ttf.offY+y*ttf.height + ttf_textClip.y;
SDL_BlitSurface(textSurface, &ttf_textClip, sdl.surface, &ttf_textRect);

View File

@ -31,6 +31,7 @@
#include "timer.h"
#include <math.h>
#include "8255.h"
#include "jega.h"
#if defined(_MSC_VER)
# pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */
@ -1584,6 +1585,25 @@ void KEYBOARD_AddKey1(KBD_KEYS keytype,bool pressed) {
case KBD_lwindows:extend=true;ret=0x5B;break;
case KBD_rwindows:extend=true;ret=0x5C;break;
case KBD_rwinmenu:extend=true;ret=0x5D;break;
case KBD_underscore:ret = 86; break;//for AX layout
case KBD_yen:ret = 43; break;//for AX layout
case KBD_conv:ret = (INT16_AX_GetKBDBIOSMode() == 0x51)? 0x5b: 57; break;//for AX layout
case KBD_nconv:ret = (INT16_AX_GetKBDBIOSMode() == 0x51) ? 0x5a: 57; break;//for AX layout
case KBD_ax:ret = (INT16_AX_GetKBDBIOSMode() == 0x51) ? 0x5c: 0; break;//for AX layout
/* System Scan Code for AX keys
JP mode Make Break US mode Make Break
³ÏŠ· 5Ah DAh Space 39h(57) B9h
ÏŠ· 5Bh DBh Space 39h(57) B9h
Š¿Žš E0h-38h E0h-B8h RAlt (status flag)
AX 5Ch DCh (unused)
*/
/* Character code in JP mode (implemented in KBD BIOS)
Key Ch Sh Ct Al
5A ³ÏŠ· - AB AC AD AE
5B ÏŠ· - A7 A8 A9 AA
38 Š¿Žš - 3A 3A
5c AX - D2 D3 D4 D5
*/
case KBD_jp_muhenkan:ret=0x7B;break;
case KBD_jp_henkan:ret=0x79;break;
case KBD_jp_hiragana:ret=0x70;break;/*also Katakana */

View File

@ -137,6 +137,7 @@
#include "menu.h"
#include "mem.h"
#include "render.h"
#include "jega.h"
#include <string.h>
#include <stdlib.h>
@ -1484,6 +1485,233 @@ void VGA_Init() {
AddVMEventFunction(VM_EVENT_RESET,AddVMEventFunctionFuncPair(VGA_Reset));
}
JEGA_DATA jega;
// Store font
void JEGA_writeFont() {
jega.RSTAT &= ~0x02;
Bitu chr = jega.RDFFB;
Bitu chr_2 = jega.RDFSB;
// Check the char code is in Wide charset of Shift-JIS
if ((chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc)) {
if (jega.fontIndex >= 32) jega.fontIndex = 0;
chr <<= 8;
//fix vertical char position
chr |= chr_2;
if (jega.fontIndex < 16)
// read font from register and store it
jfont_dbcs_16[chr * 32 + jega.fontIndex * 2] = jega.RDFAP;// w16xh16 font
else
jfont_dbcs_16[chr * 32 + (jega.fontIndex - 16) * 2 + 1] = jega.RDFAP;// w16xh16 font
}
else
{
if (jega.fontIndex >= 19) jega.fontIndex = 0;
jfont_sbcs_19[chr * 19 + jega.fontIndex] = jega.RDFAP;// w16xh16 font
}
jega.fontIndex++;
jega.RSTAT |= 0x02;
}
// Read font
void JEGA_readFont() {
jega.RSTAT &= ~0x02;
Bitu chr = jega.RDFFB;
Bitu chr_2 = jega.RDFSB;
// Check the char code is in Wide charset of Shift-JIS
if ((chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc)) {
if (jega.fontIndex >= 32) jega.fontIndex = 0;
chr <<= 8;
//fix vertical char position
chr |= chr_2;
if (jega.fontIndex < 16)
// get font and set to register
jega.RDFAP = jfont_dbcs_16[chr * 32 + jega.fontIndex * 2];// w16xh16 font
else
jega.RDFAP = jfont_dbcs_16[chr * 32 + (jega.fontIndex - 16) * 2 + 1];
}
else
{
if (jega.fontIndex >= 19) jega.fontIndex = 0;
jega.RDFAP = jfont_sbcs_19[chr * 19 + jega.fontIndex];// w16xh16 font
}
jega.fontIndex++;
jega.RSTAT |= 0x02;
}
void write_p3d5_jega(Bitu reg, Bitu val, Bitu iolen) {
switch (reg) {
case 0xb9://Mode register 1
jega.RMOD1 = val;
break;
case 0xba://Mode register 2
jega.RMOD2 = val;
break;
case 0xbb://ANK Group sel
jega.RDAGS = val;
break;
case 0xbc:// Font access first byte
if (jega.RDFFB != val) {
jega.RDFFB = val;
jega.fontIndex = 0;
}
break;
case 0xbd:// Font access Second Byte
if (jega.RDFSB != val) {
jega.RDFSB = val;
jega.fontIndex = 0;
}
break;
case 0xbe:// Font Access Pattern
jega.RDFAP = val;
JEGA_writeFont();
break;
//case 0x09:// end scan line
// jega.RPESL = val;
// break;
//case 0x14:// under scan line
// jega.RPULP = val;
// break;
case 0xdb:
jega.RPSSC = val;
break;
case 0xd9:
jega.RPSSU = val;
break;
case 0xda:
jega.RPSSL = val;
break;
case 0xdc://super imposed (only AX-2 system, not implemented)
jega.RPPAJ = val;
break;
case 0xdd:
jega.RCMOD = val;
break;
//case 0x0e://Cursor location Upper bits
// jega.RCCLH = val;
// break;
//case 0x0f://Cursor location Lower bits
// jega.RCCLL = val;
// break;
//case 0x0a://Cursor Start Line
// jega.RCCSL = val;
// break;
//case 0x0b://Cursor End Line
// jega.RCCEL = val;
// break;
case 0xde://Cursor Skew control
jega.RCSKW = val;
break;
case 0xdf://Unused?
jega.ROMSL = val;
break;
case 0xbf://font r/w register
jega.RSTAT = val;
break;
default:
LOG(LOG_VGAMISC, LOG_NORMAL)("VGA:GFX:JEGA:Write to illegal index %2X", reg);
break;
}
}
//CRT Control Register can be read from I/O 3D5h, after setting index at I/O 3D4h
Bitu read_p3d5_jega(Bitu reg, Bitu iolen) {
switch (reg) {
case 0xb9:
return jega.RMOD1;
case 0xba:
return jega.RMOD2;
case 0xbb:
return jega.RDAGS;
case 0xbc:// BCh RDFFB Font access First Byte
return jega.RDFFB;
case 0xbd:// BDh RDFFB Font access Second Byte
return jega.RDFSB;
case 0xbe:// BEh RDFAP Font Access Pattern
JEGA_readFont();
return jega.RDFAP;
//case 0x09:
// return jega.RPESL;
//case 0x14:
// return jega.RPULP;
case 0xdb:
return jega.RPSSC;
case 0xd9:
return jega.RPSSU;
case 0xda:
return jega.RPSSL;
case 0xdc:
return jega.RPPAJ;
case 0xdd:
return jega.RCMOD;
//case 0x0e:
// return jega.RCCLH;
//case 0x0f:
// return jega.RCCLL;
//case 0x0a:
// return jega.RCCSL;
//case 0x0b:
// return jega.RCCEL;
case 0xde:
return jega.RCSKW;
case 0xdf:
return jega.ROMSL;
case 0xbf:
return 0x03;//Font always read/writeable
default:
LOG(LOG_VGAMISC, LOG_NORMAL)("VGA:GFX:JEGA:Read from illegal index %2X", reg);
break;
}
return 0x0;
}
void JEGA_setupAX(void) {
memset(&jega, 0, sizeof(JEGA_DATA));
jega.RMOD1 = 0xC8;//b9: Mode register 1
jega.RMOD2 = 0x00;//ba: Mode register 2
jega.RDAGS = 0x00;//bb: ANK Group sel (not implemented)
jega.RDFFB = 0x00;//bc: Font access first byte
jega.RDFSB = 0x00;//bd: second
jega.RDFAP = 0x00;//be: Font Access Pattern
jega.RPESL = 0x00;//09: end scan line (superceded by EGA)
jega.RPULP = 0x00;//14: under scan line (superceded by EGA)
jega.RPSSC = 1;//db: DBCS start scan line
jega.RPSSU = 3;//d9: 2x DBCS upper start scan
jega.RPSSL = 0;//da: 2x DBCS lower start scan
jega.RPPAJ = 0x00;//dc: super imposed (only AX-2 system, not implemented)
jega.RCMOD = 0x00;//dd: Cursor Mode (not implemented)
jega.RCCLH = 0x00;//0e: Cursor location Upper bits (superceded by EGA)
jega.RCCLL = 0x00;//0f: Cursor location Lower bits (superceded by EGA)
jega.RCCSL = 0x00;//0a: Cursor Start Line (superceded by EGA)
jega.RCCEL = 0x00;//0b: Cursor End Line (superceded by EGA)
jega.RCSKW = 0x20;//de: Cursor Skew control (not implemented)
jega.ROMSL = 0x00;//df: Unused?
jega.RSTAT = 0x03;//bf: Font register accessible status
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS, 0);
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_JEGA_RMOD1, jega.RMOD1);
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_JEGA_RMOD2, jega.RMOD2);
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_GRAPH_ATTR, 0);
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_GRAPH_CHAR, 0);
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_VTRAM_SEGADDR, 0);
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_KBDSTATUS, 0x00);
}
void SVGA_Setup_JEGA(void) {
JEGA_setupAX();
svga.write_p3d5 = &write_p3d5_jega;
svga.read_p3d5 = &read_p3d5_jega;
// Adjust memory to 256K
vga.mem.memsize = 256 * 1024;
/* JEGA BIOS ROM signature for AX architecture
To run MS-DOS, signature ("JA") must be
put at C000h:N*512-18+2 ;N=Number of ROM blocks (rom_base+2)
*/
PhysPt rom_base = PhysMake(0xc000, 0);
phys_writeb(rom_base + 0x40 * 512 - 18 + 2, 'J');
phys_writeb(rom_base + 0x40 * 512 - 18 + 3, 'A');
}
void SVGA_Setup_Driver(void) {
memset(&svga, 0, sizeof(SVGA_Driver));
@ -1501,6 +1729,7 @@ void SVGA_Setup_Driver(void) {
SVGA_Setup_ParadisePVGA1A();
break;
default:
if (IS_JEGA_ARCH) SVGA_Setup_JEGA();
break;
}
}

View File

@ -33,6 +33,7 @@
#include "../gui/render_scalers.h"
#include "vga.h"
#include "pic.h"
#include "jega.h"
#include "menu.h"
#include "timer.h"
#include "config.h"
@ -1952,49 +1953,156 @@ template <const unsigned int card,typename templine_type_t> static inline uint8_
Bitu blocks = vga.draw.blocks;
if (vga.draw.panning) blocks++; // if the text is panned part of an
// additional character becomes visible
Bitu background, foreground;
Bitu chr, chr_left, attr, bsattr;
bool chr_wide = false;
while (blocks--) { // for each character in the line
VGA_Latch pixels;
pixels.d = *vidmem;
vidmem += (uintptr_t)1U << (uintptr_t)vga.config.addr_shift;
Bitu chr = pixels.b[0];
Bitu attr = pixels.b[1];
// the font pattern
Bitu font = vga.draw.font_tables[(attr >> 3)&1][(chr<<5)+line];
Bitu background = attr >> 4u;
// if blinking is enabled bit7 is not mapped to attributes
if (vga.draw.blinking) background &= ~0x8u;
// choose foreground color if blinking not set for this cell or blink on
Bitu foreground = (vga.draw.blink || (!(attr&0x80)))?
(attr&0xf):background;
// underline: all foreground [freevga: 0x77, previous 0x7]
if (GCC_UNLIKELY(((attr&0x77) == 0x01) &&
(vga.crtc.underline_location&0x1f)==line))
background = foreground;
if (vga.draw.char9dot) {
font <<=1; // 9 pixels
// extend to the 9th pixel if needed
if ((font&0x2) && (vga.attr.mode_control&0x04) &&
(chr>=0xc0) && (chr<=0xdf)) font |= 1;
for (Bitu n = 0; n < 9; n++) {
if (card == MCH_VGA)
*draw++ = vga.dac.xlat32[(font&0x100)? foreground:background];
else /*MCH_EGA*/
*draw++ = vga.attr.palette[(font&0x100)? foreground:background];
font <<= 1;
while (blocks--) {
if (isJEGAEnabled()) {
VGA_Latch pixels;
pixels.d = *vidmem;
vidmem += (uintptr_t)1U << (uintptr_t)vga.config.addr_shift;
chr = pixels.b[0];
attr = pixels.b[1];
if (!chr_wide) {
if (!(jega.RMOD2 & 0x80))
{
background = attr >> 4;
foreground = (vga.draw.blink || (!(attr & 0x80))) ? (attr & 0xf) : background;
if (vga.draw.blinking) background &= ~0x8;
bsattr = 0;
}
else {
foreground = (vga.draw.blink || (!(attr & 0x80))) ? (attr & 0xf) : background;
background = 0;
bsattr = attr;
if (bsattr & 0x40) {
Bitu tmp = background;
background = foreground;
foreground = tmp;
}
}
if(isKanji1(chr) && blocks > 1) {
chr_left=chr;
chr_wide=true;
blocks++;
} else {
Bitu font = jfont_sbcs_19[chr*19+line];
for (Bitu n = 0; n < 8; n++) {
*draw++ = vga.attr.palette[(font & 0x80) ? foreground : background];
font <<= 1;
}
if (bsattr & 0x20) {
draw -= 8;
*draw = vga.attr.palette[foreground];
draw += 8;
}
if (line == 18 && bsattr & 0x10) {
draw -= 8;
for (Bitu n = 0; n < 8; n++)
*draw++ = vga.attr.palette[foreground];
}
chr_wide=false;
}
}
else
{
Bitu pad_y = jega.RPSSC;
Bitu exattr = 0;
if (jega.RMOD2 & 0x40) {
exattr = attr;
if ((exattr & 0x30) == 0x30) pad_y = jega.RPSSL;
else if (exattr & 0x30) pad_y = jega.RPSSU;
}
if (line >= pad_y && line < 16 + pad_y) {
if (isKanji2(chr)) {
Bitu fline = line - pad_y;
chr_left <<= 8;
chr |= chr_left;
if (exattr & 0x20) {
if (exattr & 0x10) fline = (fline >> 1) + 8;
else fline = fline >> 1;
}
if (exattr & 0x40) {
Bitu font = jfont_dbcs_16[chr * 32 + fline * 2];
if (!(exattr & 0x08))
font = jfont_dbcs_16[chr * 32 + fline * 2 + 1];
for (Bitu n = 0; n < 8; n++) {
*draw++ = vga.attr.palette[(font & 0x80) ? foreground : background];
*draw++ = vga.attr.palette[(font & 0x80) ? foreground : background];
font <<= 1;
}
} else {
Bitu font = jfont_dbcs_16[chr * 32 + fline * 2];
font <<= 8;
font |= jfont_dbcs_16[chr * 32 + fline * 2 + 1];
if (exattr &= 0x80)
{
Bitu font2 = font;
font2 >>= 1;
font |= font2;
}
for (Bitu n = 0; n < 16; n++) {
*draw++ = vga.attr.palette[(font & 0x8000) ? foreground : background];
font <<= 1;
}
}
} else for (Bitu n = 0; n < 16; n++)
*draw++ = vga.attr.palette[background];
} else if (line == (17 + pad_y) && (bsattr & 0x10)) {
for (Bitu n = 0; n < 16; n++)
*draw++ = vga.attr.palette[foreground];
} else for (Bitu n = 0; n < 16; n++) *draw++ = vga.attr.palette[background];
if (bsattr & 0x20) {
draw -= 16;
*draw = vga.attr.palette[foreground];
draw += 16;
}
chr_wide=false;
blocks--;
}
} else {
for (Bitu n = 0; n < 8; n++) {
if (card == MCH_VGA)
*draw++ = vga.dac.xlat32[(font&0x80)? foreground:background];
else /*MCH_EGA*/
*draw++ = vga.attr.palette[(font&0x80)? foreground:background];
VGA_Latch pixels;
font <<= 1;
pixels.d = *vidmem;
vidmem += (uintptr_t)1U << (uintptr_t)vga.config.addr_shift;
Bitu chr = pixels.b[0];
Bitu attr = pixels.b[1];
// the font pattern
Bitu font = vga.draw.font_tables[(attr >> 3)&1][(chr<<5)+line];
Bitu background = attr >> 4u;
// if blinking is enabled bit7 is not mapped to attributes
if (vga.draw.blinking) background &= ~0x8u;
// choose foreground color if blinking not set for this cell or blink on
Bitu foreground = (vga.draw.blink || (!(attr&0x80)))?
(attr&0xf):background;
// underline: all foreground [freevga: 0x77, previous 0x7]
if (GCC_UNLIKELY(((attr&0x77) == 0x01) &&
(vga.crtc.underline_location&0x1f)==line))
background = foreground;
if (vga.draw.char9dot) {
font <<=1; // 9 pixels
// extend to the 9th pixel if needed
if ((font&0x2) && (vga.attr.mode_control&0x04) &&
(chr>=0xc0) && (chr<=0xdf)) font |= 1;
for (Bitu n = 0; n < 9; n++) {
if (card == MCH_VGA)
*draw++ = vga.dac.xlat32[(font&0x100)? foreground:background];
else /*MCH_EGA*/
*draw++ = vga.attr.palette[(font&0x100)? foreground:background];
font <<= 1;
}
} else {
for (Bitu n = 0; n < 8; n++) {
if (card == MCH_VGA)
*draw++ = vga.dac.xlat32[(font&0x80)? foreground:background];
else /*MCH_EGA*/
*draw++ = vga.attr.palette[(font&0x80)? foreground:background];
font <<= 1;
}
}
}
}
@ -4886,6 +4994,11 @@ void VGA_SetupDrawing(Bitu /*val*/) {
case M_TEXT:
vga.draw.blocks=width;
// if char9_set is true, allow 9-pixel wide fonts
if (isJEGAEnabled()) { //if Kanji Text Disable is off
vga.draw.char9dot = false;
height = 480;
bpp = 16;
}
if ((vga.seq.clocking_mode&0x01) || !vga.draw.char9_set) {
// 8-pixel wide
pix_per_char = 8;

View File

@ -36,6 +36,7 @@
#include "serialport.h"
#include "mapper.h"
#include "vga.h"
#include "jega.h"
#include "shiftjis.h"
#include "pc98_gdc.h"
#include "pc98_gdc_const.h"
@ -5553,6 +5554,23 @@ static Bitu INT17_Handler(void) {
reg_ah=parallelPortObjects[reg_dx]->getPrinterStatus();
//LOG_MSG("printer status: %x",reg_ah);
break;
case 0x20: /* Some sort of printerdriver install check*/
break;
case 0x50: // Printer BIOS for AX
if (!IS_JEGA_ARCH) break;
switch (reg_al) {
case 0x00:// Set JP/US mode in PRT BIOS
LOG(LOG_BIOS, LOG_NORMAL)("AX PRT BIOS 5000h is called. (not implemented)");
reg_al = 0x01; // Return error (not implemented)
break;
case 0x01:// Get JP/US mode in PRT BIOS
reg_al = 0x01; // Return US mode (not implemented)
break;
default:
LOG(LOG_BIOS, LOG_ERROR)("Unhandled AX Function 50%2X", reg_al);
break;
}
break;
}
return CBRET_NONE;
}

View File

@ -27,6 +27,7 @@
#include "dos_inc.h"
#include "SDL.h"
#include "int10.h"
#include "jega.h"
#if defined(_MSC_VER)
# pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */
@ -1595,6 +1596,32 @@ Bitu INT16_Handler(void) {
((mem_readb(BIOS_KEYBOARD_FLAGS2)&4)<<5) | // SysReq pressed, bit 7
(mem_readb(BIOS_KEYBOARD_FLAGS3)&0x0c); // Right Ctrl/Alt pressed, bits 2,3
break;
case 0x50:// Set/Get JP/US mode in KBD BIOS
if (!IS_JEGA_ARCH) break;
switch (reg_al) {
case 0x00:
LOG(LOG_BIOS, LOG_NORMAL)("AX KBD BIOS 5000h is called.");
if (INT16_AX_SetKBDBIOSMode(reg_bx)) reg_al = 0x00;
else reg_al = 0x01;
break;
case 0x01:
LOG(LOG_BIOS,LOG_NORMAL)("AX KBD BIOS 5001h is called.");
reg_bx = INT16_AX_GetKBDBIOSMode();
reg_al = 0;
break;
default:
LOG(LOG_BIOS,LOG_ERROR)("Unhandled AX Function %X",reg_al);
reg_al=0x2;//return unknown error
break;
}
break;
case 0x51:// Get the shift status
if (!IS_JEGA_ARCH) break;
if (INT16_AX_GetKBDBIOSMode() != 0x51) break;//exit if not in JP mode
LOG(LOG_BIOS,LOG_NORMAL)("AX KBD BIOS 51xxh is called.");
reg_al = mem_readb(BIOS_KEYBOARD_FLAGS1);
reg_ah = mem_readb(BIOS_KEYBOARD_AX_KBDSTATUS) & 0x02;
break;
case 0x55:
/* Weird call used by some dos apps */
LOG(LOG_BIOS,LOG_NORMAL)("INT16:55:Word TSR compatible call");

View File

@ -28,6 +28,7 @@
#include "mouse.h"
#include "setup.h"
#include "render.h"
#include "jega.h"
Int10Data int10;
bool blinking=true;
@ -768,6 +769,185 @@ CX 640x480 800x600 1024x768/1280x1024
break;
}
break;
case 0x50:// Set/Read JP/US mode of CRT BIOS
switch (reg_al) {
case 0x00:
LOG(LOG_INT10, LOG_NORMAL)("AX CRT BIOS 5000h is called.");
if (INT10_AX_SetCRTBIOSMode(reg_bx)) reg_al = 0x00;
else reg_al = 0x01;
break;
case 0x01:
//LOG(LOG_INT10,LOG_NORMAL)("AX CRT BIOS 5001h is called.");
reg_bx=INT10_AX_GetCRTBIOSMode();
reg_al=0;
break;
default:
LOG(LOG_INT10,LOG_ERROR)("Unhandled AX Function %X",reg_al);
reg_al=0x0;
break;
}
break;
case 0x51:// Save/Read JFONT pattern
if(INT10_AX_GetCRTBIOSMode() == 0x01) break;//exit if CRT BIOS is in US mode
switch (reg_al) {
//INT 10h/AX=5100h Store user font pattern
//IN
//ES:BP=Index of store buffer
//DX=Char code
//BH=width bits of char
//BL=height bits of char
//OUT
//AL=status 00h=Success 01h=Failed
case 0x00:
{
LOG(LOG_INT10, LOG_NORMAL)("AX CRT BIOS 5100h is called.");
Bitu buf_es = SegValue(es);
Bitu buf_bp = reg_bp;
Bitu chr = reg_dx;
Bitu w_chr = reg_bh;
Bitu h_chr = reg_bl;
Bitu font;
if (w_chr == 16 && h_chr == 16) {
for (Bitu line = 0; line < 16; line++)
{
//Order of font pattern is different between FONTX2 and AX(JEGA).
font = real_readb(buf_es, buf_bp + line);
jfont_dbcs_16[chr * 32 + line * 2] = font;
font = real_readb(buf_es, buf_bp + line + 16);
jfont_dbcs_16[chr * 32 + line * 2 + 1] = font;
}
reg_al = 0x00;
}
else
reg_al = 0x01;
break;
}
//INT 10h/AX=5101h Read character pattern
//IN
//ES:BP=Index of read buffer
//DX=Char code
//BH=width bits of char
//BL=height bits of char
//OUT
//AL=status 00h=Success 01h=Failed
case 0x01:
{
LOG(LOG_INT10, LOG_NORMAL)("AX CRT BIOS 5101h is called.");
Bitu buf_es = SegValue(es);
Bitu buf_bp = reg_bp;
Bitu chr = reg_dx;
Bitu w_chr = reg_bh;
Bitu h_chr = reg_bl;
Bitu font;
if (w_chr == 8) {
reg_al = 0x00;
switch (h_chr)
{
case 8:
for (Bitu line = 0; line < 8; line++)
real_writeb(buf_es, buf_bp + line, int10_font_08[chr * 8 + line]);
break;
case 14:
for (Bitu line = 0; line < 14; line++)
real_writeb(buf_es, buf_bp + line, int10_font_14[chr * 14 + line]);
break;
case 19:
for (Bitu line = 0; line < 19; line++)
real_writeb(buf_es, buf_bp + line, jfont_sbcs_19[chr * 19 + line]);
break;
default:
reg_al = 0x01;
break;
}
}
else if (w_chr == 16 && h_chr == 16) {
reg_al = 0x00;
for (Bitu line = 0; line < 16; line++)
{
font = jfont_dbcs_16[chr * 32 + line * 2];
real_writeb(buf_es, buf_bp + line, font);
font = jfont_dbcs_16[chr * 32 + line * 2 + 1];
real_writeb(buf_es, buf_bp + line + 16, font);
}
}
else
reg_al = 0x01;
break;
}
default:
LOG(LOG_INT10,LOG_ERROR)("Unhandled AX Function %X",reg_al);
reg_al=0x1;
break;
}
break;
case 0x52:// Set/Read virtual text ram buffer when the video mode is JEGA graphic mode
if(INT10_AX_GetCRTBIOSMode() == 0x01) break;//exit if CRT BIOS is in US mode
LOG(LOG_INT10,LOG_NORMAL)("AX CRT BIOS 52xxh is called.");
switch (reg_al) {
case 0x00:
{
if (reg_bx == 0) real_writew(BIOSMEM_AX_SEG, BIOSMEM_AX_VTRAM_SEGADDR, 0);
else
{
LOG(LOG_INT10, LOG_NORMAL)("AX CRT BIOS set VTRAM segment address at %x", reg_bx);
real_writew(BIOSMEM_AX_SEG, BIOSMEM_AX_VTRAM_SEGADDR, reg_bx);
/* Fill VTRAM with 0x20(Space) */
for (int y = 0; y < 25; y++)
for (int x = 0; x < 80; x++)
SetVTRAMChar(x, y, 0x20, 0x00);
}
break;
}
case 0x01:
{
Bitu vtram_seg = real_readw(BIOSMEM_AX_SEG, BIOSMEM_AX_VTRAM_SEGADDR);
if (vtram_seg == 0x0000) reg_bx = 0;
else reg_bx = vtram_seg;
break;
}
default:
LOG(LOG_INT10,LOG_ERROR)("Unhandled AX Function %X",reg_al);
break;
}
break;
case 0x82:// Set/Read the scroll mode when the video mode is JEGA graphic mode
if(INT10_AX_GetCRTBIOSMode() == 0x01) break;//exit if CRT BIOS is in US mode
LOG(LOG_INT10,LOG_NORMAL)("AX CRT BIOS 82xxh is called.");
switch (reg_al) {
case 0x00:
if (reg_bl == -1) {//Read scroll mode
reg_al = real_readb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS) & 0x01;
}
else {//Set scroll mode
Bit8u tmp = real_readb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS);
reg_al = tmp & 0x01;//Return previous scroll mode
tmp |= (reg_bl & 0x01);
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS, tmp);
}
break;
default:
LOG(LOG_INT10,LOG_ERROR)("Unhandled AX Function %X",reg_al);
break;
}
break;
case 0x83:// Read the video RAM address and virtual text video RAM
//Out: AX=base address of video RAM, ES:BX=base address of virtual text video RAM
if(INT10_AX_GetCRTBIOSMode() == 0x01) break;//exit if CRT BIOS is in US mode
LOG(LOG_INT10,LOG_NORMAL)("AX CRT BIOS 83xxh is called.");
switch (reg_al) {
case 0x00:
{
reg_ax = CurMode->pstart;
Bitu vtram_seg = real_readw(BIOSMEM_AX_SEG, BIOSMEM_AX_VTRAM_SEGADDR);
RealMakeSeg(es, vtram_seg >> 4);
reg_bx = vtram_seg << 4;
break;
}
default:
LOG(LOG_INT10,LOG_ERROR)("Unhandled AX Function %X",reg_al);
break;
}
break;
case 0xf0:
INT10_EGA_RIL_ReadRegister(reg_bl, reg_dx);
break;
@ -1152,6 +1332,59 @@ RealPt GetSystemBiosINT10Vector(void) {
return 0;
}
Bitu INT10_AX_GetCRTBIOSMode(void) {
if (!IS_JEGA_ARCH) return 0x01;
if (real_readb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS) & 0x80) return 0x51;//if in US mode
else return 0x01;
}
bool INT10_AX_SetCRTBIOSMode(Bitu mode) {
if (!IS_JEGA_ARCH) return false;
Bit8u tmp = real_readb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS);
switch (mode) {
//Todo: verify written value
case 0x01:
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS, tmp & 0x7F);
LOG(LOG_INT10, LOG_NORMAL)("AX CRT BIOS has been set to US mode.");
INT10_SetVideoMode(0x03);
return true;
/* -------------------SET to JP mode in CRT BIOS -------------------- */
case 0x51:
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS, tmp | 0x80);
LOG(LOG_INT10, LOG_NORMAL)("AX CRT BIOS has been set to JP mode.");
// Mouse_BeforeNewVideoMode(true);
// change to the default video mode (03h) with vram cleared
INT10_SetVideoMode(0x03);
// Mouse_AfterNewVideoMode(true);;
return true;
default:
return false;
}
}
Bitu INT16_AX_GetKBDBIOSMode(void) {
if (!IS_JEGA_ARCH) return 0x01;
if (real_readb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS) & 0x40) return 0x51;//if in US mode
else return 0x01;
}
bool INT16_AX_SetKBDBIOSMode(Bitu mode) {
if (!IS_JEGA_ARCH) return false;
Bit8u tmp = real_readb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS);
switch (mode) {
//Todo: verify written value
case 0x01:
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS, tmp & 0xBF);
LOG(LOG_INT10, LOG_NORMAL)("AX KBD BIOS has been set to US mode.");
return true;
case 0x51:
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_JPNSTATUS, tmp | 0x40);
LOG(LOG_INT10, LOG_NORMAL)("AX KBD BIOS has been set to JP mode.");
return true;
default:
return false;
}
}
extern bool VGA_BIOS_use_rom;
void INT10_Startup(Section *sec) {

View File

@ -130,6 +130,7 @@ typedef struct {
RealPt font_16;
RealPt font_14_alternate;
RealPt font_16_alternate;
RealPt font_19;
RealPt static_state;
RealPt video_save_pointers;
RealPt video_dynamic_save_area;

View File

@ -26,8 +26,11 @@
#include "int10.h"
#include "shiftjis.h"
#include "callback.h"
#include "jega.h"
#include <string.h>
Bit8u prevchr = 0;
uint8_t DefaultANSIAttr();
#if defined(_MSC_VER)
@ -542,6 +545,12 @@ void ReadCharAttr(uint16_t col,uint16_t row,uint8_t page,uint16_t * result) {
}
break;
default:
if (isJEGAEnabled()) {
if (real_readw(BIOSMEM_AX_SEG, BIOSMEM_AX_VTRAM_SEGADDR) != 0) {
ReadVTRAMChar(col, row, result);
return;
}
}
fontdata=Real2Phys(RealGetVec(0x43));
break;
}
@ -595,6 +604,78 @@ void INT10_PC98_CurMode_Relocate(void) {
/* deprecated */
}
/* Draw DBCS char in graphics mode*/
void WriteCharJ(Bit16u col, Bit16u row, Bit8u page, Bit8u chr, Bit8u attr, bool useattr)
{
Bitu x, y, pos = row*real_readw(BIOSMEM_SEG, BIOSMEM_NB_COLS) + col;
Bit8u back, cheight = real_readb(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT);
Bit16u sjischr = prevchr;
sjischr <<= 8;
sjischr |= chr;
if (GCC_UNLIKELY(!useattr)) { //Set attribute(color) to a sensible value
static bool warned_use = false;
if (GCC_UNLIKELY(!warned_use)) {
LOG(LOG_INT10, LOG_ERROR)("writechar used without attribute in non-textmode %c %X", chr, chr);
warned_use = true;
}
attr = 0xf;
}
//Attribute behavior of mode 6; mode 11 does something similar but
//it is in INT 10h handler because it only applies to function 09h
if (CurMode->mode == 0x06) attr = (attr & 0x80) | 1;
switch (CurMode->type) {
case M_VGA:
case M_EGA:
/* enable all planes for EGA modes (Ultima 1 colour bug) */
/* might be put into INT10_PutPixel but different vga bios
implementations have different opinions about this */
IO_Write(0x3c4, 0x2); IO_Write(0x3c5, 0xf);
// fall-through
default:
back = attr & 0x80;
break;
}
x = (pos%CurMode->twidth - 1) * 8;//move right 1 column.
y = (pos / CurMode->twidth)*cheight;
Bit16u ty = (Bit16u)y + 1;
for (Bit8u h = 0; h<16 ; h++) {
Bit16u bitsel = 0x8000;
Bit16u bitline = jfont_dbcs_16[sjischr * 32 + h * 2];
bitline <<= 8;
bitline |= jfont_dbcs_16[sjischr * 32 + h * 2 + 1];
Bit16u tx = (Bit16u)x;
while (bitsel) {
INT10_PutPixel(tx, ty, page, (bitline&bitsel) ? attr : back);
tx++;
bitsel >>= 1;
}
ty++;
}
}
/* Read char code and attribute from Virtual Text RAM (for AX)*/
void ReadVTRAMChar(Bit16u col, Bit16u row, Bit16u * result) {
Bitu addr = real_readw(BIOSMEM_AX_SEG, BIOSMEM_AX_VTRAM_SEGADDR);
addr <<= 4;
addr += 2 * (80 * row + col);
*result = mem_readw(addr);
}
/* Write char code and attribute into Virtual Text RAM (for AX)*/
void SetVTRAMChar(Bit16u col, Bit16u row, Bit8u chr, Bit8u attr)
{
Bitu addr = real_readw(BIOSMEM_AX_SEG, BIOSMEM_AX_VTRAM_SEGADDR);
addr <<= 4;
addr += 2 * (80 * row + col);
mem_writeb(addr,chr);
mem_writeb(addr+1, attr);
}
void WriteChar(uint16_t col,uint16_t row,uint8_t page,uint16_t chr,uint8_t attr,bool useattr) {
/* Externally used by the mouse routine */
PhysPt fontdata;
@ -662,6 +743,18 @@ void WriteChar(uint16_t col,uint16_t row,uint8_t page,uint16_t chr,uint8_t attr,
}
break;
default:
if (isJEGAEnabled()) {
if (real_readw(BIOSMEM_AX_SEG, BIOSMEM_AX_VTRAM_SEGADDR) != 0)
SetVTRAMChar(col, row, chr, attr);
if (isKanji1(chr) && prevchr == 0)
prevchr = chr;
else if (isKanji2(chr) && prevchr != 0)
{
WriteCharJ(col, row, page, chr, attr, useattr);
prevchr = 0;
return;
}
}
fontdata=RealGetVec(0x43);
break;
}
@ -809,6 +902,13 @@ static void INT10_TeletypeOutputAttr(uint8_t chr,uint8_t attr,bool useattr,uint8
}
chr=' ';
default:
/* Return if the char code is DBCS at the end of the line (for AX) */
if (cur_col + 1 == ncols && isJEGAEnabled() && isKanji1(chr))
{
INT10_TeletypeOutputAttr(' ', attr, useattr, page);
cur_row = CURSOR_POS_ROW(page);
cur_col = CURSOR_POS_COL(page);
}
/* Draw the actual Character */
WriteChar(cur_col,cur_row,page,chr,attr,useattr);
cur_col++;

View File

@ -23,6 +23,7 @@
#include "inout.h"
#include "int10.h"
#include "callback.h"
#include "jega.h"
bool int10_vga_bios_vector = true;
bool rom_bios_8x8_cga_font = true;
@ -149,6 +150,10 @@ void INT10_ReloadFont(void) {
if (IS_VGA_ARCH && svgaCard==SVGA_None && CurMode->mode==7) map=0x80;
INT10_LoadFont(Real2Phys(int10.rom.font_14),false,256,0,map,14);
break;
case 19:
if (IS_EGA_ARCH && svgaCard == SVGA_None) map = 0x80;
INT10_LoadFont(Real2Phys(int10.rom.font_19), false, 256, 0, map, 19);
break;
case 16:
default:
if (IS_VGA_ARCH && svgaCard==SVGA_None) map=0x80;
@ -385,6 +390,11 @@ void INT10_SetupRomMemory(void) {
phys_writeb(rom_base+int10.rom.used++,int10_font_16_alternate[i]);
}
}
else if (IS_JEGA_ARCH) {
int10.rom.font_19 = RealMake(0xC000, int10.rom.used);
for (i = 0; i < 256 * 19; i++)
phys_writeb(rom_base + int10.rom.used++, jfont_sbcs_19[i]);
}
else {
int10.rom.font_16=0; /* why write the 16-high version if not emulating VGA? */
int10.rom.font_16_alternate=0;
@ -494,6 +504,12 @@ void INT10_ReloadRomFonts(void) {
for (unsigned int i=0;i<128*8;i++) {
phys_writeb(font8pt+i,int10_font_08[i+128*8]);
}
if (IS_JEGA_ARCH) {
PhysPt font19pt = Real2Phys(int10.rom.font_19);
for (Bitu i = 0; i < 256 * 19; i++) {
phys_writeb(font19pt + i, jfont_sbcs_19[i]);
}
}
INT10_SetupRomMemoryChecksum();
}

View File

@ -30,6 +30,7 @@
#include "render.h"
#include "menu.h"
#include "regs.h"
#include "jega.h"
#include "callback.h"
#define SEQ_REGS 0x05
@ -443,6 +444,23 @@ VideoModeBlock ModeList_EGA[]={
{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
};
VideoModeBlock ModeList_JEGA[]={
/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */
{ 0x000 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
{ 0x001 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _DOUBLESCAN },
{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _DOUBLESCAN },
{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_DOUBLESCAN },
{ 0x007 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
{ 0x010 ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },
// JEGA modes for AX
//{ 0x002 ,M_JEGA_TEXT ,640 ,480 ,80 ,25 ,8 ,19 ,8 ,0xB8000 ,0x1000 ,96 ,525 ,80 ,480 ,0 },//AX-2 is not implemented;
{ 0x003 ,M_TEXT ,640 ,480 ,80 ,25 ,8 ,19 ,8 ,0xB8000 ,0x1000 ,96 ,525 ,80 ,480 ,0 },
//{ 0x052 ,M_JEGA_GFX ,640 ,480 ,80 ,25 ,8 ,19 ,8 ,0xA0000 ,0x10000 ,96 ,525 ,80 ,480 ,0 },//AX-2 is not implemented;
//{ 0x053 ,M_EGA ,640 ,480 ,80 ,25 ,8 ,19 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },
{ 0x053 ,M_EGA ,640 ,480 ,80 ,25 ,8 ,19 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },
};
VideoModeBlock ModeList_OTHER[]={
/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde ,special flags */
{ 0x000 ,M_TEXT ,320 ,400 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x0800 ,56 ,31 ,40 ,25 ,0 },
@ -816,7 +834,9 @@ static void FinishSetMode(bool clearmem) {
#endif
/* Set font pointer */
if (CurMode->mode<=3 || CurMode->mode==7)
if ((isJEGAEnabled()) && (CurMode->mode == 0x03 || CurMode->mode == 0x53))
RealSetVec(0x43, int10.rom.font_19);
else if (CurMode->mode<=3 || CurMode->mode==7)
RealSetVec(0x43,int10.rom.font_8_first);
else {
switch (CurMode->cheight) {
@ -1273,7 +1293,31 @@ bool INT10_SetVideoMode(uint16_t mode) {
// uint8_t vga_switches=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES);
uint8_t modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
if (IS_VGA_ARCH) {
if (IS_JEGA_ARCH) {
IO_WriteB(0x3d4, 0xb9);
Bitu tmp = IO_ReadB(0x3d5);
tmp |= 0x40;
IO_WriteB(0x3d5, tmp);
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_JEGA_RMOD1, tmp);
}
if (INT10_AX_GetCRTBIOSMode() == 0x51) {
if (mode == 0x02) mode = 0x03;//Video mode 02h redirect to 03h (AX-1)
if (mode == 0x52) mode = 0x53;//Video mode 52h redirect to 53h (AX-1)
if (mode == 0x03 || mode == 0x53)
{
//Enable JEGA Display Out only in video mode 03h or 53h
IO_WriteB(0x3d4, 0xb9);
Bitu tmp = IO_ReadB(0x3d5);
tmp &= 0xbf;
IO_WriteB(0x3d5, tmp);
real_writeb(BIOSMEM_AX_SEG, BIOSMEM_AX_JEGA_RMOD1, tmp);;
}
if (!SetCurMode(ModeList_JEGA, mode)) {
LOG(LOG_INT10, LOG_ERROR)("JEGA:Trying to set illegal mode %X", mode);
return false;
}
}
else if (IS_VGA_ARCH) {
if (svga.accepts_mode) {
if (!svga.accepts_mode(mode)) return false;
}