Initial XGA-2 implementation, (same as XGA-1 internally, but able to do 800x600 officially), selection is possible only on QT at the moment.

Refactored the ROP/MIX of the XGA accelerator.
Bus type variable added to make sure the device is an ISA-16 device or MCA in its dedicated register.
This commit is contained in:
TC1995
2022-07-03 23:01:46 +02:00
parent eb0ba3d1c4
commit f0a78c7642
6 changed files with 237 additions and 169 deletions

View File

@@ -64,6 +64,7 @@ typedef struct xga_t
uint8_t pal_b, pal_b_prefetch;
uint8_t sprite_data[1024];
uint8_t scrollcache;
uint8_t direct_color;
uint8_t *vram, *changedvram;
int16_t hwc_pos_x;
@@ -92,6 +93,7 @@ typedef struct xga_t
int op_mode_reset, linear_endian_reverse;
int sprite_pos, sprite_pos_prefetch, cursor_data_on;
int pal_test;
int type, bus;
uint32_t linear_base, linear_size, banked_mask;
uint32_t base_addr_1mb;

View File

@@ -0,0 +1,22 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* IBM XGA emulation.
*
*
*
* Authors: TheCollector1995.
*
* Copyright 2022 TheCollector1995.
*/
#ifndef VIDEO_XGA_DEVICE_H
# define VIDEO_XGA_DEVICE_H
extern const device_t xga_device;
extern const device_t xga_isa_device;
#endif /*VIDEO_XGA_DEVICE_H*/

View File

