Skip to content

Commit

Permalink
S3 XGA: Add support for accelerated 4bpp 16-color packed SVGA modes, …
Browse files Browse the repository at this point in the history
…which fixes display problems with ORCAD S3 support
  • Loading branch information
joncampbell123 committed Jul 9, 2024
1 parent 61aa6a6 commit b095cf2
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 18 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
NEXT
- S3 XGA emulation: Add XGA acceleration for 4bpp packed 16-color
SVGA modes. A CAD package has S3 support drivers that use the
16-color 4bpp packed modes and expects XGA acceleration to work.
(joncampbell123).
- Add "-o int13" option to IMGMOUNT to direct the FAT driver to do
all disk I/O through INT 13h instead of directly. This is intended
for certain demoscene productions that apparently like to make
Expand Down
19 changes: 14 additions & 5 deletions src/hardware/vga_s3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ extern bool enable_pci_vga;
extern unsigned int vbe_window_granularity;
extern unsigned int vbe_window_size;

void S3_UpdateXGAColorMode(void) {
switch (vga.s3.reg_50 & S3_XGA_CMASK) {
case S3_XGA_32BPP: vga.s3.xga_color_mode = M_LIN32; break;
case S3_XGA_16BPP: vga.s3.xga_color_mode = M_LIN16; break;
case S3_XGA_8BPP:
/* FIXME: 4/8bpp packed is controlled by the advanced function control register (0x4AE8) bit 2 which is not yet emulated here */
vga.s3.xga_color_mode = M_LIN8;
if ((vga.s3.misc_control_2 >> 4) == 0xF/*hacked 4bpp*/) vga.s3.xga_color_mode = M_LIN4;
break;
}
}

void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) {
(void)iolen;//UNUSED
switch (reg) {
Expand Down Expand Up @@ -170,11 +182,7 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) {
break;
case 0x50: // Extended System Control 1
vga.s3.reg_50 = (uint8_t)val;
switch (val & S3_XGA_CMASK) {
case S3_XGA_32BPP: vga.s3.xga_color_mode = M_LIN32; break;
case S3_XGA_16BPP: vga.s3.xga_color_mode = M_LIN16; break;
case S3_XGA_8BPP: vga.s3.xga_color_mode = M_LIN8; break;
}
S3_UpdateXGAColorMode();
switch (val & S3_XGA_WMASK) {
case S3_XGA_1024: vga.s3.xga_screen_width = 1024; break;
case S3_XGA_1152: vga.s3.xga_screen_width = 1152; break;
Expand Down Expand Up @@ -399,6 +407,7 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) {
13 (732/764) 32bit (1 pixel/VCLK)
*/
vga.s3.misc_control_2=(uint8_t)val;
S3_UpdateXGAColorMode();
VGA_DetermineMode();
break;
case 0x69: /* Extended System Control 3 */
Expand Down
42 changes: 29 additions & 13 deletions src/hardware/vga_xga.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,13 @@ void XGA_DrawPoint(Bitu x, Bitu y, Bitu c) {
one is actually 24-bit. Without this step there may be some graphics corruption (mainly,
during windows dragging. */
switch(XGA_COLOR_MODE) {
case M_LIN4:
{
uint8_t shf = ((memaddr^1u)&1u)*4u;
if (GCC_UNLIKELY((memaddr/2) >= vga.mem.memsize)) break;
vga.mem.linear[memaddr/2] = (vga.mem.linear[memaddr/2] & (0xF0 >> shf)) + ((c&0xF) << shf);
}
break;
case M_LIN8:
if (GCC_UNLIKELY(memaddr >= vga.mem.memsize)) break;
vga.mem.linear[memaddr] = (uint8_t)c;
Expand All @@ -374,11 +381,12 @@ void XGA_DrawPoint(Bitu x, Bitu y, Bitu c) {
default:
break;
}

}

Bitu XGA_PointMask() {
switch(XGA_COLOR_MODE) {
case M_LIN4:
return 0xFul;
case M_LIN8:
return 0xFFul;
case M_LIN15:
Expand All @@ -396,19 +404,23 @@ Bitu XGA_GetPoint(Bitu x, Bitu y) {
uint32_t memaddr = (uint32_t)((y * XGA_SCREEN_WIDTH) + x);

switch(XGA_COLOR_MODE) {
case M_LIN8:
if (GCC_UNLIKELY(memaddr >= vga.mem.memsize)) break;
return vga.mem.linear[memaddr];
case M_LIN15:
case M_LIN16:
if (GCC_UNLIKELY(memaddr*2 >= vga.mem.memsize)) break;
return ((uint16_t*)(vga.mem.linear))[memaddr];
case M_LIN32:
if (GCC_UNLIKELY(memaddr*4 >= vga.mem.memsize)) break;
return ((uint32_t*)(vga.mem.linear))[memaddr];
default:
break;
case M_LIN4:
if (GCC_UNLIKELY((memaddr/2) >= vga.mem.memsize)) break;
return (vga.mem.linear[memaddr/2] >> (((memaddr&1)^1)*4)) & 0xF;
case M_LIN8:
if (GCC_UNLIKELY(memaddr >= vga.mem.memsize)) break;
return vga.mem.linear[memaddr];
case M_LIN15:
case M_LIN16:
if (GCC_UNLIKELY(memaddr*2 >= vga.mem.memsize)) break;
return ((uint16_t*)(vga.mem.linear))[memaddr];
case M_LIN32:
if (GCC_UNLIKELY(memaddr*4 >= vga.mem.memsize)) break;
return ((uint32_t*)(vga.mem.linear))[memaddr];
default:
break;
}

return 0;
}

Expand Down Expand Up @@ -1420,6 +1432,8 @@ void XGA_DrawCmd(Bitu val, Bitu len) {

void XGA_SetDualReg(uint32_t& reg, Bitu val) {
switch(XGA_COLOR_MODE) {
case M_LIN4:
reg = (uint8_t)(val&0xf); break;
case M_LIN8:
reg = (uint8_t)(val&0xff); break;
case M_LIN15:
Expand All @@ -1441,6 +1455,8 @@ void XGA_SetDualReg(uint32_t& reg, Bitu val) {

Bitu XGA_GetDualReg(uint32_t reg) {
switch(XGA_COLOR_MODE) {
case M_LIN4:
return (uint8_t)(reg&0xf);
case M_LIN8:
return (uint8_t)(reg&0xff);
case M_LIN15: case M_LIN16:
Expand Down

0 comments on commit b095cf2

Please sign in to comment.