Graphics snapshot handling for standard VGA and compatible modes (old graphics

API) moved to the gui code. Splitted graphics_tile_update() in a common and a
specific part. The common part handles the snapshot case if active. As a side
effect, the snapshot feature now works for CGA modes, too. Fixed palette colors
in 8 bpp snapshots.
This commit is contained in:
Volker Ruppert 2012-10-15 19:43:06 +00:00
parent 1fd6745aea
commit bdf28d89dd
4 changed files with 91 additions and 70 deletions

View File

@ -103,6 +103,8 @@ bx_gui_c::bx_gui_c(void): disp_mode(DISP_MODE_SIM)
guest_xres = 640;
guest_yres = 480;
guest_bpp = 8;
snapshot_mode = 0;
snapshot_buffer = NULL;
memset(palette, 0, sizeof(palette));
}
@ -408,6 +410,29 @@ void bx_gui_c::make_text_snapshot(char **snapshot, Bit32u *length)
*length = txt_addr;
}
void bx_gui_c::set_snapshot_mode(bx_bool mode)
{
unsigned pixel_bytes, bufsize;
BX_GUI_THIS snapshot_mode = mode;
if (mode) {
pixel_bytes = ((BX_GUI_THIS guest_bpp + 1) >> 3);
bufsize = BX_GUI_THIS guest_xres * BX_GUI_THIS guest_yres * pixel_bytes;
BX_GUI_THIS snapshot_buffer = (Bit8u*)malloc(bufsize);
if (BX_GUI_THIS snapshot_buffer != NULL) {
memset(BX_GUI_THIS snapshot_buffer, 0, bufsize);
DEV_vga_redraw_area(0, 0, BX_GUI_THIS guest_xres, BX_GUI_THIS guest_yres);
DEV_vga_refresh();
}
} else {
if (BX_GUI_THIS snapshot_buffer != NULL) {
free(BX_GUI_THIS snapshot_buffer);
BX_GUI_THIS snapshot_buffer = NULL;
DEV_vga_redraw_area(0, 0, BX_GUI_THIS guest_xres, BX_GUI_THIS guest_yres);
}
}
}
// create a text snapshot and copy to the system clipboard. On guis that
// we haven't figured out how to support yet, dump to a file instead.
void bx_gui_c::copy_handler(void)
@ -432,7 +457,7 @@ void bx_gui_c::copy_handler(void)
// create a text snapshot and dump it to a file
void bx_gui_c::snapshot_handler(void)
{
int fd, i, j, mode, pitch;
int fd, i, j, pitch;
Bit8u *snapshot_ptr = NULL;
Bit8u *row_buffer, *pixel_ptr, *row_ptr;
Bit8u bmp_header[54], iBits, b1, b2;
@ -466,16 +491,13 @@ void bx_gui_c::snapshot_handler(void)
if (ilen > 0) {
BX_INFO(("GFX snapshot: %u x %u x %u bpp (%u bytes)", BX_GUI_THIS guest_xres,
BX_GUI_THIS guest_yres, BX_GUI_THIS guest_bpp, ilen));
} else {
BX_ERROR(("snapshot button failed: cannot allocate memory"));
return;
}
if (BX_GUI_THIS dialog_caps & BX_GUI_DLG_SNAPSHOT) {
int ret = SIM->ask_filename (filename, sizeof(filename),
"Save snapshot as...", "snapshot.bmp",
bx_param_string_c::SAVE_FILE_DIALOG);
if (ret < 0) { // cancelled
free(snapshot_ptr);
if (snapshot_ptr != NULL) free(snapshot_ptr);
return;
}
} else {
@ -489,9 +511,13 @@ void bx_gui_c::snapshot_handler(void)
);
if (fd < 0) {
BX_ERROR(("snapshot button failed: cannot create BMP file"));
free(snapshot_ptr);
if (snapshot_ptr != NULL) free(snapshot_ptr);
return;
}
if (ilen == 0) {
BX_GUI_THIS set_snapshot_mode(1);
snapshot_ptr = BX_GUI_THIS snapshot_buffer;
}
iBits = (BX_GUI_THIS guest_bpp == 8) ? 8 : 24;
rlen = (BX_GUI_THIS guest_xres * (iBits >> 3) + 3) & ~3;
len = rlen * BX_GUI_THIS guest_yres + 54;
@ -518,7 +544,7 @@ void bx_gui_c::snapshot_handler(void)
bmp_header[28] = iBits;
write(fd, bmp_header, 54);
if (BX_GUI_THIS guest_bpp == 8) {
write(fd, bx_gui->palette, 256 * 4);
write(fd, BX_GUI_THIS palette, 256 * 4);
}
pitch = BX_GUI_THIS guest_xres * ((BX_GUI_THIS guest_bpp + 1) >> 3);
row_buffer = (Bit8u*)malloc(rlen);
@ -555,7 +581,11 @@ void bx_gui_c::snapshot_handler(void)
}
free(row_buffer);
close(fd);
if (ilen > 0) {
free(snapshot_ptr);
} else {
BX_GUI_THIS set_snapshot_mode(0);
}
}
}
@ -925,11 +955,40 @@ void bx_gui_c::graphics_tile_update_in_place(unsigned x0, unsigned y0,
delete [] tile;
}
void bx_gui_c::graphics_tile_update_common(Bit8u *tile, unsigned x, unsigned y)
{
unsigned i, pitch, pixel_bytes, nbytes, tilebytes;
Bit8u *src, *dst;
if (BX_GUI_THIS snapshot_mode) {
if (BX_GUI_THIS snapshot_buffer != NULL) {
pixel_bytes = ((BX_GUI_THIS guest_bpp + 1) >> 3);
tilebytes = BX_GUI_THIS x_tilesize * pixel_bytes;
if ((x + BX_GUI_THIS x_tilesize) <= BX_GUI_THIS guest_xres) {
nbytes = tilebytes;
} else {
nbytes = (BX_GUI_THIS guest_xres - x) * pixel_bytes;
}
pitch = BX_GUI_THIS guest_xres * pixel_bytes;
src = tile;
dst = BX_GUI_THIS snapshot_buffer + (y * pitch) + x;
for (i = 0; i < y_tilesize; i++) {
memcpy(dst, src, nbytes);
src += tilebytes;
dst += pitch;
if (++y >= BX_GUI_THIS guest_yres) break;
}
}
} else {
graphics_tile_update(tile, x, y);
}
}
bx_bool bx_gui_c::palette_change_common(Bit8u index, Bit8u red, Bit8u green, Bit8u blue)
{
palette[index].red = red;
palette[index].green = green;
palette[index].blue = blue;
BX_GUI_THIS palette[index].red = red;
BX_GUI_THIS palette[index].green = green;
BX_GUI_THIS palette[index].blue = blue;
return palette_change(index, red, green, blue);
}

