Merge pull request #1456 from 86Box/tc1995

Port of the reworked svga memory addressing, normal chain4 mapping an…
This commit is contained in:
Miran Grča
2021-05-30 05:59:50 +02:00
committed by GitHub
13 changed files with 1254 additions and 821 deletions

View File

@@ -146,6 +146,16 @@ typedef struct svga_t
/*Used to implement CRTC[0x17] bit 2 hsync divisor*/
int hsync_divisor;
/*Tseng-style chain4 mode - CRTC dword mode is the same as byte mode, chain4
addresses are shifted to match*/
int packed_chain4;
/*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/
int force_dword_mode;
int remap_required;
uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr);
void *ramdac, *clock_gen;
} svga_t;

View File

@@ -27,6 +27,8 @@ extern int scrollcache;
extern uint8_t edatlookup[4][4];
void svga_recalc_remap_func(svga_t *svga);
void svga_render_null(svga_t *svga);
void svga_render_blank(svga_t *svga);
void svga_render_overscan_left(svga_t *svga);
@@ -37,6 +39,7 @@ void svga_render_text_80_ksc5601(svga_t *svga);
void svga_render_2bpp_lowres(svga_t *svga);
void svga_render_2bpp_highres(svga_t *svga);
void svga_render_2bpp_headland_highres(svga_t *svga);
void svga_render_4bpp_lowres(svga_t *svga);
void svga_render_4bpp_highres(svga_t *svga);
void svga_render_8bpp_lowres(svga_t *svga);

View File

@@ -0,0 +1,126 @@
/*Variables :
byte/word/doubleword mode
word has MA13/MA15->MA0
ET4000 treats doubleword as byte
row 0 -> MA13
row 1 -> MA14
*/
//S3 - enhanced mode mappings CR31.3 can force doubleword mode
//Cirrus Logic handles SVGA writes seperately
//S3, CL, TGUI blitters need checking
//CL, S3, Mach64, ET4000, Banshee, TGUI all okay
//Still to check - ViRGE, HT216
#define VAR_BYTE_MODE (0 << 0)
#define VAR_WORD_MODE_MA13 (1 << 0)
#define VAR_WORD_MODE_MA15 (2 << 0)
#define VAR_DWORD_MODE (3 << 0)
#define VAR_MODE_MASK (3 << 0)
#define VAR_ROW0_MA13 (1 << 2)
#define VAR_ROW1_MA14 (1 << 3)
#define ADDRESS_REMAP_FUNC(nr) \
static uint32_t address_remap_func_ ## nr(svga_t *svga, uint32_t in_addr) \
{ \
uint32_t out_addr; \
\
switch (nr & VAR_MODE_MASK) \
{ \
case VAR_BYTE_MODE: \
out_addr = in_addr; \
break; \
\
case VAR_WORD_MODE_MA13: \
out_addr = ((in_addr << 1) & 0x1fff8) | \
((in_addr >> 13) & 0x4) | \
(in_addr & ~0x1ffff); \
break; \
\
case VAR_WORD_MODE_MA15: \
out_addr = ((in_addr << 1) & 0x1fff8) | \
((in_addr >> 15) & 0x4) | \
(in_addr & ~0x1ffff); \
break; \
\
case VAR_DWORD_MODE: \
out_addr = ((in_addr << 2) & 0x3fff0) | \
((in_addr >> 14) & 0xc) | \
(in_addr & ~0x3ffff); \
break; \
} \
\
if (nr & VAR_ROW0_MA13) \
out_addr = (out_addr & ~0x8000) | \
((svga->sc & 1) ? 0x8000 : 0); \
if (nr & VAR_ROW1_MA14) \
out_addr = (out_addr & ~0x10000) | \
((svga->sc & 2) ? 0x10000 : 0); \
\
return out_addr; \
}
ADDRESS_REMAP_FUNC(0)
ADDRESS_REMAP_FUNC(1)
ADDRESS_REMAP_FUNC(2)
ADDRESS_REMAP_FUNC(3)
ADDRESS_REMAP_FUNC(4)
ADDRESS_REMAP_FUNC(5)
ADDRESS_REMAP_FUNC(6)
ADDRESS_REMAP_FUNC(7)
ADDRESS_REMAP_FUNC(8)
ADDRESS_REMAP_FUNC(9)
ADDRESS_REMAP_FUNC(10)
ADDRESS_REMAP_FUNC(11)
ADDRESS_REMAP_FUNC(12)
ADDRESS_REMAP_FUNC(13)
ADDRESS_REMAP_FUNC(14)
ADDRESS_REMAP_FUNC(15)
static uint32_t (*address_remap_funcs[16])(svga_t *svga, uint32_t in_addr) =
{
address_remap_func_0,
address_remap_func_1,
address_remap_func_2,
address_remap_func_3,
address_remap_func_4,
address_remap_func_5,
address_remap_func_6,
address_remap_func_7,
address_remap_func_8,
address_remap_func_9,
address_remap_func_10,
address_remap_func_11,
address_remap_func_12,
address_remap_func_13,
address_remap_func_14,
address_remap_func_15
};
void svga_recalc_remap_func(svga_t *svga)
{
int func_nr;
if (svga->fb_only)
func_nr = 0;
else {
if (svga->force_dword_mode)
func_nr = VAR_DWORD_MODE;
else if (svga->crtc[0x14] & 0x40)
func_nr = svga->packed_chain4 ? VAR_BYTE_MODE : VAR_DWORD_MODE;
else if (svga->crtc[0x17] & 0x40)
func_nr = VAR_BYTE_MODE;
else if (svga->crtc[0x17] & 0x20)
func_nr = VAR_WORD_MODE_MA15;
else
func_nr = VAR_WORD_MODE_MA13;
if (!(svga->crtc[0x17] & 0x01))
func_nr |= VAR_ROW0_MA13;
if (!(svga->crtc[0x17] & 0x02))
func_nr |= VAR_ROW1_MA14;
}
svga->remap_required = (func_nr != 0);
svga->remap_func = address_remap_funcs[func_nr];
}

View File

@@ -47,6 +47,7 @@
#define BIOS_GD5422_PATH "roms/video/cirruslogic/cl5422.bin"
#define BIOS_GD5426_PATH "roms/video/cirruslogic/Diamond SpeedStar PRO VLB v3.04.bin"
#define BIOS_GD5428_ISA_PATH "roms/video/cirruslogic/5428.bin"
#define BIOS_GD5428_MCA_PATH "roms/video/cirruslogic/SVGA141.ROM"
#define BIOS_GD5428_PATH "roms/video/cirruslogic/vlbusjapan.BIN"
#define BIOS_GD5429_PATH "roms/video/cirruslogic/5429.vbi"
#define BIOS_GD5430_VLB_PATH "roms/video/cirruslogic/diamondvlbus.bin"
@@ -214,7 +215,6 @@ typedef struct gd54xx_t
int card;
uint8_t pos_regs[8];
svga_t *mb_vga;
uint32_t lfb_base, vgablt_base;
@@ -691,7 +691,8 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
}
}
svga->attrff ^= 1;
return;
return;
case 0x3c4:
svga->seqaddr = val;
break;
@@ -761,6 +762,8 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((val & 0x3f) * 256));
break;
case 0x07:
svga->packed_chain4 = svga->seqregs[7] & 1;
svga_recalctimings(svga);
if (gd54xx_is_5422(svga))
gd543x_recalc_mapping(gd54xx);
else
@@ -878,7 +881,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
}
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) &&
!svga->gdcreg[1]) && svga->chain4;
!svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only);
if (((svga->gdcaddr == 5) && ((val ^ o) & 0x70)) ||
((svga->gdcaddr == 6) && ((val ^ o) & 1)))
svga_recalctimings(svga);
@@ -1018,6 +1021,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
}
}
return;
case 0x3d4:
svga->crtcreg = val & gd54xx->crtcreg_mask;
return;
@@ -1595,8 +1599,11 @@ gd54xx_recalctimings(svga_t *svga)
if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) {
if (linedbl)
svga->render = svga_render_8bpp_lowres;
else
else {
svga->render = svga_render_8bpp_highres;
if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga))
svga->hdisp <<= 1;
}
} else if (svga->gdcreg[5] & 0x40)
svga->render = svga_render_8bpp_lowres;
@@ -1642,8 +1649,9 @@ gd54xx_recalctimings(svga_t *svga)
svga->render = svga_render_32bpp_lowres;
else
svga->render = svga_render_32bpp_highres;
if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436)
if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436) {
svga->rowoffset *= 2;
}
} else {
svga->bpp = 24;
if (linedbl)
@@ -3686,9 +3694,9 @@ cl_pci_write(int func, int addr, uint8_t val, void *p)
static uint8_t
gd5428_mca_read(int port, void *p)
{
gd54xx_t *gd54xx = (gd54xx_t *)p;
return gd54xx->pos_regs[port & 7];
gd54xx_t *gd54xx = (gd54xx_t *)p;
return gd54xx->pos_regs[port & 7];
}
static void
@@ -3698,17 +3706,15 @@ gd5428_mca_write(int port, uint8_t val, void *p)
if (port < 0x102)
return;
gd54xx->pos_regs[port & 7] = val;
gd54xx->pos_regs[port & 7] = val;
gd543x_recalc_mapping(gd54xx);
}
static uint8_t
gd5428_mca_feedb(void *p)
{
gd54xx_t *gd54xx = (gd54xx_t *)p;
return gd54xx->pos_regs[2] & 1;
return 1;
}
static void
@@ -3761,6 +3767,8 @@ static void
case CIRRUS_ID_CLGD5428:
if (gd54xx->vlb)
romfn = BIOS_GD5428_PATH;
else if (gd54xx->mca)
romfn = BIOS_GD5428_MCA_PATH;
else
romfn = BIOS_GD5428_ISA_PATH;
break;
@@ -3953,7 +3961,8 @@ static void
if (gd54xx->mca) {
gd54xx->pos_regs[0] = 0x7b;
gd54xx->pos_regs[1] = 0x91;
mca_add(gd5428_mca_read, gd5428_mca_write, gd5428_mca_feedb, NULL, gd54xx);
mca_add(gd5428_mca_read, gd5428_mca_write, gd5428_mca_feedb, NULL, gd54xx);
io_sethandler(0x46e8, 0x0001, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx);
}
if (gd54xx_is_5434(svga)) {
@@ -4013,6 +4022,12 @@ gd5428_isa_available(void)
return rom_present(BIOS_GD5428_ISA_PATH);
}
static int
gd5428_mca_available(void)
{
return rom_present(BIOS_GD5428_MCA_PATH);
}
static int
gd5429_available(void)
{
@@ -4369,7 +4384,7 @@ const device_t gd5428_mca_device =
gd54xx_init,
gd54xx_close,
NULL,
{ gd5428_available },
{ gd5428_mca_available },
gd54xx_speed_changed,
gd54xx_force_redraw,
NULL

View File

@@ -742,6 +742,8 @@ et4000_init(const device_t *info)
dev->svga.translate_address = get_et4000_addr;
dev->svga.packed_chain4 = 1;
return(dev);
}

