mirror of
https://github.com/86Box/86Box.git
synced 2026-02-24 02:18:20 -07:00
Merge remote-tracking branch 'upstream/master' into feature/ich2
This commit is contained in:
@@ -68,7 +68,8 @@ enum {
|
||||
};
|
||||
|
||||
/*Addition flags returned by CPUID function 0x80000001*/
|
||||
#define CPUID_3DNOW (1UL << 31UL)
|
||||
#define CPUID_3DNOW (1UL << 31UL)
|
||||
#define CPUID_3DNOWE (1UL << 30UL)
|
||||
|
||||
/* Make sure this is as low as possible. */
|
||||
cpu_state_t cpu_state;
|
||||
@@ -1167,6 +1168,11 @@ cpu_set(void)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if ((cpu_s->cpu_type == CPU_K6_2P) || (cpu_s->cpu_type == CPU_K6_3P)) {
|
||||
x86_opcodes_3DNOW = ops_3DNOWE;
|
||||
x86_dynarec_opcodes_3DNOW = dynarec_ops_3DNOWE;
|
||||
}
|
||||
|
||||
timing_rr = 1; /* register dest - register src */
|
||||
timing_rm = 2; /* register dest - memory src */
|
||||
timing_mr = 3; /* memory dest - register src */
|
||||
@@ -1202,6 +1208,8 @@ cpu_set(void)
|
||||
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX;
|
||||
if (cpu_s->cpu_type >= CPU_K6_2)
|
||||
cpu_features |= CPU_FEATURE_3DNOW;
|
||||
if ((cpu_s->cpu_type == CPU_K6_2P) || (cpu_s->cpu_type == CPU_K6_3P))
|
||||
cpu_features |= CPU_FEATURE_3DNOWE;
|
||||
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
|
||||
#if defined(DEV_BRANCH) && defined(USE_AMD_K5)
|
||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE;
|
||||
@@ -1831,7 +1839,7 @@ cpu_CPUID(void)
|
||||
case 0x80000001:
|
||||
EAX = CPUID + 0x100;
|
||||
EBX = ECX = 0;
|
||||
EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW;
|
||||
EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW | CPUID_3DNOWE;
|
||||
break;
|
||||
case 0x80000002: /* Processor name string */
|
||||
EAX = 0x2d444d41; /* AMD-K6(tm)-III P */
|
||||
|
||||
@@ -509,14 +509,15 @@ extern int isibm486;
|
||||
extern int is_nec;
|
||||
extern int is_rapidcad;
|
||||
extern int hasfpu;
|
||||
#define CPU_FEATURE_RDTSC (1 << 0)
|
||||
#define CPU_FEATURE_MSR (1 << 1)
|
||||
#define CPU_FEATURE_MMX (1 << 2)
|
||||
#define CPU_FEATURE_CR4 (1 << 3)
|
||||
#define CPU_FEATURE_VME (1 << 4)
|
||||
#define CPU_FEATURE_CX8 (1 << 5)
|
||||
#define CPU_FEATURE_3DNOW (1 << 6)
|
||||
#define CPU_FEATURE_RDTSC (1 << 0)
|
||||
#define CPU_FEATURE_MSR (1 << 1)
|
||||
#define CPU_FEATURE_MMX (1 << 2)
|
||||
#define CPU_FEATURE_CR4 (1 << 3)
|
||||
#define CPU_FEATURE_VME (1 << 4)
|
||||
#define CPU_FEATURE_CX8 (1 << 5)
|
||||
#define CPU_FEATURE_3DNOW (1 << 6)
|
||||
#define CPU_FEATURE_SYSCALL (1 << 7)
|
||||
#define CPU_FEATURE_3DNOWE (1 << 8)
|
||||
|
||||
extern uint32_t cpu_features;
|
||||
|
||||
|
||||
@@ -148,6 +148,7 @@ extern const OpFn dynarec_ops_fpu_686_df_a32[256];
|
||||
extern const OpFn dynarec_ops_REPE[1024];
|
||||
extern const OpFn dynarec_ops_REPNE[1024];
|
||||
extern const OpFn dynarec_ops_3DNOW[256];
|
||||
extern const OpFn dynarec_ops_3DNOWE[256];
|
||||
#else
|
||||
void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f);
|
||||
#endif
|
||||
@@ -250,6 +251,7 @@ extern const OpFn ops_fpu_686_df_a32[256];
|
||||
extern const OpFn ops_REPE[1024];
|
||||
extern const OpFn ops_REPNE[1024];
|
||||
extern const OpFn ops_3DNOW[256];
|
||||
extern const OpFn ops_3DNOWE[256];
|
||||
|
||||
#define C0 (1<<8)
|
||||
#define C1 (1<<9)
|
||||
|
||||
@@ -58,6 +58,17 @@ static int opPF2ID(uint32_t fetchdat)
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPF2IW(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].sw[0] = (int32_t)src.f[0];
|
||||
cpu_state.MM[cpu_reg].sw[1] = (int32_t)src.f[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFACC(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
@@ -71,6 +82,47 @@ static int opPFACC(uint32_t fetchdat)
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFNACC(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
float tempf;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
tempf = cpu_state.MM[cpu_reg].f[0] - cpu_state.MM[cpu_reg].f[1];
|
||||
cpu_state.MM[cpu_reg].f[1] = src.f[0] - src.f[1];
|
||||
cpu_state.MM[cpu_reg].f[0] = tempf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFPNACC(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
float tempf;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
tempf = cpu_state.MM[cpu_reg].f[0] - cpu_state.MM[cpu_reg].f[1];
|
||||
cpu_state.MM[cpu_reg].f[1] = src.f[0] + src.f[1];
|
||||
cpu_state.MM[cpu_reg].f[0] = tempf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSWAPD(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
float tempf, tempf2;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
/* We have to do this in case source and destination overlap. */
|
||||
tempf = src.f[0];
|
||||
tempf2 = src.f[1];
|
||||
cpu_state.MM[cpu_reg].f[1] = tempf;
|
||||
cpu_state.MM[cpu_reg].f[0] = tempf2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPFADD(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
@@ -268,6 +320,17 @@ static int opPI2FD(uint32_t fetchdat)
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPI2FW(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].f[0] = (float)src.sw[0];
|
||||
cpu_state.MM[cpu_reg].f[1] = (float)src.sw[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPMULHRW(uint32_t fetchdat)
|
||||
{
|
||||
if (cpu_mod == 3)
|
||||
@@ -318,6 +381,30 @@ const OpFn OP_TABLE(3DNOW)[256] =
|
||||
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
};
|
||||
|
||||
const OpFn OP_TABLE(3DNOWE)[256] =
|
||||
{
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPI2FW, opPI2FD, ILLEGAL, ILLEGAL,
|
||||
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPF2IW, opPF2ID, ILLEGAL, ILLEGAL,
|
||||
/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
|
||||
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
|
||||
/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPFNACC, ILLEGAL, ILLEGAL, ILLEGAL, opPFPNACC, ILLEGAL,
|
||||
/*90*/ opPFCMPGE, ILLEGAL, ILLEGAL, ILLEGAL, opPFMIN, ILLEGAL, opPFRCP, opPFRSQRT, ILLEGAL, ILLEGAL, opPFSUB, ILLEGAL, ILLEGAL, ILLEGAL, opPFADD, ILLEGAL,
|
||||
/*a0*/ opPFCMPGT, ILLEGAL, ILLEGAL, ILLEGAL, opPFMAX, ILLEGAL, opPFRCPIT1, opPFRSQIT1, ILLEGAL, ILLEGAL, opPFSUBR, ILLEGAL, ILLEGAL, ILLEGAL, opPFACC, ILLEGAL,
|
||||
/*b0*/ opPFCMPEQ, ILLEGAL, ILLEGAL, ILLEGAL, opPFMUL, ILLEGAL, opPFRCPIT2, opPMULHRW, ILLEGAL, ILLEGAL, ILLEGAL, opPSWAPD, ILLEGAL, ILLEGAL, ILLEGAL, opPAVGUSB,
|
||||
|
||||
/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
};
|
||||
|
||||
static int op3DNOW_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t opcode;
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# 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.
|
||||
# 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.
|
||||
# This file is part of the 86Box distribution.
|
||||
#
|
||||
# CMake build script.
|
||||
# CMake build script.
|
||||
#
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
#
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
#
|
||||
|
||||
add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c
|
||||
@@ -20,12 +20,12 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c
|
||||
vid_svga_render.c vid_ddc.c vid_vga.c vid_ati_eeprom.c vid_ati18800.c
|
||||
vid_ati28800.c vid_ati_mach64.c vid_ati68860_ramdac.c vid_bt48x_ramdac.c
|
||||
vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.c
|
||||
vid_et4000.c vid_sc1148x_ramdac.c vid_sc1502x_ramdac.c vid_et4000w32.c
|
||||
vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c vid_rtg310x.c
|
||||
vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c
|
||||
vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c
|
||||
vid_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c
|
||||
vid_xga.c)
|
||||
vid_et3000.c vid_et4000.c vid_sc1148x_ramdac.c vid_sc1502x_ramdac.c
|
||||
vid_et4000w32.c vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c
|
||||
vid_rtg310x.c vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c
|
||||
vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c
|
||||
vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_nga.c
|
||||
vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c)
|
||||
|
||||
if(MGA)
|
||||
target_compile_definitions(vid PRIVATE USE_MGA)
|
||||
|
||||
301
src/video/vid_et3000.c
Normal file
301
src/video/vid_et3000.c
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* 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 Tseng Labs ET3000.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/mca.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/vid_svga_render.h>
|
||||
|
||||
#define BIOS_ROM_PATH "roms/video/et3000/Tseng ET3000AX ISA VGA-VGA ULTRA.bin"
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int type;
|
||||
|
||||
svga_t svga;
|
||||
|
||||
rom_t bios_rom;
|
||||
|
||||
uint8_t banking;
|
||||
} et3000_t;
|
||||
|
||||
static video_timings_t timing_et3000_isa = { VIDEO_ISA, 3, 3, 6, 5, 5, 10 };
|
||||
|
||||
static uint8_t et3000_in(uint16_t addr, void *priv);
|
||||
static void et3000_out(uint16_t addr, uint8_t val, void *priv);
|
||||
|
||||
static uint8_t
|
||||
et3000_in(uint16_t addr, void *priv)
|
||||
{
|
||||
et3000_t *dev = (et3000_t *) priv;
|
||||
svga_t *svga = &dev->svga;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3cd: /*Banking*/
|
||||
return dev->banking;
|
||||
|
||||
case 0x3d4:
|
||||
return svga->crtcreg;
|
||||
|
||||
case 0x3d5:
|
||||
return svga->crtc[svga->crtcreg];
|
||||
}
|
||||
|
||||
return svga_in(addr, svga);
|
||||
}
|
||||
|
||||
static void
|
||||
et3000_out(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
et3000_t *dev = (et3000_t *) priv;
|
||||
svga_t *svga = &dev->svga;
|
||||
uint8_t old;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3c0:
|
||||
case 0x3c1:
|
||||
if (svga->attrff && (svga->attraddr == 0x16)) {
|
||||
svga->attrregs[0x16] = val;
|
||||
svga->chain4 &= ~0x10;
|
||||
if (svga->gdcreg[5] & 0x40)
|
||||
svga->chain4 |= (svga->attrregs[0x16] & 0x10);
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3c5:
|
||||
if (svga->seqaddr == 4) {
|
||||
svga->seqregs[4] = val;
|
||||
|
||||
svga->chain2_write = !(val & 4);
|
||||
svga->chain4 = (svga->chain4 & ~8) | (val & 8);
|
||||
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4 && !(svga->adv_flags & FLAG_ADDR_BY8);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3cf:
|
||||
if ((svga->gdcaddr & 15) == 5) {
|
||||
svga->chain4 &= ~0x10;
|
||||
if (val & 0x40)
|
||||
svga->chain4 |= (svga->attrregs[0x16] & 0x10);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3cd: /*Banking*/
|
||||
dev->banking = val;
|
||||
if (!(svga->crtc[0x23] & 0x80) && !(svga->gdcreg[6] & 0x08)) {
|
||||
switch ((val >> 6) & 3) {
|
||||
case 0: /*128K segments*/
|
||||
svga->write_bank = (val & 7) << 17;
|
||||
svga->read_bank = ((val >> 3) & 7) << 17;
|
||||
break;
|
||||
case 1: /*64K segments*/
|
||||
svga->write_bank = (val & 7) << 16;
|
||||
svga->read_bank = ((val >> 3) & 7) << 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x3d4:
|
||||
svga->crtcreg = val & 0x3f;
|
||||
return;
|
||||
|
||||
case 0x3d5:
|
||||
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
|
||||
return;
|
||||
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
|
||||
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
|
||||
old = svga->crtc[svga->crtcreg];
|
||||
svga->crtc[svga->crtcreg] = val;
|
||||
|
||||
if (old != val) {
|
||||
if (svga->crtcreg < 0x0e || svga->crtcreg > 0x10) {
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
static void
|
||||
et3000_recalctimings(svga_t *svga)
|
||||
{
|
||||
svga->ma_latch |= (svga->crtc[0x23] & 2) << 15;
|
||||
if (svga->crtc[0x25] & 1)
|
||||
svga->vblankstart |= 0x400;
|
||||
if (svga->crtc[0x25] & 2)
|
||||
svga->vtotal |= 0x400;
|
||||
if (svga->crtc[0x25] & 4)
|
||||
svga->dispend |= 0x400;
|
||||
if (svga->crtc[0x25] & 8)
|
||||
svga->vsyncstart |= 0x400;
|
||||
if (svga->crtc[0x25] & 0x10)
|
||||
svga->split |= 0x400;
|
||||
|
||||
svga->interlace = !!(svga->crtc[0x25] & 0x80);
|
||||
|
||||
if (svga->attrregs[0x16] & 0x10) {
|
||||
svga->ma_latch <<= (1 << 0);
|
||||
svga->rowoffset <<= (1 << 0);
|
||||
switch (svga->gdcreg[5] & 0x60) {
|
||||
case 0x00:
|
||||
svga->render = svga_render_4bpp_highres;
|
||||
svga->hdisp *= 2;
|
||||
break;
|
||||
case 0x20:
|
||||
svga->render = svga_render_2bpp_highres;
|
||||
break;
|
||||
case 0x40:
|
||||
case 0x60:
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* pclog("HDISP = %i, HTOTAL = %i, ROWOFFSET = %i, INTERLACE = %i\n",
|
||||
svga->hdisp, svga->htotal, svga->rowoffset, svga->interlace); */
|
||||
|
||||
switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x24] << 1) & 4)) {
|
||||
case 0:
|
||||
case 1:
|
||||
break;
|
||||
case 3:
|
||||
svga->clock = (cpuclock * (double) (1ull << 32)) / 40000000.0;
|
||||
break;
|
||||
case 5:
|
||||
svga->clock = (cpuclock * (double) (1ull << 32)) / 65000000.0;
|
||||
break;
|
||||
default:
|
||||
svga->clock = (cpuclock * (double) (1ull << 32)) / 36000000.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
et3000_init(const device_t *info)
|
||||
{
|
||||
const char *fn;
|
||||
et3000_t *dev;
|
||||
|
||||
dev = (et3000_t *) malloc(sizeof(et3000_t));
|
||||
memset(dev, 0x00, sizeof(et3000_t));
|
||||
dev->name = info->name;
|
||||
dev->type = info->local;
|
||||
fn = BIOS_ROM_PATH;
|
||||
|
||||
switch (dev->type) {
|
||||
case 0: /* ISA ET3000AX */
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et3000_isa);
|
||||
svga_init(info, &dev->svga, dev, device_get_config_int("memory") << 10,
|
||||
et3000_recalctimings, et3000_in, et3000_out,
|
||||
NULL, NULL);
|
||||
io_sethandler(0x03c0, 32,
|
||||
et3000_in, NULL, NULL, et3000_out, NULL, NULL, dev);
|
||||
break;
|
||||
}
|
||||
|
||||
rom_init(&dev->bios_rom, (char *) fn,
|
||||
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
dev->svga.bpp = 8;
|
||||
dev->svga.miscout = 1;
|
||||
|
||||
dev->svga.packed_chain4 = 1;
|
||||
|
||||
return (dev);
|
||||
}
|
||||
|
||||
static void
|
||||
et3000_close(void *priv)
|
||||
{
|
||||
et3000_t *dev = (et3000_t *) priv;
|
||||
|
||||
svga_close(&dev->svga);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
et3000_speed_changed(void *priv)
|
||||
{
|
||||
et3000_t *dev = (et3000_t *) priv;
|
||||
|
||||
svga_recalctimings(&dev->svga);
|
||||
}
|
||||
|
||||
static void
|
||||
et3000_force_redraw(void *priv)
|
||||
{
|
||||
et3000_t *dev = (et3000_t *) priv;
|
||||
|
||||
dev->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
static int
|
||||
et3000_available(void)
|
||||
{
|
||||
return rom_present(BIOS_ROM_PATH);
|
||||
}
|
||||
|
||||
static const device_config_t et3000_config[] = {
|
||||
{ .name = "memory",
|
||||
.description = "Memory size",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_int = 512,
|
||||
.selection = {
|
||||
{ .description = "256 KB",
|
||||
.value = 256 },
|
||||
{ .description = "512 KB",
|
||||
.value = 512 },
|
||||
{ .description = "1 MB",
|
||||
.value = 1024 },
|
||||
{ .description = "" } } },
|
||||
{ .type = CONFIG_END }
|
||||
};
|
||||
|
||||
const device_t et3000_isa_device = {
|
||||
.name = "Tseng Labs ET3000AX (ISA)",
|
||||
.internal_name = "et3000ax",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = et3000_init,
|
||||
.close = et3000_close,
|
||||
.reset = NULL,
|
||||
{ .available = et3000_available },
|
||||
.speed_changed = et3000_speed_changed,
|
||||
.force_redraw = et3000_force_redraw,
|
||||
.config = et3000_config
|
||||
};
|
||||
@@ -143,6 +143,7 @@ video_cards[] = {
|
||||
{ &nec_sv9000_device },
|
||||
{ &et4000k_isa_device },
|
||||
{ &et2000_device },
|
||||
{ &et3000_isa_device },
|
||||
{ &et4000_isa_device },
|
||||
{ &et4000w32_device },
|
||||
{ &et4000w32i_isa_device },
|
||||
|
||||
@@ -714,6 +714,7 @@ VIDOBJ := agpgart.o video.o \
|
||||
vid_bt48x_ramdac.o \
|
||||
vid_av9194.o vid_icd2061.o vid_ics2494.o vid_ics2595.o \
|
||||
vid_cl54xx.o \
|
||||
vid_et3000.o \
|
||||
vid_et4000.o vid_sc1148x_ramdac.o \
|
||||
vid_sc1502x_ramdac.o \
|
||||
vid_et4000w32.o vid_stg_ramdac.o \
|
||||
|
||||
Reference in New Issue
Block a user