Full VGA support, including old CGA modes, VGA planar and mode X
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@346 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
39cf780327
commit
17b0018b42
257
hw/vga.c
257
hw/vga.c
|
@ -49,6 +49,7 @@
|
||||||
#include "thunk.h"
|
#include "thunk.h"
|
||||||
|
|
||||||
//#define DEBUG_VGA
|
//#define DEBUG_VGA
|
||||||
|
//#define DEBUG_VGA_MEM
|
||||||
|
|
||||||
#define MSR_COLOR_EMULATION 0x01
|
#define MSR_COLOR_EMULATION 0x01
|
||||||
#define MSR_PAGE_SELECT 0x20
|
#define MSR_PAGE_SELECT 0x20
|
||||||
|
@ -85,7 +86,8 @@ typedef struct VGAState {
|
||||||
DisplayState *ds;
|
DisplayState *ds;
|
||||||
uint32_t font_offsets[2];
|
uint32_t font_offsets[2];
|
||||||
int graphic_mode;
|
int graphic_mode;
|
||||||
int shift_control;
|
uint8_t shift_control;
|
||||||
|
uint8_t double_scan;
|
||||||
uint32_t line_offset;
|
uint32_t line_offset;
|
||||||
uint32_t line_compare;
|
uint32_t line_compare;
|
||||||
uint32_t start_addr;
|
uint32_t start_addr;
|
||||||
|
@ -93,10 +95,11 @@ typedef struct VGAState {
|
||||||
uint32_t last_width, last_height;
|
uint32_t last_width, last_height;
|
||||||
uint8_t cursor_start, cursor_end;
|
uint8_t cursor_start, cursor_end;
|
||||||
uint32_t cursor_offset;
|
uint32_t cursor_offset;
|
||||||
|
unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
|
||||||
/* tell for each page if it has been updated since the last time */
|
/* tell for each page if it has been updated since the last time */
|
||||||
uint8_t vram_updated[VGA_RAM_SIZE / 4096];
|
uint8_t vram_updated[VGA_RAM_SIZE / 4096];
|
||||||
uint32_t last_palette[256];
|
uint32_t last_palette[256];
|
||||||
#define CH_ATTR_SIZE (132 * 60)
|
#define CH_ATTR_SIZE (160 * 100)
|
||||||
uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
|
uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
|
||||||
} VGAState;
|
} VGAState;
|
||||||
|
|
||||||
|
@ -199,6 +202,7 @@ static const uint32_t dmask4[4] = {
|
||||||
|
|
||||||
static uint32_t expand4[256];
|
static uint32_t expand4[256];
|
||||||
static uint16_t expand2[256];
|
static uint16_t expand2[256];
|
||||||
|
static uint8_t expand4to8[16];
|
||||||
|
|
||||||
VGAState vga_state;
|
VGAState vga_state;
|
||||||
int vga_io_memory;
|
int vga_io_memory;
|
||||||
|
@ -503,7 +507,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
|
||||||
int memory_map_mode, plane, write_mode, b, func_select;
|
int memory_map_mode, plane, write_mode, b, func_select;
|
||||||
uint32_t write_mask, bit_mask, set_mask;
|
uint32_t write_mask, bit_mask, set_mask;
|
||||||
|
|
||||||
#ifdef DEBUG_VGA
|
#ifdef DEBUG_VGA_MEM
|
||||||
printf("vga: [0x%x] = 0x%02x\n", addr, val);
|
printf("vga: [0x%x] = 0x%02x\n", addr, val);
|
||||||
#endif
|
#endif
|
||||||
/* convert to VGA memory offset */
|
/* convert to VGA memory offset */
|
||||||
|
@ -533,7 +537,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
|
||||||
plane = addr & 3;
|
plane = addr & 3;
|
||||||
if (s->sr[2] & (1 << plane)) {
|
if (s->sr[2] & (1 << plane)) {
|
||||||
s->vram_ptr[addr] = val;
|
s->vram_ptr[addr] = val;
|
||||||
#ifdef DEBUG_VGA
|
#ifdef DEBUG_VGA_MEM
|
||||||
printf("vga: chain4: [0x%x]\n", addr);
|
printf("vga: chain4: [0x%x]\n", addr);
|
||||||
#endif
|
#endif
|
||||||
s->vram_updated[addr >> 12] = 1;
|
s->vram_updated[addr >> 12] = 1;
|
||||||
|
@ -544,7 +548,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
|
||||||
if (s->sr[2] & (1 << plane)) {
|
if (s->sr[2] & (1 << plane)) {
|
||||||
addr = ((addr & ~1) << 1) | plane;
|
addr = ((addr & ~1) << 1) | plane;
|
||||||
s->vram_ptr[addr] = val;
|
s->vram_ptr[addr] = val;
|
||||||
#ifdef DEBUG_VGA
|
#ifdef DEBUG_VGA_MEM
|
||||||
printf("vga: odd/even: [0x%x]\n", addr);
|
printf("vga: odd/even: [0x%x]\n", addr);
|
||||||
#endif
|
#endif
|
||||||
s->vram_updated[addr >> 12] = 1;
|
s->vram_updated[addr >> 12] = 1;
|
||||||
|
@ -615,7 +619,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
|
||||||
((uint32_t *)s->vram_ptr)[addr] =
|
((uint32_t *)s->vram_ptr)[addr] =
|
||||||
(((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
|
(((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
|
||||||
(val & write_mask);
|
(val & write_mask);
|
||||||
#ifdef DEBUG_VGA
|
#ifdef DEBUG_VGA_MEM
|
||||||
printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
|
printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
|
||||||
addr * 4, write_mask, val);
|
addr * 4, write_mask, val);
|
||||||
#endif
|
#endif
|
||||||
|
@ -699,28 +703,43 @@ static inline int c6_to_8(int v)
|
||||||
return (v << 2) | (b << 1) | b;
|
return (v << 2) | (b << 1) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
|
||||||
|
{
|
||||||
|
unsigned int col;
|
||||||
|
col = rgb_to_pixel8(r, g, b);
|
||||||
|
col |= col << 8;
|
||||||
|
col |= col << 16;
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
|
||||||
|
{
|
||||||
|
unsigned int col;
|
||||||
|
col = rgb_to_pixel15(r, g, b);
|
||||||
|
col |= col << 16;
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
|
||||||
|
{
|
||||||
|
unsigned int col;
|
||||||
|
col = rgb_to_pixel16(r, g, b);
|
||||||
|
col |= col << 16;
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
|
||||||
|
{
|
||||||
|
unsigned int col;
|
||||||
|
col = rgb_to_pixel32(r, g, b);
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
/* return true if the palette was modified */
|
/* return true if the palette was modified */
|
||||||
static int update_palette16(VGAState *s)
|
static int update_palette16(VGAState *s)
|
||||||
{
|
{
|
||||||
int full_update, i, depth;
|
int full_update, i;
|
||||||
uint32_t v, col, *palette;
|
uint32_t v, col, *palette;
|
||||||
unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
|
|
||||||
depth = s->ds->depth;
|
|
||||||
switch(depth) {
|
|
||||||
case 8:
|
|
||||||
rgb_to_pixel = rgb_to_pixel8;
|
|
||||||
break;
|
|
||||||
case 15:
|
|
||||||
rgb_to_pixel = rgb_to_pixel15;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
case 16:
|
|
||||||
rgb_to_pixel = rgb_to_pixel16;
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
rgb_to_pixel = rgb_to_pixel32;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
full_update = 0;
|
full_update = 0;
|
||||||
palette = s->last_palette;
|
palette = s->last_palette;
|
||||||
|
@ -731,17 +750,9 @@ static int update_palette16(VGAState *s)
|
||||||
else
|
else
|
||||||
v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
|
v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
|
||||||
v = v * 3;
|
v = v * 3;
|
||||||
col = rgb_to_pixel(c6_to_8(s->palette[v]),
|
col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
|
||||||
c6_to_8(s->palette[v + 1]),
|
c6_to_8(s->palette[v + 1]),
|
||||||
c6_to_8(s->palette[v + 2]));
|
c6_to_8(s->palette[v + 2]));
|
||||||
|
|
||||||
if (depth == 8) {
|
|
||||||
col |= col << 8;
|
|
||||||
col |= col << 16;
|
|
||||||
} else if (depth <= 16) {
|
|
||||||
col |= col << 16;
|
|
||||||
}
|
|
||||||
// printf("%2d: %08x\n", i, col);
|
|
||||||
if (col != palette[i]) {
|
if (col != palette[i]) {
|
||||||
full_update = 1;
|
full_update = 1;
|
||||||
palette[i] = col;
|
palette[i] = col;
|
||||||
|
@ -750,6 +761,28 @@ static int update_palette16(VGAState *s)
|
||||||
return full_update;
|
return full_update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return true if the palette was modified */
|
||||||
|
static int update_palette256(VGAState *s)
|
||||||
|
{
|
||||||
|
int full_update, i;
|
||||||
|
uint32_t v, col, *palette;
|
||||||
|
|
||||||
|
full_update = 0;
|
||||||
|
palette = s->last_palette;
|
||||||
|
v = 0;
|
||||||
|
for(i = 0; i < 256; i++) {
|
||||||
|
col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
|
||||||
|
c6_to_8(s->palette[v + 1]),
|
||||||
|
c6_to_8(s->palette[v + 2]));
|
||||||
|
if (col != palette[i]) {
|
||||||
|
full_update = 1;
|
||||||
|
palette[i] = col;
|
||||||
|
}
|
||||||
|
v += 3;
|
||||||
|
}
|
||||||
|
return full_update;
|
||||||
|
}
|
||||||
|
|
||||||
/* update start_addr and line_offset. Return TRUE if modified */
|
/* update start_addr and line_offset. Return TRUE if modified */
|
||||||
static int update_basic_params(VGAState *s)
|
static int update_basic_params(VGAState *s)
|
||||||
{
|
{
|
||||||
|
@ -806,6 +839,13 @@ static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
|
||||||
vga_draw_glyph8_32,
|
vga_draw_glyph8_32,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
|
||||||
|
vga_draw_glyph16_8,
|
||||||
|
vga_draw_glyph16_16,
|
||||||
|
vga_draw_glyph16_16,
|
||||||
|
vga_draw_glyph16_32,
|
||||||
|
};
|
||||||
|
|
||||||
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
|
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
|
||||||
vga_draw_glyph9_8,
|
vga_draw_glyph9_8,
|
||||||
vga_draw_glyph9_16,
|
vga_draw_glyph9_16,
|
||||||
|
@ -882,12 +922,19 @@ static void vga_draw_text(VGAState *s, int full_update)
|
||||||
cw = 8;
|
cw = 8;
|
||||||
if (s->sr[1] & 0x01)
|
if (s->sr[1] & 0x01)
|
||||||
cw = 9;
|
cw = 9;
|
||||||
|
if (s->sr[1] & 0x08)
|
||||||
|
cw = 16; /* NOTE: no 18 pixel wide */
|
||||||
x_incr = cw * ((s->ds->depth + 7) >> 3);
|
x_incr = cw * ((s->ds->depth + 7) >> 3);
|
||||||
width = (s->cr[0x01] + 1);
|
width = (s->cr[0x01] + 1);
|
||||||
|
if (s->cr[0x06] == 100) {
|
||||||
|
/* ugly hack for CGA 160x100x16 - explain me the logic */
|
||||||
|
height = 100;
|
||||||
|
} else {
|
||||||
height = s->cr[0x12] |
|
height = s->cr[0x12] |
|
||||||
((s->cr[0x07] & 0x02) << 7) |
|
((s->cr[0x07] & 0x02) << 7) |
|
||||||
((s->cr[0x07] & 0x40) << 3);
|
((s->cr[0x07] & 0x40) << 3);
|
||||||
height = (height + 1) / cheight;
|
height = (height + 1) / cheight;
|
||||||
|
}
|
||||||
if (width != s->last_width || height != s->last_height ||
|
if (width != s->last_width || height != s->last_height ||
|
||||||
cw != s->last_cw || cw != s->last_cw) {
|
cw != s->last_cw || cw != s->last_cw) {
|
||||||
dpy_resize(s->ds, width * cw, height * cheight);
|
dpy_resize(s->ds, width * cw, height * cheight);
|
||||||
|
@ -914,6 +961,9 @@ static void vga_draw_text(VGAState *s, int full_update)
|
||||||
cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
|
cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
|
||||||
|
|
||||||
depth_index = get_depth_index(s->ds->depth);
|
depth_index = get_depth_index(s->ds->depth);
|
||||||
|
if (cw == 16)
|
||||||
|
vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
|
||||||
|
else
|
||||||
vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
|
vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
|
||||||
vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
|
vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
|
||||||
|
|
||||||
|
@ -944,7 +994,7 @@ static void vga_draw_text(VGAState *s, int full_update)
|
||||||
font_ptr += 32 * 4 * ch;
|
font_ptr += 32 * 4 * ch;
|
||||||
bgcol = palette[cattr >> 4];
|
bgcol = palette[cattr >> 4];
|
||||||
fgcol = palette[cattr & 0x0f];
|
fgcol = palette[cattr & 0x0f];
|
||||||
if (cw == 8) {
|
if (cw != 9) {
|
||||||
vga_draw_glyph8(d1, linesize,
|
vga_draw_glyph8(d1, linesize,
|
||||||
font_ptr, cheight, fgcol, bgcol);
|
font_ptr, cheight, fgcol, bgcol);
|
||||||
} else {
|
} else {
|
||||||
|
@ -966,7 +1016,7 @@ static void vga_draw_text(VGAState *s, int full_update)
|
||||||
if (line_last >= line_start && line_start < cheight) {
|
if (line_last >= line_start && line_start < cheight) {
|
||||||
h = line_last - line_start + 1;
|
h = line_last - line_start + 1;
|
||||||
d = d1 + linesize * line_start;
|
d = d1 + linesize * line_start;
|
||||||
if (cw == 8) {
|
if (cw != 9) {
|
||||||
vga_draw_glyph8(d, linesize,
|
vga_draw_glyph8(d, linesize,
|
||||||
cursor_glyph, h, fgcol, bgcol);
|
cursor_glyph, h, fgcol, bgcol);
|
||||||
} else {
|
} else {
|
||||||
|
@ -989,17 +1039,45 @@ static void vga_draw_text(VGAState *s, int full_update)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static vga_draw_line_func *vga_draw_line_table[4 * 6] = {
|
enum {
|
||||||
|
VGA_DRAW_LINE2,
|
||||||
|
VGA_DRAW_LINE2D2,
|
||||||
|
VGA_DRAW_LINE4,
|
||||||
|
VGA_DRAW_LINE4D2,
|
||||||
|
VGA_DRAW_LINE8D2,
|
||||||
|
VGA_DRAW_LINE8,
|
||||||
|
VGA_DRAW_LINE15,
|
||||||
|
VGA_DRAW_LINE16,
|
||||||
|
VGA_DRAW_LINE32,
|
||||||
|
VGA_DRAW_LINE_NB,
|
||||||
|
};
|
||||||
|
|
||||||
|
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
|
||||||
vga_draw_line2_8,
|
vga_draw_line2_8,
|
||||||
vga_draw_line2_16,
|
vga_draw_line2_16,
|
||||||
vga_draw_line2_16,
|
vga_draw_line2_16,
|
||||||
vga_draw_line2_32,
|
vga_draw_line2_32,
|
||||||
|
|
||||||
|
vga_draw_line2d2_8,
|
||||||
|
vga_draw_line2d2_16,
|
||||||
|
vga_draw_line2d2_16,
|
||||||
|
vga_draw_line2d2_32,
|
||||||
|
|
||||||
vga_draw_line4_8,
|
vga_draw_line4_8,
|
||||||
vga_draw_line4_16,
|
vga_draw_line4_16,
|
||||||
vga_draw_line4_16,
|
vga_draw_line4_16,
|
||||||
vga_draw_line4_32,
|
vga_draw_line4_32,
|
||||||
|
|
||||||
|
vga_draw_line4d2_8,
|
||||||
|
vga_draw_line4d2_16,
|
||||||
|
vga_draw_line4d2_16,
|
||||||
|
vga_draw_line4d2_32,
|
||||||
|
|
||||||
|
vga_draw_line8d2_8,
|
||||||
|
vga_draw_line8d2_16,
|
||||||
|
vga_draw_line8d2_16,
|
||||||
|
vga_draw_line8d2_32,
|
||||||
|
|
||||||
vga_draw_line8_8,
|
vga_draw_line8_8,
|
||||||
vga_draw_line8_16,
|
vga_draw_line8_16,
|
||||||
vga_draw_line8_16,
|
vga_draw_line8_16,
|
||||||
|
@ -1029,14 +1107,13 @@ static vga_draw_line_func *vga_draw_line_table[4 * 6] = {
|
||||||
*/
|
*/
|
||||||
static void vga_draw_graphic(VGAState *s, int full_update)
|
static void vga_draw_graphic(VGAState *s, int full_update)
|
||||||
{
|
{
|
||||||
int y, update, page_min, page_max, linesize, y_start;
|
int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
|
||||||
int width, height, shift_control, line_offset, page0, page1, bwidth;
|
int width, height, shift_control, line_offset, page0, page1, bwidth;
|
||||||
|
int disp_width;
|
||||||
uint8_t *d;
|
uint8_t *d;
|
||||||
uint32_t v, addr1, addr;
|
uint32_t v, addr1, addr;
|
||||||
vga_draw_line_func *vga_draw_line;
|
vga_draw_line_func *vga_draw_line;
|
||||||
|
|
||||||
full_update |= update_palette16(s);
|
|
||||||
|
|
||||||
full_update |= update_basic_params(s);
|
full_update |= update_basic_params(s);
|
||||||
|
|
||||||
width = (s->cr[0x01] + 1) * 8;
|
width = (s->cr[0x01] + 1) * 8;
|
||||||
|
@ -1044,30 +1121,53 @@ static void vga_draw_graphic(VGAState *s, int full_update)
|
||||||
((s->cr[0x07] & 0x02) << 7) |
|
((s->cr[0x07] & 0x02) << 7) |
|
||||||
((s->cr[0x07] & 0x40) << 3);
|
((s->cr[0x07] & 0x40) << 3);
|
||||||
height = (height + 1);
|
height = (height + 1);
|
||||||
|
disp_width = width;
|
||||||
|
|
||||||
if (width != s->last_width ||
|
shift_control = (s->gr[0x05] >> 5) & 3;
|
||||||
|
double_scan = (s->cr[0x09] & 0x80);
|
||||||
|
if (shift_control != s->shift_control ||
|
||||||
|
double_scan != s->double_scan) {
|
||||||
|
full_update = 1;
|
||||||
|
s->shift_control = shift_control;
|
||||||
|
s->double_scan = double_scan;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shift_control == 0) {
|
||||||
|
full_update |= update_palette16(s);
|
||||||
|
if (s->sr[0x01] & 8) {
|
||||||
|
v = VGA_DRAW_LINE4D2;
|
||||||
|
disp_width <<= 1;
|
||||||
|
} else {
|
||||||
|
v = VGA_DRAW_LINE4;
|
||||||
|
}
|
||||||
|
} else if (shift_control == 1) {
|
||||||
|
full_update |= update_palette16(s);
|
||||||
|
if (s->sr[0x01] & 8) {
|
||||||
|
v = VGA_DRAW_LINE2D2;
|
||||||
|
disp_width <<= 1;
|
||||||
|
} else {
|
||||||
|
v = VGA_DRAW_LINE2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
full_update |= update_palette256(s);
|
||||||
|
v = VGA_DRAW_LINE8D2;
|
||||||
|
double_scan = 1; /* XXX: explain me why it is always activated */
|
||||||
|
}
|
||||||
|
vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
|
||||||
|
|
||||||
|
if (disp_width != s->last_width ||
|
||||||
height != s->last_height) {
|
height != s->last_height) {
|
||||||
dpy_resize(s->ds, width, height);
|
dpy_resize(s->ds, disp_width, height);
|
||||||
s->last_width = width;
|
s->last_width = disp_width;
|
||||||
s->last_height = height;
|
s->last_height = height;
|
||||||
full_update = 1;
|
full_update = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
shift_control = (s->gr[0x05] >> 5) & 3;
|
|
||||||
if (shift_control != s->shift_control) {
|
|
||||||
full_update = 1;
|
|
||||||
s->shift_control = shift_control;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shift_control == 0)
|
|
||||||
v = 1; /* 4 bit/pixel */
|
|
||||||
else if (shift_control == 1)
|
|
||||||
v = 0; /* 2 bit/pixel */
|
|
||||||
else
|
|
||||||
v = 2; /* 8 bit/pixel */
|
|
||||||
vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
|
|
||||||
|
|
||||||
line_offset = s->line_offset;
|
line_offset = s->line_offset;
|
||||||
|
#if 0
|
||||||
|
printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
|
||||||
|
width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
|
||||||
|
#endif
|
||||||
addr1 = (s->start_addr * 4);
|
addr1 = (s->start_addr * 4);
|
||||||
bwidth = width * 4;
|
bwidth = width * 4;
|
||||||
y_start = -1;
|
y_start = -1;
|
||||||
|
@ -1075,14 +1175,17 @@ static void vga_draw_graphic(VGAState *s, int full_update)
|
||||||
page_max = -1;
|
page_max = -1;
|
||||||
d = s->ds->data;
|
d = s->ds->data;
|
||||||
linesize = s->ds->linesize;
|
linesize = s->ds->linesize;
|
||||||
|
y1 = 0;
|
||||||
for(y = 0; y < height; y++) {
|
for(y = 0; y < height; y++) {
|
||||||
addr = addr1;
|
addr = addr1;
|
||||||
if (!(s->cr[0x17] & 1)) {
|
if (!(s->cr[0x17] & 1)) {
|
||||||
|
int shift;
|
||||||
/* CGA compatibility handling */
|
/* CGA compatibility handling */
|
||||||
addr = (addr & ~0x2000) | ((y & 1) << 13);
|
shift = 14 + ((s->cr[0x17] >> 6) & 1);
|
||||||
|
addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
|
||||||
}
|
}
|
||||||
if (!(s->cr[0x17] & 2)) {
|
if (!(s->cr[0x17] & 2)) {
|
||||||
addr = (addr & ~0x4000) | ((y & 2) << 13);
|
addr = (addr & ~0x8000) | ((y1 & 2) << 14);
|
||||||
}
|
}
|
||||||
page0 = addr >> 12;
|
page0 = addr >> 12;
|
||||||
page1 = (addr + bwidth - 1) >> 12;
|
page1 = (addr + bwidth - 1) >> 12;
|
||||||
|
@ -1103,21 +1206,26 @@ static void vga_draw_graphic(VGAState *s, int full_update)
|
||||||
if (y_start >= 0) {
|
if (y_start >= 0) {
|
||||||
/* flush to display */
|
/* flush to display */
|
||||||
dpy_update(s->ds, 0, y_start,
|
dpy_update(s->ds, 0, y_start,
|
||||||
width, y - y_start);
|
disp_width, y - y_start);
|
||||||
y_start = -1;
|
y_start = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (y == s->line_compare) {
|
if (!double_scan || (y & 1) != 0) {
|
||||||
|
if (y1 == s->line_compare) {
|
||||||
addr1 = 0;
|
addr1 = 0;
|
||||||
} else {
|
} else {
|
||||||
|
mask = (s->cr[0x17] & 3) ^ 3;
|
||||||
|
if ((y1 & mask) == mask)
|
||||||
addr1 += line_offset;
|
addr1 += line_offset;
|
||||||
}
|
}
|
||||||
|
y1++;
|
||||||
|
}
|
||||||
d += linesize;
|
d += linesize;
|
||||||
}
|
}
|
||||||
if (y_start >= 0) {
|
if (y_start >= 0) {
|
||||||
/* flush to display */
|
/* flush to display */
|
||||||
dpy_update(s->ds, 0, y_start,
|
dpy_update(s->ds, 0, y_start,
|
||||||
width, y - y_start);
|
disp_width, y - y_start);
|
||||||
}
|
}
|
||||||
/* reset modified pages */
|
/* reset modified pages */
|
||||||
if (page_max != -1) {
|
if (page_max != -1) {
|
||||||
|
@ -1199,7 +1307,7 @@ int vga_init(DisplayState *ds, uint8_t *vga_ram_base,
|
||||||
unsigned long vga_ram_offset, int vga_ram_size)
|
unsigned long vga_ram_offset, int vga_ram_size)
|
||||||
{
|
{
|
||||||
VGAState *s = &vga_state;
|
VGAState *s = &vga_state;
|
||||||
int i, j, v;
|
int i, j, v, b;
|
||||||
|
|
||||||
for(i = 0;i < 256; i++) {
|
for(i = 0;i < 256; i++) {
|
||||||
v = 0;
|
v = 0;
|
||||||
|
@ -1214,9 +1322,34 @@ int vga_init(DisplayState *ds, uint8_t *vga_ram_base,
|
||||||
}
|
}
|
||||||
expand2[i] = v;
|
expand2[i] = v;
|
||||||
}
|
}
|
||||||
|
for(i = 0; i < 16; i++) {
|
||||||
|
v = 0;
|
||||||
|
for(j = 0; j < 4; j++) {
|
||||||
|
b = ((i >> j) & 1);
|
||||||
|
v |= b << (2 * j);
|
||||||
|
v |= b << (2 * j + 1);
|
||||||
|
}
|
||||||
|
expand4to8[i] = v;
|
||||||
|
}
|
||||||
|
|
||||||
vga_reset(s);
|
vga_reset(s);
|
||||||
|
|
||||||
|
switch(ds->depth) {
|
||||||
|
case 8:
|
||||||
|
s->rgb_to_pixel = rgb_to_pixel8_dup;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
s->rgb_to_pixel = rgb_to_pixel15_dup;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case 16:
|
||||||
|
s->rgb_to_pixel = rgb_to_pixel16_dup;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
s->rgb_to_pixel = rgb_to_pixel32_dup;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
s->vram_ptr = vga_ram_base;
|
s->vram_ptr = vga_ram_base;
|
||||||
s->vram_offset = vga_ram_offset;
|
s->vram_offset = vga_ram_offset;
|
||||||
s->vram_size = vga_ram_size;
|
s->vram_size = vga_ram_size;
|
||||||
|
|
|
@ -37,15 +37,11 @@
|
||||||
|
|
||||||
#if DEPTH != 15
|
#if DEPTH != 15
|
||||||
|
|
||||||
static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
|
static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d,
|
||||||
const uint8_t *font_ptr, int h,
|
uint32_t font_data,
|
||||||
uint32_t fgcol, uint32_t bgcol)
|
uint32_t xorcol,
|
||||||
|
uint32_t bgcol)
|
||||||
{
|
{
|
||||||
uint32_t font_data, xorcol;
|
|
||||||
|
|
||||||
xorcol = bgcol ^ fgcol;
|
|
||||||
do {
|
|
||||||
font_data = font_ptr[0];
|
|
||||||
#if BPP == 1
|
#if BPP == 1
|
||||||
((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
|
((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
|
||||||
((uint32_t *)d)[3] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
|
((uint32_t *)d)[3] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
|
||||||
|
@ -64,6 +60,38 @@ static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
|
||||||
((uint32_t *)d)[6] = ((-(font_data >> 1) & 1) & xorcol) ^ bgcol;
|
((uint32_t *)d)[6] = ((-(font_data >> 1) & 1) & xorcol) ^ bgcol;
|
||||||
((uint32_t *)d)[7] = ((-(font_data >> 0) & 1) & xorcol) ^ bgcol;
|
((uint32_t *)d)[7] = ((-(font_data >> 0) & 1) & xorcol) ^ bgcol;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
|
||||||
|
const uint8_t *font_ptr, int h,
|
||||||
|
uint32_t fgcol, uint32_t bgcol)
|
||||||
|
{
|
||||||
|
uint32_t font_data, xorcol;
|
||||||
|
|
||||||
|
xorcol = bgcol ^ fgcol;
|
||||||
|
do {
|
||||||
|
font_data = font_ptr[0];
|
||||||
|
glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
|
||||||
|
font_ptr += 4;
|
||||||
|
d += linesize;
|
||||||
|
} while (--h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize,
|
||||||
|
const uint8_t *font_ptr, int h,
|
||||||
|
uint32_t fgcol, uint32_t bgcol)
|
||||||
|
{
|
||||||
|
uint32_t font_data, xorcol;
|
||||||
|
|
||||||
|
xorcol = bgcol ^ fgcol;
|
||||||
|
do {
|
||||||
|
font_data = font_ptr[0];
|
||||||
|
glue(vga_draw_glyph_line_, DEPTH)(d,
|
||||||
|
expand4to8[font_data >> 4],
|
||||||
|
xorcol, bgcol);
|
||||||
|
glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP,
|
||||||
|
expand4to8[font_data & 0x0f],
|
||||||
|
xorcol, bgcol);
|
||||||
font_ptr += 4;
|
font_ptr += 4;
|
||||||
d += linesize;
|
d += linesize;
|
||||||
} while (--h);
|
} while (--h);
|
||||||
|
@ -151,6 +179,48 @@ static void glue(vga_draw_line2_, DEPTH)(VGAState *s1, uint8_t *d,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if BPP == 1
|
||||||
|
#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v)
|
||||||
|
#elif BPP == 2
|
||||||
|
#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v)
|
||||||
|
#else
|
||||||
|
#define PUT_PIXEL2(d, n, v) \
|
||||||
|
((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 4 color mode, dup2 horizontal
|
||||||
|
*/
|
||||||
|
static void glue(vga_draw_line2d2_, DEPTH)(VGAState *s1, uint8_t *d,
|
||||||
|
const uint8_t *s, int width)
|
||||||
|
{
|
||||||
|
uint32_t plane_mask, *palette, data, v;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
palette = s1->last_palette;
|
||||||
|
plane_mask = mask16[s1->ar[0x12] & 0xf];
|
||||||
|
width >>= 3;
|
||||||
|
for(x = 0; x < width; x++) {
|
||||||
|
data = ((uint32_t *)s)[0];
|
||||||
|
data &= plane_mask;
|
||||||
|
v = expand2[GET_PLANE(data, 0)];
|
||||||
|
v |= expand2[GET_PLANE(data, 2)] << 2;
|
||||||
|
PUT_PIXEL2(d, 0, palette[v >> 12]);
|
||||||
|
PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
|
||||||
|
PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
|
||||||
|
PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
|
||||||
|
|
||||||
|
v = expand2[GET_PLANE(data, 1)];
|
||||||
|
v |= expand2[GET_PLANE(data, 3)] << 2;
|
||||||
|
PUT_PIXEL2(d, 4, palette[v >> 12]);
|
||||||
|
PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
|
||||||
|
PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
|
||||||
|
PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
|
||||||
|
d += BPP * 16;
|
||||||
|
s += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 16 color mode
|
* 16 color mode
|
||||||
*/
|
*/
|
||||||
|
@ -184,7 +254,62 @@ static void glue(vga_draw_line4_, DEPTH)(VGAState *s1, uint8_t *d,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 256 color mode
|
* 16 color mode, dup2 horizontal
|
||||||
|
*/
|
||||||
|
static void glue(vga_draw_line4d2_, DEPTH)(VGAState *s1, uint8_t *d,
|
||||||
|
const uint8_t *s, int width)
|
||||||
|
{
|
||||||
|
uint32_t plane_mask, data, v, *palette;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
palette = s1->last_palette;
|
||||||
|
plane_mask = mask16[s1->ar[0x12] & 0xf];
|
||||||
|
width >>= 3;
|
||||||
|
for(x = 0; x < width; x++) {
|
||||||
|
data = ((uint32_t *)s)[0];
|
||||||
|
data &= plane_mask;
|
||||||
|
v = expand4[GET_PLANE(data, 0)];
|
||||||
|
v |= expand4[GET_PLANE(data, 1)] << 1;
|
||||||
|
v |= expand4[GET_PLANE(data, 2)] << 2;
|
||||||
|
v |= expand4[GET_PLANE(data, 3)] << 3;
|
||||||
|
PUT_PIXEL2(d, 0, palette[v >> 28]);
|
||||||
|
PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
|
||||||
|
PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
|
||||||
|
PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
|
||||||
|
PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
|
||||||
|
PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
|
||||||
|
PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
|
||||||
|
PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
|
||||||
|
d += BPP * 16;
|
||||||
|
s += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 256 color mode, double pixels
|
||||||
|
*
|
||||||
|
* XXX: add plane_mask support (never used in standard VGA modes)
|
||||||
|
*/
|
||||||
|
static void glue(vga_draw_line8d2_, DEPTH)(VGAState *s1, uint8_t *d,
|
||||||
|
const uint8_t *s, int width)
|
||||||
|
{
|
||||||
|
uint32_t *palette;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
palette = s1->last_palette;
|
||||||
|
width >>= 3;
|
||||||
|
for(x = 0; x < width; x++) {
|
||||||
|
PUT_PIXEL2(d, 0, palette[s[0]]);
|
||||||
|
PUT_PIXEL2(d, 1, palette[s[1]]);
|
||||||
|
PUT_PIXEL2(d, 2, palette[s[2]]);
|
||||||
|
PUT_PIXEL2(d, 3, palette[s[3]]);
|
||||||
|
d += BPP * 8;
|
||||||
|
s += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* standard 256 color mode
|
||||||
*
|
*
|
||||||
* XXX: add plane_mask support (never used in standard VGA modes)
|
* XXX: add plane_mask support (never used in standard VGA modes)
|
||||||
*/
|
*/
|
||||||
|
@ -289,6 +414,7 @@ static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef PUT_PIXEL2
|
||||||
#undef DEPTH
|
#undef DEPTH
|
||||||
#undef BPP
|
#undef BPP
|
||||||
#undef PIXEL_TYPE
|
#undef PIXEL_TYPE
|
||||||
|
|
Loading…
Reference in a new issue