View File

@@ -46,16 +46,6 @@
#define BIOS_ROM_PATH_W32P "roms/video/et4000w32/ET4K_W32.BIN"
#define BIOS_ROM_PATH_W32P_REVC "roms/video/et4000w32/et4000w32pcardex.BIN"
#define FIFO_SIZE 65536
#define FIFO_MASK (FIFO_SIZE - 1)
#define FIFO_ENTRY_SIZE (1 << 31)
#define FIFO_ENTRIES (et4000->fifo_write_idx - et4000->fifo_read_idx)
#define FIFO_FULL ((et4000->fifo_write_idx - et4000->fifo_read_idx) >= (FIFO_SIZE-1))
#define FIFO_EMPTY (et4000->fifo_read_idx == et4000->fifo_write_idx)
#define FIFO_TYPE 0xff000000
#define FIFO_ADDR 0x00ffffff
#define ACL_WRST 1
#define ACL_RDST 2
@@ -73,20 +63,6 @@ enum
ET4000W32P_DIAMOND
};
enum
{
FIFO_INVALID = (0x00 << 24),
FIFO_WRITE_BYTE = (0x01 << 24),
FIFO_WRITE_MMU = (0x02 << 24)
};
typedef struct
{
uint32_t addr_type;
uint32_t val;
} fifo_entry_t;
typedef struct et4000w32p_t
{
@@ -138,15 +114,6 @@ typedef struct et4000w32p_t
uint32_t base[3];
uint8_t ctrl;
} mmu;
fifo_entry_t fifo[FIFO_SIZE];
volatile int fifo_read_idx, fifo_write_idx;
thread_t * fifo_thread;
event_t * wake_fifo_thread;
event_t * fifo_not_full_event;
uint64_t blitter_time, status_time;
} et4000w32p_t;
@@ -198,7 +165,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p)
et4000w32p_t *et4000 = (et4000w32p_t *)p;
svga_t *svga = &et4000->svga;
uint8_t old;
uint32_t add2addr;
uint32_t add2addr = 0;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
@@ -287,18 +254,30 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p)
case 0x210b: case 0x211b: case 0x212b: case 0x213b:
case 0x214b: case 0x215b: case 0x216b: case 0x217b:
et4000->regs[et4000->index] = val;
svga->hwcursor.xsize = svga->hwcursor.ysize = (et4000->regs[0xEF] & 4) ? 128 : 64;
svga->hwcursor.xsize = svga->hwcursor.ysize = ((et4000->regs[0xEF] & 4) || (et4000->type == ET4000W32)) ? 128 : 64;
svga->hwcursor.x = et4000->regs[0xE0] | ((et4000->regs[0xE1] & 7) << 8);
svga->hwcursor.y = et4000->regs[0xE4] | ((et4000->regs[0xE5] & 7) << 8);
svga->hwcursor.ena = !!(et4000->regs[0xF7] & 0x80);
svga->hwcursor.xoff = et4000->regs[0xE2];
svga->hwcursor.yoff = et4000->regs[0xE6];
if (et4000->type == ET4000W32) {
switch (svga->bpp) {
case 8:
svga->hwcursor.xoff += 32;
break;
}
}
if (svga->hwcursor.xsize == 128) {
svga->hwcursor.xoff = et4000->regs[0xE2] & 0x7f;
svga->hwcursor.yoff = et4000->regs[0xE6] & 0x7f;
svga->hwcursor.xoff &= 0x7f;
svga->hwcursor.yoff &= 0x7f;
} else {
svga->hwcursor.xoff = et4000->regs[0xE2] & 0x3f;
svga->hwcursor.yoff = et4000->regs[0xE6] & 0x3f;
svga->hwcursor.xoff &= 0x3f;
svga->hwcursor.yoff &= 0x3f;
}
svga->hwcursor.addr = (et4000->regs[0xe8] | (et4000->regs[0xe9] << 8) | ((et4000->regs[0xea] & 7) << 16)) << 2;
add2addr = svga->hwcursor.yoff * ((svga->hwcursor.xsize == 128) ? 32 : 16);
svga->hwcursor.addr += add2addr;
return;
@@ -385,28 +364,42 @@ et4000w32p_recalctimings(svga_t *svga)
svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen);
if (svga->adv_flags & FLAG_NOSKEW) {
/* On the Cardex ET4000/W32p-based cards, adjust text mode clocks by 1. */
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */
svga->ma_latch--;
/* On the Cardex ET4000/W32p-based cards, adjust text mode clocks by 1. */
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */
svga->ma_latch--;
if ((svga->seqregs[1] & 8)) /*40 column*/
svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18;
else
svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9;
} else {
/* Also adjust the graphics mode clocks in some cases. */
if ((svga->gdcreg[5] & 0x40) && (svga->bpp != 32)) {
if ((svga->bpp == 15) || (svga->bpp == 16) || (svga->bpp == 24))
if ((svga->seqregs[1] & 8)) /*40 column*/
svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18;
else
svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9;
} else {
/* Also adjust the graphics mode clocks in some cases. */
if ((svga->gdcreg[5] & 0x40) && (svga->bpp != 32)) {
if ((svga->bpp == 15) || (svga->bpp == 16) || (svga->bpp == 24))
svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18;
else
svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9;
}
}
}
}
et4000->adjust_cursor = 0;
if (et4000->type == ET4000W32) {
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
if (svga->gdcreg[5] & 0x40) {
switch (svga->bpp) {
case 8:
if (svga->hdisp == 640 || svga->hdisp == 800 || svga->hdisp == 1024)
break;
svga->hdisp -= 24;
break;
}
}
}
}
switch (svga->bpp) {
et4000->adjust_cursor = 0;
switch (svga->bpp) {
case 15: case 16:
svga->hdisp >>= 1;
if (et4000->type <= ET4000W32P_REVC)
@@ -417,7 +410,7 @@ et4000w32p_recalctimings(svga_t *svga)
if (et4000->type <= ET4000W32P_REVC)
et4000->adjust_cursor = 2;
break;
}
}
svga->render = svga_render_blank;
if (!svga->scrblank && svga->attr_palette_enable) {
@@ -655,7 +648,7 @@ et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val)
if (!(et4000->acl.internal.ctrl_routing & 0x37))
et4000w32p_blit(0xFFFFFF, ~0, 0, 0, et4000);
et4000->acl.cpu_input_num = 0;
}
}
if (et4000->acl.internal.ctrl_routing & 7) {
et4000->acl.cpu_input = (et4000->acl.cpu_input &~ (0xFF << (et4000->acl.cpu_input_num << 3))) |
@@ -679,86 +672,6 @@ et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val)
}
static void
fifo_thread(void *param)
{
et4000w32p_t *et4000 = (et4000w32p_t *)param;
uint64_t start_time = 0;
uint64_t end_time = 0;
fifo_entry_t *fifo;
while (1) {
thread_set_event(et4000->fifo_not_full_event);
thread_wait_event(et4000->wake_fifo_thread, -1);
thread_reset_event(et4000->wake_fifo_thread);
et4000->blitter_busy = 1;
while (!FIFO_EMPTY) {
start_time = plat_timer_read();
fifo = &et4000->fifo[et4000->fifo_read_idx & FIFO_MASK];
switch (fifo->addr_type & FIFO_TYPE) {
case FIFO_WRITE_BYTE:
et4000w32p_accel_write_fifo(et4000, fifo->addr_type & FIFO_ADDR, fifo->val);
break;
case FIFO_WRITE_MMU:
et4000w32p_accel_write_mmu(et4000, fifo->addr_type & FIFO_ADDR, fifo->val);
break;
}
et4000->fifo_read_idx++;
fifo->addr_type = FIFO_INVALID;
if (FIFO_ENTRIES > 0xe000)
thread_set_event(et4000->fifo_not_full_event);
end_time = plat_timer_read();
et4000->blitter_time += end_time - start_time;
}
et4000->blitter_busy = 0;
}
}
static __inline void
wake_fifo_thread(et4000w32p_t *et4000)
{
thread_set_event(et4000->wake_fifo_thread); /* Wake up FIFO thread if moving from idle */
}
static void
et4000w32p_wait_fifo_idle(et4000w32p_t *et4000)
{
while (!FIFO_EMPTY) {
wake_fifo_thread(et4000);
thread_wait_event(et4000->fifo_not_full_event, 1);
}
}
static void
et4000w32p_queue(et4000w32p_t *et4000, uint32_t addr, uint32_t val, uint32_t type)
{
fifo_entry_t *fifo = &et4000->fifo[et4000->fifo_write_idx & FIFO_MASK];
if (FIFO_FULL) {
thread_reset_event(et4000->fifo_not_full_event);
if (FIFO_FULL)
thread_wait_event(et4000->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/
}
fifo->val = val;
fifo->addr_type = (addr & FIFO_ADDR) | type;
et4000->fifo_write_idx++;
if ((FIFO_ENTRIES > 0xe000) || (FIFO_ENTRIES < 8))
wake_fifo_thread(et4000);
}
void
et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p)
{
@@ -771,10 +684,7 @@ et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p)
case 0x4000: /* MMU 2 */
et4000->bank = (addr >> 13) & 3;
if (et4000->mmu.ctrl & (1 << et4000->bank)) {
if (et4000->type >= ET4000W32P_REVC)
et4000w32p_queue(et4000, addr & 0x7fff, val, FIFO_WRITE_MMU);
else
et4000w32p_accel_write_mmu(et4000, addr & 0x7fff, val);
et4000w32p_accel_write_mmu(et4000, addr & 0x7fff, val);
} else {
if (((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) < svga->vram_max) {
svga->vram[(addr & 0x1fff) + et4000->mmu.base[et4000->bank]] = val;
@@ -784,10 +694,7 @@ et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p)
break;
case 0x6000:
if ((addr & 0x7fff) >= 0x7f80) {
if (et4000->type >= ET4000W32P_REVC)
et4000w32p_queue(et4000, addr & 0x7fff, val, FIFO_WRITE_BYTE);
else
et4000w32p_accel_write_fifo(et4000, addr & 0x7fff, val);
et4000w32p_accel_write_fifo(et4000, addr & 0x7fff, val);
} else switch (addr & 0x7fff) {
case 0x7f00: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xFFFFFF00) | val; break;
case 0x7f01: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xFFFF00FF) | (val << 8); break;
@@ -822,9 +729,6 @@ et4000w32p_mmu_read(uint32_t addr, void *p)
case 0x4000: /* MMU 2 */
bank = (addr >> 13) & 3;
if (et4000->mmu.ctrl & (1 << bank)) {
if (et4000->type >= ET4000W32P_REVC)
et4000w32p_wait_fifo_idle(et4000);
temp = 0xff;
if (et4000->acl.cpu_dat_pos) {
et4000->acl.cpu_dat_pos--;
@@ -844,10 +748,6 @@ et4000w32p_mmu_read(uint32_t addr, void *p)
return svga->vram[(addr&0x1fff) + et4000->mmu.base[bank]];
case 0x6000:
if ((addr & 0x7fff) >= 0x7f80) {
if (et4000->type >= ET4000W32P_REVC)
et4000w32p_wait_fifo_idle(et4000);
}
switch (addr & 0x7fff) {
case 0x7f00: return et4000->mmu.base[0];
case 0x7f01: return et4000->mmu.base[0] >> 8;
@@ -867,10 +767,6 @@ et4000w32p_mmu_read(uint32_t addr, void *p)
if (et4000->type >= ET4000W32P_REVC) {
temp = et4000->acl.status;
temp &= ~(ACL_RDST | ACL_WRST);
if (!FIFO_EMPTY)
temp |= ACL_RDST;
if (FIFO_FULL)
temp |= ACL_WRST;
if (temp == ACL_XYST && (et4000->acl.internal.ctrl_routing == 1 || et4000->acl.internal.ctrl_routing == 2))
temp |= ACL_RDST;
} else {
@@ -1280,13 +1176,29 @@ et4000w32p_hwcursor_draw(svga_t *svga, int displine)
int shift = (et4000->adjust_cursor + 1);
int width = (svga->hwcursor_latch.xsize - svga->hwcursor_latch.xoff);
int pitch = (svga->hwcursor_latch.xsize == 128) ? 32 : 16;
int x_acc = 4;
int minus_width = 0;
uint8_t dat;
offset = svga->hwcursor_latch.xoff;
if (et4000->type == ET4000W32) {
switch (svga->bpp) {
case 8:
minus_width = 0;
x_acc = 2;
break;
case 15: case 16:
minus_width = 64;
x_acc = 2;
break;
}
}
for (x = 0; x < width; x += 4) {
for (x = 0; x < (width - minus_width); x += x_acc) {
dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)];
xx = svga->hwcursor_latch.x + svga->x_add + x;
if (!(xx % shift)) {
xx2 = xx / shift;
if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0;
@@ -1318,7 +1230,7 @@ et4000w32p_hwcursor_draw(svga_t *svga, int displine)
offset += 4;
}
svga->hwcursor_latch.addr += pitch;
svga->hwcursor_latch.addr += pitch;
}
@@ -1375,10 +1287,10 @@ et4000w32p_pci_read(int func, int addr, void *p)
case 0x07: return 1 << 1; /* Medium DEVSEL timing */
case 0x08: return 0x06; /* Revision ID */
case 0x08: return (et4000->rev); /* Revision ID */
case 0x09: return 0; /* Programming interface */
case 0x0a: return 0x00; /* Supports VGA interface, XGA compatible */
case 0x0a: return 0x00; /* Supports VGA interface */
case 0x0b: return 0x03; /* This has to be done in order to make this card work with the two 486 PCI machines. */
case 0x10: return 0x00; /* Linear frame buffer address */
@@ -1450,8 +1362,17 @@ et4000w32p_init(const device_t *info)
et4000w32p_t *et4000 = malloc(sizeof(et4000w32p_t));
memset(et4000, 0, sizeof(et4000w32p_t));
vram_size = device_get_config_int("memory");
et4000->interleaved = (vram_size == 2 && (info->local >= ET4000W32I)) ? 1 : 0;
et4000->pci = (info->flags & DEVICE_PCI) ? 0x80 : 0x00;
et4000->vlb = (info->flags & DEVICE_VLB) ? 0x40 : 0x00;
/*The ET4000/W32i ISA BIOS seems to not support 2MB of VRAM*/
if ((info->local == ET4000W32) || ((info->local == ET4000W32I) && !(et4000->vlb)))
vram_size = 1;
else
vram_size = device_get_config_int("memory");
/*The interleaved VRAM was introduced by the ET4000/W32i*/
et4000->interleaved = ((vram_size == 2) && (info->local != ET4000W32)) ? 1 : 0;
if (info->flags & DEVICE_PCI)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_pci);
@@ -1467,22 +1388,22 @@ et4000w32p_init(const device_t *info)
NULL);
et4000->vram_mask = (vram_size << 20) - 1;
et4000->svga.decode_mask = (vram_size << 20) - 1;
et4000->type = info->local;
et4000->pci = (info->flags & DEVICE_PCI) ? 0x80 : 0x00;
et4000->vlb = (info->flags & DEVICE_VLB) ? 0x40 : 0x00;
switch(et4000->type) {
case ET4000W32:
/* ET4000/W32 */
et4000->rev = 0;
rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32, 0xc0000, 0x8000, 0x7fff, 0,
MEM_MAPPING_EXTERNAL);
et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device);
et4000->svga.clock_gen = et4000->svga.ramdac;
et4000->svga.getclock = sdac_getclock;
break;
break;
case ET4000W32I:
/* ET4000/W32i rev B */
@@ -1577,12 +1498,7 @@ et4000w32p_init(const device_t *info)
et4000->pci_regs[0x32] = 0x00;
et4000->pci_regs[0x33] = 0xf0;
if (et4000->type >= ET4000W32P_REVC) {
et4000w32_log("Thread started\n");
et4000->wake_fifo_thread = thread_create_event();
et4000->fifo_not_full_event = thread_create_event();
et4000->fifo_thread = thread_create(fifo_thread, et4000);
}
et4000->svga.packed_chain4 = 1;
return et4000;
}
@@ -1644,12 +1560,6 @@ et4000w32p_close(void *p)
svga_close(&et4000->svga);
if (et4000->type >= ET4000W32P_REVC) {
thread_kill(et4000->fifo_thread);
thread_destroy_event(et4000->wake_fifo_thread);
thread_destroy_event(et4000->fifo_not_full_event);
}
free(et4000);
}
@@ -1702,7 +1612,7 @@ const device_t et4000w32_device =
{ et4000w32_available },
et4000w32p_speed_changed,
et4000w32p_force_redraw,
et4000w32p_config
NULL
};
const device_t et4000w32_onboard_device =
@@ -1713,7 +1623,7 @@ const device_t et4000w32_onboard_device =
{ et4000w32_available },
et4000w32p_speed_changed,
et4000w32p_force_redraw,
et4000w32p_config
NULL
};
const device_t et4000w32i_isa_device =
@@ -1724,7 +1634,7 @@ const device_t et4000w32i_isa_device =
{ et4000w32i_isa_available },
et4000w32p_speed_changed,
et4000w32p_force_redraw,
et4000w32p_config
NULL
};
const device_t et4000w32i_vlb_device =