View File

@ -90,7 +90,7 @@ public:
virtual void text_update(Bit8u *old_text, Bit8u *new_text,
unsigned long cursor_x, unsigned long cursor_y,
bx_vga_tminfo_t *tm_info) = 0;
virtual void graphics_tile_update(Bit8u *snapshot, unsigned x, unsigned y) = 0;
virtual void graphics_tile_update(Bit8u *tile, unsigned x, unsigned y) = 0;
virtual bx_svga_tileinfo_t *graphics_tile_info(bx_svga_tileinfo_t *info);
virtual Bit8u *graphics_tile_get(unsigned x, unsigned y, unsigned *w, unsigned *h);
virtual void graphics_tile_update_in_place(unsigned x, unsigned y, unsigned w, unsigned h);
@ -143,6 +143,7 @@ public:
void init(int argc, char **argv, unsigned max_xres, unsigned max_yres,
unsigned x_tilesize, unsigned y_tilesize);
void cleanup(void);
void graphics_tile_update_common(Bit8u *tile, unsigned x, unsigned y);
bx_bool palette_change_common(Bit8u index, Bit8u red, Bit8u green, Bit8u blue);
void update_drive_status_buttons(void);
static void mouse_enabled_changed(bx_bool val);
@ -170,8 +171,9 @@ protected:
static void config_handler(void);
static void userbutton_handler(void);
static void save_restore_handler(void);
// text snapshot helper function
// snapshot helper functions
static void make_text_snapshot(char **snapshot, Bit32u *length);
static void set_snapshot_mode(bx_bool mode);
// status bar LED timer
static void led_timer_handler(void *);
void led_timer(void);
@ -225,11 +227,13 @@ protected:
unsigned guest_xres;
unsigned guest_yres;
unsigned guest_bpp;
// current palette (for graphics snapshot
// graphics snapshot
bx_bool snapshot_mode;
Bit8u *snapshot_buffer;
struct {
Bit8u red;
Bit8u green;
Bit8u blue;
Bit8u green;
Bit8u red;
Bit8u reserved;
} palette[256];
// mouse toggle setup
@ -256,7 +260,7 @@ virtual void specific_init(int argc, char **argv, \
virtual void text_update(Bit8u *old_text, Bit8u *new_text, \
unsigned long cursor_x, unsigned long cursor_y, \
bx_vga_tminfo_t *tm_info); \
virtual void graphics_tile_update(Bit8u *snapshot, unsigned x, unsigned y); \
virtual void graphics_tile_update(Bit8u *tile, unsigned x, unsigned y); \
virtual void handle_events(void); \
virtual void flush(void); \
virtual void clear_screen(void); \

View File

@ -677,7 +677,7 @@ void bx_vga_c::update(void)
}
}
SET_TILE_UPDATED (xti, yti, 0);
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
bx_gui->graphics_tile_update_common(BX_VGA_THIS s.tile, xc, yc);
}
}
}
@ -767,7 +767,7 @@ void bx_vga_c::mem_write(bx_phy_address addr, Bit8u value)
Bit32u bx_vga_c::get_gfx_snapshot(Bit8u **snapshot_ptr)
{
Bit32u len, len1;
unsigned i, shift;
unsigned i;
Bit8u *dst_ptr, *src_ptr;
if ((BX_VGA_THIS vbe.enabled) && (BX_VGA_THIS vbe.bpp >= 8)) {

View File

@ -1496,7 +1496,7 @@ void bx_vgacore_c::update(void)
}
}
SET_TILE_UPDATED (xti, yti, 0);
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
bx_gui->graphics_tile_update_common(BX_VGA_THIS s.tile, xc, yc);
}
}
}
@ -1523,7 +1523,7 @@ void bx_vgacore_c::update(void)
}
}
SET_TILE_UPDATED (xti, yti, 0);
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
bx_gui->graphics_tile_update_common(BX_VGA_THIS s.tile, xc, yc);
}
}
}
@ -1560,7 +1560,7 @@ void bx_vgacore_c::update(void)
}
}
SET_TILE_UPDATED (xti, yti, 0);
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
bx_gui->graphics_tile_update_common(BX_VGA_THIS s.tile, xc, yc);
}
}
}
@ -1594,7 +1594,7 @@ void bx_vgacore_c::update(void)
}
}
SET_TILE_UPDATED (xti, yti, 0);
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
bx_gui->graphics_tile_update_common(BX_VGA_THIS s.tile, xc, yc);
}
}
}
@ -1618,7 +1618,7 @@ void bx_vgacore_c::update(void)
}
}
SET_TILE_UPDATED (xti, yti, 0);
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
bx_gui->graphics_tile_update_common(BX_VGA_THIS s.tile, xc, yc);
}
}
}
@ -1642,7 +1642,7 @@ void bx_vgacore_c::update(void)
}
}
SET_TILE_UPDATED (xti, yti, 0);
bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
bx_gui->graphics_tile_update_common(BX_VGA_THIS s.tile, xc, yc);
}
}
}
@ -2302,51 +2302,9 @@ void bx_vgacore_c::get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight,
Bit32u bx_vgacore_c::get_gfx_snapshot(Bit8u **snapshot_ptr)
{
Bit32u len;
unsigned line_compare, start_addr, x, y;
unsigned byte_offset, px, py;
Bit8u *dst_ptr, *plane[4];
len = (BX_VGA_THIS s.last_xres * BX_VGA_THIS s.last_yres);
*snapshot_ptr = (Bit8u*)malloc(len);
if (snapshot_ptr == NULL)
// handled in the gui code
*snapshot_ptr = NULL;
return 0;
dst_ptr = *snapshot_ptr;
plane[0] = &BX_VGA_THIS s.memory[0 << BX_VGA_THIS s.plane_shift];
plane[1] = &BX_VGA_THIS s.memory[1 << BX_VGA_THIS s.plane_shift];
plane[2] = &BX_VGA_THIS s.memory[2 << BX_VGA_THIS s.plane_shift];
plane[3] = &BX_VGA_THIS s.memory[3 << BX_VGA_THIS s.plane_shift];
start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d];
line_compare = BX_VGA_THIS s.line_compare;
if (BX_VGA_THIS s.y_doublescan) line_compare >>= 1;
if ((BX_VGA_THIS s.graphics_ctrl.shift_reg == 0) &&
(BX_VGA_THIS s.graphics_ctrl.memory_mapping != 3)) {
for (y = 0; y < BX_VGA_THIS s.last_yres; y++) {
for (x = 0; x < BX_VGA_THIS s.last_xres; x++) {
*(dst_ptr++) = BX_VGA_THIS get_vga_pixel(x, y, start_addr, line_compare, 0, plane);
}
}
return len;
} else if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 2) {
for (y = 0; y < BX_VGA_THIS s.last_yres; y++) {
for (x = 0; x < BX_VGA_THIS s.last_xres; x++) {
px = x >> 1;
py = y >> BX_VGA_THIS s.y_doublescan;
byte_offset = start_addr + py * BX_VGA_THIS s.line_offset;
if (BX_VGA_THIS s.CRTC.reg[0x14] & 0x40) { // DW set: doubleword mode
byte_offset += (px & ~0x03);
} else if (BX_VGA_THIS s.CRTC.reg[0x17] & 0x40) { // B/W set: byte mode, modeX
byte_offset += (px >> 2);
} else {
byte_offset += (px >> 1) & ~0x01;
}
*(dst_ptr++) = plane[px % 4][byte_offset];
}
}
return len;
} else {
return 0;
}
}
#if BX_DEBUGGER