Rewrite of the VGA/Cirrus code to reduce code duplication.

- Moved VGA timer handler to the VGA core and handle the non-VGA case there.
  It calls the specific update() code and finally bx_gui->flush().
- Moved the VGA update frequency parameter handler and the refresh_disply()
  method to the VGA core.
- Store the VGA extension parameter in the VGA core.
- Voodoo: Fixed graphics snapshot.
This commit is contained in:
Volker Ruppert 2017-10-08 07:55:04 +00:00
parent ebbd952d3b
commit 610cec209d
7 changed files with 74 additions and 141 deletions

View File

@ -257,7 +257,7 @@ void bx_svga_cirrus_c::init_vga_extension(void)
BX_CIRRUS_THIS put("CIRRUS"); BX_CIRRUS_THIS put("CIRRUS");
// initialize SVGA stuffs. // initialize SVGA stuffs.
BX_CIRRUS_THIS bx_vgacore_c::init_iohandlers(svga_read_handler, svga_write_handler); BX_CIRRUS_THIS bx_vgacore_c::init_iohandlers(svga_read_handler, svga_write_handler);
BX_CIRRUS_THIS bx_vgacore_c::init_systemtimer(svga_timer_handler, svga_param_handler); BX_CIRRUS_THIS bx_vgacore_c::init_systemtimer();
BX_CIRRUS_THIS pci_enabled = SIM->is_pci_device("cirrus"); BX_CIRRUS_THIS pci_enabled = SIM->is_pci_device("cirrus");
BX_CIRRUS_THIS svga_init_members(); BX_CIRRUS_THIS svga_init_members();
#if BX_SUPPORT_PCI #if BX_SUPPORT_PCI
@ -440,7 +440,7 @@ void bx_svga_cirrus_c::after_restore_state(void)
BX_CIRRUS_THIS s.pel.data[i].blue<<2); BX_CIRRUS_THIS s.pel.data[i].blue<<2);
} }
BX_CIRRUS_THIS svga_needs_update_mode = 1; BX_CIRRUS_THIS svga_needs_update_mode = 1;
BX_CIRRUS_THIS svga_update(); BX_CIRRUS_THIS update();
} }
} }
@ -807,22 +807,6 @@ void bx_svga_cirrus_c::get_text_snapshot(Bit8u **text_snapshot,
BX_CIRRUS_THIS bx_vgacore_c::get_text_snapshot(text_snapshot,txHeight,txWidth); BX_CIRRUS_THIS bx_vgacore_c::get_text_snapshot(text_snapshot,txHeight,txWidth);
} }
Bit64s bx_svga_cirrus_c::svga_param_handler(bx_param_c *param, int set, Bit64s val)
{
if (set) {
Bit32u update_interval = (Bit32u)(1000000 / val);
BX_INFO(("Changing timer interval to %d", update_interval));
BX_CIRRUS_THIS svga_timer_handler(theSvga);
bx_virt_timer.activate_timer(BX_CIRRUS_THIS timer_id, update_interval, 1);
if (update_interval < 300000) {
BX_CIRRUS_THIS s.blink_counter = 300000 / (unsigned)update_interval;
} else {
BX_CIRRUS_THIS s.blink_counter = 1;
}
}
return val;
}
Bit32u bx_svga_cirrus_c::svga_read_handler(void *this_ptr, Bit32u address, unsigned io_len) Bit32u bx_svga_cirrus_c::svga_read_handler(void *this_ptr, Bit32u address, unsigned io_len)
{ {
#if !BX_USE_CIRRUS_SMF #if !BX_USE_CIRRUS_SMF
@ -1001,37 +985,6 @@ void bx_svga_cirrus_c::svga_write(Bit32u address, Bit32u value, unsigned io_len)
VGA_WRITE(address,value,io_len); VGA_WRITE(address,value,io_len);
} }
void bx_svga_cirrus_c::refresh_display(void *this_ptr, bx_bool redraw)
{
#if BX_SUPPORT_PCI
if (BX_CIRRUS_THIS s.vga_override && (BX_CIRRUS_THIS s.nvgadev != NULL)) {
BX_CIRRUS_THIS s.nvgadev->refresh_display(BX_CIRRUS_THIS s.nvgadev, redraw);
return;
}
#endif
if (redraw) {
redraw_area(0, 0, BX_CIRRUS_THIS s.last_xres, BX_CIRRUS_THIS s.last_yres);
}
svga_timer_handler(this_ptr);
}
void bx_svga_cirrus_c::svga_timer_handler(void *this_ptr)
{
#if !BX_USE_CIRRUS_SMF
bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr;
class_ptr->svga_timer();
}
void bx_svga_cirrus_c::svga_timer(void)
{
#else // !BX_USE_CIRRUS_SMF
UNUSED(this_ptr);
#endif // !BX_USE_CIRRUS_SMF
BX_CIRRUS_THIS svga_update();
bx_gui->flush();
}
void bx_svga_cirrus_c::svga_modeupdate(void) void bx_svga_cirrus_c::svga_modeupdate(void)
{ {
Bit32u iTopOffset, iWidth, iHeight; Bit32u iTopOffset, iWidth, iHeight;
@ -1214,16 +1167,10 @@ void bx_svga_cirrus_c::draw_hardware_cursor(unsigned xc, unsigned yc, bx_svga_ti
} }
} }
void bx_svga_cirrus_c::svga_update(void) void bx_svga_cirrus_c::update(void)
{ {
unsigned width, height, pitch; unsigned width, height, pitch;
#if BX_SUPPORT_PCI
if (BX_CIRRUS_THIS s.vga_override && (BX_CIRRUS_THIS s.nvgadev != NULL)) {
BX_CIRRUS_THIS s.nvgadev->update();
return;
}
#endif
/* skip screen update when the sequencer is in reset mode or video is disabled */ /* skip screen update when the sequencer is in reset mode or video is disabled */
if (! BX_CIRRUS_THIS s.sequencer.reset1 || if (! BX_CIRRUS_THIS s.sequencer.reset1 ||
! BX_CIRRUS_THIS s.sequencer.reset2 || ! BX_CIRRUS_THIS s.sequencer.reset2 ||

View File

@ -70,7 +70,6 @@ public:
virtual void init_vga_extension(void); virtual void init_vga_extension(void);
virtual void reset(unsigned type); virtual void reset(unsigned type);
virtual void refresh_display(void *this_ptr, bx_bool redraw);
virtual void redraw_area(unsigned x0, unsigned y0, virtual void redraw_area(unsigned x0, unsigned y0,
unsigned width, unsigned height); unsigned width, unsigned height);
virtual Bit8u mem_read(bx_phy_address addr); virtual Bit8u mem_read(bx_phy_address addr);
@ -87,6 +86,9 @@ public:
virtual void debug_dump(int argc, char **argv); virtual void debug_dump(int argc, char **argv);
#endif #endif
protected:
virtual void update(void);
private: private:
static Bit32u svga_read_handler(void *this_ptr, Bit32u address, unsigned io_len); static Bit32u svga_read_handler(void *this_ptr, Bit32u address, unsigned io_len);
static void svga_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); static void svga_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
@ -97,11 +99,7 @@ private:
BX_CIRRUS_SMF void mem_write_mode4and5_8bpp(Bit8u mode, Bit32u offset, Bit8u value); BX_CIRRUS_SMF void mem_write_mode4and5_8bpp(Bit8u mode, Bit32u offset, Bit8u value);
BX_CIRRUS_SMF void mem_write_mode4and5_16bpp(Bit8u mode, Bit32u offset, Bit8u value); BX_CIRRUS_SMF void mem_write_mode4and5_16bpp(Bit8u mode, Bit32u offset, Bit8u value);
static void svga_timer_handler(void *);
static Bit64s svga_param_handler(bx_param_c *param, int set, Bit64s val);
BX_CIRRUS_SMF void svga_timer(void);
BX_CIRRUS_SMF void svga_modeupdate(void); BX_CIRRUS_SMF void svga_modeupdate(void);
BX_CIRRUS_SMF void svga_update(void);
BX_CIRRUS_SMF void svga_init_members(); BX_CIRRUS_SMF void svga_init_members();

View File

@ -92,7 +92,7 @@ void bx_vga_c::init_vga_extension(void)
Bit16u max_xres, max_yres, max_bpp; Bit16u max_xres, max_yres, max_bpp;
BX_VGA_THIS init_iohandlers(read_handler, write_handler); BX_VGA_THIS init_iohandlers(read_handler, write_handler);
BX_VGA_THIS init_systemtimer(timer_handler, vga_param_handler); BX_VGA_THIS init_systemtimer();
BX_VGA_THIS pci_enabled = SIM->is_pci_device("pcivga"); BX_VGA_THIS pci_enabled = SIM->is_pci_device("pcivga");
// The following is for the VBE display extension // The following is for the VBE display extension
@ -100,7 +100,7 @@ void bx_vga_c::init_vga_extension(void)
BX_VGA_THIS vbe.enabled = 0; BX_VGA_THIS vbe.enabled = 0;
BX_VGA_THIS vbe.dac_8bit = 0; BX_VGA_THIS vbe.dac_8bit = 0;
BX_VGA_THIS vbe.base_address = 0x0000; BX_VGA_THIS vbe.base_address = 0x0000;
if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "vbe")) { if (!strcmp(BX_VGA_THIS vgaext->getptr(), "vbe")) {
BX_VGA_THIS put("BXVGA"); BX_VGA_THIS put("BXVGA");
for (addr=VBE_DISPI_IOPORT_INDEX; addr<=VBE_DISPI_IOPORT_DATA; addr++) { for (addr=VBE_DISPI_IOPORT_INDEX; addr<=VBE_DISPI_IOPORT_DATA; addr++) {
DEV_register_ioread_handler(this, vbe_read_handler, addr, "vga video", 7); DEV_register_ioread_handler(this, vbe_read_handler, addr, "vga video", 7);
@ -326,64 +326,10 @@ void bx_vga_c::write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_l
} }
} }
Bit64s bx_vga_c::vga_param_handler(bx_param_c *param, int set, Bit64s val)
{
// handler for runtime parameter 'vga: update_freq'
if (set) {
Bit32u update_interval = (Bit32u)(1000000 / val);
BX_INFO(("Changing timer interval to %d", update_interval));
BX_VGA_THIS timer_handler(theVga);
bx_virt_timer.activate_timer(BX_VGA_THIS timer_id, update_interval, 1);
if (update_interval < 300000) {
BX_VGA_THIS s.blink_counter = 300000 / (unsigned)update_interval;
} else {
BX_VGA_THIS s.blink_counter = 1;
}
}
return val;
}
void bx_vga_c::refresh_display(void *this_ptr, bx_bool redraw)
{
#if BX_SUPPORT_PCI
if (BX_VGA_THIS s.vga_override && (BX_VGA_THIS s.nvgadev != NULL)) {
BX_VGA_THIS s.nvgadev->refresh_display(BX_VGA_THIS s.nvgadev, redraw);
return;
}
#endif
if (redraw) {
redraw_area(0, 0, BX_VGA_THIS s.last_xres, BX_VGA_THIS s.last_yres);
}
timer_handler(this_ptr);
}
void bx_vga_c::timer_handler(void *this_ptr)
{
#if BX_USE_VGA_SMF == 0
bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
class_ptr->timer();
}
void bx_vga_c::timer(void)
{
#else
UNUSED(this_ptr);
#endif
update();
bx_gui->flush();
}
void bx_vga_c::update(void) void bx_vga_c::update(void)
{ {
unsigned iHeight, iWidth; unsigned iHeight, iWidth;
#if BX_SUPPORT_PCI
if (BX_VGA_THIS s.vga_override && (BX_VGA_THIS s.nvgadev != NULL)) {
BX_VGA_THIS s.nvgadev->update();
return;
}
#endif
if (BX_VGA_THIS vbe.enabled) { if (BX_VGA_THIS vbe.enabled) {
/* no screen update necessary */ /* no screen update necessary */
if ((BX_VGA_THIS s.vga_mem_updated==0) && BX_VGA_THIS s.graphics_ctrl.graphics_alpha) if ((BX_VGA_THIS s.vga_mem_updated==0) && BX_VGA_THIS s.graphics_ctrl.graphics_alpha)

View File

@ -105,12 +105,6 @@ public:
unsigned width, unsigned height); unsigned width, unsigned height);
virtual void init_vga_extension(void); virtual void init_vga_extension(void);
virtual void refresh_display(void *this_ptr, bx_bool redraw);
static void timer_handler(void *);
#if BX_USE_VGA_SMF == 0
BX_VGA_SMF void timer(void);
#endif
#if BX_SUPPORT_PCI #if BX_SUPPORT_PCI
virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len);
@ -119,8 +113,6 @@ public:
virtual void debug_dump(int argc, char **argv); virtual void debug_dump(int argc, char **argv);
#endif #endif
static Bit64s vga_param_handler(bx_param_c *param, int set, Bit64s val);
protected: protected:
static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
#if BX_USE_VGA_SMF #if BX_USE_VGA_SMF
@ -128,7 +120,7 @@ protected:
#endif #endif
void write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log); void write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log);
BX_VGA_SMF void update(void); virtual void update(void);
// Bochs VBE section // Bochs VBE section
#if BX_SUPPORT_PCI #if BX_SUPPORT_PCI

View File

@ -100,6 +100,7 @@ void bx_vgacore_c::init(void)
{ {
unsigned x,y; unsigned x,y;
BX_VGA_THIS vgaext = SIM->get_param_string(BXPN_VGA_EXTENSION);
BX_VGA_THIS extension_init = 0; BX_VGA_THIS extension_init = 0;
BX_VGA_THIS pci_enabled = 0; BX_VGA_THIS pci_enabled = 0;
@ -116,10 +117,8 @@ void bx_vgacore_c::init(void)
for (x = 0; x < BX_VGA_THIS s.num_x_tiles; x++) for (x = 0; x < BX_VGA_THIS s.num_x_tiles; x++)
SET_TILE_UPDATED(x, y, 0); SET_TILE_UPDATED(x, y, 0);
char *strptr = SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(); if (!BX_VGA_THIS extension_init && !BX_VGA_THIS vgaext->isempty()) {
if (!BX_VGA_THIS extension_init && BX_PANIC(("unknown display extension: %s", BX_VGA_THIS vgaext->getptr()));
(strlen(strptr) > 0) && strcmp(strptr, "none")) {
BX_PANIC(("unknown display extension: %s", strptr));
} }
if (!BX_VGA_THIS pci_enabled) { if (!BX_VGA_THIS pci_enabled) {
BX_MEM(0)->load_ROM(SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr(), 0xc0000, 1); BX_MEM(0)->load_ROM(SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr(), 0xc0000, 1);
@ -128,8 +127,6 @@ void bx_vgacore_c::init(void)
void bx_vgacore_c::init_standard_vga(void) void bx_vgacore_c::init_standard_vga(void)
{ {
char *extname;
// initialize VGA controllers and other internal stuff // initialize VGA controllers and other internal stuff
BX_VGA_THIS s.vga_enabled = 1; BX_VGA_THIS s.vga_enabled = 1;
BX_VGA_THIS s.misc_output.color_emulation = 1; BX_VGA_THIS s.misc_output.color_emulation = 1;
@ -165,8 +162,7 @@ void bx_vgacore_c::init_standard_vga(void)
BX_VGA_THIS s.vga_override = 0; BX_VGA_THIS s.vga_override = 0;
// initialize memory, handlers and timer (depending on extension) // initialize memory, handlers and timer (depending on extension)
extname = SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(); if (BX_VGA_THIS vgaext->isempty()) {
if ((strlen(extname) == 0) || (!strcmp(extname, "none"))) {
BX_VGA_THIS s.memsize = 0x40000; BX_VGA_THIS s.memsize = 0x40000;
if (BX_VGA_THIS s.memory == NULL) if (BX_VGA_THIS s.memory == NULL)
BX_VGA_THIS s.memory = new Bit8u[BX_VGA_THIS s.memsize]; BX_VGA_THIS s.memory = new Bit8u[BX_VGA_THIS s.memsize];
@ -257,16 +253,17 @@ void bx_vgacore_c::init_iohandlers(bx_read_handler_t f_read, bx_write_handler_t
} }
} }
void bx_vgacore_c::init_systemtimer(bx_timer_handler_t f_timer, param_event_handler f_param) void bx_vgacore_c::init_systemtimer(void)
{ {
BX_VGA_THIS realtime = SIM->get_param_bool(BXPN_VGA_REALTIME)->get(); BX_VGA_THIS realtime = SIM->get_param_bool(BXPN_VGA_REALTIME)->get();
bx_param_num_c *vga_update_freq = SIM->get_param_num(BXPN_VGA_UPDATE_FREQUENCY); bx_param_num_c *vga_update_freq = SIM->get_param_num(BXPN_VGA_UPDATE_FREQUENCY);
Bit32u update_interval = (Bit32u)(1000000 / vga_update_freq->get()); Bit32u update_interval = (Bit32u)(1000000 / vga_update_freq->get());
BX_INFO(("interval=%u, mode=%s", update_interval, BX_VGA_THIS realtime ? "realtime":"standard")); BX_INFO(("interval=%u, mode=%s", update_interval, BX_VGA_THIS realtime ? "realtime":"standard"));
if (BX_VGA_THIS timer_id == BX_NULL_TIMER_HANDLE) { if (BX_VGA_THIS timer_id == BX_NULL_TIMER_HANDLE) {
BX_VGA_THIS timer_id = bx_virt_timer.register_timer(this, f_timer, BX_VGA_THIS timer_id = bx_virt_timer.register_timer(this, vga_timer_handler,
update_interval, 1, 1, BX_VGA_THIS realtime, "vga"); update_interval, 1, 1, BX_VGA_THIS realtime, "vga");
vga_update_freq->set_handler(f_param); vga_update_freq->set_handler(vga_param_handler);
vga_update_freq->set_device_param(this);
} }
// VGA text mode cursor blink frequency 1.875 Hz // VGA text mode cursor blink frequency 1.875 Hz
if (update_interval < 266666) { if (update_interval < 266666) {
@ -2377,3 +2374,52 @@ void bx_vgacore_c::redraw_area(unsigned x0, unsigned y0, unsigned width, unsigne
sizeof(BX_VGA_THIS s.text_snapshot)); sizeof(BX_VGA_THIS s.text_snapshot));
} }
} }
void bx_vgacore_c::refresh_display(void *this_ptr, bx_bool redraw)
{
bx_vgacore_c *vgadev = (bx_vgacore_c *) this_ptr;
#if BX_SUPPORT_PCI
if (vgadev->s.vga_override && (vgadev->s.nvgadev != NULL)) {
vgadev->s.nvgadev->refresh_display(vgadev->s.nvgadev, redraw);
return;
}
#endif
if (redraw) {
redraw_area(0, 0, vgadev->s.last_xres, vgadev->s.last_yres);
}
vga_timer_handler(vgadev);
}
void bx_vgacore_c::vga_timer_handler(void *this_ptr)
{
bx_vgacore_c *vgadev = (bx_vgacore_c *) this_ptr;
#if BX_SUPPORT_PCI
if (vgadev->s.vga_override && (vgadev->s.nvgadev != NULL)) {
vgadev->s.nvgadev->update();
return;
}
#endif
vgadev->update();
bx_gui->flush();
}
#undef LOG_THIS
#define LOG_THIS vgadev->
Bit64s bx_vgacore_c::vga_param_handler(bx_param_c *param, int set, Bit64s val)
{
// handler for runtime parameter 'vga: update_freq'
if (set) {
Bit32u update_interval = (Bit32u)(1000000 / val);
bx_vgacore_c *vgadev = (bx_vgacore_c *)param->get_device_param();
BX_INFO(("Changing timer interval to %d", update_interval));
vga_timer_handler(vgadev);
bx_virt_timer.activate_timer(vgadev->timer_id, update_interval, 1);
if (update_interval < 266666) {
vgadev->s.blink_counter = 266666 / (unsigned)update_interval;
} else {
vgadev->s.blink_counter = 1;
}
}
return val;
}

View File

@ -65,7 +65,6 @@ public:
static bx_bool mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param); static bx_bool mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param);
virtual Bit8u mem_read(bx_phy_address addr); virtual Bit8u mem_read(bx_phy_address addr);
virtual void mem_write(bx_phy_address addr, Bit8u value); virtual void mem_write(bx_phy_address addr, Bit8u value);
virtual void refresh_display(void *this_ptr, bx_bool redraw) {}
virtual void set_override(bx_bool enabled, void *dev); virtual void set_override(bx_bool enabled, void *dev);
virtual void register_state(bx_list_c *parent); virtual void register_state(bx_list_c *parent);
virtual void after_restore_state(void); virtual void after_restore_state(void);
@ -75,16 +74,19 @@ public:
virtual void redraw_area(unsigned x0, unsigned y0, virtual void redraw_area(unsigned x0, unsigned y0,
unsigned width, unsigned height); unsigned width, unsigned height);
virtual void refresh_display(void *this_ptr, bx_bool redraw);
virtual void get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight, virtual void get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight,
unsigned *txWidth); unsigned *txWidth);
virtual void init_vga_extension(void) {} virtual void init_vga_extension(void) {}
static void vga_timer_handler(void *);
static Bit64s vga_param_handler(bx_param_c *param, int set, Bit64s val);
protected: protected:
void init_standard_vga(void); void init_standard_vga(void);
void init_gui(void); void init_gui(void);
void init_iohandlers(bx_read_handler_t f_read, bx_write_handler_t f_write); void init_iohandlers(bx_read_handler_t f_read, bx_write_handler_t f_write);
void init_systemtimer(bx_timer_handler_t f_timer, param_event_handler f_param); void init_systemtimer();
static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
@ -93,7 +95,7 @@ protected:
void write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log); void write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log);
Bit8u get_vga_pixel(Bit16u x, Bit16u y, Bit16u saddr, Bit16u lc, bx_bool bs, Bit8u **plane); Bit8u get_vga_pixel(Bit16u x, Bit16u y, Bit16u saddr, Bit16u lc, bx_bool bs, Bit8u **plane);
void update(void); virtual void update(void);
void determine_screen_dimensions(unsigned *piHeight, unsigned *piWidth); void determine_screen_dimensions(unsigned *piHeight, unsigned *piWidth);
void calculate_retrace_timing(void); void calculate_retrace_timing(void);
bx_bool skip_update(void); bx_bool skip_update(void);
@ -238,6 +240,7 @@ protected:
int timer_id; int timer_id;
bx_bool realtime; bx_bool realtime;
bx_param_string_c *vgaext;
bx_bool extension_init; bx_bool extension_init;
bx_bool pci_enabled; bx_bool pci_enabled;
}; };

View File

@ -633,6 +633,7 @@ void bx_voodoo_c::refresh_display(void *this_ptr, bx_bool redraw)
redraw_area(0, 0, v->fbi.width, v->fbi.height); redraw_area(0, 0, v->fbi.width, v->fbi.height);
} }
vertical_timer_handler(this_ptr); vertical_timer_handler(this_ptr);
update();
} }
void bx_voodoo_c::vertical_timer_handler(void *this_ptr) void bx_voodoo_c::vertical_timer_handler(void *this_ptr)