@@ -24,6 +24,7 @@ extern "C" {
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/video.h>
#include <86box/vid_xga_device.h>
}
#include "qt_deviceconfig.hpp"
@@ -102,6 +103,14 @@ void SettingsDisplay::on_pushButtonConfigureVoodoo_clicked() {
DeviceConfig::ConfigureDevice(&voodoo_device, 0, qobject_cast<Settings*>(Settings::settings));
}
void SettingsDisplay::on_pushButtonConfigureXga_clicked() {
if (machine_has_bus(machineId, MACHINE_BUS_MCA) > 0) {
DeviceConfig::ConfigureDevice(&xga_device, 0, qobject_cast<Settings*>(Settings::settings));
} else {
DeviceConfig::ConfigureDevice(&xga_isa_device, 0, qobject_cast<Settings*>(Settings::settings));
}
}
void SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) {
if (index < 0) {
return;
@@ -126,8 +135,14 @@ void SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) {
ui->checkBoxXga->setEnabled(hasIsa16 || has_MCA);
if (hasIsa16 || has_MCA)
ui->checkBoxXga->setChecked(xga_enabled);
ui->pushButtonConfigureXga->setEnabled((hasIsa16 || has_MCA) && ui->checkBoxXga->isChecked());
}
void SettingsDisplay::on_checkBoxVoodoo_stateChanged(int state) {
ui->pushButtonConfigureVoodoo->setEnabled(state == Qt::Checked);
}
void SettingsDisplay::on_checkBoxXga_stateChanged(int state) {
ui->pushButtonConfigureXga->setEnabled(state == Qt::Checked);
}

View File

@@ -22,8 +22,10 @@ public slots:
private slots:
void on_checkBoxVoodoo_stateChanged(int state);
void on_checkBoxXga_stateChanged(int state);
void on_comboBoxVideo_currentIndexChanged(int index);
void on_pushButtonConfigureVoodoo_clicked();
void on_pushButtonConfigureXga_clicked();
void on_pushButtonConfigure_clicked();
private:

View File

@@ -70,6 +70,13 @@
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="pushButtonConfigureXga">
<property name="text">
<string>Configure</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxXga">
<property name="text">

View File

@@ -32,9 +32,11 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
#include <86box/vid_xga_device.h>
#include "cpu.h"
#define XGA_BIOS_PATH "roms/video/xga/XGA_37F9576_Ver200.BIN"
#define XGA2_BIOS_PATH "roms/video/xga/xga2_v300.bin"
static void xga_ext_outb(uint16_t addr, uint8_t val, void *p);
static uint8_t xga_ext_inb(uint16_t addr, void *p);
@@ -44,7 +46,7 @@ xga_updatemapping(svga_t *svga)
{
xga_t *xga = &svga->xga;
//pclog("OpMode = %x, linear base = %08x, aperture cntl = %d, opmodereset1 = %d, access mode = %x\n", xga->op_mode, xga->linear_base, xga->aperture_cntl, xga->op_mode_reset, xga->access_mode);
//pclog("OpMode = %x, linear base = %08x, aperture cntl = %d, opmodereset1 = %d, access mode = %x, map = %x.\n", xga->op_mode, xga->linear_base, xga->aperture_cntl, xga->op_mode_reset, xga->access_mode, svga->gdcreg[6] & 0x0c);
if ((xga->op_mode & 7) >= 4) {
if (xga->aperture_cntl == 1) {
mem_mapping_disable(&svga->mapping);
@@ -112,12 +114,8 @@ xga_recalctimings(svga_t *svga)
xga->v_blankstart = xga->vblankstart + 1;
xga->h_disp = (xga->hdisp + 1) << 3;
xga->h_total = (xga->htotal + 1) << 3;
xga->rowoffset = (xga->hdisp + 1);
if ((xga->disp_cntl_2 & 7) == 4) {
xga->rowoffset = 0x80;
}
xga->interlace = !!(xga->disp_cntl_1 & 0x08);
xga->rowcount = (xga->disp_cntl_2 & 0xc0) >> 6;
@@ -131,7 +129,6 @@ xga_recalctimings(svga_t *svga)
}
xga->ma_latch = xga->disp_start_addr;
xga->h_disp_time = xga->h_disp;
switch (xga->clk_sel_1 & 0x0c) {
case 0:
@@ -301,6 +298,10 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val)
svga_recalctimings(svga);
break;
case 0x59:
xga->direct_color = val;
break;
case 0x60:
xga->sprite_pal_addr_idx = (xga->sprite_pal_addr_idx & 0x3f00) | val;
svga->dac_pos = 0;
@@ -349,8 +350,8 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val)
svga->dac_pos++;
break;
case 2:
index = svga->dac_addr & 0xff;
xga->pal_b = val;
index = svga->dac_addr & 0xff;
svga->vgapal[index].r = svga->dac_r;
svga->vgapal[index].g = svga->dac_g;
svga->vgapal[index].b = xga->pal_b;
@@ -404,6 +405,8 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *p)
break;
case 4:
xga->access_mode &= ~8;
if ((xga->disp_cntl_2 & 7) == 4)
xga->aperture_cntl = 0;
break;
case 6:
vga_on = 0;
@@ -467,7 +470,7 @@ xga_ext_inb(uint16_t addr, void *p)
case 0x0f:
switch (xga->regs_idx) {
case 4:
ret = 1;
ret = (xga->bus & DEVICE_MCA) ? 1 : 0;
break;
case 0x10:
ret = xga->htotal & 0xff;
@@ -572,15 +575,19 @@ xga_ext_inb(uint16_t addr, void *p)
ret = xga->disp_cntl_2;
break;
case 0x52:
ret = 0x0a;
ret = 0x0b;
break;
case 0x53:
ret = 0xa0;
ret = 0xb0;
break;
case 0x54:
ret = xga->clk_sel_1;
break;
case 0x59:
ret = xga->direct_color;
break;
case 0x60:
ret = xga->sprite_pal_addr_idx & 0xff;
break;
@@ -664,61 +671,45 @@ xga_ext_inb(uint16_t addr, void *p)
#define READW(addr, dat) \
dat = *(uint16_t *)&xga->vram[(addr) & (xga->vram_mask)];
#define READW_REVERSE(addr, dat) \
dat = xga->vram[(addr + 1) & (xga->vram_mask - 1)] & 0xff; \
dat |= (xga->vram[(addr) & (xga->vram_mask - 1)] << 8);
#define WRITEW(addr, dat) \
*(uint16_t *)&xga->vram[((addr)) & (xga->vram_mask)] = dat; \
xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = changeframecount;
static uint32_t
xga_rop(uint32_t s, uint8_t d, uint8_t op)
{
switch(op) {
default:
case 0:
return 0;
case 1:
return s & d;
case 2:
return s & ~d;
case 3:
return s;
case 4:
return ~s & d;
case 5:
return d;
case 6:
return s ^ d;
case 7:
return s | d;
case 8:
return ~s & ~d;
case 9:
return s ^ ~d;
case 0x0a:
return ~d;
case 0x0b:
return s | ~d;
case 0x0c:
return ~s;
case 0x0d:
return ~s | d;
case 0x0e:
return ~s | ~d;
case 0x0f:
return -1;
case 0x10:
return MAX(s, d);
case 0x11:
return MIN(s, d);
case 0x12:
return MIN(0xff, s + d);
case 0x13:
return MAX(0, d - s);
case 0x14:
return MAX(0, s - d);
case 0x15:
return (s + d) >> 1;
}
}
#define WRITEW_REVERSE(addr, dat) \
xga->vram[((addr + 1)) & (xga->vram_mask - 1)] = dat & 0xff; \
xga->vram[((addr)) & (xga->vram_mask - 1)] = dat >> 8; \
xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = changeframecount;
#define ROP(mix, d, s) { \
switch ((mix) ? (xga->accel.frgd_mix & 0x1f) : (xga->accel.bkgd_mix & 0x1f)) { \
case 0x00: d = 0; break; \
case 0x01: d = s & d; break; \
case 0x02: d = s & ~d; break; \
case 0x03: d = s; break; \
case 0x04: d = ~s & d; break; \
case 0x05: d = d; break; \
case 0x06: d = s ^ d; break; \
case 0x07: d = s | d; break; \
case 0x08: d = ~s & ~d; break; \
case 0x09: d = s ^ ~d; break; \
case 0x0a: d = ~d; break; \
case 0x0b: d = s | ~d; break; \
case 0x0c: d = ~s; break; \
case 0x0d: d = ~s | d; break; \
case 0x0e: d = ~s | ~d; break; \
case 0x0f: d = ~0; break; \
case 0x10: d = MAX(s, d); break; \
case 0x11: d = MIN(s, d); break; \
case 0x12: d = MIN(0xff, s + d); break; \
case 0x13: d = MAX(0, d - s); break; \
case 0x14: d = MAX(0, s - d); break; \
case 0x15: d = (s + d) >> 1; break; \
} \
}
static uint32_t
xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int width)
@@ -738,7 +729,7 @@ xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y, int map, uint32_t b
skip = 1;
}
addr += (y * (width) >> 3);
addr += (y * (width >> 3));
addr += (x >> 3);
if (!skip) {
READ(addr, byte);
@@ -779,7 +770,7 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int
switch (xga->accel.px_map_format[map] & 7) {
case 0: /*1-bit*/
addr += (y * (width) >> 3);
addr += (y * (width >> 3));
addr += (x >> 3);
if (!skip) {
READ(addr, byte);
@@ -805,13 +796,20 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int
} else {
byte = mem_readb_phys(addr);
}
byte2 = byte;
return byte2;
return byte;
case 4: /*16-bit*/
addr += (y * (width) << 1);
addr += (y * (width << 1));
addr += (x << 1);
if (!skip) {
READW(addr, byte);
if ((xga->accel.px_map_format[map] & 8)) {
if (xga->linear_endian_reverse) {
READW(addr, byte);
} else {
READW_REVERSE(addr, byte);
}
} else {
READW(addr, byte);
}
} else {
byte = mem_readw_phys(addr);
}
@@ -874,7 +872,15 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui
addr += (y * (width) << 1);
addr += (x << 1);
if (!skip) {
WRITEW(addr, pixel);
if ((xga->accel.px_map_format[map] & 8)) {
if (xga->linear_endian_reverse) {
WRITEW(addr, pixel);
} else {
WRITEW_REVERSE(addr, pixel);
}
} else {
WRITEW(addr, pixel);
}
}
mem_writew_phys(addr, pixel);
break;
@@ -890,8 +896,6 @@ xga_short_stroke(svga_t *svga, uint8_t ssv)
uint32_t plane_mask = xga->accel.plane_mask;
uint32_t dstbase = xga->accel.px_map_base[xga->accel.dst_map];
uint32_t srcbase = xga->accel.px_map_base[xga->accel.src_map];
int mix;
int count = -1;
int y = ssv & 0x0f;
int x = 0;
int dx, dy, dirx, diry;
@@ -954,7 +958,9 @@ xga_short_stroke(svga_t *svga, uint8_t ssv)
((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) ||
((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) ||
((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
dest_dat = (dest_dat & ~plane_mask) | (xga_rop(src_dat, dest_dat, xga->accel.frgd_mix & 0x1f) & plane_mask);
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
if ((xga->accel.command & 0x30) == 0) {
if (ssv & 0x10)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1, xga->accel.px_map_height[xga->accel.dst_map] + 1);
@@ -978,7 +984,9 @@ xga_short_stroke(svga_t *svga, uint8_t ssv)
((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) ||
((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) ||
((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
dest_dat = (dest_dat & ~plane_mask) | (xga_rop(src_dat, dest_dat, xga->accel.frgd_mix & 0x1f) & plane_mask);
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
if ((xga->accel.command & 0x30) == 0) {
if (ssv & 0x10)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1, xga->accel.px_map_height[xga->accel.dst_map] + 1);
@@ -1019,11 +1027,9 @@ xga_line_draw_write(svga_t *svga)
uint32_t plane_mask = xga->accel.plane_mask;
uint32_t dstbase = xga->accel.px_map_base[xga->accel.dst_map];
uint32_t srcbase = xga->accel.px_map_base[xga->accel.src_map];
int mix;
int dminor, destxtmp, dmajor, err, tmpswap;
int steep = 1;
int xdir, ydir;
int count = -1;
int y = xga->accel.blt_width;
int x = 0;
int dx, dy;
@@ -1085,7 +1091,9 @@ xga_line_draw_write(svga_t *svga)
((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) ||
((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) ||
((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
dest_dat = (dest_dat & ~plane_mask) | (xga_rop(src_dat, dest_dat, xga->accel.frgd_mix & 0x1f) & plane_mask);
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
if ((xga->accel.command & 0x30) == 0)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1, xga->accel.px_map_height[xga->accel.dst_map] + 1);
else if (((xga->accel.command & 0x30) == 0x10) && x)
@@ -1107,7 +1115,9 @@ xga_line_draw_write(svga_t *svga)
((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) ||
((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) ||
((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
dest_dat = (dest_dat & ~plane_mask) | (xga_rop(src_dat, dest_dat, xga->accel.frgd_mix & 0x1f) & plane_mask);
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
if ((xga->accel.command & 0x30) == 0)
xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1, xga->accel.px_map_height[xga->accel.dst_map] + 1);
else if (((xga->accel.command & 0x30) == 0x10) && x)
@@ -1129,7 +1139,9 @@ xga_line_draw_write(svga_t *svga)
((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) ||
((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) ||
((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
dest_dat = (dest_dat & ~plane_mask) | (xga_rop(src_dat, dest_dat, xga->accel.frgd_mix & 0x1f) & plane_mask);
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
if ((xga->accel.command & 0x30) == 0)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1, xga->accel.px_map_height[xga->accel.dst_map] + 1);
else if (((xga->accel.command & 0x30) == 0x10) && x)
@@ -1148,7 +1160,9 @@ xga_line_draw_write(svga_t *svga)
((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) ||
((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) ||
((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
dest_dat = (dest_dat & ~plane_mask) | (xga_rop(src_dat, dest_dat, xga->accel.frgd_mix & 0x1f) & plane_mask);
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
if ((xga->accel.command & 0x30) == 0)
xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1, xga->accel.px_map_height[xga->accel.dst_map] + 1);
else if (((xga->accel.command & 0x30) == 0x10) && x)
@@ -1245,15 +1259,6 @@ xga_bitblt(svga_t *svga)
xga->accel.pattern = 1;
}
}
} else if ((dstwidth == (xga->h_disp - 1)) && (srcwidth == (xga->h_disp - 1))) {
if ((xga->accel.dst_map == 1) && (xga->accel.src_map == 1) && xga->linear_endian_reverse) {
if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x0b) && (xga->accel.px_map_format[xga->accel.src_map] >= 0x0b)) {
if ((xga->accel.command & 0xc0) == 0x40)
xga->accel.pattern = 0;
else
xga->accel.pattern = 1;
}
}
}
}
@@ -1273,7 +1278,9 @@ xga_bitblt(svga_t *svga)
((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) ||
((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) ||
((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
dest_dat = (dest_dat & ~plane_mask) | (xga_rop(src_dat, dest_dat, xga->accel.frgd_mix & 0x1f) & plane_mask);
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1, xga->accel.px_map_height[xga->accel.dst_map] + 1);
}
}
@@ -1288,7 +1295,9 @@ xga_bitblt(svga_t *svga)
((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) ||
((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) ||
((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
dest_dat = (dest_dat & ~plane_mask) | (xga_rop(src_dat, dest_dat, xga->accel.frgd_mix & 0x1f) & plane_mask);
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1, xga->accel.px_map_height[xga->accel.dst_map] + 1);
}
}
@@ -1366,7 +1375,9 @@ xga_bitblt(svga_t *svga)
((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) ||
((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) ||
((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
dest_dat = (dest_dat & ~plane_mask) | (xga_rop(src_dat, dest_dat, mix ? (xga->accel.frgd_mix & 0x1f) : (xga->accel.bkgd_mix & 0x1f)) & plane_mask);
old_dest_dat = dest_dat;
ROP(mix, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1, xga->accel.px_map_height[xga->accel.dst_map] + 1);
}
}
@@ -1385,7 +1396,9 @@ xga_bitblt(svga_t *svga)
((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) ||
((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) ||
((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
dest_dat = (dest_dat & ~plane_mask) | (xga_rop(src_dat, dest_dat, mix ? (xga->accel.frgd_mix & 0x1f) : (xga->accel.bkgd_mix & 0x1f)) & plane_mask);
old_dest_dat = dest_dat;
ROP(mix, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1, xga->accel.px_map_height[xga->accel.dst_map] + 1);
}
}
@@ -1429,7 +1442,6 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len)
addr &= 0x1fff;
if (addr >= 0x1800) {
//pclog("[%04X:%08X]: WriteMEM = %02x, val = %08x, len = %d.\n", CS, cpu_state.pc, addr & 0x7f, val, len);
switch (addr & 0x7f) {
case 0x12:
xga->accel.px_map_idx = val & 3;
@@ -1831,6 +1843,7 @@ exec_command:
//}
switch ((xga->accel.command >> 24) & 0x0f) {
case 3: /*Bresenham Line Draw Read*/
//pclog("Line Draw Read\n");
break;
case 4: /*Short Stroke Vectors*/
break;
@@ -1841,6 +1854,7 @@ exec_command:
xga_bitblt(svga);
break;
case 9: /*Inverting BitBLT*/
//pclog("Inverting BitBLT\n");
break;
}
} else if (len == 2) {
@@ -2265,8 +2279,29 @@ xga_writew_linear(uint32_t addr, uint16_t val, void *p)
return;
}
xga_write_linear(addr, val, p);
xga_write_linear(addr + 1, val >> 8, p);
if (xga->linear_endian_reverse) {
if (xga->accel.px_map_format[xga->accel.dst_map] == 0x0c) {
xga_write_linear(addr, val, p);
xga_write_linear(addr + 1, val >> 8, p);
} else if (xga->accel.px_map_format[xga->accel.dst_map] == 4) {
xga_write_linear(addr + 1, val, p);
xga_write_linear(addr, val >> 8, p);
} else {
xga_write_linear(addr, val, p);
xga_write_linear(addr + 1, val >> 8, p);
}
} else {
if (xga->accel.px_map_format[xga->accel.dst_map] == 0x0c) {
xga_write_linear(addr + 1, val, p);
xga_write_linear(addr, val >> 8, p);
} else if (xga->accel.px_map_format[xga->accel.dst_map] == 4) {
xga_write_linear(addr, val, p);
xga_write_linear(addr + 1, val >> 8, p);
} else {
xga_write_linear(addr, val, p);
xga_write_linear(addr + 1, val >> 8, p);
}
}
}
static void
@@ -2370,11 +2405,27 @@ xga_readw_linear(uint32_t addr, void *p)
{
svga_t *svga = (svga_t *)p;
xga_t *xga = &svga->xga;
uint16_t ret;
if (!xga->on)
return svga_readw_linear(addr, svga);
return xga_read_linear(addr, p) | (xga_read_linear(addr + 1, p) << 8);
if (xga->linear_endian_reverse) {
if (xga->accel.px_map_format[xga->accel.src_map] == 0x0c) {
ret = xga_read_linear(addr, p) | (xga_read_linear(addr + 1, p) << 8);
} else if (xga->accel.px_map_format[xga->accel.src_map] == 4) {
ret = xga_read_linear(addr + 1, p) | (xga_read_linear(addr, p) << 8);
} else
ret = xga_read_linear(addr, p) | (xga_read_linear(addr + 1, p) << 8);
} else {
if (xga->accel.px_map_format[xga->accel.src_map] == 0x0c) {
ret = xga_read_linear(addr + 1, p) | (xga_read_linear(addr, p) << 8);
} else if (xga->accel.px_map_format[xga->accel.src_map] == 4) {
ret = xga_read_linear(addr, p) | (xga_read_linear(addr + 1, p) << 8);
} else
ret = xga_read_linear(addr, p) | (xga_read_linear(addr + 1, p) << 8);
}
return ret;
}
static uint32_t
@@ -2417,72 +2468,6 @@ xga_do_render(svga_t *svga)
}
}
static void
xga_doblit(int wx, int wy, svga_t *svga)
{
int y_add, x_add, y_start, x_start, bottom;
uint32_t *p;
int i, j;
int xs_temp, ys_temp;
y_add = (enable_overscan) ? overscan_y : 0;
x_add = (enable_overscan) ? overscan_x : 0;
y_start = (enable_overscan) ? 0 : (overscan_y >> 1);
x_start = (enable_overscan) ? 0 : (overscan_x >> 1);
bottom = (overscan_y >> 1);
if ((wx <= 0) || (wy <= 0))
return;
xs_temp = wx;
ys_temp = wy + 1;
if (xs_temp < 64)
xs_temp = 640;
if (ys_temp < 32)
ys_temp = 200;
if ((svga->crtc[0x17] & 0x80) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
/* Screen res has changed.. fix up, and let them know. */
xsize = xs_temp;
ysize = ys_temp;
if ((xsize > 1984) || (ysize > 2016)) {
/* 2048x2048 is the biggest safe render texture, to account for overscan,
we suppress overscan starting from x 1984 and y 2016. */
x_add = 0;
y_add = 0;
suppress_overscan = 1;
} else
suppress_overscan = 0;
/* Block resolution changes while in DPMS mode to avoid getting a bogus
screen width (320). We're already rendering a blank screen anyway. */
set_screen_size(xsize + x_add, ysize + y_add);
if (video_force_resize_get())
video_force_resize_set(0);
}
if ((wx >= 160) && ((wy + 1) >= 120)) {
/* Draw (overscan_size - scroll size) lines of overscan on top and bottom. */
for (i = 0; i < svga->y_add; i++) {
p = &buffer32->line[i & 0x7ff][0];
for (j = 0; j < (xsize + x_add); j++)
p[j] = svga->overscan_color;
}
for (i = 0; i < bottom; i++) {
p = &buffer32->line[(ysize + svga->y_add + i) & 0x7ff][0];
for (j = 0; j < (xsize + x_add); j++)
p[j] = svga->overscan_color;
}
}
video_blit_memtoscreen(x_start, y_start, xsize + x_add, ysize + y_add);
}
void
xga_poll(xga_t *xga, svga_t *svga)
{
@@ -2539,9 +2524,15 @@ xga_poll(xga_t *xga, svga_t *svga)
if (xga->sc == xga->rowcount) {
xga->sc = 0;
xga->maback += (xga->rowoffset << 3);
if (xga->interlace)
if ((xga->disp_cntl_2 & 7) == 4) {
xga->maback += (xga->rowoffset << 4);
if (xga->interlace)
xga->maback += (xga->rowoffset << 4);
} else {
xga->maback += (xga->rowoffset << 3);
if (xga->interlace)
xga->maback += (xga->rowoffset << 3);
}
xga->maback &= xga->vram_mask;
xga->ma = xga->maback;
} else {
@@ -2703,6 +2694,9 @@ static void
uint32_t temp;
uint8_t *rom = NULL;
xga->type = device_get_config_int("type");
xga->bus = info->flags;
xga->vram_size = (1024 << 10);
xga->vram_mask = xga->vram_size - 1;
xga->vram = calloc(xga->vram_size, 1);
@@ -2712,7 +2706,7 @@ static void
xga->hwcursor.ysize = 64;
xga->bios_rom.sz = 0x2000;
f = rom_fopen(XGA_BIOS_PATH, "rb");
f = rom_fopen(xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, "rb");
(void)fseek(f, 0L, SEEK_END);
temp = ftell(f);
(void)fseek(f, 0L, SEEK_SET);
@@ -2761,10 +2755,10 @@ static void
mem_mapping_disable(&xga->linear_mapping);
mem_mapping_disable(&xga->memio_mapping);
xga->pos_regs[0] = 0xdb;
xga->pos_regs[0] = xga->type ? 0xda : 0xdb;
xga->pos_regs[1] = 0x8f;
if (info->flags & DEVICE_MCA) {
if (xga->bus & DEVICE_MCA) {
mca_add(xga_mca_read, xga_mca_write, xga_mca_feedb, NULL, svga);
} else {
io_sethandler(0x0100, 0x0008, xga_pos_in, NULL, NULL, NULL, NULL, NULL, svga);
@@ -2790,7 +2784,7 @@ xga_close(void *p)
static int
xga_available(void)
{
return rom_present(XGA_BIOS_PATH);
return rom_present(XGA_BIOS_PATH) && rom_present(XGA2_BIOS_PATH);
}
static void
@@ -2809,6 +2803,32 @@ xga_force_redraw(void *p)
svga->fullchange = changeframecount;
}
static const device_config_t xga_configuration[] = {
// clang-format off
{
.name = "type",
.description = "XGA type",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.selection = {
{
.description = "XGA-1",
.value = 0
},
{
.description = "XGA-2",
.value = 1
},
{ .description = "" }
}
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t xga_device = {
.name = "XGA (MCA)",
.internal_name = "xga_mca",
@@ -2820,7 +2840,7 @@ const device_t xga_device = {
{ .available = xga_available },
.speed_changed = xga_speed_changed,
.force_redraw = xga_force_redraw,
.config = NULL
.config = xga_configuration
};
const device_t xga_isa_device = {
@@ -2834,7 +2854,7 @@ const device_t xga_isa_device = {
{ .available = xga_available },
.speed_changed = xga_speed_changed,
.force_redraw = xga_force_redraw,
.config = NULL
.config = xga_configuration
};
void