mirror of
https://github.com/86Box/86Box.git
synced 2026-02-24 02:18:20 -07:00
Merge branch 'master' into experimental
This commit is contained in:
@@ -1,12 +1,28 @@
|
||||
/*ATI Mach64 emulation*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* ATi Mach64 graphics card emulation.
|
||||
*
|
||||
* Version: @(#)vid_ati_mach64.c 1.0.1 2017/06/04
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "../ibm.h"
|
||||
#include "../device.h"
|
||||
#include "../io.h"
|
||||
#include "../mem.h"
|
||||
#include "../pci.h"
|
||||
#include "../rom.h"
|
||||
#include "../thread.h"
|
||||
#include "../device.h"
|
||||
#include "../win/plat_thread.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_svga_render.h"
|
||||
@@ -14,6 +30,9 @@
|
||||
#include "vid_ati_eeprom.h"
|
||||
#include "vid_ics2595.h"
|
||||
|
||||
#ifdef CLAMP
|
||||
#undef CLAMP
|
||||
#endif
|
||||
|
||||
#define FIFO_SIZE 65536
|
||||
#define FIFO_MASK (FIFO_SIZE - 1)
|
||||
@@ -62,10 +81,12 @@ typedef struct mach64_t
|
||||
|
||||
uint8_t regs[256];
|
||||
int index;
|
||||
|
||||
int type;
|
||||
|
||||
int type;
|
||||
|
||||
uint8_t pci_regs[256];
|
||||
uint8_t int_line;
|
||||
int card;
|
||||
|
||||
int bank_r[2];
|
||||
int bank_w[2];
|
||||
@@ -192,6 +213,7 @@ typedef struct mach64_t
|
||||
uint16_t pci_id;
|
||||
uint32_t config_chip_id;
|
||||
uint32_t block_decoded_io;
|
||||
int use_block_decoded_io;
|
||||
|
||||
int pll_addr;
|
||||
uint8_t pll_regs[16];
|
||||
@@ -466,7 +488,7 @@ void mach64_updatemapping(mach64_t *mach64)
|
||||
|
||||
if (!(mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))
|
||||
{
|
||||
pclog("Update mapping - PCI disabled\n");
|
||||
/* pclog("Update mapping - PCI disabled\n"); */
|
||||
mem_mapping_disable(&svga->mapping);
|
||||
mem_mapping_disable(&mach64->linear_mapping);
|
||||
mem_mapping_disable(&mach64->mmio_mapping);
|
||||
@@ -481,7 +503,7 @@ void mach64_updatemapping(mach64_t *mach64)
|
||||
case 0x0: /*128k at A0000*/
|
||||
mem_mapping_set_handler(&mach64->svga.mapping, mach64_read, NULL, NULL, mach64_write, NULL, NULL);
|
||||
mem_mapping_set_p(&mach64->svga.mapping, mach64);
|
||||
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x1fc00);
|
||||
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
|
||||
mem_mapping_enable(&mach64->mmio_mapping);
|
||||
svga->banked_mask = 0xffff;
|
||||
break;
|
||||
@@ -500,37 +522,35 @@ void mach64_updatemapping(mach64_t *mach64)
|
||||
case 0xC: /*32k at B8000*/
|
||||
mem_mapping_set_handler(&mach64->svga.mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
|
||||
mem_mapping_set_p(&mach64->svga.mapping, svga);
|
||||
mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x07c00);
|
||||
mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
|
||||
svga->banked_mask = 0x7fff;
|
||||
break;
|
||||
}
|
||||
if (mach64->linear_base)
|
||||
{
|
||||
if (mach64->type == MACH64_GX)
|
||||
{
|
||||
if ((mach64->config_cntl & 3) == 2)
|
||||
{
|
||||
/*8 MB aperture*/
|
||||
pclog("8 MB aperture\n");
|
||||
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, 0x007FFC00);
|
||||
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + 0x007FFC00, 0x400);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*4 MB aperture*/
|
||||
pclog("4 MB aperture\n");
|
||||
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, 0x003FFC00);
|
||||
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + 0x003FFC00, 0x400);
|
||||
}
|
||||
svga->linear_base = mach64->linear_base;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mach64->type == MACH64_GX)
|
||||
{
|
||||
if ((mach64->config_cntl & 3) == 2)
|
||||
{
|
||||
/*8 MB aperture*/
|
||||
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000);
|
||||
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*4 MB aperture*/
|
||||
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (4 << 20) - 0x4000);
|
||||
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((4 << 20) - 0x4000), 0x4000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*2*8 MB aperture*/
|
||||
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000);
|
||||
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000);
|
||||
mem_mapping_set_addr(&mach64->mmio_linear_mapping_2, mach64->linear_base + ((16 << 20) - 0x4000), 0x4000);
|
||||
}
|
||||
}
|
||||
svga->linear_base = mach64->linear_base;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -540,6 +560,14 @@ void mach64_updatemapping(mach64_t *mach64)
|
||||
}
|
||||
}
|
||||
|
||||
static void mach64_update_irqs(mach64_t *mach64)
|
||||
{
|
||||
if ((mach64->crtc_int_cntl & 0xaa0024) & ((mach64->crtc_int_cntl << 1) & 0xaa0024))
|
||||
pci_set_irq(mach64->card, PCI_INTA);
|
||||
else
|
||||
pci_clear_irq(mach64->card, PCI_INTA);
|
||||
}
|
||||
|
||||
static __inline void wake_fifo_thread(mach64_t *mach64)
|
||||
{
|
||||
thread_set_event(mach64->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
|
||||
@@ -594,8 +622,8 @@ static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val
|
||||
case 0x11e: case 0x11f:
|
||||
WRITE8(addr, mach64->dst_height_width, val);
|
||||
case 0x113:
|
||||
if (((addr & 0x3ff) == 0x11b) || ((addr & 0x3ff) == 0x11f) ||
|
||||
(((addr & 0x3ff) == 0x113) && !(val & 0x80)))
|
||||
if (((addr & 0x3ff) == 0x11b || (addr & 0x3ff) == 0x11f ||
|
||||
(addr & 0x3ff) == 0x113) && !(val & 0x80))
|
||||
{
|
||||
mach64_start_fill(mach64);
|
||||
#ifdef MACH64_DEBUG
|
||||
@@ -837,10 +865,6 @@ static void mach64_accel_write_fifo_l(mach64_t *mach64, uint32_t addr, uint32_t
|
||||
static void fifo_thread(void *param)
|
||||
{
|
||||
mach64_t *mach64 = (mach64_t *)param;
|
||||
fifo_entry_t *fifo;
|
||||
|
||||
uint64_t start_time = 0;
|
||||
uint64_t end_time = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -850,8 +874,9 @@ static void fifo_thread(void *param)
|
||||
mach64->blitter_busy = 1;
|
||||
while (!FIFO_EMPTY)
|
||||
{
|
||||
start_time = timer_read();
|
||||
fifo = &mach64->fifo[mach64->fifo_read_idx & FIFO_MASK];
|
||||
uint64_t start_time = timer_read();
|
||||
uint64_t end_time;
|
||||
fifo_entry_t *fifo = &mach64->fifo[mach64->fifo_read_idx & FIFO_MASK];
|
||||
|
||||
switch (fifo->addr_type & FIFO_TYPE)
|
||||
{
|
||||
@@ -903,8 +928,7 @@ static void mach64_queue(mach64_t *mach64, uint32_t addr, uint32_t val, uint32_t
|
||||
|
||||
void mach64_cursor_dump(mach64_t *mach64)
|
||||
{
|
||||
/* pclog("Mach64 cursor :\n");
|
||||
pclog("Ena = %i X = %i Y = %i Addr = %05X Xoff = %i Yoff = %i\n", svga->hwcursor.ena, svga->hwcursor.x, svga->hwcursor.y, svga->hwcursor.addr, svga->hwcursor.xoff, svga->hwcursor.yoff);*/
|
||||
return;
|
||||
}
|
||||
|
||||
void mach64_start_fill(mach64_t *mach64)
|
||||
@@ -967,7 +991,7 @@ void mach64_start_fill(mach64_t *mach64)
|
||||
mach64->accel.dst_size = mach64_width[mach64->accel.dst_pix_width];
|
||||
mach64->accel.src_size = mach64_width[mach64->accel.src_pix_width];
|
||||
mach64->accel.host_size = mach64_width[mach64->accel.host_pix_width];
|
||||
|
||||
|
||||
if (mach64->accel.src_size == WIDTH_1BIT)
|
||||
mach64->accel.src_offset <<= 3;
|
||||
else
|
||||
@@ -978,11 +1002,12 @@ void mach64_start_fill(mach64_t *mach64)
|
||||
else
|
||||
mach64->accel.dst_offset >>= mach64->accel.dst_size;
|
||||
|
||||
mach64->accel.xinc = (mach64->dst_cntl & DST_X_DIR) ? 1 : -1;
|
||||
mach64->accel.yinc = (mach64->dst_cntl & DST_Y_DIR) ? 1 : -1;
|
||||
mach64->accel.xinc = (mach64->dst_cntl & DST_X_DIR) ? 1 : -1;
|
||||
mach64->accel.yinc = (mach64->dst_cntl & DST_Y_DIR) ? 1 : -1;
|
||||
|
||||
mach64->accel.source_host = ((mach64->dp_src & 7) == SRC_HOST) || (((mach64->dp_src >> 8) & 7) == SRC_HOST);
|
||||
|
||||
|
||||
|
||||
for (y = 0; y < 8; y++)
|
||||
{
|
||||
for (x = 0; x < 8; x++)
|
||||
@@ -996,6 +1021,9 @@ void mach64_start_fill(mach64_t *mach64)
|
||||
mach64->accel.sc_right = (mach64->sc_left_right >> 16) & 0x1fff;
|
||||
mach64->accel.sc_top = mach64->sc_top_bottom & 0x7fff;
|
||||
mach64->accel.sc_bottom = (mach64->sc_top_bottom >> 16) & 0x7fff;
|
||||
|
||||
/* mach64->accel.sc_left *= mach64_inc[mach64->accel.dst_pix_width];
|
||||
mach64->accel.sc_right *= mach64_inc[mach64->accel.dst_pix_width];*/
|
||||
|
||||
mach64->accel.dp_frgd_clr = mach64->dp_frgd_clr;
|
||||
mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr;
|
||||
@@ -1159,8 +1187,8 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
while (count)
|
||||
{
|
||||
uint32_t src_dat, dest_dat;
|
||||
uint32_t host_dat;
|
||||
int mix;
|
||||
uint32_t host_dat = 0;
|
||||
int mix = 0;
|
||||
int dst_x = (mach64->accel.dst_x + mach64->accel.dst_x_start) & 0xfff;
|
||||
int dst_y = (mach64->accel.dst_y + mach64->accel.dst_y_start) & 0xfff;
|
||||
int src_x;
|
||||
@@ -1363,9 +1391,9 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
case OP_LINE:
|
||||
while (count)
|
||||
{
|
||||
uint32_t src_dat, dest_dat;
|
||||
uint32_t host_dat;
|
||||
int mix;
|
||||
uint32_t src_dat = 0, dest_dat;
|
||||
uint32_t host_dat = 0;
|
||||
int mix = 0;
|
||||
int draw_pixel = !(mach64->dst_cntl & DST_POLYGON_EN);
|
||||
|
||||
if (mach64->accel.source_host)
|
||||
@@ -1440,7 +1468,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
}
|
||||
|
||||
READ(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, dest_dat, mach64->accel.dst_size);
|
||||
|
||||
|
||||
switch (mach64->accel.clr_cmp_fn)
|
||||
{
|
||||
case 1: /*TRUE*/
|
||||
@@ -1611,18 +1639,18 @@ static void pll_write(mach64_t *mach64, uint32_t addr, uint8_t val)
|
||||
break;
|
||||
case 2: /*Data*/
|
||||
mach64->pll_regs[mach64->pll_addr] = val;
|
||||
pclog("pll_write %02x,%02x\n", mach64->pll_addr, val);
|
||||
/* pclog("pll_write %02x,%02x\n", mach64->pll_addr, val); */
|
||||
|
||||
for (c = 0; c < 4; c++)
|
||||
for (c = 0; c < 4; c++)
|
||||
{
|
||||
double m = (double)mach64->pll_regs[PLL_REF_DIV];
|
||||
double n = (double)mach64->pll_regs[VCLK0_FB_DIV+c];
|
||||
double r = 14318184.0;
|
||||
double p = (double)(1 << ((mach64->pll_regs[VCLK_POST_DIV] >> (c*2)) & 3));
|
||||
|
||||
pclog("PLLfreq %i = %g %g m=%02x n=%02x p=%02x\n", c, (2.0 * r * n) / (m * p), p, mach64->pll_regs[PLL_REF_DIV], mach64->pll_regs[VCLK0_FB_DIV+c], mach64->pll_regs[VCLK_POST_DIV]);
|
||||
/* pclog("PLLfreq %i = %g %g m=%02x n=%02x p=%02x\n", c, (2.0 * r * n) / (m * p), p, mach64->pll_regs[PLL_REF_DIV], mach64->pll_regs[VCLK0_FB_DIV+c], mach64->pll_regs[VCLK_POST_DIV]); */
|
||||
mach64->pll_freq[c] = (2.0 * r * n) / (m * p);
|
||||
pclog(" %g\n", mach64->pll_freq[c]);
|
||||
/* pclog(" %g\n", mach64->pll_freq[c]); */
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1633,8 +1661,9 @@ static void mach64_vblank_start(svga_t *svga)
|
||||
{
|
||||
mach64_t *mach64 = (mach64_t *)svga->p;
|
||||
int overlay_cmp_mix = (mach64->overlay_key_cntl >> 8) & 0xf;
|
||||
|
||||
|
||||
mach64->crtc_int_cntl |= 4;
|
||||
mach64_update_irqs(mach64);
|
||||
|
||||
svga->overlay.x = (mach64->overlay_y_x_start >> 16) & 0x7ff;
|
||||
svga->overlay.y = mach64->overlay_y_x_start & 0x7ff;
|
||||
@@ -1657,7 +1686,10 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p)
|
||||
uint8_t ret;
|
||||
if (!(addr & 0x400))
|
||||
{
|
||||
switch (addr & 0x3ff)
|
||||
#ifdef MACH64_DEBUG
|
||||
pclog("nmach64_ext_readb: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc);
|
||||
#endif
|
||||
switch (addr & 0x3ff)
|
||||
{
|
||||
case 0x00: case 0x01: case 0x02: case 0x03:
|
||||
READ8(addr, mach64->overlay_y_x_start);
|
||||
@@ -1756,6 +1788,10 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p)
|
||||
READ8(addr, mach64->cur_horz_vert_off);
|
||||
break;
|
||||
|
||||
case 0x79:
|
||||
ret = 0x30;
|
||||
break;
|
||||
|
||||
case 0x80: case 0x81: case 0x82: case 0x83:
|
||||
READ8(addr, mach64->scratch_reg0);
|
||||
break;
|
||||
@@ -1763,10 +1799,6 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p)
|
||||
READ8(addr, mach64->scratch_reg1);
|
||||
break;
|
||||
|
||||
case 0x79:
|
||||
ret = 0x30;
|
||||
break;
|
||||
|
||||
case 0x90: case 0x91: case 0x92: case 0x93:
|
||||
READ8(addr, mach64->clock_cntl);
|
||||
break;
|
||||
@@ -2056,7 +2088,10 @@ uint32_t mach64_ext_readl(uint32_t addr, void *p)
|
||||
uint32_t ret;
|
||||
if (!(addr & 0x400))
|
||||
{
|
||||
ret = 0xffffffff;
|
||||
#ifdef MACH64_DEBUG
|
||||
pclog("nmach64_ext_readl: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc);
|
||||
#endif
|
||||
ret = 0xffffffff;
|
||||
}
|
||||
else switch (addr & 0x3ff)
|
||||
{
|
||||
@@ -2186,6 +2221,7 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p)
|
||||
mach64->crtc_int_cntl = (mach64->crtc_int_cntl & 0x75) | (val & ~0x75);
|
||||
if (val & 4)
|
||||
mach64->crtc_int_cntl &= ~4;
|
||||
mach64_update_irqs(mach64);
|
||||
break;
|
||||
|
||||
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
|
||||
@@ -2492,6 +2528,7 @@ uint8_t mach64_ext_inb(uint16_t port, void *p)
|
||||
|
||||
case 0x72ec: case 0x72ed: case 0x72ee: case 0x72ef:
|
||||
ret = mach64_ext_readb(0x400 | 0xe4 | (port & 3), p);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = 0;
|
||||
@@ -2678,7 +2715,7 @@ void mach64_ext_outw(uint16_t port, uint16_t val, void *p)
|
||||
}
|
||||
void mach64_ext_outl(uint16_t port, uint32_t val, void *p)
|
||||
{
|
||||
pclog("mach64_ext_outl : port %04X val %08X\n", port, val);
|
||||
/* pclog("mach64_ext_outl : port %04X val %08X\n", port, val); */
|
||||
switch (port)
|
||||
{
|
||||
default:
|
||||
@@ -2980,7 +3017,7 @@ void mach64_overlay_draw(svga_t *svga, int displine)
|
||||
break;
|
||||
|
||||
default:
|
||||
pclog("Unknown Mach64 scaler format %x\n", mach64->scaler_format);
|
||||
/* pclog("Unknown Mach64 scaler format %x\n", mach64->scaler_format); */
|
||||
/*Fill buffer with something recognisably wrong*/
|
||||
for (x = 0; x < mach64->svga.overlay_latch.xsize; x++)
|
||||
mach64->overlay_dat[x] = 0xff00ff;
|
||||
@@ -3097,17 +3134,20 @@ static void mach64_io_set(mach64_t *mach64)
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64);
|
||||
|
||||
for (c = 0; c < 8; c++)
|
||||
if (!mach64->use_block_decoded_io)
|
||||
{
|
||||
io_sethandler((c * 0x1000) + 0x2ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
|
||||
io_sethandler((c * 0x1000) + 0x6ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
|
||||
io_sethandler((c * 0x1000) + 0xaec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
|
||||
io_sethandler((c * 0x1000) + 0xeec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
io_sethandler((c * 0x1000) + 0x2ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
|
||||
io_sethandler((c * 0x1000) + 0x6ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
|
||||
io_sethandler((c * 0x1000) + 0xaec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
|
||||
io_sethandler((c * 0x1000) + 0xeec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64);
|
||||
}
|
||||
}
|
||||
|
||||
io_sethandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64);
|
||||
|
||||
if (mach64->block_decoded_io && mach64->block_decoded_io < 0x10000)
|
||||
if (mach64->use_block_decoded_io && mach64->block_decoded_io && mach64->block_decoded_io < 0x10000)
|
||||
io_sethandler(mach64->block_decoded_io, 0x0400, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64);
|
||||
}
|
||||
|
||||
@@ -3135,12 +3175,12 @@ uint8_t mach64_pci_read(int func, int addr, void *p)
|
||||
|
||||
case 0x09: return 0; /*Programming interface*/
|
||||
|
||||
case 0x0a: return 0x00;
|
||||
case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/
|
||||
case 0x0b: return 0x03;
|
||||
|
||||
case 0x10: return 0x00; /*Linear frame buffer address*/
|
||||
case 0x11: return 0x00;
|
||||
case 0x12: return 0x00;
|
||||
case 0x12: return mach64->linear_base >> 16;
|
||||
case 0x13: return mach64->linear_base >> 24;
|
||||
|
||||
case 0x14: return 0x01; /*Block decoded IO address*/
|
||||
@@ -3152,39 +3192,38 @@ uint8_t mach64_pci_read(int func, int addr, void *p)
|
||||
case 0x31: return 0x00;
|
||||
case 0x32: return mach64->pci_regs[0x32];
|
||||
case 0x33: return mach64->pci_regs[0x33];
|
||||
|
||||
case 0x3c: return mach64->int_line;
|
||||
case 0x3d: return PCI_INTA;
|
||||
|
||||
case 0x40: return mach64->use_block_decoded_io;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t bios_base = 0x000c0000;
|
||||
|
||||
void mach64_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
{
|
||||
mach64_t *mach64 = (mach64_t *)p;
|
||||
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case PCI_REG_COMMAND:
|
||||
mach64->pci_regs[PCI_REG_COMMAND] = val & 0x27;
|
||||
|
||||
if (val & PCI_COMMAND_IO)
|
||||
mach64_io_set(mach64);
|
||||
else
|
||||
mach64_io_remove(mach64);
|
||||
|
||||
mach64_updatemapping(mach64);
|
||||
break;
|
||||
|
||||
case 0x12:
|
||||
if (mach64->type == MACH64_VT2)
|
||||
val = 0;
|
||||
break;
|
||||
/* case 0x12:
|
||||
case 0x12:
|
||||
if (mach64->type == MACH64_VT2)
|
||||
val = 0;
|
||||
mach64->linear_base = (mach64->linear_base & 0xff000000) | ((val & 0x80) << 16);
|
||||
mach64_updatemapping(mach64);
|
||||
break; */
|
||||
break;
|
||||
case 0x13:
|
||||
mach64->linear_base = (val << 24);
|
||||
mach64->linear_base = (mach64->linear_base & 0x800000) | (val << 24);
|
||||
mach64_updatemapping(mach64);
|
||||
break;
|
||||
|
||||
@@ -3224,16 +3263,30 @@ void mach64_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
if (mach64->pci_regs[0x30] & 0x01)
|
||||
{
|
||||
uint32_t addr = (mach64->pci_regs[0x32] << 16) | (mach64->pci_regs[0x33] << 24);
|
||||
bios_base = addr;
|
||||
pclog("Mach64 bios_rom enabled at %08x\n", addr);
|
||||
/* pclog("Mach64 bios_rom enabled at %08x\n", addr); */
|
||||
mem_mapping_set_addr(&mach64->bios_rom.mapping, addr, 0x8000);
|
||||
}
|
||||
else
|
||||
{
|
||||
pclog("Mach64 bios_rom disabled\n");
|
||||
/* pclog("Mach64 bios_rom disabled\n"); */
|
||||
mem_mapping_disable(&mach64->bios_rom.mapping);
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x3c:
|
||||
mach64->int_line = val;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
if (mach64->type == MACH64_VT2)
|
||||
{
|
||||
if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
|
||||
mach64_io_remove(mach64);
|
||||
mach64->use_block_decoded_io = val & 0x04;
|
||||
if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
|
||||
mach64_io_set(mach64);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3262,7 +3315,7 @@ static void *mach64_common_init()
|
||||
|
||||
mach64_io_set(mach64);
|
||||
|
||||
pci_add(mach64_pci_read, mach64_pci_write, mach64);
|
||||
mach64->card = pci_add(mach64_pci_read, mach64_pci_write, mach64);
|
||||
|
||||
mach64->pci_regs[PCI_REG_COMMAND] = 3;
|
||||
mach64->pci_regs[0x30] = 0x00;
|
||||
@@ -3270,7 +3323,7 @@ static void *mach64_common_init()
|
||||
mach64->pci_regs[0x33] = 0x00;
|
||||
|
||||
ati68860_ramdac_init(&mach64->ramdac);
|
||||
|
||||
|
||||
mach64->dst_cntl = 3;
|
||||
|
||||
mach64->wake_fifo_thread = thread_create_event();
|
||||
@@ -3310,7 +3363,8 @@ static void *mach64vt2_init()
|
||||
mach64->config_chip_id = 0x40005654;
|
||||
mach64->dac_cntl = 1 << 16; /*Internal 24-bit DAC*/
|
||||
mach64->config_stat0 = 4;
|
||||
|
||||
mach64->use_block_decoded_io = PCI ? 4 : 0;
|
||||
|
||||
ati_eeprom_load(&mach64->eeprom, L"mach64vt.nvr", 1);
|
||||
|
||||
rom_init(&mach64->bios_rom, L"roms/atimach64vt2pci.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
@@ -3324,7 +3378,6 @@ int mach64gx_available()
|
||||
{
|
||||
return rom_present(L"roms/mach64gx/bios.bin");
|
||||
}
|
||||
|
||||
int mach64vt2_available()
|
||||
{
|
||||
return rom_present(L"roms/atimach64vt2pci.bin");
|
||||
@@ -3462,7 +3515,6 @@ device_t mach64gx_device =
|
||||
mach64_add_status_info,
|
||||
mach64gx_config
|
||||
};
|
||||
|
||||
device_t mach64vt2_device =
|
||||
{
|
||||
"ATI Mach64VT2",
|
||||
|
||||
@@ -1,2 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* ATi Mach64 graphics card emulation.
|
||||
*
|
||||
* Version: @(#)vid_ati_mach64.h 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
extern device_t mach64gx_device;
|
||||
extern device_t mach64vt2_device;
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Emulation of the old and new IBM CGA graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_cga.c 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
/*CGA emulation*/
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
@@ -62,10 +77,6 @@ void cga_out(uint16_t addr, uint8_t val, void *p)
|
||||
if ((cga->cgamode ^ val) & 1)
|
||||
{
|
||||
cga_palette = (cga->rgb_type << 1);
|
||||
if (!(val & 1) && (cga_palette > 0) && (cga_palette < 8))
|
||||
{
|
||||
cga_palette--;
|
||||
}
|
||||
cgapal_rebuild();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Emulation of the old and new IBM CGA graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_cga.h 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
typedef struct cga_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
/* Code borrowed from DOSBox and adapted by OBattler.
|
||||
Original author: reenigne. */
|
||||
/*
|
||||
* 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 CGA composite filter, borrowed from reenigne's DOSBox
|
||||
* patch and ported to C.
|
||||
*
|
||||
* Version: @(#)vid_cga.c 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: reenigne,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2015-2017 reenigne.
|
||||
* Copyright 2015-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,3 +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 CGA composite filter, borrowed from reenigne's DOSBox
|
||||
* patch and ported to C.
|
||||
*
|
||||
* Version: @(#)vid_cga.h 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: reenigne,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2015-2017 reenigne.
|
||||
* Copyright 2015-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
#define Bit8u uint8_t
|
||||
#define Bit32u uint32_t
|
||||
#define Bitu unsigned int
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
/*EGA emulation*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Emulation of the EGA, Chips & Technologies SuperEGA, and
|
||||
* AX JEGA graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_ega.c 1.0.1 2017/06/01
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* akm,
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
* Copyright 2017-2017 akm.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "../ibm.h"
|
||||
#include "../io.h"
|
||||
@@ -8,6 +29,7 @@
|
||||
#include "../device.h"
|
||||
#include "video.h"
|
||||
#include "vid_ega.h"
|
||||
#include "vid_ega_render.h"
|
||||
|
||||
|
||||
extern uint8_t edatlookup[4][4];
|
||||
@@ -23,11 +45,111 @@ static int old_overscan_color = 0;
|
||||
|
||||
int update_overscan = 0;
|
||||
|
||||
#define SBCS 0
|
||||
#define DBCS 1
|
||||
#define ID_LEN 6
|
||||
#define NAME_LEN 8
|
||||
#define SBCS19_LEN 256 * 19
|
||||
#define DBCS16_LEN 65536 * 32
|
||||
|
||||
uint8_t jfont_sbcs_19[SBCS19_LEN];//256 * 19( * 8)
|
||||
uint8_t jfont_dbcs_16[DBCS16_LEN];//65536 * 16 * 2 (* 8)
|
||||
|
||||
typedef struct {
|
||||
char id[ID_LEN];
|
||||
char name[NAME_LEN];
|
||||
unsigned char width;
|
||||
unsigned char height;
|
||||
unsigned char type;
|
||||
} fontx_h;
|
||||
|
||||
typedef struct {
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
} fontxTbl;
|
||||
|
||||
void ega_jega_write_font(ega_t *ega)
|
||||
{
|
||||
unsigned int chr = ega->RDFFB;
|
||||
unsigned int chr_2 = ega->RDFSB;
|
||||
|
||||
ega->RSTAT &= ~0x02;
|
||||
|
||||
/* Check if the character code is in the Wide character set of Shift-JIS */
|
||||
if (((chr >= 0x40) && (chr <= 0x7e)) || ((chr >= 0x80) && (chr <= 0xfc)))
|
||||
{
|
||||
if (ega->font_index >= 32)
|
||||
{
|
||||
ega->font_index = 0;
|
||||
}
|
||||
chr <<= 8;
|
||||
/* Fix vertical character position */
|
||||
chr |= chr_2;
|
||||
if (ega->font_index < 16)
|
||||
{
|
||||
jfont_dbcs_16[(chr * 32) + (ega->font_index * 2)] = ega->RDFAP; /* 16x16 font */
|
||||
}
|
||||
else
|
||||
{
|
||||
jfont_dbcs_16[(chr * 32) + ((ega->font_index - 16) * 2) + 1] = ega->RDFAP; /* 16x16 font */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ega->font_index >= 19)
|
||||
{
|
||||
ega->font_index = 0;
|
||||
}
|
||||
jfont_sbcs_19[(chr * 19) + ega->font_index] = ega->RDFAP; /* 8x19 font */
|
||||
}
|
||||
ega->font_index++;
|
||||
ega->RSTAT |= 0x02;
|
||||
}
|
||||
|
||||
void ega_jega_read_font(ega_t *ega)
|
||||
{
|
||||
unsigned int chr = ega->RDFFB;
|
||||
unsigned int chr_2 = ega->RDFSB;
|
||||
|
||||
ega->RSTAT &= ~0x02;
|
||||
|
||||
/* Check if the character code is in the Wide character set of Shift-JIS */
|
||||
if (((chr >= 0x40) && (chr <= 0x7e)) || ((chr >= 0x80) && (chr <= 0xfc)))
|
||||
{
|
||||
if (ega->font_index >= 32)
|
||||
{
|
||||
ega->font_index = 0;
|
||||
}
|
||||
chr <<= 8;
|
||||
/* Fix vertical character position */
|
||||
chr |= chr_2;
|
||||
if (ega->font_index < 16)
|
||||
{
|
||||
ega->RDFAP = jfont_dbcs_16[(chr * 32) + (ega->font_index * 2)]; /* 16x16 font */
|
||||
}
|
||||
else
|
||||
{
|
||||
ega->RDFAP = jfont_dbcs_16[(chr * 32) + ((ega->font_index - 16) * 2) + 1]; /* 16x16 font */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ega->font_index >= 19)
|
||||
{
|
||||
ega->font_index = 0;
|
||||
}
|
||||
ega->RDFAP = jfont_sbcs_19[(chr * 19) + ega->font_index]; /* 8x19 font */
|
||||
}
|
||||
ega->font_index++;
|
||||
ega->RSTAT |= 0x02;
|
||||
}
|
||||
|
||||
void ega_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
ega_t *ega = (ega_t *)p;
|
||||
int c;
|
||||
uint8_t o, old;
|
||||
uint8_t crtcreg;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
@@ -130,21 +252,82 @@ void ega_out(uint16_t addr, uint8_t val, void *p)
|
||||
break;
|
||||
case 0x3d0:
|
||||
case 0x3d4:
|
||||
ega->crtcreg = val & 31;
|
||||
ega->crtcreg = val;
|
||||
return;
|
||||
case 0x3d1:
|
||||
case 0x3d5:
|
||||
if (ega->crtcreg <= 7 && ega->crtc[0x11] & 0x80) return;
|
||||
old = ega->crtc[ega->crtcreg];
|
||||
ega->crtc[ega->crtcreg] = val;
|
||||
if (old != val)
|
||||
{
|
||||
if (ega->crtcreg < 0xe || ega->crtcreg > 0x10)
|
||||
{
|
||||
fullchange = changeframecount;
|
||||
ega_recalctimings(ega);
|
||||
}
|
||||
}
|
||||
if ((ega->crtcreg < 0xb9) || !ega->is_jega)
|
||||
{
|
||||
crtcreg = ega->crtcreg & 0x1f;
|
||||
if (crtcreg <= 7 && ega->crtc[0x11] & 0x80) return;
|
||||
old = ega->crtc[crtcreg];
|
||||
ega->crtc[crtcreg] = val;
|
||||
if (old != val)
|
||||
{
|
||||
if (crtcreg < 0xe || crtcreg > 0x10)
|
||||
{
|
||||
fullchange = changeframecount;
|
||||
ega_recalctimings(ega);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(ega->crtcreg)
|
||||
{
|
||||
case 0xb9: /* Mode register 1 */
|
||||
ega->RMOD1 = val;
|
||||
break;
|
||||
case 0xba: /* Mode register 2 */
|
||||
ega->RMOD2 = val;
|
||||
break;
|
||||
case 0xbb: /* ANK Group sel */
|
||||
ega->RDAGS = val;
|
||||
break;
|
||||
case 0xbc: /* Font access first byte */
|
||||
if (ega->RDFFB != val)
|
||||
{
|
||||
ega->RDFFB = val;
|
||||
ega->font_index = 0;
|
||||
}
|
||||
break;
|
||||
case 0xbd: /* Font access Second Byte */
|
||||
if (ega->RDFSB != val)
|
||||
{
|
||||
ega->RDFSB = val;
|
||||
ega->font_index = 0;
|
||||
}
|
||||
break;
|
||||
case 0xbe: /* Font Access Pattern */
|
||||
ega->RDFAP = val;
|
||||
ega_jega_write_font(ega);
|
||||
break;
|
||||
case 0xdb:
|
||||
ega->RPSSC = val;
|
||||
break;
|
||||
case 0xd9:
|
||||
ega->RPSSU = val;
|
||||
break;
|
||||
case 0xda:
|
||||
ega->RPSSL = val;
|
||||
break;
|
||||
case 0xdc: /* Superimposed mode (only AX-2 system, not implemented) */
|
||||
ega->RPPAJ = val;
|
||||
break;
|
||||
case 0xdd:
|
||||
ega->RCMOD = val;
|
||||
break;
|
||||
case 0xde: /* Cursor Skew control */
|
||||
ega->RCSKW = val;
|
||||
break;
|
||||
case 0xdf: /* Font R/W register */
|
||||
ega->RSTAT = val;
|
||||
break;
|
||||
default:
|
||||
pclog("JEGA: Write to illegal index %02X\n", ega->crtcreg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -174,6 +357,7 @@ static uint8_t ega_get_input_status_0(ega_t *ega)
|
||||
uint8_t ega_in(uint16_t addr, void *p)
|
||||
{
|
||||
ega_t *ega = (ega_t *)p;
|
||||
int crtcreg;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
@@ -204,7 +388,49 @@ uint8_t ega_in(uint16_t addr, void *p)
|
||||
return ega->crtcreg;
|
||||
case 0x3d1:
|
||||
case 0x3d5:
|
||||
return ega->crtc[ega->crtcreg];
|
||||
if ((ega->crtcreg < 0xb9) || !ega->is_jega)
|
||||
{
|
||||
crtcreg = ega->crtcreg & 0x1f;
|
||||
return ega->crtc[crtcreg];
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(ega->crtcreg)
|
||||
{
|
||||
case 0xb9:
|
||||
return ega->RMOD1;
|
||||
case 0xba:
|
||||
return ega->RMOD2;
|
||||
case 0xbb:
|
||||
return ega->RDAGS;
|
||||
case 0xbc: /* BCh RDFFB Font access First Byte */
|
||||
return ega->RDFFB;
|
||||
case 0xbd: /* BDh RDFFB Font access Second Byte */
|
||||
return ega->RDFSB;
|
||||
case 0xbe: /* BEh RDFAP Font Access Pattern */
|
||||
ega_jega_read_font(ega);
|
||||
return ega->RDFAP;
|
||||
case 0xdb:
|
||||
return ega->RPSSC;
|
||||
case 0xd9:
|
||||
return ega->RPSSU;
|
||||
case 0xda:
|
||||
return ega->RPSSL;
|
||||
case 0xdc:
|
||||
return ega->RPPAJ;
|
||||
case 0xdd:
|
||||
return ega->RCMOD;
|
||||
case 0xde:
|
||||
return ega->RCSKW;
|
||||
case 0xdf:
|
||||
return ega->ROMSL;
|
||||
case 0xbf:
|
||||
return 0x03; /* The font is always readable and writable */
|
||||
default:
|
||||
pclog("JEGA: Read from illegal index %02X\n", ega->crtcreg);
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
case 0x3da:
|
||||
ega->attrff = 0;
|
||||
ega->stat ^= 0x30; /*Fools IBM EGA video BIOS self-test*/
|
||||
@@ -270,28 +496,10 @@ void ega_recalctimings(ega_t *ega)
|
||||
ega->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
|
||||
}
|
||||
|
||||
int ega_display_line(ega_t *ega)
|
||||
{
|
||||
int y_add = (enable_overscan) ? (overscan_y >> 1) : 0;
|
||||
unsigned int dl = ega->displine;
|
||||
if (ega->crtc[9] & 0x1f)
|
||||
{
|
||||
dl -= (ega->crtc[8] & 0x1f);
|
||||
}
|
||||
dl += y_add;
|
||||
dl &= 0x7ff;
|
||||
return dl;
|
||||
}
|
||||
|
||||
void ega_poll(void *p)
|
||||
{
|
||||
ega_t *ega = (ega_t *)p;
|
||||
uint8_t chr, dat, attr;
|
||||
uint32_t charaddr;
|
||||
int x, xx;
|
||||
uint32_t fg, bg;
|
||||
int offset;
|
||||
uint8_t edat[4];
|
||||
int x;
|
||||
int drawcursor = 0;
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
@@ -299,7 +507,6 @@ void ega_poll(void *p)
|
||||
int x_add_ex = enable_overscan ? 16 : 0;
|
||||
uint32_t *q, i, j;
|
||||
int wx = 640, wy = 350;
|
||||
int dl = ega_display_line(ega);
|
||||
|
||||
if (!ega->linepos)
|
||||
{
|
||||
@@ -318,204 +525,36 @@ void ega_poll(void *p)
|
||||
|
||||
if (ega->scrblank)
|
||||
{
|
||||
for (x = 0; x < ega->hdisp; x++)
|
||||
{
|
||||
switch (ega->seqregs[1] & 9)
|
||||
{
|
||||
case 0:
|
||||
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[dl])[(x * 9) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
case 1:
|
||||
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[(x * 8) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
case 8:
|
||||
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[dl])[(x * 18) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
case 9:
|
||||
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[dl])[(x * 16) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ega_render_blank(ega);
|
||||
}
|
||||
else if (!(ega->gdcreg[6] & 1))
|
||||
{
|
||||
if (fullchange)
|
||||
{
|
||||
for (x = 0; x < ega->hdisp; x++)
|
||||
{
|
||||
drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
|
||||
chr = ega->vram[(ega->ma << 1) & ega->vrammask];
|
||||
attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask];
|
||||
|
||||
if (attr & 8) charaddr = ega->charsetb + (chr * 128);
|
||||
else charaddr = ega->charseta + (chr * 128);
|
||||
|
||||
if (drawcursor)
|
||||
{
|
||||
bg = ega->pallook[ega->egapal[attr & 15]];
|
||||
fg = ega->pallook[ega->egapal[attr >> 4]];
|
||||
}
|
||||
else
|
||||
{
|
||||
fg = ega->pallook[ega->egapal[attr & 15]];
|
||||
bg = ega->pallook[ega->egapal[attr >> 4]];
|
||||
if (attr & 0x80 && ega->attrregs[0x10] & 8)
|
||||
{
|
||||
bg = ega->pallook[ega->egapal[(attr >> 4) & 7]];
|
||||
if (ega->blink & 16)
|
||||
fg = bg;
|
||||
}
|
||||
}
|
||||
|
||||
dat = ega->vram[charaddr + (ega->sc << 2)];
|
||||
if (ega->seqregs[1] & 8)
|
||||
{
|
||||
if (ega->seqregs[1] & 1)
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[(((x << 4) + 32 + (xx << 1)) & 2047) + x_add] =
|
||||
((uint32_t *)buffer32->line[dl])[(((x << 4) + 33 + (xx << 1)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + (xx << 1)) & 2047) + x_add] =
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 33 + (xx << 1)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 16) & 2047) + x_add] =
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 17) & 2047) + x_add] = bg;
|
||||
else
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 16) & 2047) + x_add] =
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 17) & 2047) + x_add] = (dat & 1) ? fg : bg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ega->seqregs[1] & 1)
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[(((x << 3) + 32 + xx) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + xx) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + 8) & 2047) + x_add] = bg;
|
||||
else
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + 8) & 2047) + x_add] = (dat & 1) ? fg : bg;
|
||||
}
|
||||
}
|
||||
ega->ma += 4;
|
||||
ega->ma &= ega->vrammask;
|
||||
}
|
||||
}
|
||||
ega_render_text_standard(ega, drawcursor);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ega->gdcreg[5] & 0x20)
|
||||
{
|
||||
case 0x00:
|
||||
if (ega->seqregs[1] & 8)
|
||||
{
|
||||
offset = ((8 - ega->scrollcache) << 1) + 16;
|
||||
for (x = 0; x <= ega->hdisp; x++)
|
||||
{
|
||||
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
|
||||
{
|
||||
edat[0] = ega->vram[ega->ma | 0x8000];
|
||||
edat[1] = ega->vram[ega->ma | 0x8001];
|
||||
edat[2] = ega->vram[ega->ma | 0x8002];
|
||||
edat[3] = ega->vram[ega->ma | 0x8003];
|
||||
}
|
||||
else
|
||||
{
|
||||
edat[0] = ega->vram[ega->ma];
|
||||
edat[1] = ega->vram[ega->ma | 0x1];
|
||||
edat[2] = ega->vram[ega->ma | 0x2];
|
||||
edat[3] = ega->vram[ega->ma | 0x3];
|
||||
}
|
||||
ega->ma += 4;
|
||||
ega->ma &= ega->vrammask;
|
||||
|
||||
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = (8 - ega->scrollcache) + 24;
|
||||
for (x = 0; x <= ega->hdisp; x++)
|
||||
{
|
||||
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
|
||||
{
|
||||
edat[0] = ega->vram[ega->ma | 0x8000];
|
||||
edat[1] = ega->vram[ega->ma | 0x8001];
|
||||
edat[2] = ega->vram[ega->ma | 0x8002];
|
||||
edat[3] = ega->vram[ega->ma | 0x8003];
|
||||
}
|
||||
else
|
||||
{
|
||||
edat[0] = ega->vram[ega->ma];
|
||||
edat[1] = ega->vram[ega->ma | 0x1];
|
||||
edat[2] = ega->vram[ega->ma | 0x2];
|
||||
edat[3] = ega->vram[ega->ma | 0x3];
|
||||
}
|
||||
ega->ma += 4;
|
||||
ega->ma &= ega->vrammask;
|
||||
|
||||
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 6 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 4 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 2 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (ega->seqregs[1] & 8)
|
||||
{
|
||||
ega_render_4bpp_lowres(ega);
|
||||
}
|
||||
else
|
||||
{
|
||||
ega_render_4bpp_highres(ega);
|
||||
}
|
||||
break;
|
||||
case 0x20:
|
||||
offset = ((8 - ega->scrollcache) << 1) + 16;
|
||||
for (x = 0; x <= ega->hdisp; x++)
|
||||
{
|
||||
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
|
||||
{
|
||||
edat[0] = ega->vram[(ega->ma << 1) + 0x8000];
|
||||
edat[1] = ega->vram[(ega->ma << 1) + 0x8001];
|
||||
}
|
||||
else
|
||||
{
|
||||
edat[0] = ega->vram[(ega->ma << 1)];
|
||||
edat[1] = ega->vram[(ega->ma << 1) + 1];
|
||||
}
|
||||
ega->ma += 4;
|
||||
ega->ma &= ega->vrammask;
|
||||
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add]= ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[edat[1] & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]];
|
||||
}
|
||||
break;
|
||||
if (ega->seqregs[1] & 8)
|
||||
{
|
||||
ega_render_2bpp_lowres(ega);
|
||||
}
|
||||
else
|
||||
{
|
||||
ega_render_2bpp_highres(ega);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ega->lastline < ega->displine)
|
||||
@@ -678,7 +717,8 @@ void ega_poll(void *p)
|
||||
else
|
||||
{
|
||||
if (ega->crtc[9] & 0x80)
|
||||
ega->video_res_y /= 2; if (!(ega->crtc[0x17] & 1))
|
||||
ega->video_res_y /= 2;
|
||||
if (!(ega->crtc[0x17] & 1))
|
||||
ega->video_res_y *= 2;
|
||||
ega->video_res_y /= (ega->crtc[9] & 31) + 1;
|
||||
if (ega->seqregs[1] & 8)
|
||||
@@ -686,7 +726,6 @@ void ega_poll(void *p)
|
||||
ega->video_bpp = (ega->gdcreg[5] & 0x20) ? 2 : 4;
|
||||
}
|
||||
|
||||
readflash=0;
|
||||
ega->firstline = 2000;
|
||||
ega->lastline = 0;
|
||||
|
||||
@@ -937,6 +976,8 @@ void ega_common_defaults(ega_t *ega)
|
||||
ega->extvram = 1;
|
||||
|
||||
update_overscan = 0;
|
||||
|
||||
ega->is_jega = 0;
|
||||
}
|
||||
|
||||
void *ega_standalone_init()
|
||||
@@ -1049,6 +1090,112 @@ void *sega_standalone_init()
|
||||
return ega;
|
||||
}
|
||||
|
||||
uint16_t chrtosht(FILE *fp)
|
||||
{
|
||||
uint16_t i, j;
|
||||
i = (uint8_t) getc(fp);
|
||||
j = (uint8_t) getc(fp) << 8;
|
||||
return (i | j);
|
||||
}
|
||||
|
||||
unsigned int getfontx2header(FILE *fp, fontx_h *header)
|
||||
{
|
||||
fread(header->id, ID_LEN, 1, fp);
|
||||
if (strncmp(header->id, "FONTX2", ID_LEN) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
fread(header->name, NAME_LEN, 1, fp);
|
||||
header->width = (uint8_t)getc(fp);
|
||||
header->height = (uint8_t)getc(fp);
|
||||
header->type = (uint8_t)getc(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void readfontxtbl(fontxTbl *table, unsigned int size, FILE *fp)
|
||||
{
|
||||
while (size > 0)
|
||||
{
|
||||
table->start = chrtosht(fp);
|
||||
table->end = chrtosht(fp);
|
||||
++table;
|
||||
--size;
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadFontxFile(wchar_t *fname)
|
||||
{
|
||||
fontx_h head;
|
||||
fontxTbl *table;
|
||||
unsigned int code;
|
||||
uint8_t size;
|
||||
unsigned int i;
|
||||
|
||||
if (!fname) return;
|
||||
if(*fname=='\0') return;
|
||||
FILE * mfile=romfopen(fname,L"rb");
|
||||
if (!mfile)
|
||||
{
|
||||
pclog("MSG: Can't open FONTX2 file: %s\n",fname);
|
||||
return;
|
||||
}
|
||||
if (getfontx2header(mfile, &head) != 0)
|
||||
{
|
||||
fclose(mfile);
|
||||
pclog("MSG: FONTX2 header is incorrect\n");
|
||||
return;
|
||||
}
|
||||
/* switch whether the font is DBCS or not */
|
||||
if (head.type == DBCS)
|
||||
{
|
||||
if (head.width == 16 && head.height == 16)
|
||||
{
|
||||
size = getc(mfile);
|
||||
table = (fontxTbl *)calloc(size, sizeof(fontxTbl));
|
||||
readfontxtbl(table, size, mfile);
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
for (code = table[i].start; code <= table[i].end; code++)
|
||||
{
|
||||
fread(&jfont_dbcs_16[(code * 32)], sizeof(uint8_t), 32, mfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(mfile);
|
||||
pclog("MSG: FONTX2 DBCS font size is not correct\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (head.width == 8 && head.height == 19)
|
||||
{
|
||||
fread(jfont_sbcs_19, sizeof(uint8_t), SBCS19_LEN, mfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(mfile);
|
||||
pclog("MSG: FONTX2 SBCS font size is not correct\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
fclose(mfile);
|
||||
}
|
||||
|
||||
void *jega_standalone_init()
|
||||
{
|
||||
ega_t *ega = (ega_t *) sega_standalone_init();
|
||||
|
||||
LoadFontxFile(L"roms/JPNHN19X.FNT");
|
||||
LoadFontxFile(L"roms/JPNZN16X.FNT");
|
||||
|
||||
ega->is_jega = 1;
|
||||
|
||||
return ega;
|
||||
}
|
||||
|
||||
static int ega_standalone_available()
|
||||
{
|
||||
return rom_present(L"roms/ibm_6277356_ega_card_u44_27128.bin");
|
||||
@@ -1114,3 +1261,15 @@ device_t sega_device =
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
device_t jega_device =
|
||||
{
|
||||
"AX JEGA",
|
||||
0,
|
||||
jega_standalone_init,
|
||||
ega_close,
|
||||
sega_standalone_available,
|
||||
ega_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -1,6 +1,26 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Emulation of the EGA, Chips & Technologies SuperEGA, and
|
||||
* AX JEGA graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_ega.h 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* akm,
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
* Copyright 2017-2017 akm.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct ega_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
@@ -68,6 +88,12 @@ typedef struct ega_t
|
||||
int vrammask;
|
||||
|
||||
int video_res_x, video_res_y, video_bpp;
|
||||
|
||||
uint8_t RMOD1, RMOD2, RDAGS, RDFFB, RDFSB, RDFAP, RPESL, RPULP, RPSSC, RPSSU, RPSSL;
|
||||
uint8_t RPPAJ;
|
||||
uint8_t RCMOD, RCCLH, RCCLL, RCCSL, RCCEL, RCSKW, ROMSL, RSTAT;
|
||||
int is_jega, font_index;
|
||||
int chr_left, chr_wide;
|
||||
} ega_t;
|
||||
|
||||
extern int update_overscan;
|
||||
|
||||
305
src/VIDEO/vid_ega_render.c
Normal file
305
src/VIDEO/vid_ega_render.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* EGA renderers.
|
||||
*
|
||||
* Version: @(#)vid_ega_render.c 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../ibm.h"
|
||||
#include "../device.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "video.h"
|
||||
#include "vid_ega.h"
|
||||
#include "vid_ega_render.h"
|
||||
|
||||
|
||||
int ega_display_line(ega_t *ega)
|
||||
{
|
||||
int y_add = (enable_overscan) ? (overscan_y >> 1) : 0;
|
||||
unsigned int dl = ega->displine;
|
||||
if (ega->crtc[9] & 0x1f)
|
||||
{
|
||||
dl -= (ega->crtc[8] & 0x1f);
|
||||
}
|
||||
dl += y_add;
|
||||
dl &= 0x7ff;
|
||||
return dl;
|
||||
}
|
||||
|
||||
void ega_render_blank(ega_t *ega)
|
||||
{
|
||||
int x_add = (enable_overscan) ? 8 : 0;
|
||||
int dl = ega_display_line(ega);
|
||||
int x, xx;
|
||||
|
||||
for (x = 0; x < ega->hdisp; x++)
|
||||
{
|
||||
switch (ega->seqregs[1] & 9)
|
||||
{
|
||||
case 0:
|
||||
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[dl])[(x * 9) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
case 1:
|
||||
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[(x * 8) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
case 8:
|
||||
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[dl])[(x * 18) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
case 9:
|
||||
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[dl])[(x * 16) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ega_render_text_standard(ega_t *ega, int drawcursor)
|
||||
{
|
||||
int x_add = (enable_overscan) ? 8 : 0;
|
||||
int dl = ega_display_line(ega);
|
||||
uint8_t chr, dat, attr;
|
||||
uint32_t charaddr;
|
||||
int x, xx;
|
||||
uint32_t fg, bg;
|
||||
|
||||
if (fullchange)
|
||||
{
|
||||
for (x = 0; x < ega->hdisp; x++)
|
||||
{
|
||||
drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
|
||||
chr = ega->vram[(ega->ma << 1) & ega->vrammask];
|
||||
attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask];
|
||||
|
||||
if (attr & 8) charaddr = ega->charsetb + (chr * 128);
|
||||
else charaddr = ega->charseta + (chr * 128);
|
||||
|
||||
if (drawcursor)
|
||||
{
|
||||
bg = ega->pallook[ega->egapal[attr & 15]];
|
||||
fg = ega->pallook[ega->egapal[attr >> 4]];
|
||||
}
|
||||
else
|
||||
{
|
||||
fg = ega->pallook[ega->egapal[attr & 15]];
|
||||
bg = ega->pallook[ega->egapal[attr >> 4]];
|
||||
if (attr & 0x80 && ega->attrregs[0x10] & 8)
|
||||
{
|
||||
bg = ega->pallook[ega->egapal[(attr >> 4) & 7]];
|
||||
if (ega->blink & 16)
|
||||
fg = bg;
|
||||
}
|
||||
}
|
||||
|
||||
dat = ega->vram[charaddr + (ega->sc << 2)];
|
||||
if (ega->seqregs[1] & 8)
|
||||
{
|
||||
if (ega->seqregs[1] & 1)
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[(((x << 4) + 32 + (xx << 1)) & 2047) + x_add] =
|
||||
((uint32_t *)buffer32->line[dl])[(((x << 4) + 33 + (xx << 1)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + (xx << 1)) & 2047) + x_add] =
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 33 + (xx << 1)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 16) & 2047) + x_add] =
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 17) & 2047) + x_add] = bg;
|
||||
else
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 16) & 2047) + x_add] =
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 18) + 32 + 17) & 2047) + x_add] = (dat & 1) ? fg : bg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ega->seqregs[1] & 1)
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[(((x << 3) + 32 + xx) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + xx) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + 8) & 2047) + x_add] = bg;
|
||||
else
|
||||
((uint32_t *)buffer32->line[dl])[(((x * 9) + 32 + 8) & 2047) + x_add] = (dat & 1) ? fg : bg;
|
||||
}
|
||||
}
|
||||
ega->ma += 4;
|
||||
ega->ma &= ega->vrammask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ega_render_2bpp_lowres(ega_t *ega)
|
||||
{
|
||||
int x_add = (enable_overscan) ? 8 : 0;
|
||||
int dl = ega_display_line(ega);
|
||||
int x;
|
||||
int offset;
|
||||
uint8_t edat[4];
|
||||
|
||||
offset = ((8 - ega->scrollcache) << 1) + 16;
|
||||
for (x = 0; x <= ega->hdisp; x++)
|
||||
{
|
||||
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
|
||||
{
|
||||
edat[0] = ega->vram[(ega->ma << 1) + 0x8000];
|
||||
edat[1] = ega->vram[(ega->ma << 1) + 0x8001];
|
||||
}
|
||||
else
|
||||
{
|
||||
edat[0] = ega->vram[(ega->ma << 1)];
|
||||
edat[1] = ega->vram[(ega->ma << 1) + 1];
|
||||
}
|
||||
ega->ma += 4;
|
||||
ega->ma &= ega->vrammask;
|
||||
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add]= ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[edat[1] & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]];
|
||||
}
|
||||
}
|
||||
|
||||
void ega_render_2bpp_highres(ega_t *ega)
|
||||
{
|
||||
int x_add = (enable_overscan) ? 8 : 0;
|
||||
int dl = ega_display_line(ega);
|
||||
int x;
|
||||
int offset;
|
||||
uint8_t edat[4];
|
||||
|
||||
offset = ((8 - ega->scrollcache) << 1) + 16;
|
||||
for (x = 0; x <= ega->hdisp; x++)
|
||||
{
|
||||
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
|
||||
{
|
||||
edat[0] = ega->vram[(ega->ma << 1) + 0x8000];
|
||||
edat[1] = ega->vram[(ega->ma << 1) + 0x8001];
|
||||
}
|
||||
else
|
||||
{
|
||||
edat[0] = ega->vram[(ega->ma << 1)];
|
||||
edat[1] = ega->vram[(ega->ma << 1) + 1];
|
||||
}
|
||||
ega->ma += 4;
|
||||
ega->ma &= ega->vrammask;
|
||||
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[edat[1] & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]];
|
||||
}
|
||||
}
|
||||
|
||||
void ega_render_4bpp_lowres(ega_t *ega)
|
||||
{
|
||||
int x_add = (enable_overscan) ? 8 : 0;
|
||||
int dl = ega_display_line(ega);
|
||||
uint8_t dat;
|
||||
int x;
|
||||
int offset;
|
||||
uint8_t edat[4];
|
||||
|
||||
offset = ((8 - ega->scrollcache) << 1) + 16;
|
||||
for (x = 0; x <= ega->hdisp; x++)
|
||||
{
|
||||
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
|
||||
{
|
||||
edat[0] = ega->vram[ega->ma | 0x8000];
|
||||
edat[1] = ega->vram[ega->ma | 0x8001];
|
||||
edat[2] = ega->vram[ega->ma | 0x8002];
|
||||
edat[3] = ega->vram[ega->ma | 0x8003];
|
||||
}
|
||||
else
|
||||
{
|
||||
edat[0] = ega->vram[ega->ma];
|
||||
edat[1] = ega->vram[ega->ma | 0x1];
|
||||
edat[2] = ega->vram[ega->ma | 0x2];
|
||||
edat[3] = ega->vram[ega->ma | 0x3];
|
||||
}
|
||||
ega->ma += 4;
|
||||
ega->ma &= ega->vrammask;
|
||||
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
}
|
||||
}
|
||||
|
||||
void ega_render_4bpp_highres(ega_t *ega)
|
||||
{
|
||||
int x_add = (enable_overscan) ? 8 : 0;
|
||||
int dl = ega_display_line(ega);
|
||||
uint8_t dat;
|
||||
int x;
|
||||
int offset;
|
||||
uint8_t edat[4];
|
||||
|
||||
offset = (8 - ega->scrollcache) + 24;
|
||||
for (x = 0; x <= ega->hdisp; x++)
|
||||
{
|
||||
if (ega->sc & 1 && !(ega->crtc[0x17] & 1))
|
||||
{
|
||||
edat[0] = ega->vram[ega->ma | 0x8000];
|
||||
edat[1] = ega->vram[ega->ma | 0x8001];
|
||||
edat[2] = ega->vram[ega->ma | 0x8002];
|
||||
edat[3] = ega->vram[ega->ma | 0x8003];
|
||||
}
|
||||
else
|
||||
{
|
||||
edat[0] = ega->vram[ega->ma];
|
||||
edat[1] = ega->vram[ega->ma | 0x1];
|
||||
edat[2] = ega->vram[ega->ma | 0x2];
|
||||
edat[3] = ega->vram[ega->ma | 0x3];
|
||||
}
|
||||
ega->ma += 4;
|
||||
ega->ma &= ega->vrammask;
|
||||
|
||||
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 6 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 4 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 2 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
}
|
||||
}
|
||||
37
src/VIDEO/vid_ega_render.h
Normal file
37
src/VIDEO/vid_ega_render.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* EGA renderers.
|
||||
*
|
||||
* Version: @(#)vid_ega_render.h 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
extern int firstline_draw, lastline_draw;
|
||||
extern int displine;
|
||||
extern int sc;
|
||||
|
||||
extern uint32_t ma, ca;
|
||||
extern int con, cursoron, cgablink;
|
||||
|
||||
extern int scrollcache;
|
||||
|
||||
extern uint8_t edatlookup[4][4];
|
||||
|
||||
void ega_render_blank(ega_t *ega);
|
||||
void ega_render_text_standard(ega_t *ega, int drawcursor);
|
||||
void ega_render_text_jega(ega_t *ega);
|
||||
|
||||
void ega_render_2bpp_lowres(ega_t *ega);
|
||||
void ega_render_2bpp_highres(ega_t *ega);
|
||||
void ega_render_4bpp_lowres(ega_t *ega);
|
||||
void ega_render_4bpp_highres(ega_t *ega);
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "../pci.h"
|
||||
#include "../rom.h"
|
||||
#include "../device.h"
|
||||
#include "../thread.h"
|
||||
#include "../win/plat_thread.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_icd2061.h"
|
||||
@@ -235,14 +235,6 @@ uint8_t et4000w32p_in(uint16_t addr, void *p)
|
||||
return svga->crtcreg;
|
||||
case 0x3D5:
|
||||
return svga->crtc[svga->crtcreg];
|
||||
|
||||
case 0x3DA:
|
||||
svga->attrff = 0;
|
||||
svga->cgastat ^= 0x30;
|
||||
temp = svga->cgastat & 0x39;
|
||||
if (svga->hdisp_on) temp |= 2;
|
||||
if (!(svga->cgastat & 8)) temp |= 0x80;
|
||||
return temp;
|
||||
|
||||
case 0x210A: case 0x211A: case 0x212A: case 0x213A:
|
||||
case 0x214A: case 0x215A: case 0x216A: case 0x217A:
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
#include "../pci.h"
|
||||
#include "../pic.h"
|
||||
#include "../rom.h"
|
||||
#include "../thread.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "../win/plat_thread.h"
|
||||
#include "video.h"
|
||||
#include "vid_nv_riva128.h"
|
||||
#include "vid_svga.h"
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
/*S3 emulation*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Emulation of the S3 Trio32, S3 Trio64, and S3 Vision864
|
||||
* graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_s3.c 1.0.1 2017/06/04
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "../ibm.h"
|
||||
#include "../io.h"
|
||||
#include "../mem.h"
|
||||
#include "../pci.h"
|
||||
#include "../rom.h"
|
||||
#include "../thread.h"
|
||||
#include "../device.h"
|
||||
#include "../win/plat_thread.h"
|
||||
#include "video.h"
|
||||
#include "vid_s3.h"
|
||||
#include "vid_svga.h"
|
||||
@@ -76,12 +93,15 @@ typedef struct s3_t
|
||||
int chip;
|
||||
|
||||
uint8_t id, id_ext, id_ext_pci;
|
||||
|
||||
uint8_t int_line;
|
||||
|
||||
int packed_mmio;
|
||||
|
||||
uint32_t linear_base, linear_size;
|
||||
|
||||
uint8_t pci_regs[256];
|
||||
int card;
|
||||
|
||||
uint32_t vram_mask;
|
||||
|
||||
@@ -132,8 +152,17 @@ typedef struct s3_t
|
||||
int blitter_busy;
|
||||
uint64_t blitter_time;
|
||||
uint64_t status_time;
|
||||
|
||||
uint8_t subsys_cntl, subsys_stat;
|
||||
uint8_t status_9ae9;
|
||||
} s3_t;
|
||||
|
||||
#define INT_VSY (1 << 0)
|
||||
#define INT_GE_BSY (1 << 1)
|
||||
#define INT_FIFO_OVR (1 << 2)
|
||||
#define INT_FIFO_EMP (1 << 3)
|
||||
#define INT_MASK 0xf
|
||||
|
||||
void s3_updatemapping();
|
||||
|
||||
void s3_accel_write(uint32_t addr, uint8_t val, void *p);
|
||||
@@ -155,6 +184,19 @@ static void s3_wait_fifo_idle(s3_t *s3)
|
||||
}
|
||||
}
|
||||
|
||||
static void s3_update_irqs(s3_t *s3)
|
||||
{
|
||||
if (!PCI)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (s3->subsys_cntl & s3->subsys_stat & INT_MASK)
|
||||
pci_set_irq(s3->card, PCI_INTA);
|
||||
else
|
||||
pci_clear_irq(s3->card, PCI_INTA);
|
||||
}
|
||||
|
||||
void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3);
|
||||
|
||||
#define WRITE8(addr, var, val) switch ((addr) & 3) \
|
||||
@@ -402,70 +444,88 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
|
||||
static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val)
|
||||
{
|
||||
if (s3->accel.cmd & 0x100)
|
||||
{
|
||||
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = (val >> 8) | (val << 8);
|
||||
if ((s3->accel.cmd & 0x600) == 0x000)
|
||||
s3_accel_start(8, 1, val | (val << 16), 0, s3);
|
||||
else
|
||||
s3_accel_start(16, 1, val | (val << 16), 0, s3);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((s3->accel.cmd & 0x600) == 0x000)
|
||||
s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
|
||||
}
|
||||
}
|
||||
if (port & 0x8000)
|
||||
{
|
||||
s3_accel_out_fifo(s3, port, val);
|
||||
s3_accel_out_fifo(s3, port + 1, val >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s3->accel.cmd & 0x100)
|
||||
{
|
||||
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = (val >> 8) | (val << 8);
|
||||
if ((s3->accel.cmd & 0x600) == 0x000)
|
||||
s3_accel_start(8, 1, val | (val << 16), 0, s3);
|
||||
else
|
||||
s3_accel_start(16, 1, val | (val << 16), 0, s3);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((s3->accel.cmd & 0x600) == 0x000)
|
||||
s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val)
|
||||
{
|
||||
if (s3->accel.cmd & 0x100)
|
||||
{
|
||||
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
|
||||
{
|
||||
if (s3->accel.cmd & 0x400)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
|
||||
s3_accel_start(32, 1, val, 0, s3);
|
||||
}
|
||||
else if ((s3->accel.cmd & 0x600) == 0x200)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
|
||||
s3_accel_start(16, 1, val, 0, s3);
|
||||
s3_accel_start(16, 1, val >> 16, 0, s3);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
|
||||
s3_accel_start(8, 1, val, 0, s3);
|
||||
s3_accel_start(8, 1, val >> 16, 0, s3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s3->accel.cmd & 0x400)
|
||||
s3_accel_start(4, 1, 0xffffffff, val, s3);
|
||||
else if ((s3->accel.cmd & 0x600) == 0x200)
|
||||
{
|
||||
s3_accel_start(2, 1, 0xffffffff, val, s3);
|
||||
s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
|
||||
}
|
||||
else
|
||||
{
|
||||
s3_accel_start(1, 1, 0xffffffff, val, s3);
|
||||
s3_accel_start(1, 1, 0xffffffff, val >> 16, s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (port & 0x8000)
|
||||
{
|
||||
s3_accel_out_fifo(s3, port, val);
|
||||
s3_accel_out_fifo(s3, port + 1, val >> 8);
|
||||
s3_accel_out_fifo(s3, port + 2, val >> 16);
|
||||
s3_accel_out_fifo(s3, port + 3, val >> 24);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s3->accel.cmd & 0x100)
|
||||
{
|
||||
if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
|
||||
{
|
||||
if (s3->accel.cmd & 0x400)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
|
||||
s3_accel_start(32, 1, val, 0, s3);
|
||||
}
|
||||
else if ((s3->accel.cmd & 0x600) == 0x200)
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
|
||||
s3_accel_start(16, 1, val, 0, s3);
|
||||
s3_accel_start(16, 1, val >> 16, 0, s3);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
|
||||
s3_accel_start(8, 1, val, 0, s3);
|
||||
s3_accel_start(8, 1, val >> 16, 0, s3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s3->accel.cmd & 0x400)
|
||||
s3_accel_start(4, 1, 0xffffffff, val, s3);
|
||||
else if ((s3->accel.cmd & 0x600) == 0x200)
|
||||
{
|
||||
s3_accel_start(2, 1, 0xffffffff, val, s3);
|
||||
s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
|
||||
}
|
||||
else
|
||||
{
|
||||
s3_accel_start(1, 1, 0xffffffff, val, s3);
|
||||
s3_accel_start(1, 1, 0xffffffff, val >> 16, s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val)
|
||||
@@ -707,9 +767,19 @@ static void fifo_thread(void *param)
|
||||
s3->blitter_time += end_time - start_time;
|
||||
}
|
||||
s3->blitter_busy = 0;
|
||||
s3->subsys_stat |= INT_FIFO_EMP;
|
||||
s3_update_irqs(s3);
|
||||
}
|
||||
}
|
||||
|
||||
static void s3_vblank_start(svga_t *svga)
|
||||
{
|
||||
s3_t *s3 = (s3_t *)svga->p;
|
||||
|
||||
s3->subsys_stat |= INT_VSY;
|
||||
s3_update_irqs(s3);
|
||||
}
|
||||
|
||||
static void s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type)
|
||||
{
|
||||
fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK];
|
||||
@@ -1111,9 +1181,12 @@ void s3_accel_out(uint16_t port, uint8_t val, void *p)
|
||||
else switch (port)
|
||||
{
|
||||
case 0x42e8:
|
||||
s3->subsys_stat &= ~val;
|
||||
s3_update_irqs(s3);
|
||||
break;
|
||||
case 0x42e9:
|
||||
s3->accel.subsys_cntl = val;
|
||||
s3->subsys_cntl = val;
|
||||
s3_update_irqs(s3);
|
||||
break;
|
||||
case 0x46e8:
|
||||
s3->accel.setup_md = val;
|
||||
@@ -1143,9 +1216,9 @@ uint8_t s3_accel_in(uint16_t port, void *p)
|
||||
switch (port)
|
||||
{
|
||||
case 0x42e8:
|
||||
return 0;
|
||||
return s3->subsys_stat;
|
||||
case 0x42e9:
|
||||
return 0;
|
||||
return s3->subsys_cntl;
|
||||
|
||||
case 0x82e8:
|
||||
s3_wait_fifo_idle(s3);
|
||||
@@ -1202,7 +1275,7 @@ uint8_t s3_accel_in(uint16_t port, void *p)
|
||||
if (!FIFO_EMPTY)
|
||||
temp |= 0x02; /*Hardware busy*/
|
||||
else
|
||||
temp |= 0x04; /*FIFO empty*/
|
||||
temp |= s3->status_9ae9; /*FIFO empty*/
|
||||
if (FIFO_FULL)
|
||||
temp |= 0xf8; /*FIFO full*/
|
||||
return temp;
|
||||
@@ -1587,6 +1660,15 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
|
||||
s3->accel.dest = s3->accel.cy * s3->width;
|
||||
}
|
||||
|
||||
s3->status_9ae9 = 4; /*To avoid the spam from OS/2's drivers*/
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input)
|
||||
{
|
||||
s3->status_9ae9 = 2; /*To avoid the spam from OS/2's drivers*/
|
||||
return; /*Wait for data from CPU*/
|
||||
}
|
||||
|
||||
if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
|
||||
|
||||
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
|
||||
@@ -2042,6 +2124,9 @@ uint8_t s3_pci_read(int func, int addr, void *p)
|
||||
case 0x31: return 0x00;
|
||||
case 0x32: return s3->pci_regs[0x32];
|
||||
case 0x33: return s3->pci_regs[0x33];
|
||||
|
||||
case 0x3c: return s3->int_line;
|
||||
case 0x3d: return PCI_INTA;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2054,7 +2139,7 @@ void s3_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
switch (addr)
|
||||
{
|
||||
case PCI_REG_COMMAND:
|
||||
s3->pci_regs[PCI_REG_COMMAND] = val & 0x27;
|
||||
s3->pci_regs[PCI_REG_COMMAND] = val & 0x23;
|
||||
if (val & PCI_COMMAND_IO)
|
||||
s3_io_set(s3);
|
||||
else
|
||||
@@ -2083,6 +2168,10 @@ void s3_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
mem_mapping_disable(&s3->bios_rom.mapping);
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x3c:
|
||||
s3->int_line = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2135,6 +2224,8 @@ static void *s3_init(wchar_t *bios_fn, int chip)
|
||||
svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5);
|
||||
svga->crtc[0x37] = 1 | (7 << 5);
|
||||
|
||||
svga->vblank_start = s3_vblank_start;
|
||||
|
||||
svga->crtc[0x53] = 1 << 3;
|
||||
svga->crtc[0x59] = 0x70;
|
||||
|
||||
@@ -2142,9 +2233,9 @@ static void *s3_init(wchar_t *bios_fn, int chip)
|
||||
|
||||
if (PCI)
|
||||
{
|
||||
pci_add(s3_pci_read, s3_pci_write, s3);
|
||||
s3->card = pci_add(s3_pci_read, s3_pci_write, s3);
|
||||
}
|
||||
|
||||
|
||||
s3->pci_regs[0x04] = 3;
|
||||
|
||||
s3->pci_regs[0x30] = 0x00;
|
||||
@@ -2156,6 +2247,8 @@ static void *s3_init(wchar_t *bios_fn, int chip)
|
||||
s3->wake_fifo_thread = thread_create_event();
|
||||
s3->fifo_not_full_event = thread_create_event();
|
||||
s3->fifo_thread = thread_create(fifo_thread, s3);
|
||||
|
||||
s3->int_line = 0;
|
||||
|
||||
return s3;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Emulation of the S3 Trio32, S3 Trio64, and S3 Vision864
|
||||
* graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_s3.h 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
device_t s3_bahamas64_device;
|
||||
device_t s3_9fx_device;
|
||||
device_t s3_phoenix_trio32_device;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "../pci.h"
|
||||
#include "../rom.h"
|
||||
#include "../device.h"
|
||||
#include "../thread.h"
|
||||
#include "../win/plat_thread.h"
|
||||
#include "video.h"
|
||||
#include "vid_s3_virge.h"
|
||||
#include "vid_svga.h"
|
||||
@@ -121,6 +121,7 @@ typedef struct virge_t
|
||||
uint32_t linear_base, linear_size;
|
||||
|
||||
uint8_t pci_regs[256];
|
||||
int card;
|
||||
|
||||
int is_375;
|
||||
|
||||
@@ -228,6 +229,8 @@ typedef struct virge_t
|
||||
event_t *fifo_not_full_event;
|
||||
|
||||
int virge_busy;
|
||||
|
||||
uint8_t subsys_stat, subsys_cntl;
|
||||
} virge_t;
|
||||
|
||||
static __inline void wake_fifo_thread(virge_t *virge)
|
||||
@@ -292,6 +295,26 @@ enum
|
||||
CMD_SET_COMMAND_NOP = (15 << 27)
|
||||
};
|
||||
|
||||
#define INT_VSY (1 << 0)
|
||||
#define INT_S3D_DONE (1 << 1)
|
||||
#define INT_FIFO_OVF (1 << 2)
|
||||
#define INT_FIFO_EMP (1 << 3)
|
||||
#define INT_3DF_EMP (1 << 6)
|
||||
#define INT_MASK 0xff
|
||||
|
||||
static void s3_virge_update_irqs(virge_t *virge)
|
||||
{
|
||||
if (!PCI)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & virge->subsys_cntl & INT_MASK))
|
||||
pci_set_irq(virge->card, PCI_INTA);
|
||||
else
|
||||
pci_clear_irq(virge->card, PCI_INTA);
|
||||
}
|
||||
|
||||
static void s3_virge_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
virge_t *virge = (virge_t *)p;
|
||||
@@ -339,6 +362,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p)
|
||||
case 0x32:
|
||||
if ((svga->crtc[0x67] & 0xc) != 0xc)
|
||||
svga->vrammask = (val & 0x40) ? 0x3ffff : ((virge->memory_size << 20) - 1);
|
||||
s3_virge_update_irqs(virge);
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
@@ -691,6 +715,14 @@ static void s3_virge_updatemapping(virge_t *virge)
|
||||
|
||||
}
|
||||
|
||||
static void s3_virge_vblank_start(svga_t *svga)
|
||||
{
|
||||
virge_t *virge = (virge_t *)svga->p;
|
||||
|
||||
virge->subsys_stat |= INT_VSY;
|
||||
s3_virge_update_irqs(virge);
|
||||
}
|
||||
|
||||
static void s3_virge_wait_fifo_idle(virge_t *virge)
|
||||
{
|
||||
while (!FIFO_EMPTY)
|
||||
@@ -822,6 +854,7 @@ static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p)
|
||||
ret = (0x10 << 8);
|
||||
else
|
||||
ret = (0x10 << 8) | (1 << 13);
|
||||
ret |= virge->subsys_stat;
|
||||
if (!virge->virge_busy)
|
||||
wake_fifo_thread(virge);
|
||||
break;
|
||||
@@ -1441,6 +1474,12 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
|
||||
svga_recalctimings(svga);
|
||||
svga->fullchange = changeframecount;
|
||||
break;
|
||||
|
||||
case 0x8504:
|
||||
virge->subsys_stat &= ~(val & 0xff);
|
||||
virge->subsys_cntl = (val >> 8);
|
||||
s3_virge_update_irqs(virge);
|
||||
break;
|
||||
|
||||
case 0xa000: case 0xa004: case 0xa008: case 0xa00c:
|
||||
case 0xa010: case 0xa014: case 0xa018: case 0xa01c:
|
||||
@@ -3248,6 +3287,8 @@ static void render_thread(void *param)
|
||||
thread_set_event(virge->not_full_event);
|
||||
}
|
||||
virge->s3d_busy = 0;
|
||||
virge->subsys_stat |= INT_S3D_DONE;
|
||||
s3_virge_update_irqs(virge);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3687,9 +3728,9 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
mem_mapping_disable(&virge->bios_rom.mapping);
|
||||
}
|
||||
return;
|
||||
/* case 0x3c:
|
||||
case 0x3c:
|
||||
virge->pci_regs[0x3c] = val;
|
||||
return; */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3707,6 +3748,7 @@ static void *s3_virge_init()
|
||||
s3_virge_in, s3_virge_out,
|
||||
s3_virge_hwcursor_draw,
|
||||
s3_virge_overlay_draw);
|
||||
virge->svga.vblank_start = s3_virge_vblank_start;
|
||||
|
||||
rom_init(&virge->bios_rom, L"roms/s3virge.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
if (PCI)
|
||||
@@ -3774,7 +3816,7 @@ static void *s3_virge_init()
|
||||
|
||||
virge->is_375 = 0;
|
||||
|
||||
pci_add(s3_virge_pci_read, s3_virge_pci_write, virge);
|
||||
virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge);
|
||||
|
||||
virge->wake_render_thread = thread_create_event();
|
||||
virge->wake_main_thread = thread_create_event();
|
||||
@@ -3883,7 +3925,7 @@ static void *s3_virge_988_init()
|
||||
return virge;
|
||||
}
|
||||
|
||||
static void *s3_virge_375_init()
|
||||
static void *s3_virge_375_init(wchar_t *romfn)
|
||||
{
|
||||
virge_t *virge = malloc(sizeof(virge_t));
|
||||
memset(virge, 0, sizeof(virge_t));
|
||||
@@ -3898,7 +3940,7 @@ static void *s3_virge_375_init()
|
||||
s3_virge_hwcursor_draw,
|
||||
s3_virge_overlay_draw);
|
||||
|
||||
rom_init(&virge->bios_rom, L"roms/86c375_1.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
rom_init(&virge->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
if (PCI)
|
||||
mem_mapping_disable(&virge->bios_rom.mapping);
|
||||
|
||||
@@ -3979,6 +4021,16 @@ static void *s3_virge_375_init()
|
||||
return virge;
|
||||
}
|
||||
|
||||
static void *s3_virge_375_1_init()
|
||||
{
|
||||
return s3_virge_375_init(L"roms/86c375_1.bin");
|
||||
}
|
||||
|
||||
static void *s3_virge_375_4_init()
|
||||
{
|
||||
return s3_virge_375_init(L"roms/86c375_4.bin");
|
||||
}
|
||||
|
||||
static void s3_virge_close(void *p)
|
||||
{
|
||||
virge_t *virge = (virge_t *)p;
|
||||
@@ -4012,11 +4064,16 @@ static int s3_virge_988_available()
|
||||
return rom_present(L"roms/diamondstealth3000.VBI");
|
||||
}
|
||||
|
||||
static int s3_virge_375_available()
|
||||
static int s3_virge_375_1_available()
|
||||
{
|
||||
return rom_present(L"roms/86c375_1.bin");
|
||||
}
|
||||
|
||||
static int s3_virge_375_4_available()
|
||||
{
|
||||
return rom_present(L"roms/86c375_4.bin");
|
||||
}
|
||||
|
||||
static void s3_virge_speed_changed(void *p)
|
||||
{
|
||||
virge_t *virge = (virge_t *)p;
|
||||
@@ -4148,9 +4205,22 @@ device_t s3_virge_375_device =
|
||||
{
|
||||
"S3 ViRGE/DX",
|
||||
0,
|
||||
s3_virge_375_init,
|
||||
s3_virge_375_1_init,
|
||||
s3_virge_close,
|
||||
s3_virge_375_available,
|
||||
s3_virge_375_1_available,
|
||||
s3_virge_speed_changed,
|
||||
s3_virge_force_redraw,
|
||||
s3_virge_add_status_info,
|
||||
s3_virge_config
|
||||
};
|
||||
|
||||
device_t s3_virge_375_4_device =
|
||||
{
|
||||
"S3 ViRGE/DX (VBE 2.0)",
|
||||
0,
|
||||
s3_virge_375_4_init,
|
||||
s3_virge_close,
|
||||
s3_virge_375_4_available,
|
||||
s3_virge_speed_changed,
|
||||
s3_virge_force_redraw,
|
||||
s3_virge_add_status_info,
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
extern device_t s3_virge_device;
|
||||
extern device_t s3_virge_988_device;
|
||||
extern device_t s3_virge_375_device;
|
||||
extern device_t s3_virge_375_4_device;
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
/*Generic SVGA handling*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Generic SVGA handling.
|
||||
*
|
||||
* Version: @(#)vid_svga.c 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
/*This is intended to be used by another SVGA driver, and not as a card in it's own right*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -870,8 +884,6 @@ void svga_poll(void *p)
|
||||
if (!svga->override)
|
||||
svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga);
|
||||
|
||||
readflash = 0;
|
||||
|
||||
svga->firstline = 2000;
|
||||
svga->lastline = 0;
|
||||
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Generic SVGA handling.
|
||||
*
|
||||
* Version: @(#)vid_svga.h 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
typedef struct svga_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* SVGA renderers.
|
||||
*
|
||||
* Version: @(#)vid_svga_render.c 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../ibm.h"
|
||||
#include "../mem.h"
|
||||
@@ -43,10 +58,75 @@ int svga_display_line(svga_t *svga)
|
||||
|
||||
void svga_render_blank(svga_t *svga)
|
||||
{
|
||||
#if 0
|
||||
int x, xx;
|
||||
int y_add = (enable_overscan) ? 16 : 0;
|
||||
int x_add = y_add >> 1;
|
||||
int dl = svga_display_line(svga);
|
||||
uint32_t *p;
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
if (dl >= 2046)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (x = 0; x < svga->hdisp; x++)
|
||||
{
|
||||
switch (svga->seqregs[1] & 9)
|
||||
{
|
||||
case 0:
|
||||
for (xx = 0; xx < 9; xx++)
|
||||
{
|
||||
p = ((uint32_t *)buffer32->line[dl]);
|
||||
if (&(p[(x * 9) + xx + 32 + x_add]) != NULL)
|
||||
{
|
||||
p[(x * 9) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
{
|
||||
p = ((uint32_t *)buffer32->line[dl]);
|
||||
if (&(p[(x * 8) + xx + 32 + x_add]) != NULL)
|
||||
{
|
||||
p[(x * 8) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 8:
|
||||
for (xx = 0; xx < 18; xx++)
|
||||
{
|
||||
p = ((uint32_t *)buffer32->line[dl]);
|
||||
if (&(p[(x * 18) + xx + 32 + x_add]) != NULL)
|
||||
{
|
||||
p[(x * 18) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 9:
|
||||
for (xx = 0; xx < 16; xx++)
|
||||
{
|
||||
p = ((uint32_t *)buffer32->line[dl]);
|
||||
if (&(p[(x * 16) + xx + 32 + x_add]) != NULL)
|
||||
{
|
||||
p[(x * 16) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
int x, xx;
|
||||
int y_add = (enable_overscan) ? 16 : 0;
|
||||
int x_add = y_add >> 1;
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
@@ -57,16 +137,16 @@ void svga_render_blank(svga_t *svga)
|
||||
switch (svga->seqregs[1] & 9)
|
||||
{
|
||||
case 0:
|
||||
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[dl])[(x * 9) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 9) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
break;
|
||||
case 1:
|
||||
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[(x * 8) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 8) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
break;
|
||||
case 8:
|
||||
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[dl])[(x * 18) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 18) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
break;
|
||||
case 9:
|
||||
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[dl])[(x * 16) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 16) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* SVGA renderers.
|
||||
*
|
||||
* Version: @(#)vid_svga_render.h 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
extern int firstline_draw, lastline_draw;
|
||||
extern int displine;
|
||||
extern int sc;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "../pci.h"
|
||||
#include "../rom.h"
|
||||
#include "../device.h"
|
||||
#include "../thread.h"
|
||||
#include "../win/plat_thread.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_svga_render.h"
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../pci.h"
|
||||
#include "../thread.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "../win/plat_thread.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_voodoo.h"
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#include "../rom.h"
|
||||
#include "../config.h"
|
||||
#include "../device.h"
|
||||
#include "../thread.h"
|
||||
#include "../timer.h"
|
||||
#include "../win/plat_thread.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#ifndef __unix
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "vid_wy700.h"
|
||||
|
||||
|
||||
int vid_cga_contrast = 0;
|
||||
int cga_palette = 0;
|
||||
|
||||
typedef struct
|
||||
@@ -104,6 +105,7 @@ static VIDEO_CARD video_cards[] =
|
||||
{"Phoenix S3 Trio64", "px_trio64", &s3_phoenix_trio64_device, GFX_PHOENIX_TRIO64},
|
||||
{"Plantronics ColorPlus", "plantronics", &colorplus_device, GFX_COLORPLUS},
|
||||
{"S3 ViRGE/DX", "virge375", &s3_virge_375_device, GFX_VIRGEDX},
|
||||
{"S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20", &s3_virge_375_4_device, GFX_VIRGEDX4},
|
||||
{"Trident TGUI9440", "tgui9440", &tgui9440_device, GFX_TGUI9440},
|
||||
{"Trident TVGA8900D", "tvga8900d", &tvga8900d_device, GFX_TVGA},
|
||||
{"Tseng ET4000AX", "et4000ax", &et4000_device, GFX_ET4000},
|
||||
@@ -203,8 +205,8 @@ uint8_t edatlookup[4][4];
|
||||
|
||||
int enable_overscan;
|
||||
int overscan_x, overscan_y;
|
||||
|
||||
int force_43;
|
||||
int enable_flash;
|
||||
|
||||
/*Video timing settings -
|
||||
|
||||
|
||||
@@ -81,10 +81,9 @@ extern void (*video_blit_memtoscreen_8_func)(int x, int y, int w, int h);
|
||||
/* Enable EGA/(S)VGA overscan border. */
|
||||
extern int enable_overscan;
|
||||
extern int overscan_x, overscan_y;
|
||||
|
||||
/* Forcibly stretch emulated video output to 4:3 or not. */
|
||||
extern int force_43;
|
||||
/* Enable disk activity flash. */
|
||||
extern int enable_flash;
|
||||
|
||||
extern int video_timing_b, video_timing_w, video_timing_l;
|
||||
extern int video_speed;
|
||||
@@ -112,6 +111,7 @@ void ddraw_fs_take_screenshot(wchar_t *fn);
|
||||
#endif
|
||||
|
||||
extern int cga_palette;
|
||||
extern int vid_cga_contrast;
|
||||
|
||||
void loadfont(wchar_t *s, int format);
|
||||
void initvideo();
|
||||
|
||||
Reference in New Issue
Block a user