View File

@@ -127,10 +127,20 @@ ht216_log(const char *fmt, ...)
#define ht216_log(fmt, ...)
#endif
/*Remap address for chain-4/doubleword style layout*/
static __inline uint32_t
dword_remap(svga_t *svga, uint32_t in_addr)
{
if (svga->packed_chain4)
return in_addr;
return ((in_addr & 0xfffc) << 2) | ((in_addr & 0x30000) >> 14) | (in_addr & ~0x3ffff);
}
static void
ht216_recalc_bank_regs(ht216_t *ht216, int mode)
{
svga_t *svga = &ht216->svga;
if (mode) {
ht216->read_bank_reg[0] = ht216->ht_regs[0xe8];
ht216->write_bank_reg[0] = ht216->ht_regs[0xe8];
@@ -142,14 +152,14 @@ ht216_recalc_bank_regs(ht216_t *ht216, int mode)
ht216->write_bank_reg[0] = ((ht216->ht_regs[0xf6] & 0x3) << 6);
ht216->write_bank_reg[1] = ((ht216->ht_regs[0xf6] & 0x3) << 6);
if ((ht216->ht_regs[0xfc] & 0x20) || (ht216->ht_regs[0xfc] & 0x04)) {
if (svga->packed_chain4 || (ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE)) {
ht216->read_bank_reg[0] |= (ht216->misc & 0x20);
ht216->read_bank_reg[1] |= (ht216->misc & 0x20);
ht216->write_bank_reg[0] |= (ht216->misc & 0x20);
ht216->write_bank_reg[1] |= (ht216->misc & 0x20);
}
if ((ht216->ht_regs[0xfc] & 0x20) || ((ht216->ht_regs[0xfc] & 0x06) == 0x04)) {
if (svga->packed_chain4 || ((ht216->ht_regs[0xfc] & 0x06) == 0x04)) {
ht216->read_bank_reg[0] |= ((ht216->ht_regs[0xf9] & 1) << 4);
ht216->read_bank_reg[1] |= ((ht216->ht_regs[0xf9] & 1) << 4);
ht216->write_bank_reg[0] |= ((ht216->ht_regs[0xf9] & 1) << 4);
@@ -355,7 +365,8 @@ ht216_out(uint16_t addr, uint8_t val, void *p)
break;
case 0xfc:
ht216_log("HT216 reg 0xfc write = %02x, mode = 0, chain4 = %x, bit 7 = %02x\n", val, svga->chain4, val & 0x80);
ht216_log("HT216 reg 0xfc write = %02x, mode = 0, chain4 = %x, bit 7 = %02x, packedchain = %02x\n", val, svga->chain4, val & 0x80, val & 0x20);
svga->packed_chain4 = !!(val & 0x20);
ht216_recalc_bank_regs(ht216, 0);
ht216_remap(ht216);
svga->fullchange = changeframecount;
@@ -383,6 +394,11 @@ ht216_out(uint16_t addr, uint8_t val, void *p)
else
svga->banked_mask = 0xffff;
}
if (svga->gdcaddr <= 8) {
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) &&
!svga->gdcreg[1]) && svga->chain4 && svga->packed_chain4;
}
break;
case 0x3D4:
@@ -559,82 +575,6 @@ ht216_remap(ht216_t *ht216)
}
void
ht216_1_2bpp_highres(svga_t *svga)
{
int changed_offset, x;
int oddeven;
uint32_t addr, *p;
uint8_t edat[4];
uint8_t dat;
if ((svga->displine + svga->y_add) < 0)
return;
changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) {
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
addr = svga->ma;
oddeven = 0;
if (!(svga->crtc[0x17] & 0x40)) {
addr = (addr << 1) & svga->vram_mask;
if (svga->seqregs[1] & 4)
oddeven = (addr & 4) ? 1 : 0;
addr &= ~7;
if ((svga->crtc[0x17] & 0x20) && (svga->ma & 0x20000))
addr |= 4;
if (!(svga->crtc[0x17] & 0x20) && (svga->ma & 0x8000))
addr |= 4;
}
if (!(svga->crtc[0x17] & 0x01))
addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0);
if (!(svga->crtc[0x17] & 0x02))
addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0);
if (svga->seqregs[1] & 4) {
edat[0] = svga->vram[addr | oddeven];
edat[2] = svga->vram[addr | oddeven | 0x2];
edat[1] = edat[3] = 0;
} else {
*(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]);
}
svga->ma += 4;
svga->ma &= svga->vram_mask;
if (svga->crtc[0x17] & 0x80) {
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
} else
memset(p, 0x00, 8 * sizeof(uint32_t));
p += 8;
}
}
}
void
ht216_recalctimings(svga_t *svga)
{
@@ -674,7 +614,7 @@ ht216_recalctimings(svga_t *svga)
if (svga->crtc[0x17] == 0xeb) {
svga->rowoffset <<= 1;
svga->render = ht216_1_2bpp_highres;
svga->render = svga_render_2bpp_headland_highres;
}
if (svga->bpp == 8) {
@@ -691,7 +631,7 @@ ht216_recalctimings(svga_t *svga)
ht216->adjust_cursor = 1;
svga->render = svga_render_8bpp_highres;
} else {
ht216_log("8bpp low\n");
ht216_log("8bpp low, packed = %02x, chain4 = %02x\n", svga->packed_chain4, svga->chain4);
svga->render = svga_render_8bpp_lowres;
}
} else if (ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE) {
@@ -702,6 +642,8 @@ ht216_recalctimings(svga_t *svga)
svga->hdisp++;
svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
svga->rowoffset <<= 1;
if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/
svga->crtc[0x17] |= 0x40;
}
svga->render = svga_render_8bpp_highres;
}
@@ -711,7 +653,7 @@ ht216_recalctimings(svga_t *svga)
svga->render = svga_render_15bpp_highres;
}
svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 14);
svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 14);
if (svga->crtc[0x17] == 0xeb) /*Looks like that 1024x768 mono mode expects 512K of video memory*/
svga->vram_display_mask = 0x7ffff;
@@ -787,7 +729,6 @@ extalu(int op, uint8_t input_a, uint8_t input_b)
return val;
}
static void
ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_unexpanded)
{
@@ -801,12 +742,12 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u
writemask2 = svga->seqregs[2];
if (!(svga->gdcreg[6] & 1))
svga->fullchange = 2;
svga->fullchange = 2;
if (svga->chain4 || svga->fb_only) {
if (svga->chain4) {
writemask2 = 1 << (addr & 3);
addr &= ~3;
} else if (svga->chain2_write && (svga->crtc[0x17] != 0xeb)) {
addr = dword_remap(svga, addr) & ~3;
} else if (svga->chain2_write && (svga->crtc[0x17] != 0xeb)) {
writemask2 &= ~0xa;
if (addr & 1)
writemask2 <<= 1;
@@ -984,9 +925,10 @@ ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t bi
uint8_t input_a = 0, input_b = 0;
uint8_t fg, bg;
uint8_t output;
uint32_t remapped_addr = dword_remap(svga, addr);
if (ht216->ht_regs[0xcd] & HT_REG_CD_RMWMDE) /*RMW*/
input_b = svga->vram[addr];
input_b = svga->vram[remapped_addr];
else
input_b = ht216->bg_latch[addr & 7];
@@ -1011,8 +953,8 @@ ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t bi
fg = extalu(ht216->ht_regs[0xce] >> 4, input_a, input_b);
bg = extalu(ht216->ht_regs[0xce] & 0xf, input_a, input_b);
output = (fg & rop_select) | (bg & ~rop_select);
svga->vram[addr] = (svga->vram[addr] & ~bit_mask) | (output & bit_mask);
svga->changedvram[addr >> 12] = changeframecount;
svga->vram[addr] = (svga->vram[remapped_addr] & ~bit_mask) | (output & bit_mask);
svga->changedvram[remapped_addr >> 12] = changeframecount;
}
static void
@@ -1027,12 +969,12 @@ ht216_dm_masked_write(ht216_t *ht216, uint32_t addr, uint8_t val, uint8_t bit_ma
writemask2 = svga->seqregs[2];
if (!(svga->gdcreg[6] & 1))
svga->fullchange = 2;
svga->fullchange = 2;
if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) {
if (svga->chain4) {
writemask2 = 1 << (addr & 3);
addr &= ~3;
} else if (svga->chain2_write) {
addr = dword_remap(svga, addr) & ~3;
} else if (svga->chain2_write) {
writemask2 &= ~0xa;
if (addr & 1)
writemask2 <<= 1;
@@ -1304,7 +1246,7 @@ ht216_read_common(ht216_t *ht216, uint32_t addr)
count = (1 << count);
if (svga->chain4 || svga->fb_only) {
if (svga->chain4 && svga->packed_chain4) {
addr &= svga->decode_mask;
if (addr >= svga->vram_max)
return 0xff;
@@ -1312,9 +1254,12 @@ ht216_read_common(ht216_t *ht216, uint32_t addr)
if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE)
latch_addr += (svga->gdcreg[3] & 7);
for (i = 0; i < 8; i++)
ht216->bg_latch[i] = svga->vram[latch_addr + i];
return svga->vram[addr & svga->vram_mask];
} else if (svga->chain2_read && (svga->crtc[0x17] != 0xeb)) {
ht216->bg_latch[i] = svga->vram[dword_remap(svga, latch_addr + i)];
return svga->vram[dword_remap(svga, addr) & svga->vram_mask];
} else if (svga->chain4) {
readplane = addr & 3;
addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
} else if (svga->chain2_read && (svga->crtc[0x17] != 0xeb)) {
readplane = (readplane & 2) | (addr & 1);
addr &= ~1;
addr <<= 2;

View File

@@ -47,6 +47,8 @@ typedef struct paradise_t
WD90C30
} type;
uint32_t vram_mask;
uint32_t read_bank[4], write_bank[4];
} paradise_t;
@@ -112,17 +114,20 @@ void paradise_out(uint16_t addr, uint8_t val, void *p)
paradise_remap(paradise);
return;
}
if (svga->gdcaddr == 0x9 || svga->gdcaddr == 0xa)
if (svga->gdcaddr == 0x9 || svga->gdcaddr == 0xa || svga->gdcaddr == 0xb)
{
svga->gdcreg[svga->gdcaddr] = val;
paradise_remap(paradise);
return;
}
if (svga->gdcaddr == 0xe)
{
if (svga->gdcaddr == 0xd) {
svga->gdcreg[0xd] = val;
svga_recalctimings(svga);
return;
}
if (svga->gdcaddr == 0xe) {
svga->gdcreg[0xe] = val;
paradise_remap(paradise);
svga_recalctimings(svga);
svga_recalctimings(svga);
return;
}
break;
@@ -152,6 +157,13 @@ void paradise_out(uint16_t addr, uint8_t val, void *p)
svga_recalctimings(&paradise->svga);
}
}
switch (svga->crtcreg) {
case 0x2f:
if (paradise->type != PVGA1A)
svga->vram_display_mask = (val & 1) ? 0x3ffff : paradise->vram_mask;
break;
}
break;
}
svga_out(addr, val, svga);
@@ -219,8 +231,8 @@ void paradise_remap(paradise_t *paradise)
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & mask) << 12;
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0xa] & mask) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
}
else if (svga->gdcreg[0xe] & 0x08)
{
else if (svga->gdcreg[0xb] & 0x08)
{
if (svga->gdcreg[0x6] & 0xc)
{
paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0xa] & mask) << 12;
@@ -243,19 +255,37 @@ void paradise_remap(paradise_t *paradise)
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0x9] & mask) << 12;
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & mask) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
}
if (paradise->type == WD90C11) {
paradise->read_bank[1] &= 0x7ffff;
paradise->write_bank[1] &= 0x7ffff;
} else {
paradise->read_bank[1] &= 0xfffff;
paradise->write_bank[1] &= 0xfffff;
}
}
void paradise_recalctimings(svga_t *svga)
{
paradise_t *paradise = (paradise_t *) svga->p;
if (paradise->type == WD90C30)
svga->interlace = (svga->crtc[0x2d] & 0x20);
if (svga->gdcreg[0xd] & 0x08) svga->ma_latch |= 0x10000;
if (svga->gdcreg[0xd] & 0x10) svga->ma_latch |= 0x20000;
if (svga->gdcreg[0xe] & 0x01) {
svga->bpp = 8;
svga->lowres = 0;
svga->render = svga_render_8bpp_highres;
if (paradise->type == WD90C30) {
if (svga->crtc[0x3d] & 0x01) svga->vtotal |= 0x400;
if (svga->crtc[0x3d] & 0x02) svga->dispend |= 0x400;
if (svga->crtc[0x3d] & 0x04) svga->vsyncstart |= 0x400;
if (svga->crtc[0x3d] & 0x08) svga->vblankstart |= 0x400;
if (svga->crtc[0x3d] & 0x10) svga->split |= 0x400;
svga->interlace = (svga->crtc[0x2d] & 0x20);
}
svga->lowres = !(svga->gdcreg[0xe] & 0x01);
if (svga->bpp == 8 && !svga->lowres) {
svga->render = svga_render_8bpp_highres;
}
}
@@ -263,7 +293,6 @@ static void paradise_write(uint32_t addr, uint8_t val, void *p)
{
paradise_t *paradise = (paradise_t *)p;
addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3];
svga_write_linear(addr, val, &paradise->svga);
}
static void paradise_writew(uint32_t addr, uint16_t val, void *p)
@@ -306,6 +335,7 @@ void *paradise_init(const device_t *info, uint32_t memsize)
paradise_in, paradise_out,
NULL,
NULL);
paradise->vram_mask = memsize - 1;
break;
case WD90C11:
svga_init(info, &paradise->svga, paradise, 1 << 19, /*512kb*/
@@ -313,6 +343,7 @@ void *paradise_init(const device_t *info, uint32_t memsize)
paradise_in, paradise_out,
NULL,
NULL);
paradise->vram_mask = (1 << 19) - 1;
break;
case WD90C30:
svga_init(info, &paradise->svga, paradise, memsize,
@@ -320,11 +351,12 @@ void *paradise_init(const device_t *info, uint32_t memsize)
paradise_in, paradise_out,
NULL,
NULL);
paradise->vram_mask = memsize - 1;
break;
}
mem_mapping_set_handler(&paradise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL);
mem_mapping_set_p(&paradise->svga.mapping, paradise);
mem_mapping_set_handler(&svga->mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL);
mem_mapping_set_p(&svga->mapping, paradise);
/* Common to all three types. */
svga->crtc[0x31] = 'W';

