Closed mfld-fr closed 3 years ago
Interesting. I will look into this after #56 is committed, as it needs your new "reference" PC BIOS in order to boot...
It looks like INT 10h AH=00h video mode 4 (according to Table of Video Modes) is 320x200 four-color graphics; I assume EGA 4-plane mode. Its probably a lot of work to emulate the EGA graphics modes, not sure how worth it this would be. Also, the SDL backend will need to be modified to resize its window from 640x400 (used for 80x25 text) to 320x200 etc for each graphics mode. (And it looks like there's 4 other graphics modes as well, all different sizes).
Emulating the EGA 4-plane mode involves interpreting the following outb
functions to the CRT Controller (taken from Nano-X EGA graphics driver):
/* Program the Set/Reset Register for drawing in color COLOR for write
mode 0. */
#define set_color(c) { outb (0, 0x3ce); outb (c, 0x3cf); }
/* Set the Enable Set/Reset Register. */
#define set_enable_sr(mask) { outb (1, 0x3ce); outb (mask, 0x3cf); }
/* Select the Bit Mask Register on the Graphics Controller. */
#define select_mask() { outb (8, 0x3ce); }
/* Program the Bit Mask Register to affect only the pixels selected in
MASK. The Bit Mask Register must already have been selected with
select_mask (). */
#define set_mask(mask) { outb (mask, 0x3cf); }
/* Set the Data Rotate Register. Bits 0-2 are rotate count, bits 3-4
are logical operation (0=NOP, 1=AND, 2=OR, 3=XOR). */
#define set_op(op) { outb (3, 0x3ce); outb (op, 0x3cf); }
/* Set the Memory Plane Write Enable register. */
#define set_write_planes(mask) { outb (2, 0x3c4); outb (mask, 0x3c5); }
/* Set the Read Map Select register. */
#define set_read_plane(plane) { outb (4, 0x3ce); outb (plane, 0x3cf); }
/* Set the Graphics Mode Register. The write mode is in bits 0-1, the
read mode is in bit 3. */
#define set_mode(mode) { outb (5, 0x3ce); outb (mode, 0x3cf); }
Now you know why framebuffers took over the world (at least before graphics pipeline GPUs) and nobody writes any code for EGA/VGA 4-plane hardware anymore!!!
To give you an example of how complicated EGA graphics are, here is the "fast" EGA horizontal line draw code from the Nano-X driver. This is what it takes to just "quickly" draw a horizontal line. On ELKS, users with real IBM PC hardware are complaining how slow this displays (in C, not ASM). I can't imagine the speed under EMU86!
/* read-modify-write at address*/
#define RMW_FP(addr) ((*(FARADDR)(addr)) |= 1)
/* Draw horizontal line from x1,y to x2,y not including final point*/
void
ega_drawhorzline(PSD psd, unsigned int x1, unsigned int x2, unsigned int y,
PIXELVAL c)
{
FARADDR dst, last;
--x2;
assert (x1 >= 0 && x1 < psd->xres);
assert (x2 >= 0 && x2 < psd->xres);
assert (x2 >= x1);
assert (y >= 0 && y < psd->yres);
assert (c >= 0 && c < psd->ncolors);
DRAWON;
set_color (c);
set_op(mode_table[gr_mode]);
/*
* The following fast drawhline code is buggy for XOR drawing,
* for some reason. So, we use the equivalent slower drawpixel
* method when not drawing MODE_SET.
*/
if(gr_mode == MODE_SET) {
dst = SCREENBASE + x1 / 8 + y * BYTESPERLINE;
select_mask ();
if (x1 / 8 == x2 / 8) {
set_mask ((0xff >> (x1 % 8)) & (0xff << (7 - x2 % 8)));
RMW_FP (dst);
} else {
set_mask (0xff >> (x1 % 8));
RMW_FP (dst++);
set_mask (0xff);
last = SCREENBASE + x2 / 8 + y * BYTESPERLINE;
while (dst < last)
PUTBYTE_FP(dst++, 1);
set_mask (0xff << (7 - x2 % 8));
RMW_FP (dst);
}
} else {
/* slower method, draw pixel by pixel*/
select_mask ();
while(x1 < x2) {
set_mask (mask[x1&7]);
RMW_FP (SCREENBASE + x1++ / 8 + y * BYTESPERLINE);
}
}
DRAWOFF;
}
Hey, stop running, that issue was a only a joke after #30 :smile_cat: !
EMU86 is not intended for end user PC emulation, as stated in the README. One can play Alleycat with QEMU or whatever, and CGA support brings nothing in term of debugging for embedded.
Going further in booting a 'standard' OS like MS-DOS or FreeDOS was only a test case for the emulation engine.
This is a very good test case for the graphical console :wink: