Banshee: Double the screen width in 'half mode' if height > width.

This commit is contained in:
Volker Ruppert 2024-01-20 22:30:47 +01:00
parent f014160835
commit db0d16ff09
5 changed files with 106 additions and 46 deletions

View File

@ -269,6 +269,7 @@ void bx_banshee_c::register_state(void)
new bx_shadow_data_c(banshee, "crtc", (Bit8u*)v->banshee.crtc, 0x27, 1);
new bx_shadow_num_c(banshee, "disp_bpp", &v->banshee.disp_bpp);
BXRS_PARAM_BOOL(banshee, half_mode, v->banshee.half_mode);
BXRS_PARAM_BOOL(banshee, double_width, v->banshee.double_width);
BXRS_PARAM_BOOL(banshee, dac_8bit, v->banshee.dac_8bit);
BXRS_PARAM_BOOL(banshee, desktop_tiled, v->banshee.desktop_tiled);
BXRS_PARAM_BOOL(banshee, overlay_tiled, v->banshee.overlay_tiled);
@ -330,7 +331,6 @@ void bx_banshee_c::after_restore_state(void)
bx_pci_device_c::after_restore_pci_state(mem_read_handler);
if ((v->banshee.io[io_vidProcCfg] & 0x01) && (theVoodooVga != NULL)) {
v->fbi.clut_dirty = 1;
update_timing();
theVoodooVga->banshee_update_mode();
}
start_fifo_thread();
@ -368,13 +368,15 @@ void bx_banshee_c::draw_hwcursor(unsigned xc, unsigned yc, bx_svga_tileinfo_t *i
Bit8u ccode, pbits, pval0, pval1;
Bit32u colour = 0, start;
Bit16u index, pitch;
Bit16u hwcx = v->banshee.hwcursor.x;
Bit16u hwcy = v->banshee.hwcursor.y;
int i;
if ((xc <= v->banshee.hwcursor.x) &&
((int)(xc + X_TILESIZE) > (v->banshee.hwcursor.x - 63)) &&
(yc <= v->banshee.hwcursor.y) &&
((int)(yc + Y_TILESIZE) > (v->banshee.hwcursor.y - 63))) {
if (v->banshee.double_width) {
hwcx = (hwcx << 1) - 63;
}
if ((xc <= hwcx) && ((int)(xc + X_TILESIZE) > (hwcx - 63)) &&
(yc <= hwcy) && ((int)(yc + Y_TILESIZE) > (hwcy - 63))) {
if ((v->banshee.io[io_vidProcCfg] & 0x181) == 0x81) {
start = v->banshee.io[io_vidDesktopStartAddr];
pitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
@ -388,30 +390,30 @@ void bx_banshee_c::draw_hwcursor(unsigned xc, unsigned yc, bx_svga_tileinfo_t *i
}
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
if ((v->banshee.hwcursor.x - 63) < (int)xc) {
if ((hwcx - 63) < (int)xc) {
cx = xc;
if ((v->banshee.hwcursor.x - xc + 1) > w) {
if ((hwcx - xc + 1) > w) {
cw = w;
} else {
cw = v->banshee.hwcursor.x - xc + 1;
cw = hwcx - xc + 1;
}
px = 63 - (v->banshee.hwcursor.x - xc);
px = 63 - (hwcx - xc);
} else {
cx = v->banshee.hwcursor.x - 63;
cw = w - (v->banshee.hwcursor.x - 63 - xc);
cx = hwcx - 63;
cw = w - (hwcx - 63 - xc);
px = 0;
}
if ((v->banshee.hwcursor.y - 63) < (int)yc) {
if ((hwcy - 63) < (int)yc) {
cy = yc;
if ((v->banshee.hwcursor.y - yc + 1) > h) {
if ((hwcy - yc + 1) > h) {
ch = h;
} else {
ch = v->banshee.hwcursor.y - yc + 1;
ch = hwcy - yc + 1;
}
py = 63 - (v->banshee.hwcursor.y - yc);
py = 63 - (hwcy - yc);
} else {
cy = v->banshee.hwcursor.y - 63;
ch = h - (v->banshee.hwcursor.y - 63 - yc);
cy = hwcy - 63;
ch = h - (hwcy - 63 - yc);
py = 0;
}
tile_ptr += ((cy - yc) * info->pitch);
@ -431,7 +433,11 @@ void bx_banshee_c::draw_hwcursor(unsigned xc, unsigned yc, bx_svga_tileinfo_t *i
colour = v->banshee.hwcursor.color[1];
} else {
if (v->banshee.half_mode) {
vid_ptr = disp_ptr + (y >> 1) * pitch + x * (v->banshee.disp_bpp >> 3);
if (v->banshee.double_width) {
vid_ptr = disp_ptr + (y >> 1) * pitch + (x >> 1) * (v->banshee.disp_bpp >> 3);
} else {
vid_ptr = disp_ptr + (y >> 1) * pitch + x * (v->banshee.disp_bpp >> 3);
}
} else {
vid_ptr = disp_ptr + y * pitch + x * (v->banshee.disp_bpp >> 3);
}
@ -699,7 +705,6 @@ void bx_banshee_c::write(Bit32u address, Bit32u value, unsigned io_len)
if ((v->banshee.io[reg] ^ old) & 0x3c00)
v->fbi.clut_dirty = 1;
if ((v->banshee.io[reg] & 0x01) && ((old & 0x01) == 0x00)) {
update_timing();
if (theVoodooVga != NULL) {
theVoodooVga->banshee_update_mode();
}
@ -724,7 +729,11 @@ void bx_banshee_c::write(Bit32u address, Bit32u value, unsigned io_len)
if (v->banshee.hwcursor.enabled != prev_hwce) {
x0 = (v->banshee.hwcursor.x < 63) ? 0 : (v->banshee.hwcursor.x - 63);
y0 = (v->banshee.hwcursor.y < 63) ? 0 : (v->banshee.hwcursor.y - 63);
theVoodooVga->redraw_area(x0, y0, 64, 64);
if (v->banshee.double_width) {
theVoodooVga->redraw_area(x0 << 1, y0, 64, 64);
} else {
theVoodooVga->redraw_area(x0, y0, 64, 64);
}
}
if ((v->banshee.io[reg] >> 2) & 1) {
BX_ERROR(("vidProcCfg: overlay stereo mode not supported yet"));
@ -745,7 +754,11 @@ void bx_banshee_c::write(Bit32u address, Bit32u value, unsigned io_len)
if (v->banshee.hwcursor.enabled && (value != old)) {
x0 = (v->banshee.hwcursor.x < 63) ? 0 : (v->banshee.hwcursor.x - 63);
y0 = (v->banshee.hwcursor.y < 63) ? 0 : (v->banshee.hwcursor.y - 63);
theVoodooVga->redraw_area(x0, y0, 64, 64);
if (v->banshee.double_width) {
theVoodooVga->redraw_area(x0 << 1, y0, 64, 64);
} else {
theVoodooVga->redraw_area(x0, y0, 64, 64);
}
}
break;
@ -756,10 +769,18 @@ void bx_banshee_c::write(Bit32u address, Bit32u value, unsigned io_len)
if (v->banshee.hwcursor.enabled && (value != old)) {
x0 = (prev_hwcx < 63) ? 0 : (prev_hwcx - 63);
y0 = (prev_hwcy < 63) ? 0 : (prev_hwcy - 63);
theVoodooVga->redraw_area(prev_hwcx - 63, prev_hwcy - 63, 64, 64);
if (v->banshee.double_width) {
theVoodooVga->redraw_area(x0 << 1, y0, 64, 64);
} else {
theVoodooVga->redraw_area(x0, y0, 64, 64);
}
x0 = (v->banshee.hwcursor.x < 63) ? 0 : (v->banshee.hwcursor.x - 63);
y0 = (v->banshee.hwcursor.y < 63) ? 0 : (v->banshee.hwcursor.y - 63);
theVoodooVga->redraw_area(x0, y0, 64, 64);
if (v->banshee.double_width) {
theVoodooVga->redraw_area(x0 << 1, y0, 64, 64);
} else {
theVoodooVga->redraw_area(x0, y0, 64, 64);
}
}
break;
@ -1645,6 +1666,10 @@ void bx_banshee_c::blt_complete()
y <<= 1;
h <<= 1;
}
if (v->banshee.double_width) {
x <<= 1;
w <<= 1;
}
if ((v->banshee.io[io_vidProcCfg] & 0x101) == 0x101) {
v->fbi.video_changed = 1;
} else {
@ -2860,10 +2885,17 @@ void bx_voodoo_vga_c::banshee_update_mode(void)
return;
}
v->banshee.half_mode = (v->banshee.io[io_vidProcCfg] >> 4) & 1;
if (v->banshee.half_mode && (v->fbi.height > v->fbi.width)) {
v->fbi.width <<= 1;
v->banshee.double_width = true;
} else {
v->banshee.double_width = false;
}
theVoodooDevice->update_timing();
BX_INFO(("switched to %d x %d x %d @ %d Hz", v->fbi.width, v->fbi.height,
v->banshee.disp_bpp, (unsigned)v->vertfreq));
bx_gui->dimension_update(v->fbi.width, v->fbi.height, 0, 0, v->banshee.disp_bpp);
bx_virt_timer.deactivate_timer(vertical_timer_id);
bx_virt_timer.deactivate_timer(vga_vtimer_id);
// compatibilty settings for VGA core
BX_VVGA_THIS s.last_xres = v->fbi.width;
BX_VVGA_THIS s.last_yres = v->fbi.height;

View File

@ -64,7 +64,7 @@ bx_vgacore_c::bx_vgacore_c()
{
memset(&s, 0, sizeof(s));
update_timer_id = BX_NULL_TIMER_HANDLE;
vertical_timer_id = BX_NULL_TIMER_HANDLE;
vga_vtimer_id = BX_NULL_TIMER_HANDLE;
}
bx_vgacore_c::~bx_vgacore_c()
@ -238,8 +238,8 @@ void bx_vgacore_c::init_systemtimer(void)
vga_update_freq->set_runtime_param(0);
}
}
if (BX_VGA_THIS vertical_timer_id == BX_NULL_TIMER_HANDLE) {
BX_VGA_THIS vertical_timer_id = bx_virt_timer.register_timer(this, vertical_timer_handler,
if (BX_VGA_THIS vga_vtimer_id == BX_NULL_TIMER_HANDLE) {
BX_VGA_THIS vga_vtimer_id = bx_virt_timer.register_timer(this, vertical_timer_handler,
100000, 1, 1, BX_VGA_THIS vsync_realtime, "vga vsync");
}
BX_VGA_THIS set_update_timer(update_interval);
@ -1209,7 +1209,7 @@ void bx_vgacore_c::set_override(bool enabled, void *dev)
BX_VGA_THIS vga_redraw_area(0, 0, BX_VGA_THIS s.last_xres, BX_VGA_THIS s.last_yres);
BX_VGA_THIS start_vertical_timer();
} else {
bx_virt_timer.deactivate_timer(BX_VGA_THIS vertical_timer_id);
bx_virt_timer.deactivate_timer(BX_VGA_THIS vga_vtimer_id);
}
if (BX_VGA_THIS update_mode_vsync) {
BX_VGA_THIS set_update_timer(0);
@ -2339,7 +2339,7 @@ void bx_vgacore_c::vertical_timer_handler(void *this_ptr)
void bx_vgacore_c::vertical_timer(void)
{
BX_VGA_THIS vtimer_toggle ^= 1;
bx_virt_timer.activate_timer(BX_VGA_THIS vertical_timer_id,
bx_virt_timer.activate_timer(BX_VGA_THIS vga_vtimer_id,
BX_VGA_THIS vtimer_interval[BX_VGA_THIS vtimer_toggle], 0);
if (BX_VGA_THIS vtimer_toggle) {
BX_VGA_THIS s.CRTC.start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d];
@ -2381,7 +2381,7 @@ void bx_vgacore_c::start_vertical_timer(void)
BX_VGA_THIS vtimer_toggle = 0;
BX_VGA_THIS vtimer_interval[0] = BX_VGA_THIS s.vrend_usec;
BX_VGA_THIS vtimer_interval[1] = BX_VGA_THIS s.vtotal_usec - BX_VGA_THIS s.vrend_usec;
bx_virt_timer.activate_timer(BX_VGA_THIS vertical_timer_id, vtimer_interval[0], 0);
bx_virt_timer.activate_timer(BX_VGA_THIS vga_vtimer_id, vtimer_interval[0], 0);
}
#undef LOG_THIS

View File

@ -280,7 +280,7 @@ protected:
bool update_realtime;
bool update_mode_vsync;
// vertical timer stuff
int vertical_timer_id;
int vga_vtimer_id;
bool vsync_realtime;
Bit8u vtimer_toggle;
Bit32u vtimer_interval[2];

View File

@ -644,7 +644,11 @@ void bx_voodoo_base_c::update(void)
for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
if (GET_TILE_UPDATED(xti, yti)) {
if (v->banshee.half_mode) {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + xc);
if (v->banshee.double_width) {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + (xc >> 1));
} else {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + xc);
}
} else {
vid_ptr = disp_ptr + (yc * pitch + xc);
}
@ -653,7 +657,10 @@ void bx_voodoo_base_c::update(void)
vid_ptr2 = vid_ptr;
tile_ptr2 = tile_ptr;
for (c=0; c<w; c++) {
colour = v->fbi.clut[*(vid_ptr2++)];
colour = v->fbi.clut[*(vid_ptr2)];
if (!v->banshee.double_width || (c & 1)) {
vid_ptr2++;
}
colour = MAKE_COLOUR(
colour & 0xff0000, 24, info.red_shift, info.red_mask,
colour & 0x00ff00, 16, info.green_shift, info.green_mask,
@ -687,7 +694,11 @@ void bx_voodoo_base_c::update(void)
for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
if (GET_TILE_UPDATED(xti, yti)) {
if (v->banshee.half_mode) {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + (xc << 1));
if (v->banshee.double_width) {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + xc);
} else {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + (xc << 1));
}
} else {
vid_ptr = disp_ptr + (yc * pitch + (xc << 1));
}
@ -696,8 +707,11 @@ void bx_voodoo_base_c::update(void)
vid_ptr2 = vid_ptr;
tile_ptr2 = tile_ptr;
for (c=0; c<w; c++) {
index = *(vid_ptr2++);
index |= *(vid_ptr2++) << 8;
index = *(vid_ptr2);
index |= *(vid_ptr2 + 1) << 8;
if (!v->banshee.double_width || (c & 1)) {
vid_ptr2 += 2;
}
colour = MAKE_COLOUR(
v->fbi.pen[index] & 0x0000ff, 8, info.blue_shift, info.blue_mask,
v->fbi.pen[index] & 0x00ff00, 16, info.green_shift, info.green_mask,
@ -731,7 +745,11 @@ void bx_voodoo_base_c::update(void)
for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
if (GET_TILE_UPDATED(xti, yti)) {
if (v->banshee.half_mode) {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + 3*xc);
if (v->banshee.double_width) {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + 3 * (xc >> 1));
} else {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + 3 * xc);
}
} else {
vid_ptr = disp_ptr + (yc * pitch + 3*xc);
}
@ -740,9 +758,12 @@ void bx_voodoo_base_c::update(void)
vid_ptr2 = vid_ptr;
tile_ptr2 = tile_ptr;
for (c=0; c<w; c++) {
blue = *(vid_ptr2++);
green = *(vid_ptr2++);
red = *(vid_ptr2++);
blue = *(vid_ptr2);
green = *(vid_ptr2 + 1);
red = *(vid_ptr2 + 2);
if (!v->banshee.double_width || (c & 1)) {
vid_ptr2 += 3;
}
colour = MAKE_COLOUR(
red, 8, info.red_shift, info.red_mask,
green, 8, info.green_shift, info.green_mask,
@ -776,7 +797,11 @@ void bx_voodoo_base_c::update(void)
for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++) {
if (GET_TILE_UPDATED(xti, yti)) {
if (v->banshee.half_mode) {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + (xc << 2));
if (v->banshee.double_width) {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + (xc << 1));
} else {
vid_ptr = disp_ptr + ((yc >> 1) * pitch + (xc << 2));
}
} else {
vid_ptr = disp_ptr + (yc * pitch + (xc << 2));
}
@ -785,10 +810,12 @@ void bx_voodoo_base_c::update(void)
vid_ptr2 = vid_ptr;
tile_ptr2 = tile_ptr;
for (c=0; c<w; c++) {
blue = *(vid_ptr2++);
green = *(vid_ptr2++);
red = *(vid_ptr2++);
vid_ptr2++;
blue = *(vid_ptr2);
green = *(vid_ptr2 + 1);
red = *(vid_ptr2 + 2);
if (!v->banshee.double_width || (c & 1)) {
vid_ptr2 += 4;
}
colour = MAKE_COLOUR(
red, 8, info.red_shift, info.red_mask,
green, 8, info.green_shift, info.green_mask,

View File

@ -1728,6 +1728,7 @@ struct _banshee_info
Bit8u crtc[0x27]; /* VGA CRTC registers */
Bit8u disp_bpp;
bool half_mode;
bool double_width;
bool dac_8bit;
bool desktop_tiled;
bool overlay_tiled;