mirror of
https://github.com/86Box/86Box.git
synced 2026-03-03 19:28:22 -07:00
Merge remote-tracking branch 'upstream/master' into feature/machine_z150
This commit is contained in:
@@ -68,7 +68,8 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*Addition flags returned by CPUID function 0x80000001*/
|
/*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. */
|
/* Make sure this is as low as possible. */
|
||||||
cpu_state_t cpu_state;
|
cpu_state_t cpu_state;
|
||||||
@@ -1167,6 +1168,11 @@ cpu_set(void)
|
|||||||
# endif
|
# endif
|
||||||
#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_rr = 1; /* register dest - register src */
|
||||||
timing_rm = 2; /* register dest - memory src */
|
timing_rm = 2; /* register dest - memory src */
|
||||||
timing_mr = 3; /* memory dest - register 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;
|
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)
|
if (cpu_s->cpu_type >= CPU_K6_2)
|
||||||
cpu_features |= CPU_FEATURE_3DNOW;
|
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);
|
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
|
||||||
#if defined(DEV_BRANCH) && defined(USE_AMD_K5)
|
#if defined(DEV_BRANCH) && defined(USE_AMD_K5)
|
||||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE;
|
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE;
|
||||||
@@ -1831,7 +1839,7 @@ cpu_CPUID(void)
|
|||||||
case 0x80000001:
|
case 0x80000001:
|
||||||
EAX = CPUID + 0x100;
|
EAX = CPUID + 0x100;
|
||||||
EBX = ECX = 0;
|
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;
|
break;
|
||||||
case 0x80000002: /* Processor name string */
|
case 0x80000002: /* Processor name string */
|
||||||
EAX = 0x2d444d41; /* AMD-K6(tm)-III P */
|
EAX = 0x2d444d41; /* AMD-K6(tm)-III P */
|
||||||
|
|||||||
@@ -503,14 +503,15 @@ extern int isibm486;
|
|||||||
extern int is_nec;
|
extern int is_nec;
|
||||||
extern int is_rapidcad;
|
extern int is_rapidcad;
|
||||||
extern int hasfpu;
|
extern int hasfpu;
|
||||||
#define CPU_FEATURE_RDTSC (1 << 0)
|
#define CPU_FEATURE_RDTSC (1 << 0)
|
||||||
#define CPU_FEATURE_MSR (1 << 1)
|
#define CPU_FEATURE_MSR (1 << 1)
|
||||||
#define CPU_FEATURE_MMX (1 << 2)
|
#define CPU_FEATURE_MMX (1 << 2)
|
||||||
#define CPU_FEATURE_CR4 (1 << 3)
|
#define CPU_FEATURE_CR4 (1 << 3)
|
||||||
#define CPU_FEATURE_VME (1 << 4)
|
#define CPU_FEATURE_VME (1 << 4)
|
||||||
#define CPU_FEATURE_CX8 (1 << 5)
|
#define CPU_FEATURE_CX8 (1 << 5)
|
||||||
#define CPU_FEATURE_3DNOW (1 << 6)
|
#define CPU_FEATURE_3DNOW (1 << 6)
|
||||||
#define CPU_FEATURE_SYSCALL (1 << 7)
|
#define CPU_FEATURE_SYSCALL (1 << 7)
|
||||||
|
#define CPU_FEATURE_3DNOWE (1 << 8)
|
||||||
|
|
||||||
extern uint32_t cpu_features;
|
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_REPE[1024];
|
||||||
extern const OpFn dynarec_ops_REPNE[1024];
|
extern const OpFn dynarec_ops_REPNE[1024];
|
||||||
extern const OpFn dynarec_ops_3DNOW[256];
|
extern const OpFn dynarec_ops_3DNOW[256];
|
||||||
|
extern const OpFn dynarec_ops_3DNOWE[256];
|
||||||
#else
|
#else
|
||||||
void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f);
|
void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f);
|
||||||
#endif
|
#endif
|
||||||
@@ -250,6 +251,7 @@ extern const OpFn ops_fpu_686_df_a32[256];
|
|||||||
extern const OpFn ops_REPE[1024];
|
extern const OpFn ops_REPE[1024];
|
||||||
extern const OpFn ops_REPNE[1024];
|
extern const OpFn ops_REPNE[1024];
|
||||||
extern const OpFn ops_3DNOW[256];
|
extern const OpFn ops_3DNOW[256];
|
||||||
|
extern const OpFn ops_3DNOWE[256];
|
||||||
|
|
||||||
#define C0 (1<<8)
|
#define C0 (1<<8)
|
||||||
#define C1 (1<<9)
|
#define C1 (1<<9)
|
||||||
|
|||||||
@@ -58,6 +58,17 @@ static int opPF2ID(uint32_t fetchdat)
|
|||||||
|
|
||||||
return 0;
|
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)
|
static int opPFACC(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
MMX_REG src;
|
MMX_REG src;
|
||||||
@@ -71,6 +82,47 @@ static int opPFACC(uint32_t fetchdat)
|
|||||||
|
|
||||||
return 0;
|
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)
|
static int opPFADD(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
MMX_REG src;
|
MMX_REG src;
|
||||||
@@ -268,6 +320,17 @@ static int opPI2FD(uint32_t fetchdat)
|
|||||||
|
|
||||||
return 0;
|
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)
|
static int opPMULHRW(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
if (cpu_mod == 3)
|
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,
|
/*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)
|
static int op3DNOW_a16(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
uint8_t opcode;
|
uint8_t opcode;
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
#
|
#
|
||||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||||
# running old operating systems and software designed for IBM
|
# running old operating systems and software designed for IBM
|
||||||
# PC systems and compatibles from 1981 through fairly recent
|
# PC systems and compatibles from 1981 through fairly recent
|
||||||
# system designs based on the PCI bus.
|
# 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
|
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_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_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_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_et3000.c vid_et4000.c vid_sc1148x_ramdac.c vid_sc1502x_ramdac.c
|
||||||
vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c vid_rtg310x.c
|
vid_et4000w32.c vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c
|
||||||
vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c
|
vid_rtg310x.c vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c
|
||||||
vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c
|
vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c
|
||||||
vid_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c
|
vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_nga.c
|
||||||
vid_xga.c)
|
vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c)
|
||||||
|
|
||||||
if(MGA)
|
if(MGA)
|
||||||
target_compile_definitions(vid PRIVATE USE_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 },
|
{ &nec_sv9000_device },
|
||||||
{ &et4000k_isa_device },
|
{ &et4000k_isa_device },
|
||||||
{ &et2000_device },
|
{ &et2000_device },
|
||||||
|
{ &et3000_isa_device },
|
||||||
{ &et4000_isa_device },
|
{ &et4000_isa_device },
|
||||||
{ &et4000w32_device },
|
{ &et4000w32_device },
|
||||||
{ &et4000w32i_isa_device },
|
{ &et4000w32i_isa_device },
|
||||||
|
|||||||
@@ -708,6 +708,7 @@ VIDOBJ := agpgart.o video.o \
|
|||||||
vid_bt48x_ramdac.o \
|
vid_bt48x_ramdac.o \
|
||||||
vid_av9194.o vid_icd2061.o vid_ics2494.o vid_ics2595.o \
|
vid_av9194.o vid_icd2061.o vid_ics2494.o vid_ics2595.o \
|
||||||
vid_cl54xx.o \
|
vid_cl54xx.o \
|
||||||
|
vid_et3000.o \
|
||||||
vid_et4000.o vid_sc1148x_ramdac.o \
|
vid_et4000.o vid_sc1148x_ramdac.o \
|
||||||
vid_sc1502x_ramdac.o \
|
vid_sc1502x_ramdac.o \
|
||||||
vid_et4000w32.o vid_stg_ramdac.o \
|
vid_et4000w32.o vid_stg_ramdac.o \
|
||||||
|
|||||||
Reference in New Issue
Block a user