View File

@@ -353,6 +353,28 @@ static uint8_t s3_accel_in(uint16_t port, void *p);
static uint8_t s3_pci_read(int func, int addr, void *p);
static void s3_pci_write(int func, int addr, uint8_t val, void *p);
/*Remap address for chain-4/doubleword style layout*/
static __inline uint32_t
dword_remap(uint32_t in_addr)
{
return ((in_addr << 2) & 0x3fff0) |
((in_addr >> 14) & 0xc) |
(in_addr & ~0x3fffc);
}
static __inline uint32_t
dword_remap_w(uint32_t in_addr)
{
return ((in_addr << 2) & 0x1fff8) |
((in_addr >> 14) & 0x6) |
(in_addr & ~0x1fffe);
}
static __inline uint32_t
dword_remap_l(uint32_t in_addr)
{
return ((in_addr << 2) & 0xfffc) |
((in_addr >> 14) & 0x3) |
(in_addr & ~0xffff);
}
static __inline void
wake_fifo_thread(s3_t *s3)
@@ -1635,8 +1657,10 @@ s3_hwcursor_draw(svga_t *svga, int displine)
for (x = 0; x < 64; x += 16)
{
dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1];
dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3];
uint32_t remapped_addr = dword_remap(svga->hwcursor_latch.addr);
dat[0] = (svga->vram[remapped_addr] << 8) | svga->vram[remapped_addr + 1];
dat[1] = (svga->vram[remapped_addr + 2] << 8) | svga->vram[remapped_addr + 3];
if (svga->crtc[0x55] & 0x10) {
/*X11*/
for (xx = 0; xx < 16; xx++) {
@@ -2240,6 +2264,7 @@ s3_out(uint16_t addr, uint8_t val, void *p)
{
case 0x31:
s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4);
svga->force_dword_mode = val & 0x08;
break;
case 0x32:
if (svga->crtc[0x31] & 0x30)
@@ -3698,9 +3723,9 @@ polygon_setup(s3_t *s3)
}
#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \
else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \
else dat = vram_l[(addr) & (s3->vram_mask >> 2)];
#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[dword_remap(addr) & s3->vram_mask]; \
else if (s3->bpp == 1) dat = vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)]; \
else dat = vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)];
#define MIX_READ { \
switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \
@@ -4005,18 +4030,18 @@ polygon_setup(s3_t *s3)
#define WRITE(addr, dat) if (s3->bpp == 0) \
{ \
svga->vram[(addr) & s3->vram_mask] = dat; \
svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \
svga->vram[dword_remap(addr) & s3->vram_mask] = dat; \
svga->changedvram[(dword_remap(addr) & s3->vram_mask) >> 12] = changeframecount; \
} \
else if (s3->bpp == 1) \
{ \
vram_w[(addr) & (s3->vram_mask >> 1)] = dat; \
svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \
vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)] = dat; \
svga->changedvram[(dword_remap_w(addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \
} \
else \
{ \
vram_l[(addr) & (s3->vram_mask >> 2)] = dat; \
svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \
vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)] = dat; \
svga->changedvram[(dword_remap_l(addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \
}

View File

@@ -3886,6 +3886,8 @@ static void *s3_virge_init(const device_t *info)
virge->i2c = i2c_gpio_init("ddc_s3_virge");
virge->ddc = ddc_init(i2c_gpio_get_bus(virge->i2c));
virge->svga.packed_chain4 = 1;
return virge;
}

View File

@@ -178,7 +178,7 @@ svga_out(uint16_t addr, uint8_t val, void *p)
svga->chain2_write = !(val & 4);
svga->chain4 = val & 8;
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) &&
!svga->gdcreg[1]) && svga->chain4 && !(svga->adv_flags & FLAG_ADDR_BY8);
!svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8);
break;
}
break;
@@ -261,7 +261,7 @@ svga_out(uint16_t addr, uint8_t val, void *p)
}
svga->gdcreg[svga->gdcaddr & 15] = val;
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) &&
!svga->gdcreg[1]) && svga->chain4;
!svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only);
if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) ||
((svga->gdcaddr & 15) == 6 && (val ^ o) & 1))
svga_recalctimings(svga);
@@ -575,7 +575,9 @@ svga_recalctimings(svga_t *svga)
if (svga->dispontime < TIMER_USEC)
svga->dispontime = TIMER_USEC;
if (svga->dispofftime < TIMER_USEC)
svga->dispofftime = TIMER_USEC;
svga->dispofftime = TIMER_USEC;
svga_recalc_remap_func(svga);
/* Inform the user interface of any DPMS mode changes. */
if (svga->dpms) {
@@ -1058,9 +1060,14 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p)
if ((svga->adv_flags & FLAG_ADDR_BY8) && (svga->writemode < 4))
addr <<= 3;
else if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) {
else if (((svga->chain4 && svga->packed_chain4) || svga->fb_only) && (svga->writemode < 4)) {
writemask2 = 1 << (addr & 3);
addr &= ~3;
} else if (svga->chain4 && (svga->writemode < 4)) {
writemask2 = 1 << (addr & 3);
if (!linear)
addr &= ~3;
addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
} else if (svga->chain2_write) {
writemask2 &= ~0xa;
if (addr & 1)
@@ -1239,7 +1246,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p)
if (svga->adv_flags & FLAG_ADDR_BY8)
addr <<= 3;
else if (svga->chain4 || svga->fb_only) {
else if ((svga->chain4 && svga->packed_chain4) || svga->fb_only) {
addr &= svga->decode_mask;
if (svga->translate_address)
addr = svga->translate_address(addr, p);
@@ -1249,6 +1256,9 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p)
for (i = 0; i < count; i++)
svga->latch.b[i] = svga->vram[latch_addr | i];
return svga->vram[addr & svga->vram_mask];
} else if (svga->chain4) {
readplane = addr & 3;
addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
} else if (svga->chain2_read) {
readplane = (readplane & 2) | (addr & 1);
addr &= ~1;

File diff suppressed because it is too large Load Diff

View File

@@ -70,8 +70,6 @@
#include "cpu.h"
#include <86box/plat.h>
#include <86box/video.h>
#include <86box/i2c.h>
#include <86box/vid_ddc.h>
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
@@ -107,45 +105,19 @@
but the Windows 3.1 driver always reads bytes and write words of 0xffff.*/
#define ROM_TGUI_9400CXI "roms/video/tgui9440/9400CXI.vbi"
#define ROM_TGUI_9440 "roms/video/tgui9440/9440.vbi"
#define ROM_TGUI_9440 "roms/video/tgui9440/9440.VBI"
#define EXT_CTRL_16BIT 0x01
#define EXT_CTRL_MONO_EXPANSION 0x02
#define EXT_CTRL_MONO_TRANSPARENT 0x04
#define EXT_CTRL_LATCH_COPY 0x08
#define FIFO_SIZE 65536
#define FIFO_MASK (FIFO_SIZE - 1)
#define FIFO_ENTRY_SIZE (1 << 31)
#define FIFO_ENTRIES (tgui->fifo_write_idx - tgui->fifo_read_idx)
#define FIFO_FULL ((tgui->fifo_write_idx - tgui->fifo_read_idx) >= FIFO_SIZE)
#define FIFO_EMPTY (tgui->fifo_read_idx == tgui->fifo_write_idx)
#define FIFO_TYPE 0xff000000
#define FIFO_ADDR 0x00ffffff
enum
{
TGUI_9400CXI = 0,
TGUI_9440
};
enum
{
FIFO_INVALID = (0x00 << 24),
FIFO_WRITE_BYTE = (0x01 << 24),
FIFO_WRITE_FB_BYTE = (0x04 << 24),
FIFO_WRITE_FB_WORD = (0x05 << 24),
FIFO_WRITE_FB_LONG = (0x06 << 24)
};
typedef struct
{
uint32_t addr_type;
uint32_t val;
} fifo_entry_t;
typedef struct tgui_t
{
mem_mapping_t linear_mapping;
@@ -177,6 +149,7 @@ typedef struct tgui_t
int use_src;
int pitch, bpp;
int val_access;
uint16_t tgui_pattern[8][8];
} accel;
@@ -184,7 +157,7 @@ typedef struct tgui_t
uint8_t ext_gdc_regs[16]; /*TGUI9400CXi only*/
uint8_t copy_latch[16];
uint8_t tgui_3d8, tgui_3d9;
uint8_t tgui_3d8, tgui_3d9, port3CD;
int oldmode;
uint8_t oldctrl1;
uint8_t oldctrl2,newctrl2;
@@ -197,21 +170,8 @@ typedef struct tgui_t
int clock_m, clock_n, clock_k;
uint32_t vram_size, vram_mask;
fifo_entry_t fifo[FIFO_SIZE];
volatile int fifo_read_idx, fifo_write_idx;
thread_t *fifo_thread;
event_t *wake_fifo_thread;
event_t *fifo_not_full_event;
int blitter_busy;
uint64_t blitter_time;
uint64_t status_time;
volatile int write_blitter;
void *i2c, *ddc;
} tgui_t;
video_timings_t timing_tgui_vlb = {VIDEO_BUS, 4, 8, 16, 4, 8, 16};
@@ -219,8 +179,6 @@ video_timings_t timing_tgui_pci = {VIDEO_PCI, 4, 8, 16, 4, 8, 16};
void tgui_recalcmapping(tgui_t *tgui);
static void fifo_thread(void *param);
uint8_t tgui_accel_read(uint32_t addr, void *priv);
uint16_t tgui_accel_read_w(uint32_t addr, void *priv);
uint32_t tgui_accel_read_l(uint32_t addr, void *priv);
@@ -243,6 +201,23 @@ static void tgui_ext_write(uint32_t addr, uint8_t val, void *p);
static void tgui_ext_writew(uint32_t addr, uint16_t val, void *p);
static void tgui_ext_writel(uint32_t addr, uint32_t val, void *p);
/*Remap address for chain-4/doubleword style layout*/
static __inline uint32_t
dword_remap(uint32_t in_addr)
{
return ((in_addr << 2) & 0x3fff0) |
((in_addr >> 14) & 0xc) |
(in_addr & ~0x3fffc);
}
static __inline uint32_t
dword_remap_w(uint32_t in_addr)
{
return ((in_addr << 2) & 0x1fff8) |
((in_addr >> 14) & 0x6) |
(in_addr & ~0x1fffe);
}
void tgui_out(uint16_t addr, uint8_t val, void *p)
{
tgui_t *tgui = (tgui_t *)p;
@@ -309,9 +284,11 @@ void tgui_out(uint16_t addr, uint8_t val, void *p)
svga->bpp = 8;
break;
}
svga_recalctimings(svga);
return;
}
/*FALLTHROUGH*/
break;
case 0x3C7: case 0x3C8: case 0x3C9:
if (tgui->type == TGUI_9400CXI)
{
@@ -319,7 +296,7 @@ void tgui_out(uint16_t addr, uint8_t val, void *p)
return;
}
tgui->ramdac_state = 0;
break;
break;
case 0x3CF:
if (svga->gdcaddr == 0x23)
@@ -384,16 +361,12 @@ void tgui_out(uint16_t addr, uint8_t val, void *p)
{
tgui->linear_base = ((val & 0xf) | ((val >> 2) & 0x30)) << 20;
tgui->linear_size = (val & 0x10) ? 0x200000 : 0x100000;
tgui->svga.decode_mask = (val & 0x10) ? 0x1fffff : 0xfffff;
svga->decode_mask = (val & 0x10) ? 0x1fffff : 0xfffff;
}
tgui_recalcmapping(tgui);
}
break;
case 0x37:
i2c_gpio_set(tgui->i2c, (val & 0x02) || !(val & 0x04), (val & 0x01) || !(val & 0x08));
break;
case 0x40: case 0x41: case 0x42: case 0x43:
case 0x44: case 0x45: case 0x46: case 0x47:
if (tgui->type >= TGUI_9440)
@@ -462,7 +435,7 @@ uint8_t tgui_in(uint16_t addr, void *p)
case TGUI_9400CXI:
return 0x93; /*TGUI9400CXi*/
case TGUI_9440:
return 0xe3; /*TGUI9440AGi*/
return 0xa3; /*TGUI9440AGi*/
}
}
if ((svga->seqaddr & 0xf) == 0xd)
@@ -479,16 +452,19 @@ uint8_t tgui_in(uint16_t addr, void *p)
break;
case 0x3C6:
if (tgui->type == TGUI_9400CXI)
return tkd8001_ramdac_in(addr, svga->ramdac, svga);
return tkd8001_ramdac_in(addr, svga->ramdac, svga);
if (tgui->ramdac_state == 4)
return tgui->ramdac_ctrl;
tgui->ramdac_state++;
return tgui->ramdac_ctrl;
tgui->ramdac_state++;
break;
case 0x3C7: case 0x3C8: case 0x3C9:
if (tgui->type == TGUI_9400CXI)
return tkd8001_ramdac_in(addr, svga->ramdac, svga);
tgui->ramdac_state = 0;
break;
case 0x3CD:
return tgui->port3CD;
case 0x3CF:
if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32)
return tgui->ext_gdc_regs[svga->gdcaddr & 15];
@@ -497,18 +473,6 @@ uint8_t tgui_in(uint16_t addr, void *p)
return svga->crtcreg;
case 0x3D5:
temp = svga->crtc[svga->crtcreg];
if (svga->crtcreg == 0x37) {
if (!(svga->crtc[0x37] & 0x04)) {
temp &= 0xfd;
if (i2c_gpio_get_scl(tgui->i2c))
temp |= 0x02;
}
if (!(svga->crtc[0x37] & 0x08)) {
temp &= 0xfe;
if (i2c_gpio_get_sda(tgui->i2c))
temp |= 0x01;
}
}
return temp;
case 0x3d8:
return tgui->tgui_3d8;
@@ -647,6 +611,7 @@ void tgui_recalcmapping(tgui_t *tgui)
if (svga->crtc[0x21] & 0x20)
{
mem_mapping_disable(&svga->mapping);
pclog("Linear size = %08x, linear base = %08x\n", tgui->linear_size, tgui->linear_base);
mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size);
if (tgui->type >= TGUI_9440)
{
@@ -688,7 +653,7 @@ void tgui_recalcmapping(tgui_t *tgui)
break;
case 0x4: /*64k at A0000*/
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
mem_mapping_enable(&tgui->accel_mapping);
mem_mapping_enable(&tgui->accel_mapping);
svga->banked_mask = 0xffff;
break;
case 0x8: /*32k at B0000*/
@@ -711,12 +676,15 @@ void tgui_hwcursor_draw(svga_t *svga, int displine)
int pitch = (svga->hwcursor.xsize == 64) ? 16 : 8;
int byte, bit;
uint32_t color;
uint32_t remapped_addr;
if (svga->interlace && svga->hwcursor_oddeven)
svga->hwcursor_latch.addr += pitch;
svga->hwcursor_latch.addr += pitch;
remapped_addr = dword_remap(svga->hwcursor_latch.addr);
for (xx = 0; xx < svga->hwcursor.xsize; xx++) {
byte = svga->hwcursor_latch.addr + (xx >> 3);
byte = remapped_addr + (xx >> 3);
bit = (7 - (xx & 7));
dat[0] = (svga->vram[byte] >> bit) & 0x01; /* AND */
dat[1] = (svga->vram[(pitch >> 1) + byte] >> bit) & 0x01; /* XOR */
@@ -805,14 +773,14 @@ void tgui_pci_write(int func, int addr, uint8_t val, void *p)
case 0x12:
tgui->linear_base = (tgui->linear_base & 0xff000000) | ((val & 0xe0) << 16);
tgui->linear_size = 2 << 20;
tgui->svga.decode_mask = 0x1fffff;
svga->decode_mask = 0x1fffff;
svga->crtc[0x21] = (svga->crtc[0x21] & ~0xf) | (val >> 4);
tgui_recalcmapping(tgui);
break;
case 0x13:
tgui->linear_base = (tgui->linear_base & 0xe00000) | (val << 24);
tgui->linear_size = 2 << 20;
tgui->svga.decode_mask = 0x1fffff;
svga->decode_mask = 0x1fffff;
svga->crtc[0x21] = (svga->crtc[0x21] & ~0xc0) | (val >> 6);
tgui_recalcmapping(tgui);
break;
@@ -832,9 +800,13 @@ static uint8_t tgui_ext_linear_read(uint32_t addr, void *p)
return 0xff;
addr &= ~0xf;
for (c = 0; c < 16; c++)
tgui->copy_latch[c] = svga->vram[addr+c];
addr = dword_remap(addr);
for (c = 0; c < 16; c++) {
tgui->copy_latch[c] = svga->vram[addr+c];
addr += ((c & 3) == 3) ? 13 : 1;
}
return svga->vram[addr & svga->vram_mask];
}
@@ -862,7 +834,9 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
if (addr >= svga->vram_max)
return;
addr &= svga->vram_mask;
addr &= ~0x7;
addr &= (tgui->ext_gdc_regs[0] & 8) ? ~0xf : ~0x7;
addr = dword_remap(addr);
svga->changedvram[addr >> 12] = changeframecount;
switch (tgui->ext_gdc_regs[0] & 0xf)
@@ -873,7 +847,7 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0];
addr++;
addr += (c == 4) ? 13 : 1;
}
break;
@@ -883,7 +857,7 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1];
addr++;
addr += (c == 4) ? 13 : 1;
}
break;
@@ -893,7 +867,7 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[0];
addr++;
addr += (c == 4) ? 13 : 1;
}
break;
@@ -903,15 +877,16 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1];
addr++;
addr += (c == 4) ? 13 : 1;
}
break;
case 0x8: case 0x9: case 0xa: case 0xb:
case 0xc: case 0xd: case 0xe: case 0xf:
addr &= ~0xf;
for (c = 0; c < 16; c++)
*(uint8_t *)&svga->vram[addr+c] = tgui->copy_latch[c];
for (c = 0; c < 16; c++) {
*(uint8_t *)&svga->vram[addr] = tgui->copy_latch[c];
addr += ((c & 3) == 3) ? 13 : 1;
}
break;
}
}
@@ -932,6 +907,8 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
return;
addr &= svga->vram_mask;
addr &= ~0xf;
addr = dword_remap(addr);
svga->changedvram[addr >> 12] = changeframecount;
val = (val >> 8) | (val << 8);
@@ -944,7 +921,7 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0];
addr++;
addr += (c & 3) ? 1 : 13;
}
break;
@@ -954,7 +931,7 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1];
addr++;
addr += (c & 3) ? 1 : 13;
}
break;
@@ -964,7 +941,7 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[0];
addr++;
addr += (c & 3) ? 1 : 13;
}
break;
@@ -974,14 +951,16 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1];
addr++;
addr += (c & 3) ? 1 : 13;
}
break;
case 0x8: case 0x9: case 0xa: case 0xb:
case 0xc: case 0xd: case 0xe: case 0xf:
for (c = 0; c < 16; c++)
for (c = 0; c < 16; c++) {
*(uint8_t *)&svga->vram[addr+c] = tgui->copy_latch[c];
addr += ((c & 3) == 3) ? 13 : 1;
}
break;
}
}
@@ -1034,8 +1013,8 @@ enum
TGUI_SOLIDFILL = 0x4000 /*Pattern all zero?*/
};
#define READ(addr, dat) if (tgui->accel.bpp == 0) dat = svga->vram[addr & 0x1fffff]; \
else dat = vram_w[addr & 0xfffff];
#define READ(addr, dat) if (tgui->accel.bpp == 0) dat = svga->vram[dword_remap(addr) & tgui->vram_mask]; \
else dat = vram_w[dword_remap_w(addr) & (tgui->vram_mask >> 1)];
#define MIX() do \
{ \
@@ -1051,13 +1030,13 @@ enum
#define WRITE(addr, dat) if (tgui->accel.bpp == 0) \
{ \
svga->vram[addr & 0x1fffff] = dat; \
svga->changedvram[((addr) & 0x1fffff) >> 12] = changeframecount; \
svga->vram[dword_remap(addr) & tgui->vram_mask] = dat; \
svga->changedvram[(dword_remap(addr) & tgui->vram_mask) >> 12] = changeframecount; \
} \
else \
{ \
vram_w[addr & 0xfffff] = dat; \
svga->changedvram[((addr) & 0xfffff) >> 11] = changeframecount; \
vram_w[dword_remap_w(addr) & (tgui->vram_mask >> 1)] = dat; \
svga->changedvram[(dword_remap_w(addr) & (tgui->vram_mask >> 1)) >> 11] = changeframecount; \
}
void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
@@ -1127,6 +1106,8 @@ void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
}
}
}
pclog("Accel command = %i\n", tgui->accel.command);
switch (tgui->accel.command)
{
case TGUI_BITBLT:
@@ -1137,7 +1118,7 @@ void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
tgui->accel.pat_x = tgui->accel.dst_x;
tgui->accel.pat_y = tgui->accel.dst_y;
}
switch (tgui->accel.flags & (TGUI_SRCMONO|TGUI_SRCDISP))
{
case TGUI_SRCCPU:
@@ -1149,19 +1130,19 @@ void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
}
if (tgui->accel.use_src)
return;
} else {
count >>= 3;
}
else
count >>= 3;
while (count)
{
if (tgui->accel.bpp == 0)
{
src_dat = cpu_dat >> 24;
src_dat = cpu_dat >> 24;
cpu_dat <<= 8;
}
else
{
src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0xff00);
src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0xff00);
cpu_dat <<= 16;
count--;
}
@@ -1215,7 +1196,7 @@ void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
if (tgui->accel.use_src)
return;
}
while (count)
while (count--)
{
src_dat = ((cpu_dat >> 31) ? tgui->accel.fg_col : tgui->accel.bg_col);
if (tgui->accel.bpp == 0)
@@ -1258,12 +1239,11 @@ void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
if (tgui->accel.use_src)
return;
}
count--;
}
break;
default:
while (count)
while (count--)
{
READ(tgui->accel.src, src_dat);
READ(tgui->accel.dst, dst_dat);
@@ -1295,7 +1275,6 @@ void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
if (tgui->accel.y > tgui->accel.size_y)
return;
}
count--;
}
break;
}
@@ -1303,16 +1282,268 @@ void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
}
}
static void tgui_accel_write_fifo(tgui_t *tgui, uint32_t addr, uint8_t val)
void tgui_accel_out(uint16_t addr, uint8_t val, void *p)
{
tgui_t *tgui = (tgui_t *)p;
switch (addr)
{
case 0x2122:
tgui->accel.ger22 = val;
tgui->accel.pitch = 512 << ((val >> 2) & 3);
tgui->accel.bpp = (val & 3) ? 1 : 0;
tgui->accel.pitch >>= tgui->accel.bpp;
break;
case 0x2124: /*Command*/
tgui->accel.command = val;
tgui_accel_command(-1, 0, tgui);
break;
case 0x2127: /*ROP*/
tgui->accel.rop = val;
tgui->accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33);
break;
case 0x2128: /*Flags*/
tgui->accel.flags = (tgui->accel.flags & 0xff00) | val;
break;
case 0x2129: /*Flags*/
tgui->accel.flags = (tgui->accel.flags & 0xff) | (val << 8);
break;
case 0x212b:
tgui->accel.offset = val & 7;
break;
case 0x212c: /*Foreground colour*/
tgui->accel.fg_col = (tgui->accel.fg_col & 0xff00) | val;
break;
case 0x212d: /*Foreground colour*/
tgui->accel.fg_col = (tgui->accel.fg_col & 0xff) | (val << 8);
break;
case 0x2130: /*Background colour*/
tgui->accel.bg_col = (tgui->accel.bg_col & 0xff00) | val;
break;
case 0x2131: /*Background colour*/
tgui->accel.bg_col = (tgui->accel.bg_col & 0xff) | (val << 8);
break;
case 0x2138: /*Dest X*/
tgui->accel.dst_x = (tgui->accel.dst_x & 0xff00) | val;
break;
case 0x2139: /*Dest X*/
tgui->accel.dst_x = (tgui->accel.dst_x & 0xff) | (val << 8);
break;
case 0x213a: /*Dest Y*/
tgui->accel.dst_y = (tgui->accel.dst_y & 0xff00) | val;
break;
case 0x213b: /*Dest Y*/
tgui->accel.dst_y = (tgui->accel.dst_y & 0xff) | (val << 8);
break;
case 0x213c: /*Src X*/
tgui->accel.src_x = (tgui->accel.src_x & 0xff00) | val;
break;
case 0x213d: /*Src X*/
tgui->accel.src_x = (tgui->accel.src_x & 0xff) | (val << 8);
break;
case 0x213e: /*Src Y*/
tgui->accel.src_y = (tgui->accel.src_y & 0xff00) | val;
break;
case 0x213f: /*Src Y*/
tgui->accel.src_y = (tgui->accel.src_y & 0xff) | (val << 8);
break;
case 0x2140: /*Size X*/
tgui->accel.size_x = (tgui->accel.size_x & 0xff00) | val;
break;
case 0x2141: /*Size X*/
tgui->accel.size_x = (tgui->accel.size_x & 0xff) | (val << 8);
break;
case 0x2142: /*Size Y*/
tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val;
break;
case 0x2143: /*Size Y*/
tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8);
break;
case 0x2180: case 0x2181: case 0x2182: case 0x2183:
case 0x2184: case 0x2185: case 0x2186: case 0x2187:
case 0x2188: case 0x2189: case 0x218a: case 0x218b:
case 0x218c: case 0x218d: case 0x218e: case 0x218f:
case 0x2190: case 0x2191: case 0x2192: case 0x2193:
case 0x2194: case 0x2195: case 0x2196: case 0x2197:
case 0x2198: case 0x2199: case 0x219a: case 0x219b:
case 0x219c: case 0x219d: case 0x219e: case 0x219f:
case 0x21a0: case 0x21a1: case 0x21a2: case 0x21a3:
case 0x21a4: case 0x21a5: case 0x21a6: case 0x21a7:
case 0x21a8: case 0x21a9: case 0x21aa: case 0x21ab:
case 0x21ac: case 0x21ad: case 0x21ae: case 0x21af:
case 0x21b0: case 0x21b1: case 0x21b2: case 0x21b3:
case 0x21b4: case 0x21b5: case 0x21b6: case 0x21b7:
case 0x21b8: case 0x21b9: case 0x21ba: case 0x21bb:
case 0x21bc: case 0x21bd: case 0x21be: case 0x21bf:
case 0x21c0: case 0x21c1: case 0x21c2: case 0x21c3:
case 0x21c4: case 0x21c5: case 0x21c6: case 0x21c7:
case 0x21c8: case 0x21c9: case 0x21ca: case 0x21cb:
case 0x21cc: case 0x21cd: case 0x21ce: case 0x21cf:
case 0x21d0: case 0x21d1: case 0x21d2: case 0x21d3:
case 0x21d4: case 0x21d5: case 0x21d6: case 0x21d7:
case 0x21d8: case 0x21d9: case 0x21da: case 0x21db:
case 0x21dc: case 0x21dd: case 0x21de: case 0x21df:
case 0x21e0: case 0x21e1: case 0x21e2: case 0x21e3:
case 0x21e4: case 0x21e5: case 0x21e6: case 0x21e7:
case 0x21e8: case 0x21e9: case 0x21ea: case 0x21eb:
case 0x21ec: case 0x21ed: case 0x21ee: case 0x21ef:
case 0x21f0: case 0x21f1: case 0x21f2: case 0x21f3:
case 0x21f4: case 0x21f5: case 0x21f6: case 0x21f7:
case 0x21f8: case 0x21f9: case 0x21fa: case 0x21fb:
case 0x21fc: case 0x21fd: case 0x21fe: case 0x21ff:
tgui->accel.pattern[addr & 0x7f] = val;
break;
}
}
void tgui_accel_out_w(uint16_t addr, uint16_t val, void *p)
{
tgui_t *tgui = (tgui_t *)p;
tgui_accel_out(addr, val, tgui);
tgui_accel_out(addr + 1, val >> 8, tgui);
}
void tgui_accel_out_l(uint16_t addr, uint32_t val, void *p)
{
tgui_t *tgui = (tgui_t *)p;
tgui_accel_out(addr, val, tgui);
tgui_accel_out(addr + 1, val >> 8, tgui);
tgui_accel_out(addr + 2, val >> 16, tgui);
tgui_accel_out(addr + 3, val >> 24, tgui);
}
uint8_t tgui_accel_in(uint16_t addr, void *p)
{
tgui_t *tgui = (tgui_t *)p;
switch (addr)
{
case 0x2120: /*Status*/
return 0;
case 0x2127: /*ROP*/
return tgui->accel.rop;
case 0x2128: /*Flags*/
return tgui->accel.flags & 0xff;
case 0x2129: /*Flags*/
return tgui->accel.flags >> 8;
case 0x212b:
return tgui->accel.offset;
case 0x212c: /*Background colour*/
return tgui->accel.bg_col & 0xff;
case 0x212d: /*Background colour*/
return tgui->accel.bg_col >> 8;
case 0x2130: /*Foreground colour*/
return tgui->accel.fg_col & 0xff;
case 0x2131: /*Foreground colour*/
return tgui->accel.fg_col >> 8;
case 0x2138: /*Dest X*/
return tgui->accel.dst_x & 0xff;
case 0x2139: /*Dest X*/
return tgui->accel.dst_x >> 8;
case 0x213a: /*Dest Y*/
return tgui->accel.dst_y & 0xff;
case 0x213b: /*Dest Y*/
return tgui->accel.dst_y >> 8;
case 0x213c: /*Src X*/
return tgui->accel.src_x & 0xff;
case 0x213d: /*Src X*/
return tgui->accel.src_x >> 8;
case 0x213e: /*Src Y*/
return tgui->accel.src_y & 0xff;
case 0x213f: /*Src Y*/
return tgui->accel.src_y >> 8;
case 0x2140: /*Size X*/
return tgui->accel.size_x & 0xff;
case 0x2141: /*Size X*/
return tgui->accel.size_x >> 8;
case 0x2142: /*Size Y*/
return tgui->accel.size_y & 0xff;
case 0x2143: /*Size Y*/
return tgui->accel.size_y >> 8;
case 0x2180: case 0x2181: case 0x2182: case 0x2183:
case 0x2184: case 0x2185: case 0x2186: case 0x2187:
case 0x2188: case 0x2189: case 0x218a: case 0x218b:
case 0x218c: case 0x218d: case 0x218e: case 0x218f:
case 0x2190: case 0x2191: case 0x2192: case 0x2193:
case 0x2194: case 0x2195: case 0x2196: case 0x2197:
case 0x2198: case 0x2199: case 0x219a: case 0x219b:
case 0x219c: case 0x219d: case 0x219e: case 0x219f:
case 0x21a0: case 0x21a1: case 0x21a2: case 0x21a3:
case 0x21a4: case 0x21a5: case 0x21a6: case 0x21a7:
case 0x21a8: case 0x21a9: case 0x21aa: case 0x21ab:
case 0x21ac: case 0x21ad: case 0x21ae: case 0x21af:
case 0x21b0: case 0x21b1: case 0x21b2: case 0x21b3:
case 0x21b4: case 0x21b5: case 0x21b6: case 0x21b7:
case 0x21b8: case 0x21b9: case 0x21ba: case 0x21bb:
case 0x21bc: case 0x21bd: case 0x21be: case 0x21bf:
case 0x21c0: case 0x21c1: case 0x21c2: case 0x21c3:
case 0x21c4: case 0x21c5: case 0x21c6: case 0x21c7:
case 0x21c8: case 0x21c9: case 0x21ca: case 0x21cb:
case 0x21cc: case 0x21cd: case 0x21ce: case 0x21cf:
case 0x21d0: case 0x21d1: case 0x21d2: case 0x21d3:
case 0x21d4: case 0x21d5: case 0x21d6: case 0x21d7:
case 0x21d8: case 0x21d9: case 0x21da: case 0x21db:
case 0x21dc: case 0x21dd: case 0x21de: case 0x21df:
case 0x21e0: case 0x21e1: case 0x21e2: case 0x21e3:
case 0x21e4: case 0x21e5: case 0x21e6: case 0x21e7:
case 0x21e8: case 0x21e9: case 0x21ea: case 0x21eb:
case 0x21ec: case 0x21ed: case 0x21ee: case 0x21ef:
case 0x21f0: case 0x21f1: case 0x21f2: case 0x21f3:
case 0x21f4: case 0x21f5: case 0x21f6: case 0x21f7:
case 0x21f8: case 0x21f9: case 0x21fa: case 0x21fb:
case 0x21fc: case 0x21fd: case 0x21fe: case 0x21ff:
return tgui->accel.pattern[addr & 0x7f];
}
return 0;
}
uint16_t tgui_accel_in_w(uint16_t addr, void *p)
{
tgui_t *tgui = (tgui_t *)p;
return tgui_accel_in(addr, tgui) | (tgui_accel_in(addr + 1, tgui) << 8);
}
uint32_t tgui_accel_in_l(uint16_t addr, void *p)
{
tgui_t *tgui = (tgui_t *)p;
return tgui_accel_in_w(addr, tgui) | (tgui_accel_in_w(addr + 2, tgui) << 16);
}
void tgui_accel_write(uint32_t addr, uint8_t val, void *p)
{
tgui_t *tgui = (tgui_t *)p;
if ((addr & ~0xff) != 0xbff00)
return;
switch (addr & 0xff)
{
case 0x22:
tgui->accel.ger22 = val;
tgui->accel.pitch = 512 << ((val >> 2) & 3);
tgui->accel.bpp = (val & 3) ? 1 : 0;
tgui->accel.pitch >>= tgui->accel.bpp;
break;
case 0x22:
tgui->accel.ger22 = val;
tgui->accel.pitch = 512 << ((val >> 2) & 3);
tgui->accel.bpp = (val & 3) ? 1 : 0;
tgui->accel.pitch >>= tgui->accel.bpp;
break;
case 0x24: /*Command*/
tgui->accel.command = val;
@@ -1425,109 +1656,6 @@ static void tgui_accel_write_fifo(tgui_t *tgui, uint32_t addr, uint8_t val)
}
}
static void tgui_accel_write_fifo_fb_b(tgui_t *tgui, uint32_t addr, uint8_t val)
{
tgui_accel_command(8, val << 24, tgui);
}
static void tgui_accel_write_fifo_fb_w(tgui_t *tgui, uint32_t addr, uint16_t val)
{
tgui_accel_command(16, (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)) << 16, tgui);
}
static void tgui_accel_write_fifo_fb_l(tgui_t *tgui, uint32_t addr, uint32_t val)
{
tgui_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), tgui);
}
static void fifo_thread(void *param)
{
tgui_t *tgui = (tgui_t *)param;
while (1)
{
thread_set_event(tgui->fifo_not_full_event);
thread_wait_event(tgui->wake_fifo_thread, -1);
thread_reset_event(tgui->wake_fifo_thread);
tgui->blitter_busy = 1;
while (!FIFO_EMPTY)
{
uint64_t start_time = plat_timer_read();
uint64_t end_time;
fifo_entry_t *fifo = &tgui->fifo[tgui->fifo_read_idx & FIFO_MASK];
switch (fifo->addr_type & FIFO_TYPE)
{
case FIFO_WRITE_BYTE:
tgui_accel_write_fifo(tgui, fifo->addr_type & FIFO_ADDR, fifo->val);
break;
case FIFO_WRITE_FB_BYTE:
tgui_accel_write_fifo_fb_b(tgui, fifo->addr_type & FIFO_ADDR, fifo->val);
break;
case FIFO_WRITE_FB_WORD:
tgui_accel_write_fifo_fb_w(tgui, fifo->addr_type & FIFO_ADDR, fifo->val);
break;
case FIFO_WRITE_FB_LONG:
tgui_accel_write_fifo_fb_l(tgui, fifo->addr_type & FIFO_ADDR, fifo->val);
break;
}
tgui->fifo_read_idx++;
fifo->addr_type = FIFO_INVALID;
if (FIFO_ENTRIES > 0xe000)
thread_set_event(tgui->fifo_not_full_event);
end_time = plat_timer_read();
tgui->blitter_time += end_time - start_time;
}
tgui->blitter_busy = 0;
}
}
static inline void wake_fifo_thread(tgui_t *tgui)
{
thread_set_event(tgui->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
}
static void tgui_wait_fifo_idle(tgui_t *tgui)
{
while (!FIFO_EMPTY)
{
wake_fifo_thread(tgui);
thread_wait_event(tgui->fifo_not_full_event, 1);
}
}
static void tgui_queue(tgui_t *tgui, uint32_t addr, uint32_t val, uint32_t type)
{
fifo_entry_t *fifo = &tgui->fifo[tgui->fifo_write_idx & FIFO_MASK];
if (FIFO_FULL)
{
thread_reset_event(tgui->fifo_not_full_event);
if (FIFO_FULL)
{
thread_wait_event(tgui->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/
}
}
fifo->val = val;
fifo->addr_type = (addr & FIFO_ADDR) | type;
tgui->fifo_write_idx++;
if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8)
wake_fifo_thread(tgui);
}
void tgui_accel_write(uint32_t addr, uint8_t val, void *p)
{
tgui_t *tgui = (tgui_t *)p;
if ((addr & ~0xff) != 0xbff00)
return;
tgui_queue(tgui, addr, val, FIFO_WRITE_BYTE);
}
void tgui_accel_write_w(uint32_t addr, uint16_t val, void *p)
{
tgui_t *tgui = (tgui_t *)p;
@@ -1549,13 +1677,9 @@ uint8_t tgui_accel_read(uint32_t addr, void *p)
tgui_t *tgui = (tgui_t *)p;
if ((addr & ~0xff) != 0xbff00)
return 0xff;
if ((addr & 0xff) != 0x20)
tgui_wait_fifo_idle(tgui);
switch (addr & 0xff)
{
case 0x20: /*Status*/
if (!FIFO_EMPTY)
return 1 << 5;
return 0;
case 0x27: /*ROP*/
@@ -1661,9 +1785,9 @@ void tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *p)
tgui_t *tgui = (tgui_t *)svga->p;
if (tgui->write_blitter)
tgui_queue(tgui, addr, val, FIFO_WRITE_FB_BYTE);
tgui_accel_command(8, val << 24, tgui);
else
svga_write_linear(addr, val, svga);
svga_write_linear(addr, val, svga);
}
void tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *p)
@@ -1672,9 +1796,9 @@ void tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *p)
tgui_t *tgui = (tgui_t *)svga->p;
if (tgui->write_blitter)
tgui_queue(tgui, addr, val, FIFO_WRITE_FB_WORD);
tgui_accel_command(16, (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)) << 16, tgui);
else
svga_writew_linear(addr, val, svga);
svga_writew_linear(addr, val, svga);
}
void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *p)
@@ -1683,9 +1807,9 @@ void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *p)
tgui_t *tgui = (tgui_t *)svga->p;
if (tgui->write_blitter)
tgui_queue(tgui, addr, val, FIFO_WRITE_FB_LONG);
tgui_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), tgui);
else
svga_writel_linear(addr, val, svga);
svga_writel_linear(addr, val, svga);
}
static void *tgui_init(const device_t *info)
@@ -1736,30 +1860,40 @@ static void *tgui_init(const device_t *info)
mem_mapping_disable(&tgui->accel_mapping);
io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui);
if (tgui->type >= TGUI_9440)
if (tgui->type >= TGUI_9440) {
io_sethandler(0x43c8, 0x0002, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui);
io_sethandler(0x2120, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x2122, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x2124, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x2127, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x2128, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x212b, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x212c, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x2130, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x2134, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x2138, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x213a, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x213c, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x213e, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x2140, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x2142, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
io_sethandler(0x2180, 0x0080, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui);
}
if ((info->flags & DEVICE_PCI) && (tgui->type >= TGUI_9440))
pci_add_card(PCI_ADD_VIDEO, tgui_pci_read, tgui_pci_write, tgui);
tgui->i2c = i2c_gpio_init("ddc_tgui9440");
tgui->ddc = ddc_init(i2c_gpio_get_bus(tgui->i2c));
tgui->wake_fifo_thread = thread_create_event();
tgui->fifo_not_full_event = thread_create_event();
tgui->fifo_thread = thread_create(fifo_thread, tgui);
return tgui;
}
static int tgui9400cxi_available()
{
return rom_present("roms/video/tgui9440/9400CXI.vbi");
return rom_present(ROM_TGUI_9400CXI);
}
static int tgui9440_available()
{
return rom_present("roms/video/tgui9440/9440.vbi");
return rom_present(ROM_TGUI_9440);
}
void tgui_close(void *p)
@@ -1768,13 +1902,6 @@ void tgui_close(void *p)
svga_close(&tgui->svga);
ddc_close(tgui->ddc);
i2c_gpio_close(tgui->i2c);
thread_kill(tgui->fifo_thread);
thread_destroy_event(tgui->wake_fifo_thread);
thread_destroy_event(tgui->fifo_not_full_event);
free(tgui);
}