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:
parent
1fd6745aea
commit
bdf28d89dd
@ -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);
|
||||
free(snapshot_ptr);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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); \
|
||||
|
@ -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)) {
|
||||
|
@ -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)
|
||||
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;
|
||||
}
|
||||
// handled in the gui code
|
||||
*snapshot_ptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if BX_DEBUGGER
|
||||
|
Loading…
Reference in New Issue
Block a user