Merge branch '86Box:master' into machine_23

This commit is contained in:
BurnedPinguin
2024-01-18 11:51:46 +01:00
committed by GitHub
65 changed files with 3584 additions and 1068 deletions

View File

@@ -1952,8 +1952,18 @@ cdrom_hard_reset(void)
dev->cd_status = CD_STATUS_EMPTY;
if (dev->host_drive == 200)
if (dev->host_drive == 200) {
#ifdef _WIN32
if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/'))
dev->image_path[strlen(dev->image_path) - 1] = '\\';
#else
if ((strlen(dev->image_path) >= 1) &&
(dev->image_path[strlen(dev->image_path) - 1] == '\\'))
dev->image_path[strlen(dev->image_path) - 1] = '/';
#endif
cdrom_image_open(dev, dev->image_path);
}
}
}
@@ -2042,6 +2052,15 @@ cdrom_reload(uint8_t id)
if (dev->prev_host_drive == 200) {
/* Reload a previous image. */
strcpy(dev->image_path, dev->prev_image_path);
#ifdef _WIN32
if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/'))
dev->image_path[strlen(dev->image_path) - 1] = '\\';
#else
if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '\\'))
dev->image_path[strlen(dev->image_path) - 1] = '/';
#endif
cdrom_image_open(dev, dev->image_path);
cdrom_insert(id);

View File

@@ -240,6 +240,7 @@ exec386_2386(int32_t cycs)
cycdiff = 0;
oldcyc = cycles;
while (cycdiff < cycle_period) {
int ins_fetch_fault = 0;
ins_cycles = cycles;
#ifndef USE_NEW_DYNAREC
@@ -259,6 +260,14 @@ exec386_2386(int32_t cycs)
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
ol = opcode_length[fetchdat & 0xff];
CHECK_READ_CS(MIN(ol, 4));
ins_fetch_fault = cpu_386_check_instruction_fault();
if (!cpu_state.abrt && ins_fetch_fault) {
x86gen();
ins_fetch_fault = 0;
/* No instructions executed at this point. */
goto block_ended;
}
if (!cpu_state.abrt) {
#ifdef ENABLE_386_LOG
@@ -267,7 +276,7 @@ exec386_2386(int32_t cycs)
#endif
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
trap |= !!(cpu_state.flags & T_FLAG);
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
@@ -287,6 +296,7 @@ exec386_2386(int32_t cycs)
if (cpu_end_block_after_ins)
cpu_end_block_after_ins--;
block_ended:
if (cpu_state.abrt) {
flags_rebuild();
tempi = cpu_state.abrt & ABRT_MASK;
@@ -309,14 +319,17 @@ exec386_2386(int32_t cycs)
#endif
}
}
if (!x86_was_reset && ins_fetch_fault)
x86gen(); /* This is supposed to be the first one serviced by the processor according to the manual. */
} else if (trap) {
flags_rebuild();
if (trap & 2) dr[6] |= 0x8000;
if (trap & 1) dr[6] |= 0x4000;
trap = 0;
#ifndef USE_NEW_DYNAREC
oldcs = CS;
#endif
cpu_state.oldpc = cpu_state.pc;
dr[6] |= 0x4000;
x86_int(1);
}

View File

@@ -80,6 +80,7 @@ int smm_in_hlt = 0;
int smi_block = 0;
int prefetch_prefixes = 0;
int rf_flag_no_clear = 0;
int tempc;
int oldcpl;
@@ -1491,7 +1492,7 @@ x86_int_sw(int num)
}
}
trap = 0;
trap &= ~1;
CPU_BLOCK_END();
}
@@ -1534,7 +1535,7 @@ x86_int_sw_rm(int num)
#endif
cycles -= timing_int_rm;
trap = 0;
trap &= ~1;
CPU_BLOCK_END();
return 0;
@@ -1655,6 +1656,37 @@ cpu_386_flags_rebuild(void)
flags_rebuild();
}
extern uint64_t mmutranslate_noabrt_2386(uint32_t addr, int rw);
int
cpu_386_check_instruction_fault(void)
{
int i = 0;
int fault = 0;
/* Report no fault if RF is set. */
if (cpu_state.eflags & RF_FLAG)
return 0;
/* Make sure breakpoints are enabled. */
if (!(dr[7] & 0xFF))
return 0;
for (i = 0; i < 4; i++) {
int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))) && !(dr[7] & (0x30000 << (4 * i)));
uint32_t translated_addr = 0xffffffff;
if (!breakpoint_enabled)
continue;
translated_addr = dr[i];
if ((cs + cpu_state.pc) == (uint32_t)translated_addr) {
dr[6] |= (1 << i);
fault = 1;
}
}
return fault;
}
int
sysenter(uint32_t fetchdat)
{

View File

@@ -674,3 +674,8 @@ seteaq(uint64_t v)
cpu_state.pc += 2
#endif
/* Resume Flag handling. */
extern int rf_flag_no_clear;
int cpu_386_check_instruction_fault(void);

View File

@@ -268,6 +268,12 @@ exec386_dynarec_int(void)
cpu_block_end = 0;
x86_was_reset = 0;
if (trap == 2) {
/* Handle the T bit in the new TSS first. */
CPU_BLOCK_END();
goto block_ended;
}
while (!cpu_block_end) {
# ifndef USE_NEW_DYNAREC
oldcs = CS;
@@ -321,13 +327,14 @@ exec386_dynarec_int(void)
CPU_BLOCK_END();
}
block_ended:
if (!cpu_state.abrt && trap) {
dr[6] |= (trap == 2) ? 0x8000 : 0x4000;
trap = 0;
# ifndef USE_NEW_DYNAREC
oldcs = CS;
# endif
cpu_state.oldpc = cpu_state.pc;
dr[6] |= 0x4000;
x86_int(1);
}
@@ -542,7 +549,7 @@ exec386_dynarec_dyn(void)
# endif
CPU_BLOCK_END();
if (cpu_state.flags & T_FLAG)
if ((cpu_state.flags & T_FLAG) || (trap == 2))
CPU_BLOCK_END();
if (smi_line)
CPU_BLOCK_END();

View File

@@ -181,7 +181,11 @@ extern void x386_dynarec_log(const char *fmt, ...);
#ifndef OPS_286_386
# include "x86_ops_cyrix.h"
#endif
#include "x86_ops_flag.h"
#ifdef OPS_286_386
# include "x86_ops_flag_2386.h"
#else
# include "x86_ops_flag.h"
#endif
#include "x86_ops_fpu.h"
#include "x86_ops_inc_dec.h"
#include "x86_ops_int.h"
@@ -200,7 +204,11 @@ extern void x386_dynarec_log(const char *fmt, ...);
# include "x86_ops_mmx_shift.h"
#endif
#include "x86_ops_mov.h"
#include "x86_ops_mov_ctrl.h"
#ifdef OPS_286_386
# include "x86_ops_mov_ctrl_2386.h"
#else
# include "x86_ops_mov_ctrl.h"
#endif
#include "x86_ops_mov_seg.h"
#include "x86_ops_movx.h"
#ifndef OPS_286_386
@@ -218,7 +226,11 @@ extern void x386_dynarec_log(const char *fmt, ...);
# include "x86_ops_rep.h"
# endif
#endif
#include "x86_ops_ret.h"
#ifdef OPS_286_386
# include "x86_ops_ret_2386.h"
#else
# include "x86_ops_ret.h"
#endif
#include "x86_ops_set.h"
#include "x86_ops_stack.h"
#ifdef OPS_286_386

View File

@@ -563,9 +563,10 @@ reset_808x(int hard)
_opseg[3] = &cpu_state.seg_ds;
pfq_size = (is8086) ? 6 : 4;
pfq_clear();
}
pfq_clear();
load_cs(0xFFFF);
cpu_state.pc = 0;
if (is_nec)

323
src/cpu/x86_ops_flag_2386.h Normal file
View File

@@ -0,0 +1,323 @@
static int
opCMC(uint32_t fetchdat)
{
flags_rebuild();
cpu_state.flags ^= C_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opCLC(uint32_t fetchdat)
{
flags_rebuild();
cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opCLD(uint32_t fetchdat)
{
cpu_state.flags &= ~D_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opCLI(uint32_t fetchdat)
{
if (!IOPLp) {
if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) {
cpu_state.eflags &= ~VIF_FLAG;
} else {
x86gpf(NULL, 0);
return 1;
}
} else
cpu_state.flags &= ~I_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opSTC(uint32_t fetchdat)
{
flags_rebuild();
cpu_state.flags |= C_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opSTD(uint32_t fetchdat)
{
cpu_state.flags |= D_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opSTI(uint32_t fetchdat)
{
if (!IOPLp) {
if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) {
if (cpu_state.eflags & VIP_FLAG) {
x86gpf(NULL, 0);
return 1;
} else
cpu_state.eflags |= VIF_FLAG;
} else {
x86gpf(NULL, 0);
return 1;
}
} else
cpu_state.flags |= I_FLAG;
/*First instruction after STI will always execute, regardless of whether
there is a pending interrupt*/
cpu_end_block_after_ins = 2;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opSAHF(uint32_t fetchdat)
{
flags_rebuild();
cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0);
#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
codegen_flags_changed = 0;
#endif
return 0;
}
static int
opLAHF(uint32_t fetchdat)
{
flags_rebuild();
AH = cpu_state.flags & 0xff;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opPUSHF(uint32_t fetchdat)
{
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
if (cr4 & CR4_VME) {
uint16_t temp;
flags_rebuild();
temp = (cpu_state.flags & ~I_FLAG) | 0x3000;
if (cpu_state.eflags & VIF_FLAG)
temp |= I_FLAG;
PUSH_W(temp);
} else {
x86gpf(NULL, 0);
return 1;
}
} else {
flags_rebuild();
PUSH_W(cpu_state.flags);
}
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 0);
return cpu_state.abrt;
}
static int
opPUSHFD(uint32_t fetchdat)
{
uint16_t tempw;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
x86gpf(NULL, 0);
return 1;
}
if (cpu_CR4_mask & CR4_VME)
tempw = cpu_state.eflags & 0x3c;
else if (CPUID)
tempw = cpu_state.eflags & 0x24;
else
tempw = cpu_state.eflags & 4;
flags_rebuild();
PUSH_L(cpu_state.flags | (tempw << 16));
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0);
return cpu_state.abrt;
}
static int
opPOPF_186(uint32_t fetchdat)
{
uint16_t tempw;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
x86gpf(NULL, 0);
return 1;
}
tempw = POP_W();
if (cpu_state.abrt)
return 1;
if (!(msw & 1))
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
else if (!(CPL))
cpu_state.flags = (tempw & 0x7fd5) | 2;
else if (IOPLp)
cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
else
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
flags_extract();
rf_flag_no_clear = 1;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0);
#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
codegen_flags_changed = 0;
#endif
return 0;
}
static int
opPOPF_286(uint32_t fetchdat)
{
uint16_t tempw;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
x86gpf(NULL, 0);
return 1;
}
tempw = POP_W();
if (cpu_state.abrt)
return 1;
if (!(msw & 1))
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
else if (!(CPL))
cpu_state.flags = (tempw & 0x7fd5) | 2;
else if (IOPLp)
cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
else
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
flags_extract();
rf_flag_no_clear = 1;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0);
#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
codegen_flags_changed = 0;
#endif
return 0;
}
static int
opPOPF(uint32_t fetchdat)
{
uint16_t tempw;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
if (cr4 & CR4_VME) {
uint32_t old_esp = ESP;
tempw = POP_W();
if (cpu_state.abrt) {
ESP = old_esp;
return 1;
}
if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) {
ESP = old_esp;
x86gpf(NULL, 0);
return 1;
}
if (tempw & I_FLAG)
cpu_state.eflags |= VIF_FLAG;
else
cpu_state.eflags &= ~VIF_FLAG;
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
} else {
x86gpf(NULL, 0);
return 1;
}
} else {
tempw = POP_W();
if (cpu_state.abrt)
return 1;
if (!(CPL) || !(msw & 1))
cpu_state.flags = (tempw & 0x7fd5) | 2;
else if (IOPLp)
cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
else
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
}
flags_extract();
rf_flag_no_clear = 1;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0);
#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
codegen_flags_changed = 0;
#endif
return 0;
}
static int
opPOPFD(uint32_t fetchdat)
{
uint32_t templ;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
x86gpf(NULL, 0);
return 1;
}
templ = POP_L();
if (cpu_state.abrt)
return 1;
if (!(CPL) || !(msw & 1))
cpu_state.flags = (templ & 0x7fd5) | 2;
else if (IOPLp)
cpu_state.flags = (cpu_state.flags & 0x3000) | (templ & 0x4fd5) | 2;
else
cpu_state.flags = (cpu_state.flags & 0x3200) | (templ & 0x4dd5) | 2;
templ &= (is486 || isibm486) ? 0x3c0000 : 0;
templ |= ((cpu_state.eflags & 3) << 16);
if (cpu_CR4_mask & CR4_VME)
cpu_state.eflags = (templ >> 16) & 0x3f;
else if (CPUID)
cpu_state.eflags = (templ >> 16) & 0x27;
else if (is486 || isibm486)
cpu_state.eflags = (templ >> 16) & 7;
else
cpu_state.eflags = (templ >> 16) & 3;
flags_extract();
rf_flag_no_clear = 1;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 0);
#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
codegen_flags_changed = 0;
#endif
return 0;
}

View File

@@ -0,0 +1,414 @@
static int
opMOV_r_CRx_a16(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
switch (cpu_reg) {
case 0:
cpu_state.regs[cpu_rm].l = cr0;
if (is486 || isibm486)
cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/
else {
if (is386)
cpu_state.regs[cpu_rm].l |= 0x7fffffe0;
else
cpu_state.regs[cpu_rm].l |= 0x7ffffff0;
}
break;
case 2:
cpu_state.regs[cpu_rm].l = cr2;
break;
case 3:
cpu_state.regs[cpu_rm].l = cr3;
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4)) {
cpu_state.regs[cpu_rm].l = cr4;
break;
}
default:
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0);
return 0;
}
static int
opMOV_r_CRx_a32(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
switch (cpu_reg) {
case 0:
cpu_state.regs[cpu_rm].l = cr0;
if (is486 || isibm486)
cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/
else {
if (is386)
cpu_state.regs[cpu_rm].l |= 0x7fffffe0;
else
cpu_state.regs[cpu_rm].l |= 0x7ffffff0;
}
break;
case 2:
cpu_state.regs[cpu_rm].l = cr2;
break;
case 3:
cpu_state.regs[cpu_rm].l = cr3;
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4)) {
cpu_state.regs[cpu_rm].l = cr4;
break;
}
default:
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1);
return 0;
}
static int
opMOV_r_DRx_a16(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
if (cpu_reg == 4 || cpu_reg == 5) {
if (cr4 & 0x8)
x86illegal();
else
cpu_reg += 2;
}
cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0);
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0);
return 0;
}
static int
opMOV_r_DRx_a32(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
if (cpu_reg == 4 || cpu_reg == 5) {
if (cr4 & 0x8)
x86illegal();
else
cpu_reg += 2;
}
cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0);
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1);
return 0;
}
static int
opMOV_CRx_r_a16(uint32_t fetchdat)
{
uint32_t old_cr0 = cr0;
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
switch (cpu_reg) {
case 0:
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001)
flushmmucache();
/* Make sure CPL = 0 when switching from real mode to protected mode. */
if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01))
cpu_state.seg_cs.access &= 0x9f;
cr0 = cpu_state.regs[cpu_rm].l;
if (cpu_16bitbus)
cr0 |= 0x10;
if (!(cr0 & 0x80000000))
mmu_perm = 4;
if (hascache && !(cr0 & (1 << 30)))
cpu_cache_int_enabled = 1;
else
cpu_cache_int_enabled = 0;
if (hascache && ((cr0 ^ old_cr0) & (1 << 30)))
cpu_update_waitstates();
if (cr0 & 1)
cpu_cur_status |= CPU_STATUS_PMODE;
else
cpu_cur_status &= ~CPU_STATUS_PMODE;
break;
case 2:
cr2 = cpu_state.regs[cpu_rm].l;
break;
case 3:
cr3 = cpu_state.regs[cpu_rm].l;
flushmmucache();
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4)) {
if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE))
flushmmucache();
cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask;
break;
}
default:
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, rmdat, 0, 0, 0, 0, 0);
return 0;
}
static int
opMOV_CRx_r_a32(uint32_t fetchdat)
{
uint32_t old_cr0 = cr0;
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
switch (cpu_reg) {
case 0:
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001)
flushmmucache();
/* Make sure CPL = 0 when switching from real mode to protected mode. */
if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01))
cpu_state.seg_cs.access &= 0x9f;
cr0 = cpu_state.regs[cpu_rm].l;
if (cpu_16bitbus)
cr0 |= 0x10;
if (!(cr0 & 0x80000000))
mmu_perm = 4;
if (hascache && !(cr0 & (1 << 30)))
cpu_cache_int_enabled = 1;
else
cpu_cache_int_enabled = 0;
if (hascache && ((cr0 ^ old_cr0) & (1 << 30)))
cpu_update_waitstates();
if (cr0 & 1)
cpu_cur_status |= CPU_STATUS_PMODE;
else
cpu_cur_status &= ~CPU_STATUS_PMODE;
break;
case 2:
cr2 = cpu_state.regs[cpu_rm].l;
break;
case 3:
cr3 = cpu_state.regs[cpu_rm].l;
flushmmucache();
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4)) {
if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE))
flushmmucache();
cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask;
break;
}
default:
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, rmdat, 0, 0, 0, 0, 1);
return 0;
}
static int
opMOV_DRx_r_a16(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
if ((dr[6] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) {
dr[7] |= 0x2000;
dr[6] &= ~0x2000;
x86gen();
return 1;
}
fetch_ea_16(fetchdat);
if (cpu_reg == 4 || cpu_reg == 5) {
if (cr4 & 0x8)
x86illegal();
else
cpu_reg += 2;
}
dr[cpu_reg] = cpu_state.regs[cpu_rm].l;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0);
CPU_BLOCK_END();
return 0;
}
static int
opMOV_DRx_r_a32(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
if (cpu_reg == 4 || cpu_reg == 5) {
if (cr4 & 0x8)
x86illegal();
else
cpu_reg += 2;
}
dr[cpu_reg] = cpu_state.regs[cpu_rm].l;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1);
CPU_BLOCK_END();
return 0;
}
static void
opMOV_r_TRx(void)
{
#if 0
uint32_t base;
base = _tr[4] & 0xfffff800;
#endif
switch (cpu_reg) {
case 3:
#if 0
pclog("[R] %08X cache = %08X\n", base + cache_index, _tr[3]);
#endif
_tr[3] = *(uint32_t *) &(_cache[cache_index]);
cache_index = (cache_index + 4) & 0xf;
break;
}
cpu_state.regs[cpu_rm].l = _tr[cpu_reg];
CLOCK_CYCLES(6);
}
static int
opMOV_r_TRx_a16(uint32_t fetchdat)
{
if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
opMOV_r_TRx();
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0);
return 0;
}
static int
opMOV_r_TRx_a32(uint32_t fetchdat)
{
if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
opMOV_r_TRx();
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1);
return 0;
}
static void
opMOV_TRx_r(void)
{
uint32_t base;
int i;
int ctl;
_tr[cpu_reg] = cpu_state.regs[cpu_rm].l;
base = _tr[4] & 0xfffff800;
ctl = _tr[5] & 3;
switch (cpu_reg) {
case 3:
#if 0
pclog("[W] %08X cache = %08X\n", base + cache_index, _tr[3]);
#endif
*(uint32_t *) &(_cache[cache_index]) = _tr[3];
cache_index = (cache_index + 4) & 0xf;
break;
case 4:
#if 0
if (!(cr0 & 1) && !(_tr[5] & (1 << 19)))
pclog("TAG = %08X, DEST = %08X\n", base, base + cache_index - 16);
#endif
break;
case 5:
#if 0
pclog("[16] EXT = %i (%i), SET = %04X\n", !!(_tr[5] & (1 << 19)), _tr[5] & 0x03, _tr[5] & 0x7f0);
#endif
if (!(_tr[5] & (1 << 19))) {
switch (ctl) {
case 0:
#if 0
pclog(" Cache fill or read...\n", base);
#endif
break;
case 1:
base += (_tr[5] & 0x7f0);
#if 0
pclog(" Writing 16 bytes to %08X...\n", base);
#endif
for (i = 0; i < 16; i += 4)
mem_writel_phys(base + i, *(uint32_t *) &(_cache[i]));
break;
case 2:
base += (_tr[5] & 0x7f0);
#if 0
pclog(" Reading 16 bytes from %08X...\n", base);
#endif
for (i = 0; i < 16; i += 4)
*(uint32_t *) &(_cache[i]) = mem_readl_phys(base + i);
break;
case 3:
#if 0
pclog(" Cache invalidate/flush...\n", base);
#endif
break;
}
}
break;
}
CLOCK_CYCLES(6);
}
static int
opMOV_TRx_r_a16(uint32_t fetchdat)
{
if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
opMOV_TRx_r();
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0);
return 0;
}
static int
opMOV_TRx_r_a32(uint32_t fetchdat)
{
if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
opMOV_TRx_r();
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1);
return 0;
}

297
src/cpu/x86_ops_ret_2386.h Normal file
View File

@@ -0,0 +1,297 @@
#ifdef USE_NEW_DYNAREC
# define CPU_SET_OXPC
#else
# define CPU_SET_OXPC oxpc = cpu_state.pc;
#endif
#define RETF_a16(stack_offset) \
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \
op_pmoderetf(0, stack_offset); \
return 1; \
} \
CPU_SET_OXPC \
if (stack32) { \
cpu_state.pc = readmemw(ss, ESP); \
op_loadcs(readmemw(ss, ESP + 2)); \
} else { \
cpu_state.pc = readmemw(ss, SP); \
op_loadcs(readmemw(ss, SP + 2)); \
} \
if (cpu_state.abrt) \
return 1; \
if (stack32) \
ESP += 4 + stack_offset; \
else \
SP += 4 + stack_offset; \
cycles -= timing_retf_rm;
#define RETF_a32(stack_offset) \
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \
op_pmoderetf(1, stack_offset); \
return 1; \
} \
CPU_SET_OXPC \
if (stack32) { \
cpu_state.pc = readmeml(ss, ESP); \
op_loadcs(readmeml(ss, ESP + 4) & 0xffff); \
} else { \
cpu_state.pc = readmeml(ss, SP); \
op_loadcs(readmeml(ss, SP + 4) & 0xffff); \
} \
if (cpu_state.abrt) \
return 1; \
if (stack32) \
ESP += 8 + stack_offset; \
else \
SP += 8 + stack_offset; \
cycles -= timing_retf_rm;
static int
opRETF_a16(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
CPU_BLOCK_END();
RETF_a16(0);
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
PREFETCH_FLUSH();
return 0;
}
static int
opRETF_a32(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
CPU_BLOCK_END();
RETF_a32(0);
PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1);
PREFETCH_FLUSH();
return 0;
}
static int
opRETF_a16_imm(uint32_t fetchdat)
{
uint16_t offset = getwordf();
int cycles_old = cycles;
UN_USED(cycles_old);
CPU_BLOCK_END();
RETF_a16(offset);
PREFETCH_RUN(cycles_old - cycles, 3, -1, 2, 0, 0, 0, 0);
PREFETCH_FLUSH();
return 0;
}
static int
opRETF_a32_imm(uint32_t fetchdat)
{
uint16_t offset = getwordf();
int cycles_old = cycles;
UN_USED(cycles_old);
CPU_BLOCK_END();
RETF_a32(offset);
PREFETCH_RUN(cycles_old - cycles, 3, -1, 0, 2, 0, 0, 1);
PREFETCH_FLUSH();
return 0;
}
static int
opIRET_186(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
x86gpf(NULL, 0);
return 1;
}
if (msw & 1) {
optype = IRET;
op_pmodeiret(0);
optype = 0;
} else {
uint16_t new_cs;
CPU_SET_OXPC
if (stack32) {
cpu_state.pc = readmemw(ss, ESP);
new_cs = readmemw(ss, ESP + 2);
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2;
ESP += 6;
} else {
cpu_state.pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2;
SP += 6;
}
op_loadcs(new_cs);
cycles -= timing_iret_rm;
}
flags_extract();
nmi_enable = 1;
rf_flag_no_clear = 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
PREFETCH_FLUSH();
return cpu_state.abrt;
}
static int
opIRET_286(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
x86gpf(NULL, 0);
return 1;
}
if (msw & 1) {
optype = IRET;
op_pmodeiret(0);
optype = 0;
} else {
uint16_t new_cs;
CPU_SET_OXPC
if (stack32) {
cpu_state.pc = readmemw(ss, ESP);
new_cs = readmemw(ss, ESP + 2);
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2;
ESP += 6;
} else {
cpu_state.pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2;
SP += 6;
}
op_loadcs(new_cs);
cycles -= timing_iret_rm;
}
flags_extract();
nmi_enable = 1;
rf_flag_no_clear = 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
PREFETCH_FLUSH();
return cpu_state.abrt;
}
static int
opIRET(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
if (cr4 & CR4_VME) {
uint16_t new_pc;
uint16_t new_cs;
uint16_t new_flags;
new_pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
new_flags = readmemw(ss, ((SP + 4) & 0xffff));
if (cpu_state.abrt)
return 1;
if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) {
x86gpf(NULL, 0);
return 1;
}
SP += 6;
if (new_flags & I_FLAG)
cpu_state.eflags |= VIF_FLAG;
else
cpu_state.eflags &= ~VIF_FLAG;
cpu_state.flags = (cpu_state.flags & 0x3300) | (new_flags & 0x4cd5) | 2;
op_loadcs(new_cs);
cpu_state.pc = new_pc;
cycles -= timing_iret_rm;
} else {
x86gpf_expected(NULL, 0);
return 1;
}
} else {
if (msw & 1) {
optype = IRET;
op_pmodeiret(0);
optype = 0;
} else {
uint16_t new_cs;
CPU_SET_OXPC
if (stack32) {
cpu_state.pc = readmemw(ss, ESP);
new_cs = readmemw(ss, ESP + 2);
cpu_state.flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2;
ESP += 6;
} else {
cpu_state.pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
cpu_state.flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2;
SP += 6;
}
op_loadcs(new_cs);
cycles -= timing_iret_rm;
}
}
flags_extract();
nmi_enable = 1;
rf_flag_no_clear = 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
PREFETCH_FLUSH();
return cpu_state.abrt;
}
static int
opIRETD(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
x86gpf_expected(NULL, 0);
return 1;
}
if (msw & 1) {
optype = IRET;
op_pmodeiret(1);
optype = 0;
} else {
uint16_t new_cs;
CPU_SET_OXPC
if (stack32) {
cpu_state.pc = readmeml(ss, ESP);
new_cs = readmemw(ss, ESP + 4);
cpu_state.flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2;
cpu_state.eflags = readmemw(ss, ESP + 10);
ESP += 12;
} else {
cpu_state.pc = readmeml(ss, SP);
new_cs = readmemw(ss, ((SP + 4) & 0xffff));
cpu_state.flags = (readmemw(ss, (SP + 8) & 0xffff) & 0xffd5) | 2;
cpu_state.eflags = readmemw(ss, (SP + 10) & 0xffff);
SP += 12;
}
op_loadcs(new_cs);
cycles -= timing_iret_rm;
}
flags_extract();
nmi_enable = 1;
rf_flag_no_clear = 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1);
PREFETCH_FLUSH();
return cpu_state.abrt;
}

View File

@@ -78,6 +78,10 @@ x86seg_log(const char *fmt, ...)
# define x86seg_log(fmt, ...)
#endif
#ifdef USE_DYNAREC
extern int cpu_block_end;
#endif
void
#ifdef OPS_286_386
x86_doabrt_2386(int x86_abrt)
@@ -2088,6 +2092,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
uint32_t new_edi;
uint32_t new_pc;
uint32_t new_flags;
uint32_t t_bit;
uint32_t addr;
uint32_t *segdat232 = (uint32_t *) segdat2;
const x86seg *dt;
@@ -2189,6 +2194,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
new_fs = readmemw(base, 0x58);
new_gs = readmemw(base, 0x5C);
new_ldt = readmemw(base, 0x60);
t_bit = readmemb(base, 0x64) & 1;
cr0 |= 8;
@@ -2279,6 +2285,15 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
op_loadseg(new_ds, &cpu_state.seg_ds);
op_loadseg(new_fs, &cpu_state.seg_fs);
op_loadseg(new_gs, &cpu_state.seg_gs);
rf_flag_no_clear = 1;
if (t_bit) {
trap |= 2;
#ifdef USE_DYNAREC
cpu_block_end = 1;
#endif
}
} else {
if (limit < 43) {
x86ts(NULL, seg);
@@ -2454,6 +2469,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
tr.limit = limit;
tr.access = segdat[2] >> 8;
tr.ar_high = segdat[3] & 0xff;
dr[7] &= 0xFFFFFFAA;
}
void

View File

@@ -87,6 +87,12 @@ x86de(UNUSED(char *s), UNUSED(uint16_t error))
#endif
}
void
x86gen(void)
{
x86_int(1);
}
void
x86gpf(UNUSED(char *s), uint16_t error)
{

View File

@@ -41,6 +41,7 @@ extern int cgate32;
extern int intgatesize;
extern void x86seg_reset(void);
extern void x86gen(void);
extern void x86de(char *s, uint16_t error);
extern void x86gpf(char *s, uint16_t error);
extern void x86gpf_expected(char *s, uint16_t error);

View File

@@ -849,3 +849,9 @@ machine_get_config_string(char *s)
return NULL;
}
const device_t*
device_context_get_device(void)
{
return device_current.dev;
}

View File

@@ -454,6 +454,15 @@ mouse_scale(int x, int y)
mouse_scale_y(y);
}
void
mouse_scale_axis(int axis, int val)
{
if (axis == 1)
mouse_scale_y(val);
else if (axis == 0)
mouse_scale_x(val);
}
void
mouse_set_z(int z)
{

View File

@@ -734,19 +734,25 @@ ide_get_sector(ide_t *ide)
static void
ide_next_sector(ide_t *ide)
{
uint32_t sector = ide->tf->sector;
uint32_t head = ide->tf->head;
if (ide->tf->lba)
ide->lba_addr++;
else {
ide->tf->sector++;
if ((ide->tf->sector == 0) || (ide->tf->sector == (ide->cfg_spt + 1))) {
ide->tf->sector = 1;
ide->tf->head++;
if ((ide->tf->head == 0) || (ide->head == ide->cfg_hpc)) {
ide->tf->head = 0;
sector++;
if ((sector == 0) || (sector == (ide->cfg_spt + 1))) {
sector = 1;
head++;
if (head == ide->cfg_hpc) {
head = 0;
ide->tf->cylinder++;
}
}
}
ide->tf->sector = sector & 0xff;
ide->tf->head = head & 0x0f;
}
static void
@@ -1411,8 +1417,7 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv)
old = dev->devctl;
dev->devctl = val;
// if (!(val & 0x02) && (old & 0x02))
if ((old ^ val) & 0x02)
if (!(val & 0x02) && (old & 0x02))
ide_irq_update(ide_boards[ide->board], 1);
}
@@ -1779,7 +1784,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
ide->tf->error = ABRT_ERR;
ide_irq_raise(ide);
}
return;
break;
default:
break;
@@ -2091,6 +2096,8 @@ ide_board_callback(void *priv)
ide->tf->atastat |= DRDY_STAT | DSC_STAT;
} else
ide->tf->atastat = DRDY_STAT | DSC_STAT;
ide->reset = 0;
}
ide = dev->ide[0];

View File

@@ -563,10 +563,8 @@ fdd_poll(void *priv)
if (fdd_notfound) {
fdd_notfound--;
#ifdef RETURN_NOIDAM
if (!fdd_notfound)
fdc_noidam(fdd_fdc);
#endif
}
}

View File

@@ -202,6 +202,8 @@ extern const char *device_get_bios_file(const device_t *dev, const char *interna
extern int device_is_valid(const device_t *, int m);
extern const device_t* device_context_get_device(void);
extern int device_get_config_int(const char *name);
extern int device_get_config_int_ex(const char *s, int dflt_int);
extern int device_get_config_hex16(const char *name);

View File

@@ -439,6 +439,8 @@ extern void mem_reset_page_blocks(void);
extern void flushmmucache(void);
extern void flushmmucache_nopc(void);
extern void mem_debug_check_addr(uint32_t addr, int write);
extern void mem_a20_init(void);
extern void mem_a20_recalc(void);

View File

@@ -93,6 +93,7 @@ extern void mouse_scale_x(int x);
extern void mouse_scale_y(int y);
extern void mouse_scalef(double x, double y);
extern void mouse_scale(int x, int y);
extern void mouse_scale_axis(int axis, int val);
extern void mouse_set_z(int z);
extern void mouse_clear_z(void);
extern void mouse_subtract_z(int *delta_z, int min, int max, int invert);

View File

@@ -149,6 +149,7 @@ extern uint32_t plat_language_code(char *langcode);
extern void plat_language_code_r(uint32_t lcid, char *outbuf, int len);
extern void plat_get_cpu_string(char *outbuf, uint8_t len);
extern double plat_get_dpi(void);
extern void plat_set_thread_name(void *thread, const char *name);
/* Resource management. */
extern void set_language(uint32_t id);

View File

@@ -28,7 +28,7 @@ extern "C" {
# define event_t plat_event_t
# define mutex_t plat_mutex_t
# define thread_create plat_thread_create
# define thread_create_named plat_thread_create_named
# define thread_wait plat_thread_wait
# define thread_create_event plat_thread_create_event
# define thread_set_event plat_thread_set_event
@@ -48,7 +48,8 @@ typedef void thread_t;
typedef void event_t;
typedef void mutex_t;
extern thread_t *thread_create(void (*thread_func)(void *param), void *param);
#define thread_create(thread_func, param) thread_create_named((thread_func), (param), #thread_func)
extern thread_t *thread_create_named(void (*thread_func)(void *param), void *param, const char *name);
extern int thread_wait(thread_t *arg);
extern event_t *thread_create_event(void);
extern void thread_set_event(event_t *arg);

View File

@@ -33,6 +33,8 @@ typedef struct hwcursor8514_t {
} hwcursor8514_t;
typedef struct ibm8514_t {
rom_t bios_rom;
rom_t bios_rom2;
hwcursor8514_t hwcursor;
hwcursor8514_t hwcursor_latch;
uint8_t pos_regs[8];
@@ -60,12 +62,12 @@ typedef struct ibm8514_t {
int dac_b;
int internal_pitch;
int hwcursor_on;
int modechange;
struct {
uint16_t subsys_cntl;
uint16_t setup_md;
uint16_t advfunc_cntl;
uint8_t ext_advfunc_cntl;
uint16_t cur_y;
uint16_t cur_x;
int16_t destx;
@@ -142,14 +144,21 @@ typedef struct ibm8514_t {
uint16_t test;
int vendor_mode[2];
int h_blankstart;
int h_blank_end_val;
int hblankstart;
int hblank_end_val;
int hblankend;
int hblank_ext;
int hblank_sub;
int v_total;
int dispend;
int v_syncstart;
int split;
int h_disp;
int h_disp_old;
int h_total;
int h_sync_width;
int h_disp_time;
int rowoffset;
int dispon;
@@ -176,20 +185,17 @@ typedef struct ibm8514_t {
uint8_t data_available;
uint8_t data_available2;
uint8_t scanmodulos;
uint8_t rowcount;
int hsync_start;
int hsync_width;
int htotal;
int hdisp;
int vtadj;
int vdadj;
int vsadj;
int hdisped;
int sc;
int vtb;
int vdb;
int vsb;
int vsyncstart;
int vsyncwidth;
int vtotal;
int v_disp;
int vdisp;
int disp_cntl;
int interlace;
@@ -205,6 +211,7 @@ typedef struct ibm8514_t {
int pitch;
int ext_pitch;
int ext_crt_pitch;
int extensions;
} ibm8514_t;
#endif /*VIDEO_8514A_H*/

View File

@@ -0,0 +1,162 @@
/*
* 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 8514/A-compatible Mach8 and Mach32 graphics
* chips from ATI for the ISA/VLB/MCA/PCI buses.
*
*
*
* Authors: TheCollector1995.
*
* Copyright 2022-2024 TheCollector1995.
*/
#ifndef VIDEO_ATI_MACH8_H
#define VIDEO_ATI_MACH8_H
typedef struct mach_t {
ati_eeprom_t eeprom;
svga_t svga;
rom_t bios_rom;
rom_t bios_rom2;
mem_mapping_t mmio_linear_mapping;
int mca_bus;
int pci_bus;
int vlb_bus;
int has_bios;
uint8_t regs[256];
uint8_t pci_regs[256];
uint8_t int_line;
uint8_t pci_slot;
uint8_t irq_state;
int index;
int ramdac_type;
int old_mode;
uint32_t memory;
uint16_t config1;
uint16_t config2;
uint8_t pos_regs[8];
uint8_t pci_cntl_reg;
uint8_t cursor_col_0;
uint8_t cursor_col_1;
uint8_t ext_cur_col_0_r;
uint8_t ext_cur_col_1_r;
uint8_t ext_cur_col_0_g;
uint8_t ext_cur_col_1_g;
uint16_t cursor_col_0_rg;
uint16_t cursor_col_1_rg;
uint16_t cursor_col_b;
uint16_t cursor_offset_lo;
uint16_t cursor_offset_lo_reg;
uint16_t cursor_offset_hi;
uint16_t cursor_offset_hi_reg;
uint16_t cursor_vh_offset;
uint16_t cursor_x;
uint16_t cursor_y;
uint16_t misc;
uint16_t memory_aperture;
uint16_t local_cntl;
uint32_t linear_base;
uint8_t ap_size;
uint8_t bank_w;
uint8_t bank_r;
uint16_t shadow_set;
uint16_t shadow_cntl;
int ext_on[2];
int compat_mode;
struct {
uint8_t line_idx;
int16_t line_array[6];
uint8_t patt_idx;
uint8_t patt_len;
uint8_t pix_trans[2];
uint8_t eeprom_control;
uint16_t dest_x_end;
uint16_t dest_x_start;
uint16_t dest_y_end;
uint16_t src_x_end;
uint16_t src_x_start;
uint16_t src_x;
uint16_t src_y;
int16_t bres_count;
uint16_t clock_sel;
uint16_t crt_pitch;
uint16_t ge_pitch;
uint16_t dest_cmp_fn;
uint16_t dp_config;
uint16_t ext_ge_config;
uint16_t ge_offset_lo;
uint16_t ge_offset_hi;
uint16_t linedraw_opt;
uint16_t max_waitstates;
uint8_t patt_data_idx;
uint8_t patt_data[0x18];
uint16_t scan_to_x;
uint16_t scratch0;
uint16_t scratch1;
uint16_t test;
uint16_t pattern;
uint16_t test2;
int src_y_dir;
int cmd_type;
int block_write_mono_pattern_enable;
int mono_pattern_enable;
int16_t cx_end_line;
int16_t cy_end_line;
int16_t cx;
int16_t cx_end;
int16_t cy_end;
int16_t dx;
int16_t dx_end;
int16_t dy;
int16_t dy_end;
int16_t dx_start;
int16_t dy_start;
int16_t cy;
int16_t sx_start;
int16_t sx_end;
int16_t sx;
int16_t x_count;
int16_t xx_count;
int16_t xxx_count;
int16_t sy;
int16_t y_count;
int16_t err;
int16_t width;
int16_t src_width;
int16_t height;
int16_t bleft, bright, btop, bbottom;
int poly_src;
int temp_cnt;
int stepx;
int stepy;
int src_stepx;
uint8_t color_pattern[16];
uint8_t color_pattern_full[32];
uint16_t color_pattern_word[8];
int mono_pattern[8][8];
uint32_t ge_offset;
uint32_t crt_offset;
uint32_t patt_len_reg;
int poly_fill;
uint16_t dst_clr_cmp_mask;
int clip_overrun;
int color_pattern_idx;
} accel;
atomic_int force_busy;
} mach_t;
#endif /*VIDEO_ATI_MACH8_H*/

View File

@@ -274,10 +274,14 @@ typedef struct svga_t {
/* Enable LUT mapping of >= 24 bpp modes. */
int lut_map;
/* Override the horizontal blanking stuff. */
int hoverride;
/* Return a 32 bpp color from a 15/16 bpp color. */
uint32_t (*conv_16to32)(struct svga_t *svga, uint16_t color, uint8_t bpp);
void * dev8514;
void * ext8514;
void * xga;
} svga_t;
@@ -293,6 +297,13 @@ extern void ibm8514_accel_out_pixtrans(svga_t *svga, uint16_t port, uint32_t
extern void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, uint8_t ssv, int len);
extern void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, int len);
#ifdef ATI_8514_ULTRA
extern void ati8514_recalctimings(svga_t *svga);
extern uint8_t ati8514_mca_read(int port, void *priv);
extern void ati8514_mca_write(int port, uint8_t val, void *priv);
extern void ati8514_init(svga_t *svga, void *ext8514, void *dev8514);
#endif
extern void xga_poll(void *priv, svga_t *svga);
extern void xga_recalctimings(svga_t *svga);

View File

@@ -306,7 +306,7 @@ extern void xga_device_add(void);
/* IBM 8514/A and clones*/
extern void ibm8514_device_add(void);
extern const device_t mach8_isa_device;
extern const device_t mach8_vga_isa_device;
extern const device_t mach32_isa_device;
extern const device_t mach32_vlb_device;
extern const device_t mach32_mca_device;
@@ -459,6 +459,7 @@ extern const device_t paradise_wd90c11_device;
extern const device_t paradise_wd90c30_device;
/* Realtek (S)VGA */
extern const device_t realtek_rtg3105_device;
extern const device_t realtek_rtg3106_device;
/* S3 9XX/8XX/Vision/Trio */

View File

@@ -2124,7 +2124,6 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
case 0x66:
softresetx86();
cpu_set_edx();
break;
default:

View File

@@ -532,7 +532,7 @@ machine_at_presario2240_init(const machine_t *model)
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_NO_BRIDGES);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0);
@@ -563,7 +563,7 @@ machine_at_presario4500_init(const machine_t *model)
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_NO_BRIDGES);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0);

View File

@@ -50,6 +50,7 @@
#include <86box/rom.h>
#include <86box/video.h>
#include <86box/vid_cga.h>
#include <86box/hdc.h>
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>

View File

@@ -63,6 +63,7 @@
#include <86box/video.h>
#include <86box/machine.h>
#include <86box/sound.h>
#include <86box/plat_unused.h>
typedef struct {
int model;
@@ -242,6 +243,56 @@ ps1_read(uint16_t port, void *priv)
return ret;
}
static const device_config_t ps1_2011_config[] = {
// clang-format off
{
.name = "bios_language",
.description = "BIOS Language",
.type = CONFIG_BIOS,
.default_string = "english_us",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.bios = {
{ .name = "English (US)", .internal_name = "english_us", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/FC0000_US.BIN", "" } },
{ .name = "English (UK)", .internal_name = "english_uk", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_UK.BIN", "roms/machines/ibmps1es/FC0000_UK.BIN", "" } },
{ .name = "English (Canada)", .internal_name = "english_ca", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_CA.BIN", "roms/machines/ibmps1es/FC0000_CA.BIN", "" } },
{ .name = "Portuguese", .internal_name = "portuguese", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_PT.BIN", "roms/machines/ibmps1es/FC0000_PT.BIN", "" } },
{ .name = "German", .internal_name = "german", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_DE.BIN", "roms/machines/ibmps1es/FC0000_DE.BIN", "" } },
{ .name = "Swedish", .internal_name = "swedish", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_SE.BIN", "roms/machines/ibmps1es/FC0000_SE.BIN", "" } },
{ .name = "French", .internal_name = "french", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_FR.BIN", "roms/machines/ibmps1es/FC0000_FR.BIN", "" } },
{ .name = "Italian", .internal_name = "italian", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 524288, .files = { "roms/machines/ibmps1es/f80000.bin", "" } },
{ .name = "Spanish", .internal_name = "spanish", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 524288, .files = { "roms/machines/ibmps1es/F80000_ES.bin", "" } },
{ .files_no = 0 }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t ps1_2011_device = {
.name = "PS/1 2011",
.internal_name = "ps/1_2011",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = &ps1_2011_config[0]
};
static void
ps1_setup(int model)
{
@@ -273,9 +324,27 @@ ps1_setup(int model)
device_add(&ps_nvr_device);
if (model == 2011) {
rom_init(&ps->high_rom,
"roms/machines/ibmps1es/f80000.bin",
0xf80000, 0x80000, 0x7ffff, 0, MEM_MAPPING_EXTERNAL);
if (!strcmp("english_us", device_get_config_bios("bios_language"))) {
/* US English */
rom_init(&ps->high_rom,
device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0),
0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL);
} else if ((device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 1)) == NULL) {
/* Combined ROM. */
rom_init(&ps->high_rom,
device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0),
0xf80000, 0x80000, 0x7ffff, 0, MEM_MAPPING_EXTERNAL);
} else {
/* Split ROM. */
rom_init(&ps->mid_rom,
device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0),
0xf80000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL);
rom_init(&ps->high_rom,
device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 1),
0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL);
}
lpt2_remove();
@@ -339,16 +408,43 @@ int
machine_ps1_m2011_init(const machine_t *model)
{
int ret;
const char* fn;
uint32_t offset;
ret = bios_load_linear("roms/machines/ibmps1es/f80000.bin",
0x000e0000, 131072, 0x60000);
if (!device_available(model->device)) {
/* No ROMs available. */
return 0;
}
if (bios_only || !ret)
device_context(model->device);
if ((fn = device_get_bios_file(model->device, device_get_config_bios("bios_language"), 1)) == NULL) {
/* Combined ROM or US English. */
fn = device_get_bios_file(model->device, device_get_config_bios("bios_language"), 0);
offset = (!strcmp("english_us", device_get_config_bios("bios_language"))) ? 0x20000 : 0x60000;
} else {
/* Separated ROM. */
offset = 0x20000;
}
if (!fn) {
fn = device_get_bios_file(model->device, "us_english", 0);
offset = 0x20000;
}
ret = bios_load_linear(fn, 0x000e0000, 131072, offset);
device_context_restore();
if (bios_only || !ret) {
return ret;
}
ps1_common_init(model);
ps1_setup(2011);
device_context(model->device);
ps1_setup(2011);
device_context_restore();
return ret;
}

View File

@@ -169,6 +169,7 @@ void
machine_common_init(UNUSED(const machine_t *model))
{
uint8_t cpu_requires_fast_pit = is486 || (!is286 && is8086 && (cpu_s->rspeed >= 8000000));
cpu_requires_fast_pit = cpu_requires_fast_pit && !cpu_16bitbus;
/* System devices first. */
pic_init();

View File

@@ -51,6 +51,7 @@ extern const device_t vid_ppc512_device;
extern const device_t vid_device_sl;
extern const device_t t1200_video_device;
extern const device_t compaq_plasma_device;
extern const device_t ps1_2011_device;
const machine_filter_t machine_types[] = {
{ "None", MACHINE_TYPE_NONE },
@@ -2585,7 +2586,7 @@ const machine_t machines[] = {
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.device = &ps1_2011_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,

View File

@@ -39,6 +39,54 @@
#include <86box/rom.h>
#include <86box/gdbstub.h>
/* Set trap for data address breakpoints. */
void
mem_debug_check_addr(uint32_t addr, int write)
{
int i = 0;
int set_trap = 0;
if (!(dr[7] & 0xFF))
return;
for (i = 0; i < 4; i++) {
uint32_t dr_addr = dr[i];
int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i)));
int len_type_pair = ((dr[7] >> 16) & (0xF << (4 * i))) >> (4 * i);
if (!breakpoint_enabled)
continue;
if (!write && (len_type_pair & 3) != 3)
continue;
if ((len_type_pair & 3) != 1)
continue;
switch ((len_type_pair >> 2) & 3)
{
case 0x00:
if (dr_addr == addr) {
set_trap = 1;
dr[6] |= (1 << i);
}
break;
case 0x01:
if ((dr_addr & ~1) == addr || ((dr_addr & ~1) + 1) == (addr + 1)) {
set_trap = 1;
dr[6] |= (1 << i);
}
break;
case 0x03:
dr_addr &= ~3;
if (addr >= dr_addr && addr < (dr_addr + 4)) {
set_trap = 1;
dr[6] |= (1 << i);
}
break;
}
}
if (set_trap)
trap |= 4;
}
uint8_t
mem_readb_map(uint32_t addr)
{
@@ -243,6 +291,7 @@ readmembl_2386(uint32_t addr)
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1);
mem_debug_check_addr(addr, 0);
addr64 = (uint64_t) addr;
mem_logical_addr = addr;
@@ -270,6 +319,7 @@ writemembl_2386(uint32_t addr, uint8_t val)
mem_mapping_t *map;
uint64_t a;
mem_debug_check_addr(addr, 1);
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1);
addr64 = (uint64_t) addr;
@@ -347,6 +397,8 @@ readmemwl_2386(uint32_t addr)
addr64a[0] = addr;
addr64a[1] = addr + 1;
mem_debug_check_addr(addr, 0);
mem_debug_check_addr(addr + 1, 0);
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2);
mem_logical_addr = addr;
@@ -402,6 +454,8 @@ writememwl_2386(uint32_t addr, uint16_t val)
addr64a[0] = addr;
addr64a[1] = addr + 1;
mem_debug_check_addr(addr, 1);
mem_debug_check_addr(addr + 1, 1);
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2);
mem_logical_addr = addr;
@@ -555,8 +609,10 @@ readmemll_2386(uint32_t addr)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 4; i++)
for (i = 0; i < 4; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 0);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4);
mem_logical_addr = addr;
@@ -626,8 +682,10 @@ writememll_2386(uint32_t addr, uint32_t val)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 4; i++)
for (i = 0; i < 4; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 1);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4);
mem_logical_addr = addr;
@@ -807,8 +865,10 @@ readmemql_2386(uint32_t addr)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 8; i++)
for (i = 0; i < 8; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 0);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8);
mem_logical_addr = addr;
@@ -870,8 +930,10 @@ writememql_2386(uint32_t addr, uint64_t val)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 8; i++)
for (i = 0; i < 8; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 1);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8);
mem_logical_addr = addr;
@@ -957,32 +1019,35 @@ do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write)
uint32_t last_addr = addr + (num - 1);
uint64_t a = 0x0000000000000000ULL;
mem_debug_check_addr(addr, write);
for (i = 0; i < num; i++)
a64[i] = (uint64_t) addr;
for (i = 0; i < num; i++) {
if (cr0 >> 31) {
/* If we have encountered at least one page fault, mark all subsequent addresses as
having page faulted, prevents false negatives in readmem*l_no_mmut. */
if ((i > 0) && cpu_state.abrt && !high_page)
a64[i] = a64[i - 1];
/* If we are on the same page, there is no need to translate again, as we can just
reuse the previous result. */
else if (i == 0) {
a = mmutranslatereal_2386(addr, write);
a64[i] = (uint32_t) a;
} else if (!(addr & 0xfff)) {
a = mmutranslatereal_2386(last_addr, write);
a64[i] = (uint32_t) a;
if (!(cr0 >> 31))
return;
if (!cpu_state.abrt) {
a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff));
a64[i] = (uint32_t) a;
}
} else {
for (i = 0; i < num; i++) {
/* If we have encountered at least one page fault, mark all subsequent addresses as
having page faulted, prevents false negatives in readmem*l_no_mmut. */
if ((i > 0) && cpu_state.abrt && !high_page)
a64[i] = a64[i - 1];
/* If we are on the same page, there is no need to translate again, as we can just
reuse the previous result. */
else if (i == 0) {
a = mmutranslatereal_2386(addr, write);
a64[i] = (uint32_t) a;
} else if (!(addr & 0xfff)) {
a = mmutranslatereal_2386(last_addr, write);
a64[i] = (uint32_t) a;
if (!cpu_state.abrt) {
a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff));
a64[i] = (uint32_t) a;
}
} else {
a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff));
a64[i] = (uint32_t) a;
}
addr++;

View File

@@ -94,6 +94,7 @@ main_thread_fn()
int frames;
QThread::currentThread()->setPriority(QThread::HighestPriority);
plat_set_thread_name(NULL, "main_thread_fn");
framecountx = 0;
// title_update = 1;
old_time = elapsed_timer.elapsed();

View File

@@ -808,6 +808,14 @@ MainWindow::initRendererMonitorSlot(int monitor_index)
}
secondaryRenderer->switchRenderer((RendererStack::Renderer) vid_api);
secondaryRenderer->setMouseTracking(true);
if (monitor_settings[monitor_index].mon_window_maximized) {
if (renderers[monitor_index])
renderers[monitor_index]->onResize(renderers[monitor_index]->width(),
renderers[monitor_index]->height());
device_force_redraw();
}
}
}
}
@@ -1379,12 +1387,12 @@ MainWindow::on_actionResizable_window_triggered(bool checked)
{
if (checked) {
vid_resize = 1;
setWindowFlag(Qt::WindowMaximizeButtonHint);
setWindowFlag(Qt::WindowMaximizeButtonHint, true);
setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, false);
setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
for (int i = 1; i < MONITORS_NUM; i++) {
if (monitors[i].target_buffer) {
renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint);
renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint, true);
renderers[i]->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
}
}

View File

@@ -456,6 +456,13 @@ MediaMenu::cdromMount(int i, const QString &filename)
cdrom[i].ops = nullptr;
memset(cdrom[i].image_path, 0, sizeof(cdrom[i].image_path));
#ifdef _WIN32
if ((fn.data() != NULL) && (strlen(fn.data()) >= 1) && (fn.data()[strlen(fn.data()) - 1] == '/'))
fn.data()[strlen(fn.data()) - 1] = '\\';
#else
if ((fn.data() != NULL) && (strlen(fn.data()) >= 1) && (fn.data()[strlen(fn.data()) - 1] == '\\'))
fn.data()[strlen(fn.data()) - 1] = '/';
#endif
cdrom_image_open(&(cdrom[i]), fn.data());
/* Signal media change to the emulated machine. */
if (cdrom[i].insert)

View File

@@ -50,6 +50,7 @@
#include "qt_util.hpp"
#ifdef Q_OS_UNIX
# include <pthread.h>
# include <sys/mman.h>
#endif
@@ -742,3 +743,48 @@ plat_get_dpi(void)
{
return util::screenOfWidget(main_window)->devicePixelRatio();
}
void
plat_set_thread_name(void *thread, const char *name)
{
#ifdef Q_OS_WINDOWS
/* SetThreadDescription was added in 14393. Revisit if we ever start requiring 10. */
static void *kernel32_handle = NULL;
static HRESULT(WINAPI *pSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription) = NULL;
static dllimp_t kernel32_imports[] = {
// clang-format off
{ "SetThreadDescription", &pSetThreadDescription },
{ NULL, NULL }
// clang-format on
};
if (!kernel32_handle) {
kernel32_handle = dynld_module("kernel32.dll", kernel32_imports);
if (!kernel32_handle) {
kernel32_handle = kernel32_imports; /* store dummy pointer to avoid trying again */
pSetThreadDescription = NULL;
}
}
if (pSetThreadDescription) {
size_t len = strlen(name) + 1;
wchar_t wname[len + 1];
mbstowcs(wname, name, len);
pSetThreadDescription(thread ? (HANDLE) thread : GetCurrentThread(), wname);
}
#else
# ifdef Q_OS_DARWIN
if (thread) /* Apple pthread can only set self's name */
return;
char truncated[64];
# else
char truncated[16];
# endif
strncpy(truncated, name, sizeof(truncated) - 1);
# ifdef Q_OS_DARWIN
pthread_setname_np(truncated);
# else
pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated);
# endif
#endif
}

View File

@@ -1581,17 +1581,17 @@ nuked_drv_write(uint16_t port, uint8_t val, void *priv)
nuked_write_reg_buffered(&dev->opl, dev->port, val);
switch (dev->port) {
case 0x02: /* Timer 1 */
case 0x002: /* Timer 1 */
dev->timer_count[0] = val;
nuked_log("Timer 0 count now: %i\n", dev->timer_count[0]);
break;
case 0x03: /* Timer 2 */
case 0x003: /* Timer 2 */
dev->timer_count[1] = val;
nuked_log("Timer 1 count now: %i\n", dev->timer_count[1]);
break;
case 0x04: /* Timer control */
case 0x004: /* Timer control */
if (val & CTRL_RESET) {
nuked_log("Resetting timer status...\n");
dev->status &= ~STAT_TMR_OVER;
@@ -1603,6 +1603,10 @@ nuked_drv_write(uint16_t port, uint8_t val, void *priv)
}
break;
case 0x105:
dev->opl.newm = val & 0x01;
break;
default:
break;
}

View File

@@ -796,7 +796,9 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv)
mixer->regs[0x36] = mixer->regs[0x37] = 0xf8;
mixer->regs[0x38] = mixer->regs[0x39] = 0x00;
mixer->regs[0x3a] = mixer->regs[0x3b] = 0x00;
mixer->regs[0x3a] = 0x00;
/* Speaker control - it appears to be in steps of 64. */
mixer->regs[0x3b] = 0x80;
mixer->regs[0x3c] = (OUTPUT_MIC | OUTPUT_CD_R | OUTPUT_CD_L | OUTPUT_LINE_R | OUTPUT_LINE_L);
mixer->regs[0x3d] = (INPUT_MIC | INPUT_CD_L | INPUT_LINE_L | INPUT_MIDI_L);
@@ -980,7 +982,7 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv)
mixer->line_r = (mixer->output_selector & OUTPUT_LINE_R) ? (sb_att_2dbstep_5bits[mixer->regs[0x39] >> 3] / 32768.0) : 0.0;
mixer->mic = sb_att_2dbstep_5bits[mixer->regs[0x3a] >> 3] / 32768.0;
mixer->speaker = sb_att_2dbstep_5bits[mixer->regs[0x3b] * 3 + 22] / 32768.0;
mixer->speaker = sb_att_7dbstep_2bits[(mixer->regs[0x3b] >> 6) & 0x3] / 32768.0;
mixer->input_gain_L = (mixer->regs[0x3f] >> 6);
mixer->input_gain_R = (mixer->regs[0x40] >> 6);

View File

@@ -14,9 +14,10 @@ struct event_cpp11_t {
extern "C" {
thread_t *
thread_create(void (*thread_rout)(void *param), void *param)
thread_create_named(void (*thread_rout)(void *param), void *param, const char *name)
{
auto thread = new std::thread([thread_rout, param] {
auto thread = new std::thread([thread_rout, param, name] {
plat_set_thread_name(NULL, name);
thread_rout(param);
});
return thread;

View File

@@ -45,6 +45,9 @@
#include <86box/ui.h>
#include <86box/gdbstub.h>
#define __USE_GNU 1 /* shouldn't be done, yet it is */
#include <pthread.h>
static int first_use = 1;
static uint64_t StartingTime;
static uint64_t Frequency;
@@ -1379,6 +1382,24 @@ plat_get_cpu_string(char *outbuf, uint8_t len) {
strncpy(outbuf, cpu_string, len);
}
void
plat_set_thread_name(void *thread, const char *name)
{
#ifdef __APPLE__
if (thread) /* Apple pthread can only set self's name */
return;
char truncated[64];
#else
char truncated[16];
#endif
strncpy(truncated, name, sizeof(truncated) - 1);
#ifdef __APPLE__
pthread_setname_np(truncated);
#else
pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated);
#endif
}
/* Converts back the language code to LCID */
void
plat_language_code_r(uint32_t lcid, char *outbuf, int len)

View File

@@ -145,6 +145,8 @@ cdrom_mount(uint8_t id, char *fn)
cdrom[id].ops->exit(&(cdrom[id]));
cdrom[id].ops = NULL;
memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path));
if ((fn != NULL) && (strlen(fn) >= 1) && (fn[strlen(fn) - 1] == '\\'))
fn[strlen(fn) - 1] = '/';
cdrom_image_open(&(cdrom[id]), fn);
/* Signal media change to the emulated machine. */
if (cdrom[id].insert)

View File

@@ -32,7 +32,7 @@ thread_run_wrapper(thread_param *arg)
}
thread_t *
thread_create(void (*thread_rout)(void *param), void *param)
thread_create_named(void (*thread_rout)(void *param), void *param, const char *name)
{
pthread_t *thread = malloc(sizeof(pthread_t));
thread_param *thrparam = malloc(sizeof(thread_param));
@@ -40,6 +40,7 @@ thread_create(void (*thread_rout)(void *param), void *param)
thrparam->param = param;
pthread_create(thread, NULL, (void *(*) (void *) ) thread_run_wrapper, thrparam);
plat_set_thread_name(thread, name);
return thread;
}
@@ -51,7 +52,7 @@ thread_wait(thread_t *arg)
}
event_t *
thread_create_event()
thread_create_event(void)
{
event_pthread_t *event = malloc(sizeof(event_pthread_t));

View File

@@ -13,7 +13,7 @@
*
* Authors: TheCollector1995.
*
* Copyright 2022-2023 TheCollector1995.
* Copyright 2022-2024 TheCollector1995.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -38,8 +38,14 @@
#include <86box/vid_xga.h>
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
#include <86box/vid_ati_eeprom.h>
#include <86box/vid_ati_mach8.h>
#include "cpu.h"
#ifdef ATI_8514_ULTRA
#define BIOS_MACH8_ROM_PATH "roms/video/mach8/11301113140.BIN"
#endif
static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *priv);
static void ibm8514_accel_outw(uint16_t port, uint16_t val, void *priv);
static uint8_t ibm8514_accel_inb(uint16_t port, void *priv);
@@ -63,6 +69,27 @@ ibm8514_log(const char *fmt, ...)
# define ibm8514_log(fmt, ...)
#endif
#define WRITE8(addr, var, val) \
switch ((addr) & 1) { \
case 0: \
var = (var & 0xff00) | (val); \
break; \
case 1: \
var = (var & 0x00ff) | ((val) << 8); \
break; \
}
#define READ8(addr, var) \
switch ((addr) & 1) { \
case 0: \
temp = (var) & 0xff; \
break; \
case 1: \
temp = ((var) >> 8) & 0xff; \
break; \
}
#define READ_PIXTRANS_WORD(cx, n) \
if ((cmd <= 1) || (cmd == 5)) { \
temp = dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & dev->vram_mask]; \
@@ -453,16 +480,15 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len)
switch (port) {
case 0x82e8:
case 0xc2e8:
if (len == 1) {
if (len == 1)
dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val;
} else
else
dev->accel.cur_y = val & 0x7ff;
break;
case 0x82e9:
case 0xc2e9:
if (len == 1) {
if (len == 1)
dev->accel.cur_y = (dev->accel.cur_y & 0xff) | ((val & 0x07) << 8);
}
break;
case 0x86e8:
@@ -474,9 +500,8 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len)
break;
case 0x86e9:
case 0xc6e9:
if (len == 1) {
if (len == 1)
dev->accel.cur_x = (dev->accel.cur_x & 0xff) | ((val & 0x07) << 8);
}
break;
case 0x8ae8:
@@ -742,16 +767,19 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len)
else {
dev->accel.multifunc_cntl = val;
dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff;
if ((dev->accel.multifunc_cntl >> 12) == 1) {
if ((dev->accel.multifunc_cntl >> 12) == 1)
dev->accel.clip_top = val & 0x7ff;
if (val & 0x400)
dev->accel.clip_top |= ~0x3ff;
}
if ((dev->accel.multifunc_cntl >> 12) == 2) {
if ((dev->accel.multifunc_cntl >> 12) == 2)
dev->accel.clip_left = val & 0x7ff;
if (val & 0x400)
dev->accel.clip_left |= ~0x3ff;
}
if ((dev->accel.multifunc_cntl >> 12) == 3)
dev->accel.multifunc[3] = val & 0x7ff;
if ((dev->accel.multifunc_cntl >> 12) == 4)
dev->accel.multifunc[4] = val & 0x7ff;
ibm8514_log("CLIPBOTTOM=%d, CLIPRIGHT=%d, bpp=%d, pitch=%d.\n", dev->accel.multifunc[3], dev->accel.multifunc[4], dev->accel_bpp, dev->pitch);
if (port == 0xfee8)
dev->accel.cmd_back = 1;
else
@@ -763,6 +791,12 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len)
if (len == 1) {
dev->accel.multifunc_cntl = (dev->accel.multifunc_cntl & 0xff) | (val << 8);
dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff;
if ((dev->accel.multifunc_cntl >> 12) == 1)
dev->accel.clip_top = dev->accel.multifunc_cntl & 0x7ff;
if ((dev->accel.multifunc_cntl >> 12) == 2)
dev->accel.clip_left = dev->accel.multifunc_cntl & 0x7ff;
if (port == 0xfee9)
dev->accel.cmd_back = 1;
else
@@ -855,151 +889,118 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len)
ibm8514_t *dev = (ibm8514_t *) svga->dev8514;
uint8_t old = 0;
if (port & 0x8000) {
if (port & 0x8000)
ibm8514_accel_out_fifo(svga, port, val, len);
} else {
else {
switch (port) {
case 0x2e8:
if (len == 1)
dev->htotal = (dev->htotal & 0xff00) | val;
else {
dev->htotal = val;
svga_recalctimings(svga);
}
break;
case 0x2e9:
if (len != 1) {
dev->htotal = (dev->htotal & 0xff) | (val << 8);
ibm8514_log("IBM 8514/A: H_TOTAL write 02E8 = %d\n", dev->htotal + 1);
svga_recalctimings(svga);
}
WRITE8(port, dev->htotal, val);
break;
case 0x6e8:
dev->hdisp = val;
ibm8514_log("IBM 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1);
svga_recalctimings(svga);
case 0x6e9:
if (!(port & 1)) {
dev->hdisped = val;
dev->hdisp = (dev->hdisped + 1) << 3;
}
ibm8514_log("IBM 8514/A: H_DISP write 06E8 = %d, advfunc=%x.\n", dev->hdisp, dev->accel.advfunc_cntl & 4);
break;
case 0xae8:
case 0xae9:
if (!(port & 1)) {
dev->hsync_start = val;
dev->hblankstart = (dev->hsync_start & 0x07) + 1;
}
ibm8514_log("IBM 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1);
svga_recalctimings(svga);
break;
case 0xee8:
case 0xee9:
if (!(port & 1)) {
dev->hsync_width = val;
dev->hblank_end_val = (dev->hblankstart + (dev->hsync_start & 0x1f) - 1) & 0x3f;
}
ibm8514_log("IBM 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1);
svga_recalctimings(svga);
break;
case 0x12e8:
if (len == 1)
dev->vtotal = (dev->vtotal & 0x1f00) | val;
else {
dev->vtotal = val & 0x1fff;
svga_recalctimings(svga);
}
break;
case 0x12e9:
if (len == 1) {
dev->vtotal = (dev->vtotal & 0xff) | ((val & 0x1f) << 8);
ibm8514_log("IBM 8514/A: V_TOTAL write 12E8 = %d\n", dev->vtotal);
svga_recalctimings(svga);
}
WRITE8(port, dev->vtotal, val);
dev->vtotal &= 0x1fff;
break;
case 0x16e8:
if (len == 1)
dev->vdisp = (dev->vdisp & 0x1f00) | val;
else {
dev->vdisp = val & 0x1fff;
svga_recalctimings(svga);
}
break;
case 0x16e9:
if (len == 1) {
dev->vdisp = (dev->vdisp & 0xff) | ((val & 0x1f) << 8);
ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp);
svga_recalctimings(svga);
}
WRITE8(port, dev->v_disp, val);
dev->v_disp &= 0x1fff;
dev->vdisp = dev->v_disp;
dev->vdisp >>= 1;
dev->vdisp++;
ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp);
break;
case 0x1ae8:
if (len == 1)
dev->vsyncstart = (dev->vsyncstart & 0x1f00) | val;
else {
dev->vsyncstart = val & 0x1fff;
svga_recalctimings(svga);
}
break;
case 0x1ae9:
if (len == 1) {
dev->vsyncstart = (dev->vsyncstart & 0xff) | ((val & 0x1f) << 8);
ibm8514_log("IBM 8514/A: V_SYNC_STRT write 1AE8 = %d\n", dev->vsyncstart);
svga_recalctimings(svga);
}
WRITE8(port, dev->vsyncstart, val);
dev->vsyncstart &= 0x1fff;
break;
case 0x1ee8:
dev->vsyncwidth = val;
case 0x1ee9:
ibm8514_log("IBM 8514/A: V_SYNC_WID write 1EE8 = %02x\n", val);
svga_recalctimings(svga);
break;
case 0x22e8:
dev->disp_cntl = val & 0x7e;
dev->interlace = !!(val & 0x10);
ibm8514_log("IBM 8514/A: DISP_CNTL write 22E8 = %02x, SCANMODULOS = %d\n", dev->disp_cntl, dev->scanmodulos);
svga_recalctimings(svga);
ibm8514_log("IBM 8514/A: DISP_CNTL write 22E8 = %02x, interlace = %d\n", dev->disp_cntl, dev->interlace);
break;
case 0x42e8:
old = dev->subsys_stat;
if ((val & 0xff) & 1)
if (val & 1)
dev->subsys_stat &= ~1;
if ((val & 0xff) & 2)
if (val & 2)
dev->subsys_stat &= ~2;
if ((val & 0xff) & 4)
if (val & 4)
dev->subsys_stat &= ~4;
if ((val & 0xff) & 8)
if (val & 8)
dev->subsys_stat &= ~8;
if (len != 1) {
old = dev->subsys_cntl;
dev->subsys_cntl = (val >> 8);
if ((old ^ dev->subsys_cntl) & 1)
dev->subsys_stat |= 1;
if ((old ^ dev->subsys_cntl) & 2)
dev->subsys_stat |= 2;
if ((old ^ dev->subsys_cntl) & 4)
dev->subsys_stat |= 4;
if ((old ^ dev->subsys_cntl) & 8)
dev->subsys_stat |= 8;
}
break;
case 0x42e9:
if (len == 1) {
old = dev->subsys_cntl;
dev->subsys_cntl = val;
if ((old ^ val) & 1)
dev->subsys_stat |= 1;
if ((old ^ val) & 2)
dev->subsys_stat |= 2;
if ((old ^ val) & 4)
dev->subsys_stat |= 4;
if ((old ^ val) & 8)
dev->subsys_stat |= 8;
}
old = dev->subsys_cntl;
dev->subsys_cntl = val;
if ((old ^ val) & 1)
dev->subsys_stat |= 1;
if ((old ^ val) & 2)
dev->subsys_stat |= 2;
if ((old ^ val) & 4)
dev->subsys_stat |= 4;
if ((old ^ val) & 8)
dev->subsys_stat |= 8;
break;
case 0x4ae8:
if (!val)
break;
dev->accel.advfunc_cntl = val & 0x0f;
dev->on[0] = val & 0x01;
vga_on = !dev->on[0];
ibm8514_log("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val);
case 0x4ae9:
WRITE8(port, dev->accel.advfunc_cntl, val);
dev->on[port & 1] = dev->accel.advfunc_cntl & 0x01;
vga_on = !dev->on[port & 1];
dev->vendor_mode[port & 1] = 0;
if (dev->on[0] || dev->on[1]) {
if (!(dev->accel.advfunc_cntl & 4)) {
if (dev->disp_cntl & 0x60) {
dev->hdisp = 640;
dev->vdisp = 480;
}
}
}
ibm8514_log("IBM 8514/A: (0x%04x): ON=%d, shadow crt=%x.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 4);
svga_recalctimings(svga);
break;
default:
break;
}
@@ -1036,16 +1037,16 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len)
vpos = dev->vc & 0x7ff;
if (vblankend > dev->v_total) {
vblankend -= dev->v_total;
if (vpos >= svga->vblankstart || vpos <= vblankend)
if ((vpos >= svga->vblankstart) || (vpos <= vblankend))
temp |= 2;
} else {
if (vpos >= svga->vblankstart && vpos <= vblankend)
if ((vpos >= svga->vblankstart) && (vpos <= vblankend))
temp |= 2;
}
break;
case 0x6e8:
temp = dev->hdisp;
temp = dev->hdisped;
break;
case 0x22e8:
@@ -1091,22 +1092,19 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len)
case 0x82e8:
case 0xc2e8:
if (len != 1) {
if (len != 1)
temp = dev->accel.cur_y;
}
break;
case 0x86e8:
case 0xc6e8:
if (len != 1) {
if (len != 1)
temp = dev->accel.cur_x;
}
break;
case 0x92e8:
if (len != 1) {
if (len != 1)
temp = dev->test;
}
break;
case 0x9ae8:
@@ -1200,12 +1198,6 @@ ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t
ibm8514_accel_start(count, cpu_input, mix_dat, cpu_dat, svga, len);
}
#define CLAMP(x) \
do { \
if ((x) & ~0xff) \
x = ((x) < 0) ? 0 : 0xff; \
} while (0)
void
ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, UNUSED(int len))
{
@@ -3831,8 +3823,6 @@ bitblt:
}
}
#undef CLAMP
void
ibm8514_render_8bpp(svga_t *svga)
{
@@ -3840,9 +3830,8 @@ ibm8514_render_8bpp(svga_t *svga)
uint32_t *p;
uint32_t dat;
if ((dev->displine + svga->y_add) < 0) {
if ((dev->displine + svga->y_add) < 0)
return;
}
if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) {
p = &buffer32->line[dev->displine + svga->y_add][svga->x_add];
@@ -4184,6 +4173,7 @@ ibm8514_poll(void *priv, svga_t *svga)
dev->maback += (dev->rowoffset << 3);
if (dev->interlace)
dev->maback += (dev->rowoffset << 3);
dev->maback &= dev->vram_mask;
dev->ma = dev->maback;
} else {
@@ -4260,65 +4250,66 @@ ibm8514_recalctimings(svga_t *svga)
{
ibm8514_t *dev = (ibm8514_t *) svga->dev8514;
if (dev->on[0]) {
dev->h_disp = (dev->hdisp + 1) << 3;
dev->pitch = (dev->accel.advfunc_cntl & 4) ? 1024 : 640;
dev->h_total = (dev->htotal + 1);
dev->v_total = (dev->vtotal + 1);
dev->v_syncstart = (dev->vsyncstart + 1);
dev->rowcount = !!(dev->disp_cntl & 0x08);
dev->dispend = ((dev->vdisp >> 1) + 1);
if (dev->dispend == 766)
dev->dispend += 2;
#ifdef ATI_8514_ULTRA
if (dev->extensions) {
if (svga->ext8514 != NULL)
ati8514_recalctimings(svga);
} else
#endif
{
if (dev->on[0] || dev->on[1]) {
dev->h_disp = dev->hdisp;
dev->h_total = dev->htotal + 1;
dev->h_blankstart = dev->hblankstart;
dev->h_blank_end_val = dev->hblank_end_val;
dev->v_total = dev->vtotal + 1;
dev->v_syncstart = dev->vsyncstart + 1;
dev->rowcount = !!(dev->disp_cntl & 0x08);
dev->dispend = dev->vdisp;
if (dev->dispend == 598)
dev->dispend += 2;
if (dev->accel.advfunc_cntl & 4) {
if (dev->h_disp == 8) {
dev->h_disp = 1024;
dev->dispend = 768;
dev->v_total = 1536;
dev->v_syncstart = 1536;
}
if (dev->dispend == 766)
dev->dispend += 2;
if (dev->dispend == 598)
dev->dispend = 600;
dev->dispend += 2;
if (dev->interlace) {
dev->dispend >>= 1;
dev->v_syncstart >>= 2;
dev->v_total >>= 2;
if (dev->accel.advfunc_cntl & 4) {
dev->pitch = 1024;
if (!dev->h_disp) {
dev->h_disp = 1024;
dev->dispend = 768;
}
svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0;
} else {
dev->v_syncstart >>= 1;
dev->v_total >>= 1;
dev->pitch = 640;
if (!dev->h_disp) {
dev->h_disp = 640;
dev->dispend = 480;
}
svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0;
}
if (dev->interlace)
dev->dispend >>= 1;
dev->rowoffset = 0x80;
svga->map8 = dev->pallook;
svga->render8514 = ibm8514_render_8bpp;
ibm8514_log("1024x768 clock mode, hdisp = %d, htotal = %d, vtotal = %d, vsyncstart = %d, interlace = %02x\n", dev->h_disp, dev->h_total, dev->v_total, dev->v_syncstart, dev->interlace);
svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0;
} else {
if (dev->h_disp == 1024) {
dev->h_disp = 640;
dev->dispend = 480;
dev->hblankend = (dev->h_blankstart & ~0x3f) | dev->h_blank_end_val;
if (dev->hblankend <= dev->h_blankstart)
dev->hblankend += 0x40;
dev->hblankend += dev->hblank_ext;
dev->hblank_sub = 0;
if (dev->hblankend > dev->h_total) {
dev->hblankend &= 0x3f;
dev->hblank_sub = dev->hblankend + 1;
dev->h_disp -= dev->hblank_sub;
}
if (dev->interlace) {
dev->dispend >>= 1;
dev->v_syncstart >>= 2;
dev->v_total >>= 2;
} else {
dev->v_syncstart >>= 1;
dev->v_total >>= 1;
}
dev->rowoffset = 0x80;
svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0;
ibm8514_log("BPP=%d, Pitch = %d, rowoffset = %d, crtc13 = %02x, highres bit = %02x, has_vga? = %d.\n", dev->bpp, dev->pitch, dev->rowoffset, svga->crtc[0x13], dev->accel.advfunc_cntl & 4, !ibm8514_standalone_enabled);
}
svga->render8514 = ibm8514_render_8bpp;
ibm8514_log("BPP=%d, Pitch = %d, rowoffset = %d, crtc13 = %02x, mode = %d, highres bit = %02x, has_vga? = %d.\n", dev->bpp, dev->pitch, dev->rowoffset, svga->crtc[0x13], dev->ibm_mode, dev->accel.advfunc_cntl & 4, !ibm8514_standalone_enabled);
}
ibm8514_log("8514 enabled, hdisp=%d, vtotal=%d, htotal=%d, dispend=%d, rowoffset=%d, split=%d, vsyncstart=%d, split=%08x\n", dev->hdisp, dev->vtotal, dev->htotal, dev->dispend, dev->rowoffset, dev->split, dev->vsyncstart, dev->split);
}
@@ -4355,6 +4346,19 @@ ibm8514_mca_feedb(void *priv)
return dev->pos_regs[2] & 1;
}
static void
ibm8514_mca_reset(void *priv)
{
svga_t *svga = (svga_t *) priv;
ibm8514_t *dev = (ibm8514_t *) svga->dev8514;
ibm8514_log("MCA reset.\n");
dev->on[0] = 0;
dev->on[1] = 0;
vga_on = 1;
ibm8514_mca_write(0x102, 0, svga);
}
static void *
ibm8514_init(const device_t *info)
{
@@ -4365,6 +4369,7 @@ ibm8514_init(const device_t *info)
ibm8514_t *dev = (ibm8514_t *) calloc(1, sizeof(ibm8514_t));
svga->dev8514 = dev;
svga->ext8514 = NULL;
dev->vram_size = 1024 << 10;
dev->vram = calloc(dev->vram_size, 1);
@@ -4376,13 +4381,56 @@ ibm8514_init(const device_t *info)
dev->type = info->flags;
dev->bpp = 0;
#ifdef ATI_8514_ULTRA
dev->extensions = device_get_config_int("extensions");
switch (dev->extensions) {
case 1:
if (rom_present(BIOS_MACH8_ROM_PATH)) {
mach = (mach_t *) calloc(1, sizeof(mach_t));
svga->ext8514 = mach;
ati8514_init(svga, svga->ext8514, svga->dev8514);
if (dev->type & DEVICE_MCA) {
rom_init(&dev->bios_rom,
BIOS_MACH8_ROM_PATH,
0xc6800, 0x1000, 0x0fff,
0x0800, MEM_MAPPING_EXTERNAL);
mem_mapping_disable(&dev->bios_rom.mapping);
dev->pos_regs[0] = 0x88;
dev->pos_regs[1] = 0x80;
mca_add(ati8514_mca_read, ati8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga);
ati_eeprom_load(&mach->eeprom, "ati8514_mca.nvr", 0);
} else {
rom_init(&dev->bios_rom,
BIOS_MACH8_ROM_PATH,
0xd0000, 0x1000, 0x0fff,
0x0800, MEM_MAPPING_EXTERNAL);
ati_eeprom_load(&mach->eeprom, "ati8514.nvr", 0);
}
break;
}
fallthrough;
default:
ibm8514_io_set(svga);
if (dev->type & DEVICE_MCA) {
dev->pos_regs[0] = 0x7f;
dev->pos_regs[1] = 0xef;
mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga);
}
break;
}
#else
ibm8514_io_set(svga);
if (dev->type & DEVICE_MCA) {
dev->pos_regs[0] = 0x7f;
dev->pos_regs[1] = 0xef;
mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, NULL, svga);
mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga);
}
#endif
return svga;
}
@@ -4392,6 +4440,10 @@ ibm8514_close(void *priv)
{
svga_t *svga = (svga_t *) priv;
ibm8514_t *dev = (ibm8514_t *) svga->dev8514;
mach_t *mach = (mach_t *) svga->ext8514;
if (mach)
free(mach);
if (dev) {
free(dev->vram);
@@ -4417,6 +4469,34 @@ ibm8514_force_redraw(void *priv)
svga->fullchange = changeframecount;
}
#ifdef ATI_8514_ULTRA
// clang-format off
static const device_config_t ext8514_config[] = {
{
.name = "extensions",
.description = "Vendor",
.type = CONFIG_SELECTION,
.default_int = 0,
.selection = {
{
.description = "IBM",
.value = 0
},
{
.description = "ATI",
.value = 1
},
{
.description = ""
}
}
},
{
.type = CONFIG_END
}
};
#endif
// clang-format off
const device_t gen8514_isa_device = {
.name = "Generic 8514/A clone (ISA)",

View File

@@ -136,6 +136,10 @@ ati28800_out(uint16_t addr, uint8_t val, void *priv)
if ((old ^ val) & 0x80)
svga_recalctimings(svga);
break;
case 0xad:
if ((old ^ val) & 0x0c)
svga_recalctimings(svga);
break;
case 0xb0:
if ((old ^ val) & 0x60)
svga_recalctimings(svga);
@@ -403,7 +407,11 @@ ati28800_recalctimings(svga_t *svga)
ati28800_t *ati28800 = (ati28800_t *) svga->priv;
int clock_sel;
clock_sel = ((svga->miscout >> 2) & 3) | ((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1);
if (ati28800->regs[0xad] & 0x08)
svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1;
clock_sel = ((svga->miscout >> 2) & 3) | ((ati28800->regs[0xbe] & 0x10) >> 1) |
((ati28800->regs[0xb9] & 2) << 1);
if (ati28800->regs[0xa3] & 0x10)
svga->ma_latch |= 0x10000;
@@ -421,6 +429,8 @@ ati28800_recalctimings(svga_t *svga)
svga->hdisp <<= 1;
svga->htotal <<= 1;
svga->rowoffset <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
svga->gdcreg[5] &= ~0x40;
}
@@ -436,6 +446,8 @@ ati28800_recalctimings(svga_t *svga)
if ((ati28800->regs[0xb6] & 0x18) == 8) {
svga->hdisp <<= 1;
svga->htotal <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
svga->ati_4color = 1;
} else
svga->ati_4color = 0;
@@ -443,7 +455,11 @@ ati28800_recalctimings(svga_t *svga)
if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) {
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen);
ati28800_log("SEQREG1 bit 3=%x. gdcreg5 bits 5-6=%02x, 4bit pel=%02x, planar 16color=%02x, apa mode=%02x, attregs10 bit 7=%02x.\n", svga->seqregs[1] & 8, svga->gdcreg[5] & 0x60, ati28800->regs[0xb3] & 0x40, ati28800->regs[0xac] & 0x40, ati28800->regs[0xb6] & 0x18, ati28800->svga.attrregs[0x10] & 0x80);
ati28800_log("SEQREG1 bit 3=%x. gdcreg5 bits 5-6=%02x, 4bit pel=%02x, "
"planar 16color=%02x, apa mode=%02x, attregs10 bit 7=%02x.\n",
svga->seqregs[1] & 8, svga->gdcreg[5] & 0x60,
ati28800->regs[0xb3] & 0x40, ati28800->regs[0xac] & 0x40,
ati28800->regs[0xb6] & 0x18, ati28800->svga.attrregs[0x10] & 0x80);
switch (svga->gdcreg[5] & 0x60) {
case 0x00:
if (svga->seqregs[1] & 8) /*Low res (320)*/
@@ -478,6 +494,8 @@ ati28800_recalctimings(svga_t *svga)
else {
svga->render = svga_render_15bpp_highres;
svga->hdisp >>= 1;
svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1;
svga->hblank_end_val >>= 1;
svga->rowoffset <<= 1;
svga->ma_latch <<= 1;
}

View File

@@ -44,6 +44,7 @@
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/timer.h>
#include <86box/video.h>
#include <86box/vid_8514a.h>

View File

@@ -113,6 +113,7 @@ typedef struct mach64_t {
uint32_t crtc_gen_cntl;
uint8_t crtc_int_cntl;
uint32_t crtc_h_sync_strt_wid;
uint32_t crtc_h_total_disp;
uint32_t crtc_v_sync_strt_wid;
uint32_t crtc_v_total_disp;
@@ -514,6 +515,10 @@ mach64_recalctimings(svga_t *svga)
svga->dispend = ((mach64->crtc_v_total_disp >> 16) & 2047) + 1;
svga->htotal = (mach64->crtc_h_total_disp & 255) + 1;
svga->hdisp_time = svga->hdisp = ((mach64->crtc_h_total_disp >> 16) & 255) + 1;
svga->hblankstart = (mach64->crtc_h_sync_strt_wid & 255) +
((mach64->crtc_h_sync_strt_wid >> 8) & 7) + 1;
svga->hblank_end_val = (svga->hblankstart +
((mach64->crtc_h_sync_strt_wid >> 16) & 31) - 1) & 63;
svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1;
svga->rowoffset = (mach64->crtc_off_pitch >> 22);
svga->clock = (cpuclock * (double) (1ULL << 32)) / ics2595_getclock(svga->clock_gen);
@@ -565,9 +570,8 @@ mach64_recalctimings(svga_t *svga)
}
svga->vram_display_mask = mach64->vram_mask;
} else {
} else
svga->vram_display_mask = (mach64->regs[0x36] & 0x01) ? mach64->vram_mask : 0x3ffff;
}
}
void
@@ -2348,6 +2352,12 @@ mach64_ext_readb(uint32_t addr, void *priv)
case 0x03:
READ8(addr, mach64->crtc_h_total_disp);
break;
case 0x04:
case 0x05:
case 0x06:
case 0x07:
READ8(addr, mach64->crtc_h_sync_strt_wid);
break;
case 0x08:
case 0x09:
case 0x0a:
@@ -3050,6 +3060,14 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv)
svga_recalctimings(&mach64->svga);
svga->fullchange = svga->monitor->mon_changeframecount;
break;
case 0x04:
case 0x05:
case 0x06:
case 0x07:
WRITE8(addr, mach64->crtc_h_sync_strt_wid, val);
svga_recalctimings(&mach64->svga);
svga->fullchange = svga->monitor->mon_changeframecount;
break;
case 0x08:
case 0x09:
case 0x0a:

File diff suppressed because it is too large Load Diff

View File

@@ -1751,6 +1751,35 @@ gd54xx_recalctimings(svga_t *svga)
uint8_t rdmask;
uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp;
svga->hblankstart = svga->crtc[2] + 1;
if (svga->crtc[0x1b] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5424) ? 0xa0 : 0x20)) {
/* Special blanking mode: the blank start and end become components of the window generator,
and the actual blanking comes from the display enable signal. */
/* This means blanking during overscan, we already calculate it that way, so just use the
same calculation and force otvercan to 0. */
svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00) |
(((svga->crtc[0x1a] >> 4) & 3) << 6);
if (svga->crtc[0x1b] & 0x20) {
svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + 1;
svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3);
/* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */
if (!svga->scrblank && svga->attr_palette_enable)
svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8;
/* No overscan in this mode. */
svga->hblank_overscan = 0;
svga->monitor->mon_overscan_y = 0;
svga->monitor->mon_overscan_x = 0;
/* Also make sure vertical blanking starts on display end. */
svga->vblankstart = svga->dispend;
}
}
svga->rowoffset = (svga->crtc[0x13]) | (((int) (uint32_t) (svga->crtc[0x1b] & 0x10)) << 4);
svga->interlace = (svga->crtc[0x1a] & 0x01);
@@ -1765,8 +1794,11 @@ gd54xx_recalctimings(svga_t *svga)
svga->render = svga_render_8bpp_lowres;
else {
svga->render = svga_render_8bpp_highres;
if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga))
if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) {
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
}
}
} else if (svga->gdcreg[5] & 0x40)
svga->render = svga_render_8bpp_lowres;
@@ -1942,6 +1974,9 @@ gd54xx_recalctimings(svga_t *svga)
svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff;
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430)
svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07);
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/
if (svga->seqregs[1] & 8) {
svga->render = svga_render_text_40;

View File

@@ -55,17 +55,19 @@
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
#define ET4000_TYPE_TC6058AF 0 /* ISA ET4000AX (TC6058AF) */
#define ET4000_TYPE_ISA 1 /* ISA ET4000AX */
#define ET4000_TYPE_MCA 2 /* MCA ET4000AX */
#define ET4000_TYPE_KOREAN 3 /* Korean ET4000 */
#define ET4000_TYPE_TRIGEM 4 /* Trigem 286M ET4000 */
#define ET4000_TYPE_KASAN 5 /* Kasan ET4000 */
#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN"
#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin"
#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom"
#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin"
#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom"
#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN"
#define TC6058AF_BIOS_ROM_PATH "roms/video/et4000/Tseng_Labs_VGA-4000_BIOS_V1.1.bin"
#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin"
#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom"
#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin"
#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom"
typedef struct {
const char *name;
@@ -115,6 +117,7 @@ et4000_in(uint16_t addr, void *priv)
{
et4000_t *dev = (et4000_t *) priv;
svga_t *svga = &dev->svga;
uint8_t ret;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
@@ -138,7 +141,8 @@ et4000_in(uint16_t addr, void *priv)
case 0x3c7:
case 0x3c8:
case 0x3c9:
return sc1502x_ramdac_in(addr, svga->ramdac, svga);
if (dev->type >= ET4000_TYPE_ISA)
return sc1502x_ramdac_in(addr, svga->ramdac, svga);
case 0x3cd: /*Banking*/
return dev->banking;
@@ -149,6 +153,26 @@ et4000_in(uint16_t addr, void *priv)
case 0x3d5:
return svga->crtc[svga->crtcreg];
case 0x3da:
svga->attrff = 0;
if (svga->cgastat & 0x01)
svga->cgastat &= ~0x30;
else
svga->cgastat ^= 0x30;
ret = svga->cgastat;
if ((svga->fcr & 0x08) && svga->dispon)
ret |= 0x08;
if (ret & 0x08)
ret &= 0x7f;
else
ret |= 0x80;
return ret;
default:
break;
}
@@ -225,12 +249,33 @@ et4000_out(uint16_t addr, uint8_t val, void *priv)
addr ^= 0x60;
switch (addr) {
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;
} else if (svga->seqaddr == 0x0e) {
svga->seqregs[0x0e] = val;
svga->chain4 &= ~0x02;
if (svga->gdcreg[5] & 0x40)
svga->chain4 |= (svga->seqregs[0x0e] & 0x02);
svga_recalctimings(svga);
return;
}
break;
case 0x3c6:
case 0x3c7:
case 0x3c8:
case 0x3c9:
sc1502x_ramdac_out(addr, val, svga->ramdac, svga);
return;
if (dev->type >= ET4000_TYPE_ISA) {
sc1502x_ramdac_out(addr, val, svga->ramdac, svga);
return;
}
break;
case 0x3cd: /*Banking*/
if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) {
@@ -241,7 +286,11 @@ et4000_out(uint16_t addr, uint8_t val, void *priv)
return;
case 0x3cf:
if ((svga->gdcaddr & 15) == 6) {
if ((svga->gdcaddr & 15) == 5) {
svga->chain4 &= ~0x02;
if (val & 0x40)
svga->chain4 |= (svga->seqregs[0x0e] & 0x02);
} else if ((svga->gdcaddr & 15) == 6) {
if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) {
svga->write_bank = (dev->banking & 0x0f) * 0x10000;
svga->read_bank = ((dev->banking >> 4) & 0x0f) * 0x10000;
@@ -418,7 +467,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv)
break;
case 1:
case 2:
et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val;
if ((et4000->kasan_cfg_index - 0xF0) <= 16)
et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val;
io_removehandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
et4000->kasan_access_addr = (et4000->kasan_cfg_regs[2] << 8) | et4000->kasan_cfg_regs[1];
io_sethandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
@@ -463,7 +513,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv)
case 4:
case 5:
if (et4000->kasan_cfg_regs[0] & 1) {
et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val;
if ((addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)) <= 4)
et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val;
}
break;
case 6:
@@ -548,6 +599,9 @@ et4000_recalctimings(svga_t *svga)
const et4000_t *dev = (et4000_t *) svga->priv;
svga->ma_latch |= (svga->crtc[0x33] & 3) << 16;
svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[2] + 1;
if (svga->crtc[0x35] & 1)
svga->vblankstart += 0x400;
if (svga->crtc[0x35] & 2)
@@ -562,8 +616,11 @@ et4000_recalctimings(svga_t *svga)
svga->rowoffset = 0x100;
if (svga->crtc[0x3f] & 1)
svga->htotal += 256;
if (svga->attrregs[0x16] & 0x20)
if (svga->attrregs[0x16] & 0x20) {
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
}
switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) {
case 0:
@@ -584,10 +641,14 @@ et4000_recalctimings(svga_t *svga)
case 15:
case 16:
svga->hdisp /= 2;
svga->hblankstart /= 2;
svga->hblank_end_val /= 2;
break;
case 24:
svga->hdisp /= 3;
svga->hblankstart /= 3;
svga->hblank_end_val /= 3;
break;
default:
@@ -606,6 +667,19 @@ et4000_recalctimings(svga_t *svga)
}
}
if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40)) {
svga->ma_latch <<= (1 << 0);
svga->rowoffset <<= (1 << 0);
svga->render = svga_render_8bpp_highres;
}
if (dev->type == ET4000_TYPE_TC6058AF) {
if (svga->render == svga_render_8bpp_lowres)
svga->render = svga_render_8bpp_tseng_lowres;
else if (svga->render == svga_render_8bpp_highres)
svga->render = svga_render_8bpp_tseng_highres;
}
if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x40)) {
svga->map8 = svga->pallook;
if (svga->lowres)
@@ -623,7 +697,8 @@ et4000_kasan_recalctimings(svga_t *svga)
et4000_recalctimings(svga);
if (svga->render == svga_render_text_80 && (et4000->kasan_cfg_regs[0] & 8)) {
svga->ma_latch -= 3;
svga->hdisp += svga->dots_per_clock;
svga->ma_latch -= 5;
svga->ca_adj = (et4000->kasan_cfg_regs[0] >> 6) - 3;
svga->ksc5601_sbyte_mask = (et4000->kasan_cfg_regs[0] & 4) << 5;
if ((et4000->kasan_cfg_regs[0] & 0x23) == 0x20 && (et4000->kasan_cfg_regs[4] & 0x80) && ((svga->crtc[0x37] & 0x0B) == 0x0A))
@@ -672,6 +747,7 @@ et4000_init(const device_t *info)
fn = BIOS_ROM_PATH;
switch (dev->type) {
case ET4000_TYPE_TC6058AF: /* ISA ET4000AX (TC6058AF) */
case ET4000_TYPE_ISA: /* ISA ET4000AX */
dev->vram_size = device_get_config_int("memory") << 10;
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa);
@@ -680,6 +756,8 @@ et4000_init(const device_t *info)
NULL, NULL);
io_sethandler(0x03c0, 32,
et4000_in, NULL, NULL, et4000_out, NULL, NULL, dev);
if (dev->type == ET4000_TYPE_TC6058AF)
fn = TC6058AF_BIOS_ROM_PATH;
break;
case ET4000_TYPE_MCA: /* MCA ET4000AX */
@@ -759,7 +837,8 @@ et4000_init(const device_t *info)
break;
}
dev->svga.ramdac = device_add(&sc1502x_ramdac_device);
if (dev->type >= ET4000_TYPE_ISA)
dev->svga.ramdac = device_add(&sc1502x_ramdac_device);
dev->vram_mask = dev->vram_size - 1;
@@ -799,6 +878,12 @@ et4000_force_redraw(void *priv)
dev->svga.fullchange = changeframecount;
}
static int
et4000_tc6058af_available(void)
{
return rom_present(TC6058AF_BIOS_ROM_PATH);
}
static int
et4000_available(void)
{
@@ -817,6 +902,33 @@ et4000_kasan_available(void)
return rom_present(KASAN_BIOS_ROM_PATH) && rom_present(KASAN_FONT_ROM_PATH);
}
static const device_config_t et4000_tc6058af_config[] = {
// clang-format off
{
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_int = 512,
.selection = {
{
.description = "256 KB",
.value = 256
},
{
.description = "512 KB",
.value = 512
},
{
.description = ""
}
}
},
{
.type = CONFIG_END
}
// clang-format on
};
static const device_config_t et4000_config[] = {
// clang-format off
{
@@ -848,6 +960,20 @@ static const device_config_t et4000_config[] = {
// clang-format on
};
const device_t et4000_tc6058af_isa_device = {
.name = "Tseng Labs ET4000AX (TC6058AF) (ISA)",
.internal_name = "et4000ax_tc6058af",
.flags = DEVICE_ISA,
.local = 0,
.init = et4000_init,
.close = et4000_close,
.reset = NULL,
{ .available = et4000_tc6058af_available },
.speed_changed = et4000_speed_changed,
.force_redraw = et4000_force_redraw,
.config = et4000_tc6058af_config
};
const device_t et4000_isa_device = {
.name = "Tseng Labs ET4000AX (ISA)",
.internal_name = "et4000ax",

View File

@@ -431,6 +431,9 @@ et4000w32p_recalctimings(svga_t *svga)
et4000w32p_t *et4000 = (et4000w32p_t *) svga->priv;
svga->ma_latch |= (svga->crtc[0x33] & 0x7) << 16;
svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[2] + 1;
if (svga->crtc[0x35] & 0x01)
svga->vblankstart += 0x400;
if (svga->crtc[0x35] & 0x02)
@@ -445,8 +448,11 @@ et4000w32p_recalctimings(svga_t *svga)
svga->rowoffset += 0x100;
if (svga->crtc[0x3F] & 0x01)
svga->htotal += 256;
if (svga->attrregs[0x16] & 0x20)
if (svga->attrregs[0x16] & 0x20) {
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
}
svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen);
@@ -472,30 +478,6 @@ et4000w32p_recalctimings(svga_t *svga)
}
}
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--;
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;
} else if ((svga->gdcreg[5] & 0x40) == 0) {
svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9;
if (svga->hdisp == 648 || svga->hdisp == 808 || svga->hdisp == 1032)
svga->hdisp -= 8;
}
}
}
if (et4000->type == ET4000W32) {
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
if (svga->gdcreg[5] & 0x40) {
@@ -518,8 +500,11 @@ et4000w32p_recalctimings(svga_t *svga)
switch (svga->bpp) {
case 15:
case 16:
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1))
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
}
if (et4000->type <= ET4000W32P_REVC) {
if (et4000->type == ET4000W32P_REVC) {
if (svga->hdisp != 1024)
@@ -530,6 +515,8 @@ et4000w32p_recalctimings(svga_t *svga)
break;
case 24:
svga->hdisp /= 3;
svga->hblankstart /= 3;
svga->hblank_end_val /= 3;
if (et4000->type <= ET4000W32P_REVC)
et4000->adjust_cursor = 2;
if ((et4000->type == ET4000W32P_DIAMOND) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232))) {
@@ -549,10 +536,6 @@ et4000w32p_recalctimings(svga_t *svga)
else
svga->render = svga_render_text_80;
} else {
if (svga->adv_flags & FLAG_NOSKEW) {
svga->ma_latch--;
}
switch (svga->gdcreg[5] & 0x60) {
case 0x00:
if (et4000->rev == 5)
@@ -2616,6 +2599,9 @@ et4000w32p_pci_read(UNUSED(int func), int addr, void *priv)
{
const et4000w32p_t *et4000 = (et4000w32p_t *) priv;
if (func > 0)
return 0xff;
addr &= 0xff;
switch (addr) {
@@ -2676,6 +2662,9 @@ et4000w32p_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
et4000w32p_t *et4000 = (et4000w32p_t *) priv;
svga_t *svga = &et4000->svga;
if (func > 0)
return;
addr &= 0xff;
switch (addr) {
@@ -2799,7 +2788,6 @@ et4000w32p_init(const device_t *info)
et4000->svga.ramdac = device_add(&stg_ramdac_device);
et4000->svga.clock_gen = et4000->svga.ramdac;
et4000->svga.getclock = stg_getclock;
et4000->svga.adv_flags |= FLAG_NOSKEW;
break;
case ET4000W32P_REVC:
@@ -2824,7 +2812,6 @@ et4000w32p_init(const device_t *info)
et4000->svga.ramdac = device_add(&stg_ramdac_device);
et4000->svga.clock_gen = et4000->svga.ramdac;
et4000->svga.getclock = stg_getclock;
et4000->svga.adv_flags |= FLAG_NOSKEW;
break;
case ET4000W32P_CARDEX:
@@ -2837,7 +2824,6 @@ et4000w32p_init(const device_t *info)
et4000->svga.ramdac = device_add(&stg_ramdac_device);
et4000->svga.clock_gen = et4000->svga.ramdac;
et4000->svga.getclock = stg_getclock;
et4000->svga.adv_flags |= FLAG_NOSKEW;
break;
case ET4000W32P_DIAMOND:

View File

@@ -312,6 +312,10 @@ ht216_out(uint16_t addr, uint8_t val, void *priv)
ht216_remap(ht216);
break;
case 0xca:
svga_recalctimings(svga);
break;
case 0xc9:
case 0xcf:
ht216_remap(ht216);
@@ -321,6 +325,7 @@ ht216_out(uint16_t addr, uint8_t val, void *priv)
svga->adv_flags &= ~FLAG_RAMDAC_SHIFT;
if (val & 0x04)
svga->adv_flags |= FLAG_RAMDAC_SHIFT;
svga_recalctimings(svga);
fallthrough;
/*Bank registers*/
case 0xe8:
@@ -688,7 +693,7 @@ ht216_recalctimings(svga_t *svga)
if (!(svga->crtc[1] & 1))
svga->hdisp--;
svga->hdisp++;
svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
svga->hdisp *= svga->dots_per_clock;
svga->rowoffset <<= 1;
if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/
svga->crtc[0x17] |= 0x40;
@@ -711,6 +716,9 @@ ht216_recalctimings(svga_t *svga)
svga->vram_display_mask = 0x7ffff;
else
svga->vram_display_mask = (ht216->ht_regs[0xf6] & 0x40) ? ht216->vram_mask : 0x3ffff;
if (ht216->ht_regs[0xe0] & 0x20)
svga->hblankstart = ((ht216->ht_regs[0xca] >> 2) << 8) + svga->crtc[4] + 1;
}
static void
@@ -1466,9 +1474,8 @@ radius_mca_feedb(UNUSED(void *priv))
return 1;
}
void
*
ht216_init(const device_t *info, uint32_t mem_size, int has_rom)
void *
ht216_init(const device_t *info, uint32_t mem_size, int has_rom)
{
ht216_t *ht216 = malloc(sizeof(ht216_t));
svga_t *svga;

View File

@@ -192,6 +192,8 @@
#define CRTCX_R0_OFFSET_MASK (3 << 4)
#define CRTCX_R1_HTOTAL8 (1 << 0)
#define CRTCX_R1_HBLKSTRT8 (1 << 1)
#define CRTCX_R1_HBLKEND6 (1 << 6)
#define CRTCX_R2_VTOTAL10 (1 << 0)
#define CRTCX_R2_VTOTAL11 (1 << 1)
@@ -941,6 +943,9 @@ mystique_recalctimings(svga_t *svga)
if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8)
svga->htotal |= 0x100;
svga->hblankstart = (((mystique->crtcext_regs[1] & 0x02) >> 2) << 8) + svga->crtc[2] + 1;
if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10)
svga->vtotal |= 0x400;
if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL11)
@@ -971,6 +976,12 @@ mystique_recalctimings(svga_t *svga)
svga->hdisp_time = svga->hdisp;
svga->rowoffset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4);
svga->dots_per_clock = 8;
svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) |
(((mystique->crtcext_regs[1] & 0x40) >> 6) << 6);
svga->hblank_overscan = 0;
if (mystique->type != MGA_2164W && mystique->type != MGA_2064W)
svga->lut_map = !!(mystique->xmiscctrl & XMISCCTRL_RAMCS);
@@ -2175,7 +2186,10 @@ mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *priv)
thread_wait_mutex(mystique->dma.lock);
WRITE8(addr, mystique->dma.primaddress, val);
mystique->dma.pri_state = 0;
mystique->dma.words_expected = 0;
if (mystique->dma.state == DMA_STATE_IDLE && !(mystique->softrap_pending || mystique->endprdmasts_pending || !mystique->softrap_status_read)) {
mystique->dma.words_expected = 0;
}
mystique->dma.state = DMA_STATE_IDLE;
thread_release_mutex(mystique->dma.lock);
break;

View File

@@ -29,7 +29,8 @@
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
#define BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN"
#define RTG_3105_BIOS_ROM_PATH "roms/video/rtg/RTG3105I.VBI"
#define RTG_3106_BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN"
typedef struct {
const char *name;
@@ -86,18 +87,18 @@ rtg_in(uint16_t addr, void *priv)
return svga->crtcreg;
case 0x3d5:
if (!(svga->crtc[0x1e] & 0x80) && (svga->crtcreg > 0x18))
return 0xff;
if (svga->crtcreg == 0x1a)
return dev->type << 6;
if (svga->crtcreg == 0x1e) {
ret = svga->crtc[0x1e];
ret &= ~3;
if (dev->vram_size == 1024)
ret = 2;
else if (dev->vram_size == 512)
ret = 1;
else
ret = 0;
return svga->crtc[0x1e] | ret;
return ret;
}
return svga->crtc[svga->crtcreg];
@@ -208,13 +209,12 @@ rtg_out(uint16_t addr, uint8_t val, void *priv)
static void
rtg_recalctimings(svga_t *svga)
{
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
const rtg_t *dev = (rtg_t *) svga->priv;
svga->ma_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17);
svga->interlace = (svga->crtc[0x19] & 1);
svga->lowres = svga->attrregs[0x10] & 0x40;
/*Clock table not available, currently a guesswork*/
switch (((svga->miscout >> 2) & 3) | ((svga->gdcreg[0x0c] & 0x20) >> 3)) {
case 0:
@@ -258,50 +258,41 @@ rtg_recalctimings(svga_t *svga)
break;
}
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
switch (svga->gdcreg[5] & 0x60) {
case 0x00:
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_4bpp_lowres;
else {
svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5);
svga->hdisp++;
svga->hdisp *= 8;
if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) {
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
switch (svga->gdcreg[5] & 0x60) {
case 0x00:
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_4bpp_lowres;
else {
if (svga->hdisp == 1280)
svga->rowoffset >>= 1;
if (svga->hdisp == 1280)
svga->rowoffset >>= 1;
svga->render = svga_render_4bpp_highres;
}
break;
case 0x20: /*4 colours*/
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_2bpp_lowres;
else
svga->render = svga_render_2bpp_highres;
break;
case 0x40:
case 0x60:
svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5);
svga->hdisp++;
svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
if (svga->crtc[0x19] & 2) {
if (svga->hdisp == 1280) {
svga->hdisp >>= 1;
} else
svga->rowoffset <<= 1;
svga->render = svga_render_8bpp_highres;
} else {
if (svga->lowres)
svga->render = svga_render_8bpp_lowres;
svga->render = svga_render_4bpp_highres;
}
break;
case 0x20: /*4 colours*/
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_2bpp_lowres;
else
svga->render = svga_render_8bpp_highres;
}
break;
svga->render = svga_render_2bpp_highres;
break;
case 0x40:
case 0x60:
if (svga->crtc[0x19] & 2) {
if (svga->hdisp == 1280)
svga->hdisp >>= 1;
else if (dev->type == 2)
svga->rowoffset <<= 1;
default:
break;
svga->render = svga_render_8bpp_highres;
} else
svga->render = svga_render_8bpp_lowres;
break;
default:
break;
}
}
}
}
@@ -316,13 +307,24 @@ rtg_init(const device_t *info)
memset(dev, 0x00, sizeof(rtg_t));
dev->name = info->name;
dev->type = info->local;
fn = BIOS_ROM_PATH;
fn = NULL;
switch (dev->type) {
case 2: /* ISA RTG3106 */
dev->vram_size = device_get_config_int("memory") << 10;
case 1: /* ISA RTG3105 */
fn = RTG_3105_BIOS_ROM_PATH;
dev->vram_size = device_get_config_int("memory");
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa);
svga_init(info, &dev->svga, dev, dev->vram_size,
svga_init(info, &dev->svga, dev, dev->vram_size << 10,
rtg_recalctimings, rtg_in, rtg_out,
NULL, NULL);
io_sethandler(0x03c0, 32,
rtg_in, NULL, NULL, rtg_out, NULL, NULL, dev);
break;
case 2: /* ISA RTG3106 */
fn = RTG_3106_BIOS_ROM_PATH;
dev->vram_size = device_get_config_int("memory");
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa);
svga_init(info, &dev->svga, dev, dev->vram_size << 10,
rtg_recalctimings, rtg_in, rtg_out,
NULL, NULL);
io_sethandler(0x03c0, 32,
@@ -371,12 +373,45 @@ rtg_force_redraw(void *priv)
}
static int
rtg_available(void)
rtg3105_available(void)
{
return rom_present(BIOS_ROM_PATH);
return rom_present(RTG_3105_BIOS_ROM_PATH);
}
static const device_config_t rtg_config[] = {
static int
rtg3106_available(void)
{
return rom_present(RTG_3106_BIOS_ROM_PATH);
}
static const device_config_t rtg3105_config[] = {
// clang-format off
{
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_int = 512,
.selection = {
{
.description = "256 KB",
.value = 256
},
{
.description = "512 KB",
.value = 512
},
{
.description = ""
}
}
},
{
.type = CONFIG_END
}
// clang-format on
};
static const device_config_t rtg3106_config[] = {
// clang-format off
{
.name = "memory",
@@ -407,16 +442,30 @@ static const device_config_t rtg_config[] = {
// clang-format on
};
const device_t realtek_rtg3105_device = {
.name = "Realtek RTG3105 (ISA)",
.internal_name = "rtg3105",
.flags = DEVICE_ISA,
.local = 1,
.init = rtg_init,
.close = rtg_close,
.reset = NULL,
{ .available = rtg3105_available },
.speed_changed = rtg_speed_changed,
.force_redraw = rtg_force_redraw,
.config = rtg3105_config
};
const device_t realtek_rtg3106_device = {
.name = "Realtek RTG3106 (ISA)",
.internal_name = "rtg3106",
.flags = DEVICE_ISA | DEVICE_AT,
.flags = DEVICE_ISA,
.local = 2,
.init = rtg_init,
.close = rtg_close,
.reset = NULL,
{ .available = rtg_available },
{ .available = rtg3106_available },
.speed_changed = rtg_speed_changed,
.force_redraw = rtg_force_redraw,
.config = rtg_config
.config = rtg3106_config
};

View File

@@ -946,10 +946,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8);
s3->accel.ssv_state = 0;
s3->accel_start(-1, 0, 0xffffffff, 0, s3);
if (s3->bpp == 3) {
if (!(s3->accel.multifunc[0xe] & 0x200) && !(svga->crtc[0x32] & 0x40))
s3->accel.multifunc[0xe] &= ~0x10;
}
break;
case 0x994a:
@@ -2781,6 +2777,10 @@ s3_out(uint16_t addr, uint8_t val, void *priv)
case 0x50:
s3->bpp = (svga->crtc[0x50] >> 4) & 3;
if (s3->bpp == 3) {
if (!(s3->accel.multifunc[0xe] & 0x200)) /*On True Color mode change, reset bit 4 of Misc Index register*/
s3->accel.multifunc[0xe] &= ~0x10;
}
break;
case 0x5c:
@@ -3153,15 +3153,16 @@ s3_recalctimings(svga_t *svga)
int clk_sel = (svga->miscout >> 2) & 3;
uint8_t mask = 0xc0;
svga->ma_latch |= (s3->ma_ext << 16);
if (s3->chip >= S3_86C928) {
svga->hdisp = svga->hdisp_old;
svga->hdisp = svga->hdisp_old;
svga->ma_latch |= (s3->ma_ext << 16);
if (s3->chip >= S3_86C928) {
if (svga->crtc[0x5d] & 0x01)
svga->htotal |= 0x100;
if (svga->crtc[0x5d] & 0x02) {
svga->hdisp_time |= 0x100;
svga->hdisp |= (0x100 * ((svga->seqregs[1] & 8) ? 16 : 8));
svga->hdisp |= 0x100 * svga->dots_per_clock;
}
if (svga->crtc[0x5e] & 0x01)
svga->vtotal |= 0x400;
@@ -3181,7 +3182,8 @@ s3_recalctimings(svga_t *svga)
svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4;
else if (svga->crtc[0x43] & 0x04)
svga->rowoffset |= 0x100;
}
} else if (svga->crtc[0x43] & 0x04)
svga->rowoffset |= 0x100;
if (!svga->rowoffset)
svga->rowoffset = 0x100;
@@ -3247,6 +3249,44 @@ s3_recalctimings(svga_t *svga)
break;
}
if (svga->crtc[0x33] & 0x20) {
/* The S3 version of the Cirrus' special blanking mode, with identical behavior. */
svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] +
((svga->crtc[3] >> 5) & 3) + 1;
svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3);
/* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */
if (!svga->scrblank && svga->attr_palette_enable)
svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8;
/* No overscan in this mode. */
svga->hblank_overscan = 0;
svga->monitor->mon_overscan_y = 0;
svga->monitor->mon_overscan_x = 0;
/* Also make sure vertical blanking starts on display end. */
svga->vblankstart = svga->dispend;
} else if (s3->chip >= S3_86C801) {
if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) {
/* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */
svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18);
}
svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1;
if (svga->crtc[0x5d] & 0x04)
svga->hblankstart += 0x100;
if (s3->chip >= S3_VISION964) {
/* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6?
The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6,
and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868,
and Vision968. */
svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) |
(((svga->crtc[0x5d] & 0x08) >> 3) << 6);
}
}
#ifdef OLD_CODE_REFERENCE
if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805 || s3->card_type == S3_NUMBER9_9FX_531 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) {
if (!(svga->crtc[0x5e] & 0x04))
@@ -3291,14 +3331,20 @@ s3_recalctimings(svga_t *svga)
switch (s3->width) {
case 1280:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
break;
case 2048: /*Account for the 1280x1024 resolution*/
switch (svga->hdisp) {
case 320:
svga->hdisp <<= 2;
svga->hblankstart <<= 2;
svga->hblank_end_val <<= 2;
break;
case 640:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
break;
default:
break;
@@ -3319,6 +3365,8 @@ s3_recalctimings(svga_t *svga)
switch (s3->width) {
case 640:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
default:
break;
@@ -3332,7 +3380,15 @@ s3_recalctimings(svga_t *svga)
case S3_VISION964:
switch (s3->card_type) {
case S3_ELSAWIN2KPROX_964:
svga->hdisp <<= 1;
switch (s3->width) {
case 1280:
case 1600:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
default:
break;
}
break;
default:
@@ -3341,17 +3397,31 @@ s3_recalctimings(svga_t *svga)
break;
case S3_VISION968:
switch (s3->card_type) {
case S3_PHOENIX_VISION968:
case S3_NUMBER9_9FX_771:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
break;
case S3_SPEA_MERCURY_P64V:
case S3_ELSAWIN2KPROX:
case S3_PHOENIX_VISION968:
svga->hdisp <<= 1;
switch (s3->width) {
case 1280:
case 1600:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
default:
break;
}
break;
case S3_MIROVIDEO40SV_ERGO_968:
switch (s3->width) {
case 1152:
case 1280:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
break;
default:
break;
@@ -3384,6 +3454,7 @@ s3_recalctimings(svga_t *svga)
} else if (s3->card_type == S3_SPEA_MERCURY_P64V) {
if (s3->width == 1280 || s3->width == 1600)
svga->hdisp <<= 1;
}
} else if (s3->card_type == S3_NUMBER9_9FX_771)
svga->hdisp <<= 1;
}
@@ -3395,12 +3466,16 @@ s3_recalctimings(svga_t *svga)
case S3_86C911:
case S3_86C924:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
case S3_86C801:
switch (s3->card_type) {
case S3_PHOENIX_86C801:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
default:
@@ -3414,15 +3489,23 @@ s3_recalctimings(svga_t *svga)
case S3_PHOENIX_86C805:
case S3_86C805_ONBOARD:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
case S3_SPEA_MIRAGE_86C805:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
switch (s3->width) {
case 800:
case 1024:
if (svga->hdisp == 400) /*SPEA specific drivers + its VBE RAM BIOS...*/
if (svga->hdisp == 400) {
/*SPEA specific drivers + its VBE RAM BIOS...*/
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
}
break;
default:
break;
@@ -3436,8 +3519,11 @@ s3_recalctimings(svga_t *svga)
case S3_86C928:
switch (s3->card_type) {
case S3_METHEUS_86C928:
if (!s3->color_16bit)
if (!s3->color_16bit) {
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
}
switch (svga->hdisp) { /*This might be a driver issue*/
case 800:
s3->width = 1024;
@@ -3460,6 +3546,8 @@ s3_recalctimings(svga_t *svga)
switch (s3->width) {
case 640:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
default:
break;
@@ -3471,14 +3559,9 @@ s3_recalctimings(svga_t *svga)
}
break;
case S3_VISION864:
switch (s3->card_type) {
case S3_MIROCRYSTAL20SD_864:
svga->hdisp >>= 1;
break;
default:
break;
}
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
case S3_VISION964:
switch (s3->card_type) {
@@ -3487,6 +3570,8 @@ s3_recalctimings(svga_t *svga)
case 1280:
case 1600:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
break;
default:
break;
@@ -3502,6 +3587,8 @@ s3_recalctimings(svga_t *svga)
case S3_PHOENIX_VISION868:
case S3_NUMBER9_9FX_531:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
default:
@@ -3513,6 +3600,9 @@ s3_recalctimings(svga_t *svga)
case S3_NUMBER9_9FX_771:
case S3_PHOENIX_VISION968:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
/* TODO: Is this still needed? */
if (svga->hdisp == 832)
svga->hdisp -= 32;
break;
@@ -3522,6 +3612,8 @@ s3_recalctimings(svga_t *svga)
case 1280:
case 1600:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
break;
default:
break;
@@ -3535,6 +3627,8 @@ s3_recalctimings(svga_t *svga)
case S3_TRIO64:
case S3_TRIO32:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
default:
@@ -3570,12 +3664,16 @@ s3_recalctimings(svga_t *svga)
case S3_86C911:
case S3_86C924:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
case S3_86C801:
switch (s3->card_type) {
case S3_PHOENIX_86C801:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
default:
@@ -3589,6 +3687,8 @@ s3_recalctimings(svga_t *svga)
case S3_PHOENIX_86C805:
case S3_86C805_ONBOARD:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
case S3_SPEA_MIRAGE_86C805:
@@ -3596,8 +3696,12 @@ s3_recalctimings(svga_t *svga)
switch (s3->width) {
case 800:
case 1024:
if (svga->hdisp == 400) /*SPEA specific drivers + its VBE RAM BIOS...*/
if (svga->hdisp == 400) {
/*SPEA specific drivers + its VBE RAM BIOS...*/
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
}
break;
default:
break;
@@ -3612,6 +3716,8 @@ s3_recalctimings(svga_t *svga)
switch (s3->card_type) {
case S3_METHEUS_86C928:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
switch (svga->hdisp) { /*This might be a driver issue*/
case 800:
s3->width = 1024;
@@ -3634,7 +3740,9 @@ s3_recalctimings(svga_t *svga)
switch (s3->width) {
case 640:
svga->hdisp >>= 1;
break;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
default:
break;
}
@@ -3645,20 +3753,17 @@ s3_recalctimings(svga_t *svga)
}
break;
case S3_VISION864:
switch (s3->card_type) {
case S3_MIROCRYSTAL20SD_864:
svga->hdisp >>= 1;
break;
default:
break;
}
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
case S3_VISION868:
switch (s3->card_type) {
case S3_PHOENIX_VISION868:
case S3_NUMBER9_9FX_531:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
default:
@@ -3672,6 +3777,8 @@ s3_recalctimings(svga_t *svga)
case 1280:
case 1600:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
break;
default:
break;
@@ -3687,6 +3794,9 @@ s3_recalctimings(svga_t *svga)
case S3_NUMBER9_9FX_771:
case S3_PHOENIX_VISION968:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
/* TODO: Is this still needed? */
if (svga->hdisp == 832)
svga->hdisp -= 32;
break;
@@ -3696,6 +3806,8 @@ s3_recalctimings(svga_t *svga)
case 1280:
case 1600:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
break;
default:
break;
@@ -3709,6 +3821,8 @@ s3_recalctimings(svga_t *svga)
case S3_TRIO64:
case S3_TRIO32:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
default:
@@ -3751,6 +3865,9 @@ s3_recalctimings(svga_t *svga)
switch (s3->card_type) {
case S3_AMI_86C924:
svga->hdisp = (svga->hdisp << 1) / 3;
svga->hblankstart = (svga->hblankstart << 1) / 3;
svga->hblank_end_val = (svga->hblank_end_val << 1) / 3;
/* TODO: Is this still needed? */
if (svga->hdisp == 645)
svga->hdisp -= 5;
break;
@@ -3763,6 +3880,8 @@ s3_recalctimings(svga_t *svga)
case S3_PHOENIX_86C801:
case S3_SPEA_MIRAGE_86C801:
svga->hdisp = (svga->hdisp << 1) / 3;
svga->hblankstart = (svga->hblankstart << 1) / 3;
svga->hblank_end_val = (svga->hblank_end_val << 1) / 3;
break;
default:
break;
@@ -3776,6 +3895,8 @@ s3_recalctimings(svga_t *svga)
case S3_SPEA_MIRAGE_86C805:
case S3_86C805_ONBOARD:
svga->hdisp = (svga->hdisp << 1) / 3;
svga->hblankstart = (svga->hblankstart << 1) / 3;
svga->hblank_end_val = (svga->hblank_end_val << 1) / 3;
break;
default:
break;
@@ -3785,27 +3906,26 @@ s3_recalctimings(svga_t *svga)
switch (s3->card_type) {
case S3_SPEA_MERCURY_LITE_PCI:
svga->hdisp = (svga->hdisp << 1) / 3;
svga->hblankstart = (svga->hblankstart << 1) / 3;
svga->hblank_end_val = (svga->hblank_end_val << 1) / 3;
break;
default:
break;
}
break;
case S3_VISION864:
switch (s3->card_type) {
case S3_MIROCRYSTAL20SD_864:
svga->hdisp = (svga->hdisp << 1) / 3;
break;
default:
break;
}
svga->hdisp = (svga->hdisp << 1) / 3;
svga->hblankstart = (svga->hblankstart << 1) / 3;
svga->hblank_end_val = (svga->hblank_end_val << 1) / 3;
break;
case S3_VISION968:
switch (s3->card_type) {
case S3_MIROVIDEO40SV_ERGO_968:
switch (s3->width) {
case 1280:
svga->hdisp = (svga->hdisp << 1) / 3;
svga->hdisp <<= 1;
svga->hdisp = ((svga->hdisp << 1) / 3) << 1;
svga->hblankstart = (svga->hblankstart << 1) / 3;
svga->hblank_end_val = ((svga->hblank_end_val << 1) / 3) << 1;
break;
default:
break;
@@ -3820,6 +3940,8 @@ s3_recalctimings(svga_t *svga)
case S3_TRIO64:
case S3_TRIO32:
svga->hdisp /= 3;
svga->hblankstart /= 3;
svga->hblank_end_val /= 3;
break;
default:
@@ -3861,6 +3983,8 @@ s3_recalctimings(svga_t *svga)
case S3_PHOENIX_VISION868:
case S3_NUMBER9_9FX_531:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
default:
break;
@@ -3873,6 +3997,8 @@ s3_recalctimings(svga_t *svga)
case 800:
case 1024:
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
default:
break;
@@ -3883,6 +4009,8 @@ s3_recalctimings(svga_t *svga)
case 1280:
case 1600:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
break;
default:
break;
@@ -3897,6 +4025,9 @@ s3_recalctimings(svga_t *svga)
case S3_NUMBER9_9FX_771:
case S3_PHOENIX_VISION968:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
/* TODO: Is this still needed? */
if (svga->hdisp == 832)
svga->hdisp -= 32;
break;
@@ -3906,6 +4037,8 @@ s3_recalctimings(svga_t *svga)
case 1280:
case 1600:
svga->hdisp <<= 1;
svga->hblankstart <<= 1;
svga->hblank_end_val <<= 1;
break;
default:
break;
@@ -3988,12 +4121,17 @@ s3_trio64v_recalctimings(svga_t *svga)
s3_t *s3 = (s3_t *) svga->priv;
int clk_sel = (svga->miscout >> 2) & 3;
if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) {
/* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */
svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18);
}
svga->hdisp = svga->hdisp_old;
if (svga->crtc[0x5d] & 0x01)
svga->htotal |= 0x100;
if (svga->crtc[0x5d] & 0x02) {
svga->hdisp_time |= 0x100;
svga->hdisp |= 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8);
svga->hdisp |= 0x100 * svga->dots_per_clock;
}
if (svga->crtc[0x5e] & 0x01)
svga->vtotal |= 0x400;
@@ -4033,6 +4171,35 @@ s3_trio64v_recalctimings(svga_t *svga)
break;
}
if ((svga->crtc[0x33] & 0x20) ||((svga->crtc[0x67] & 0xc) == 0xc)) {
/* The S3 version of the Cirrus' special blanking mode, with identical behavior. */
svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] +
((svga->crtc[3] >> 5) & 3) + 1;
svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3);
/* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */
if (!svga->scrblank && svga->attr_palette_enable)
svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8;
/* No overscan in this mode. */
svga->hblank_overscan = 0;
svga->monitor->mon_overscan_y = 0;
svga->monitor->mon_overscan_x = 0;
/* Also make sure vertical blanking starts on display end. */
svga->vblankstart = svga->dispend;
} else {
svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1;
/* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6?
The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6,
and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868,
and Vision968. */
svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) |
(((svga->crtc[0x5d] & 0x08) >> 3) << 6);
}
if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/
{
svga->ma_latch |= (s3->ma_ext << 16);
@@ -4054,14 +4221,20 @@ s3_trio64v_recalctimings(svga_t *svga)
case 15:
svga->render = svga_render_15bpp_highres;
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
case 16:
svga->render = svga_render_16bpp_highres;
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
break;
case 24:
svga->render = svga_render_24bpp_highres;
svga->hdisp /= 3;
svga->hblankstart >>= 1;
svga->hblank_end_val /= 3;
break;
case 32:
svga->render = svga_render_32bpp_highres;
@@ -4104,10 +4277,14 @@ s3_trio64v_recalctimings(svga_t *svga)
break;
case 3: /*KRGB-16 (1.5.5.5)*/
svga->htotal >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
svga->render = svga_render_15bpp_highres;
break;
case 5: /*RGB-16 (5.6.5)*/
svga->htotal >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
svga->render = svga_render_16bpp_highres;
break;
case 6: /*RGB-24 (8.8.8)*/

View File

@@ -778,11 +778,16 @@ s3_virge_recalctimings(svga_t *svga)
svga->hdisp = svga->hdisp_old;
if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) {
/* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */
svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18);
}
if (svga->crtc[0x5d] & 0x01)
svga->htotal += 0x100;
if (svga->crtc[0x5d] & 0x02) {
svga->hdisp_time += 0x100;
svga->hdisp += 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8);
svga->hdisp += 0x100 * svga->dots_per_clock;
}
if (svga->crtc[0x5e] & 0x01)
svga->vtotal += 0x400;
@@ -813,6 +818,31 @@ s3_virge_recalctimings(svga_t *svga)
svga->clock = (cpuclock * (float) (1ULL << 32)) / freq;
}
if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) {
/* The S3 version of the Cirrus' special blanking mode, with identical behavior. */
svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] +
((svga->crtc[3] >> 5) & 3) + 1;
svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3);
/* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */
if (!svga->scrblank && svga->attr_palette_enable)
svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8;
/* No overscan in this mode. */
svga->hblank_overscan = 0;
svga->monitor->mon_overscan_y = 0;
svga->monitor->mon_overscan_x = 0;
/* Also make sure vertical blanking starts on display end. */
svga->vblankstart = svga->dispend;
} else {
svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2] + 1;
svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) |
(((svga->crtc[0x5d] & 0x08) >> 3) << 6);
}
if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/
{
svga->ma_latch |= (virge->ma_ext << 16);
@@ -834,6 +864,8 @@ s3_virge_recalctimings(svga_t *svga)
if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) {
svga->htotal >>= 1;
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
}
break;
case 16:
@@ -841,6 +873,8 @@ s3_virge_recalctimings(svga_t *svga)
if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) {
svga->htotal >>= 1;
svga->hdisp >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
}
break;
case 24:
@@ -888,10 +922,14 @@ s3_virge_recalctimings(svga_t *svga)
break;
case 3: /*KRGB-16 (1.5.5.5)*/
svga->htotal >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
svga->render = svga_render_15bpp_highres;
break;
case 5: /*RGB-16 (5.6.5)*/
svga->htotal >>= 1;
svga->hblankstart >>= 1;
svga->hblank_end_val >>= 1;
svga->render = svga_render_16bpp_highres;
break;
case 6: /*RGB-24 (8.8.8)*/

View File

@@ -253,7 +253,7 @@ svga_out(uint16_t addr, uint8_t val, void *priv)
break;
case 4:
svga->chain2_write = !(val & 4);
svga->chain4 = val & 8;
svga->chain4 = (svga->chain4 & ~8) | (val & 8);
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8);
break;
@@ -355,6 +355,9 @@ svga_out(uint16_t addr, uint8_t val, void *priv)
if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1))
svga_recalctimings(svga);
break;
case 0x3da:
svga->fcr = val;
break;
default:
break;
@@ -475,6 +478,9 @@ svga_in(uint16_t addr, void *priv)
if (svga->adv_flags & FLAG_RAMDAC_SHIFT)
ret >>= 2;
break;
case 0x3ca:
ret = svga->fcr;
break;
case 0x3cc:
ret = svga->miscout;
break;
@@ -511,6 +517,8 @@ svga_in(uint16_t addr, void *priv)
ret = svga->cgastat;
if ((svga->fcr & 0x08) && svga->dispon)
ret |= 0x08;
break;
default:
@@ -564,6 +572,14 @@ svga_recalctimings(svga_t *svga)
double _dispontime;
double _dispofftime;
double disptime;
#ifdef ENABLE_SVGA_LOG
int vsyncend;
int vblankend;
int hdispstart;
int hdispend;
int hsyncstart;
int hsyncend;
#endif
svga->vtotal = svga->crtc[6];
svga->dispend = svga->crtc[0x12];
@@ -601,7 +617,7 @@ svga_recalctimings(svga_t *svga)
svga->vblankstart |= 0x200;
svga->vblankstart++;
svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5);
svga->hdisp = svga->crtc[1];
svga->hdisp++;
svga->htotal = svga->crtc[0];
@@ -624,20 +640,20 @@ svga_recalctimings(svga_t *svga)
svga->hdisp_time = svga->hdisp;
svga->render = svga_render_blank;
if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) {
/* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */
if (svga->seqregs[1] & 8)
svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18;
else
svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9;
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/
if (svga->seqregs[1] & 8) { /*40 column*/
svga->render = svga_render_text_40;
svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18;
/* Character clock is off by 1 now in 40-line modes, on all cards. */
svga->ma_latch--;
svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18;
} else {
svga->render = svga_render_text_80;
svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9;
}
svga->hdisp_old = svga->hdisp;
} else {
svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
svga->hdisp_old = svga->hdisp;
if ((svga->bpp <= 8) || ((svga->gdcreg[5] & 0x60) <= 0x20)) {
@@ -722,9 +738,26 @@ svga_recalctimings(svga_t *svga)
} else
svga->monitor->mon_overscan_x = 16;
if (svga->recalctimings_ex) {
svga->hblankstart = svga->crtc[2] + 1;
svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00);
svga_log("htotal = %i, hblankstart = %i, hblank_end_val = %02X\n",
svga->htotal, svga->hblankstart, svga->hblank_end_val);
svga->hblank_end_len = 0x00000040;
svga->hblank_overscan = 1;
if (!svga->scrblank && svga->attr_palette_enable) {
/* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */
if (svga->seqregs[1] & 8)
svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18);
else
svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9);
} else
svga->dots_per_clock = 1;
if (svga->recalctimings_ex)
svga->recalctimings_ex(svga);
}
if (ibm8514_active && (svga->dev8514 != NULL)) {
if ((dev->local & 0xff) == 0x00)
@@ -734,6 +767,21 @@ svga_recalctimings(svga_t *svga)
if (xga_active && (svga->xga != NULL))
xga_recalctimings(svga);
if (!svga->hoverride) {
svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val;
if (svga->hblankend <= svga->hblankstart)
svga->hblankend += svga->hblank_end_len;
svga->hblankend += svga->hblank_ext;
svga->hblank_sub = 0;
if (svga->hblankend > svga->htotal) {
svga->hblankend &= (svga->hblank_end_len - 1);
svga->hblank_sub = svga->hblankend + svga->hblank_overscan;
svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock);
}
}
if (svga->hdisp >= 2048)
svga->monitor->mon_overscan_x = 0;
@@ -745,6 +793,43 @@ svga_recalctimings(svga_t *svga)
crtcconst = svga->clock * svga->char_width;
#ifdef ENABLE_SVGA_LOG
vsyncend = (svga->vsyncstart & 0xfffffff0) | (svga->crtc[0x11] & 0x0f);
if (vsyncend <= svga->vsyncstart)
vsyncend += 0x00000010;
vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f);
if (vblankend <= svga->vblankstart)
vblankend += 0x00000080;
hdispstart = ((svga->crtc[3] >> 5) & 3);
hdispend = svga->crtc[1] + 1;
hsyncstart = svga->crtc[4] + ((svga->crtc[5] >> 5) & 3) + 1;
hsyncend = (hsyncstart & 0xffffffe0) | (svga->crtc[5] & 0x1f);
if (hsyncend <= hsyncstart)
hsyncend += 0x00000020;
#endif
svga_log("Last scanline in the vertical period: %i\n"
"First scanline after the last of active display: %i\n"
"First scanline with vertical retrace asserted: %i\n"
"First scanline after the last with vertical retrace asserted: %i\n"
"First scanline of blanking: %i\n"
"First scanline after the last of blanking: %i\n"
"\n"
"Last character in the horizontal period: %i\n"
"First character of active display: %i\n"
"First character after the last of active display: %i\n"
"First character with horizontal retrace asserted: %i\n"
"First character after the last with horizontal retrace asserted: %i\n"
"First character of blanking: %i\n"
"First character after the last of blanking: %i\n"
"\n"
"\n",
svga->vtotal, svga->dispend, svga->vsyncstart, vsyncend,
svga->vblankstart, vblankend,
svga->htotal, hdispstart, hdispend, hsyncstart, hsyncend,
svga->hblankstart, svga->hblankend);
disptime = svga->htotal;
_dispontime = svga->hdisp_time;
@@ -977,9 +1062,9 @@ svga_poll(void *priv)
if (ret) {
if (svga->interlace && svga->oddeven)
svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5);
svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
else
svga->ma = svga->maback = ((svga->crtc[5] & 0x60) >> 5);
svga->ma = svga->maback = ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
svga->ma = (svga->ma << 2);
svga->maback = (svga->maback << 2);
@@ -1049,9 +1134,10 @@ svga_poll(void *priv)
svga->vslines = 0;
if (svga->interlace && svga->oddeven)
svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5);
svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) +
((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
else
svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5);
svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
svga->ca = ((svga->crtc[0xe] << 8) | svga->crtc[0xf]) + ((svga->crtc[0xb] & 0x60) >> 5) + svga->ca_adj;
svga->ma = (svga->ma << 2);
@@ -1061,6 +1147,9 @@ svga_poll(void *priv)
if (svga->vsync_callback)
svga->vsync_callback(svga);
}
#if 0
if (svga->vc == lines_num) {
#endif
if (svga->vc == svga->vtotal) {
svga->vc = 0;
svga->sc = (svga->crtc[0x8] & 0x1f);
@@ -1188,7 +1277,8 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize,
svga->ramdac_type = RAMDAC_6BIT;
svga->map8 = svga->pallook;
svga->map8 = svga->pallook;
svga->hblank_overscan = 1; /* Do at least 1 character of overscan after horizontal blanking. */
return 0;
}

View File

@@ -85,9 +85,20 @@ svga_render_blank(svga_t *svga)
break;
}
#if 0
pclog("svga->displine = %i, svga->y_add = %i, svga->x_add = %i\n", svga->displine, svga->y_add, svga->x_add);
#endif
uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add];
#if 0
pclog("svga->hdisp = %i, svga->scrollcache = %i, char_width = %i, sizeof(uint32_t) = %i\n", svga->hdisp, svga->scrollcache, char_width, sizeof(uint32_t));
#endif
uint32_t line_width = (uint32_t) (svga->hdisp + svga->scrollcache) * char_width * sizeof(uint32_t);
memset(line_ptr, 0, line_width);
#if 0
pclog("line_width = %i\n", line_width);
#endif
if ((svga->hdisp + svga->scrollcache) > 0)
memset(line_ptr, 0, line_width);
}
void
@@ -96,7 +107,7 @@ svga_render_overscan_left(svga_t *svga)
if ((svga->displine + svga->y_add) < 0)
return;
if (svga->scrblank || (svga->hdisp == 0))
if (svga->scrblank || (svga->hdisp <= 0))
return;
uint32_t *line_ptr = svga->monitor->target_buffer->line[svga->displine + svga->y_add];
@@ -112,7 +123,7 @@ svga_render_overscan_right(svga_t *svga)
if ((svga->displine + svga->y_add) < 0)
return;
if (svga->scrblank || (svga->hdisp == 0))
if (svga->scrblank || (svga->hdisp <= 0))
return;
uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add + svga->hdisp];

View File

@@ -80,7 +80,7 @@ video_cards[] = {
{ &vid_none_device },
{ &vid_internal_device },
{ &atiega800p_device },
{ &mach8_isa_device, VIDEO_FLAG_TYPE_8514 },
{ &mach8_vga_isa_device, VIDEO_FLAG_TYPE_8514 },
{ &mach32_isa_device, VIDEO_FLAG_TYPE_8514 },
{ &mach64gx_isa_device },
{ &ati28800k_device },
@@ -133,6 +133,7 @@ video_cards[] = {
{ &pgc_device },
{ &cga_pravetz_device },
{ &radius_svga_multiview_isa_device },
{ &realtek_rtg3105_device },
{ &realtek_rtg3106_device },
{ &s3_diamond_stealth_vram_isa_device },
{ &s3_orchid_86c911_isa_device },
@@ -148,6 +149,7 @@ video_cards[] = {
{ &et4000k_isa_device },
{ &et2000_device },
{ &et3000_isa_device },
{ &et4000_tc6058af_isa_device },
{ &et4000_isa_device },
{ &et4000w32_device },
{ &et4000w32i_isa_device },

View File

@@ -76,7 +76,8 @@
#include <86box/vid_svga_render.h>
#define ROM_TGUI_9400CXI "roms/video/tgui9440/9400CXI.VBI"
#define ROM_TGUI_9440 "roms/video/tgui9440/BIOS.BIN"
#define ROM_TGUI_9440_VLB "roms/video/tgui9440/trident_9440_vlb.bin"
#define ROM_TGUI_9440_PCI "roms/video/tgui9440/BIOS.BIN"
#define ROM_TGUI_96xx "roms/video/tgui9660/Union.VBI"
#define EXT_CTRL_16BIT 0x01
@@ -891,7 +892,6 @@ tgui_recalcmapping(tgui_t *tgui)
}
} else {
mem_mapping_disable(&tgui->linear_mapping);
mem_mapping_disable(&tgui->accel_mapping);
switch (svga->gdcreg[6] & 0xC) {
case 0x0: /*128k at A0000*/
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
@@ -899,12 +899,6 @@ tgui_recalcmapping(tgui_t *tgui)
break;
case 0x4: /*64k at A0000*/
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
if ((svga->crtc[0x36] & 0x03) == 0x01)
mem_mapping_set_addr(&tgui->accel_mapping, 0xb4000, 0x4000);
else if ((svga->crtc[0x36] & 0x03) == 0x02)
mem_mapping_set_addr(&tgui->accel_mapping, 0xbc000, 0x4000);
else if ((svga->crtc[0x36] & 0x03) == 0x03)
mem_mapping_set_addr(&tgui->accel_mapping, tgui->ge_base, 0x4000);
svga->banked_mask = 0xffff;
break;
case 0x8: /*32k at B0000*/
@@ -919,6 +913,18 @@ tgui_recalcmapping(tgui_t *tgui)
default:
break;
}
if (tgui->pci && tgui->linear_base) /*Assume that, with PCI, linear addressing is always enabled.*/
mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size);
if ((svga->crtc[0x36] & 0x03) == 0x01)
mem_mapping_set_addr(&tgui->accel_mapping, 0xb4000, 0x4000);
else if ((svga->crtc[0x36] & 0x03) == 0x02)
mem_mapping_set_addr(&tgui->accel_mapping, 0xbc000, 0x4000);
else if ((svga->crtc[0x36] & 0x03) == 0x03)
mem_mapping_set_addr(&tgui->accel_mapping, tgui->ge_base, 0x4000);
else
mem_mapping_disable(&tgui->accel_mapping);
}
if (tgui->type >= TGUI_9440) {
@@ -982,7 +988,7 @@ tgui_pci_read(UNUSED(int func), int addr, void *priv)
return (tgui->type == TGUI_9440) ? 0x94 : 0x96;
case PCI_REG_COMMAND:
return tgui->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/
return tgui->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/
case 0x07:
return 1 << 1; /*Medium DEVSEL timing*/
@@ -1043,11 +1049,12 @@ tgui_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
switch (addr) {
case PCI_REG_COMMAND:
tgui->pci_regs[PCI_REG_COMMAND] = (val & 0x23);
if (val & PCI_COMMAND_IO) {
tgui->pci_regs[PCI_REG_COMMAND] = val & 0x23;
if (val & PCI_COMMAND_IO)
tgui_set_io(tgui);
} else
else
tgui_remove_io(tgui);
tgui_recalcmapping(tgui);
break;
@@ -3141,7 +3148,10 @@ tgui_init(const device_t *info)
bios_fn = ROM_TGUI_9400CXI;
break;
case TGUI_9440:
bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_9440;
if (tgui->pci)
bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_9440_PCI;
else
bios_fn = ROM_TGUI_9440_VLB;
break;
case TGUI_9660:
case TGUI_9680:
@@ -3193,7 +3203,7 @@ tgui_init(const device_t *info)
pci_add_card(PCI_ADD_VIDEO | PCI_ADD_STRICT, tgui_pci_read, tgui_pci_write, tgui, &tgui->pci_slot);
}
tgui->pci_regs[PCI_REG_COMMAND] = 7;
tgui->pci_regs[PCI_REG_COMMAND] = 0x83;
if (tgui->has_bios) {
tgui->pci_regs[0x30] = 0x00;
@@ -3218,9 +3228,15 @@ tgui9400cxi_available(void)
}
static int
tgui9440_available(void)
tgui9440_vlb_available(void)
{
return rom_present(ROM_TGUI_9440);
return rom_present(ROM_TGUI_9440_VLB);
}
static int
tgui9440_pci_available(void)
{
return rom_present(ROM_TGUI_9440_PCI);
}
static int
@@ -3338,7 +3354,7 @@ const device_t tgui9440_vlb_device = {
.init = tgui_init,
.close = tgui_close,
.reset = NULL,
{ .available = tgui9440_available },
{ .available = tgui9440_vlb_available },
.speed_changed = tgui_speed_changed,
.force_redraw = tgui_force_redraw,
.config = tgui9440_config
@@ -3352,7 +3368,7 @@ const device_t tgui9440_pci_device = {
.init = tgui_init,
.close = tgui_close,
.reset = NULL,
{ .available = tgui9440_available },
{ .available = tgui9440_pci_available },
.speed_changed = tgui_speed_changed,
.force_redraw = tgui_force_redraw,
.config = tgui9440_config

View File

@@ -543,7 +543,7 @@ banshee_recalctimings(svga_t *svga)
/*7 R/W Horizontal Retrace End bit 5. -
6 R/W Horizontal Retrace Start bit 8 0x4
5 R/W Horizontal Blank End bit 6. -
4 R/W Horizontal Blank Start bit 8. 0x3
4 R/W Horizontal Blank Start bit 8. 0x3 ---- Erratum: Actually, 0x02!
3 R/W Reserved. -
2 R/W Horizontal Display Enable End bit 8. 0x1
1 R/W Reserved. -
@@ -552,6 +552,34 @@ banshee_recalctimings(svga_t *svga)
svga->htotal += 0x100;
if (svga->crtc[0x1a] & 0x04)
svga->hdisp += 0x100;
if (banshee->vidProcCfg & VIDPROCCFG_VIDPROC_ENABLE) {
/* Video processing mode - assume timings akin to Cirrus' special blanking mode,
that is, no overscan and relying on display end to blank. */
svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) +
(((svga->crtc[0x1a] & 0x04) >> 2) << 8) + 1;
svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3);
/* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */
if (!svga->scrblank && svga->attr_palette_enable)
svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8;
/* No overscan in this mode. */
svga->hblank_overscan = 0;
svga->monitor->mon_overscan_y = 0;
svga->monitor->mon_overscan_x = 0;
/* Also make sure vertical blanking starts on display end. */
svga->vblankstart = svga->dispend;
svga->linedbl = 0;
} else {
svga->hblankstart = (((svga->crtc[0x1a] & 0x10) >> 4) << 8) + svga->crtc[2] + 1;
svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) |
(((svga->crtc[0x1a] & 0x20) >> 5) << 6);
}
/*6 R/W Vertical Retrace Start bit 10 0x10
5 R/W Reserved. -
4 R/W Vertical Blank Start bit 10. 0x15
@@ -567,6 +595,7 @@ banshee_recalctimings(svga_t *svga)
svga->vblankstart += 0x400;
if (svga->crtc[0x1b] & 0x40)
svga->vsyncstart += 0x400;
#if 0
banshee_log("svga->hdisp=%i\n", svga->hdisp);
#endif
@@ -614,6 +643,8 @@ banshee_recalctimings(svga_t *svga)
if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) {
svga->hdisp *= 2;
svga->htotal *= 2;
svga->hblankstart *= 2;
svga->hblank_end_val *= 2;
}
svga->interlace = !!(banshee->vidProcCfg & VIDPROCCFG_INTERLACE);
@@ -795,6 +826,7 @@ banshee_ext_outl(uint16_t addr, uint32_t val, void *priv)
case Init_vgaInit0:
banshee->vgaInit0 = val;
svga_set_ramdac_type(svga, (val & VGAINIT0_RAMDAC_8BIT ? RAMDAC_8BIT : RAMDAC_6BIT));
svga_recalctimings(svga);
break;
case Init_vgaInit1:
banshee->vgaInit1 = val;

View File

@@ -803,7 +803,7 @@ xga_ext_inb(uint16_t addr, void *priv)
break;
}
xga_log("[%04X:%08X]: EXT INB = %02x, ret = %02x\n", CS, cpu_state.pc, addr, ret);
xga_log("[%04X:%08X]: EXT INB = %02x, ret = %02x.\n\n", CS, cpu_state.pc, addr, ret);
return ret;
}
@@ -1233,9 +1233,8 @@ xga_short_stroke(svga_t *svga, uint8_t ssv)
}
}
if (!y) {
if (!y)
break;
}
dx += dirx;
dy += diry;
@@ -1249,18 +1248,13 @@ xga_short_stroke(svga_t *svga, uint8_t ssv)
xga->accel.dst_map_y = dy;
}
#define SWAP(a, b) \
tmpswap = a; \
a = b; \
b = tmpswap;
static void
xga_line_draw_write(svga_t *svga)
{
xga_t *xga = (xga_t *) svga->xga;
uint32_t src_dat;
uint32_t dest_dat;
uint32_t old_dest_dat;
uint32_t old_dest_dat = 0x00000000;
uint32_t color_cmp = xga->accel.color_cmp;
uint32_t plane_mask = xga->accel.plane_mask;
uint32_t dstbase = xga->accel.px_map_base[xga->accel.dst_map];
@@ -1269,10 +1263,6 @@ xga_line_draw_write(svga_t *svga)
int destxtmp;
int dmajor;
int err;
int tmpswap;
int steep = 1;
int xdir = (xga->accel.octant & 0x04) ? -1 : 1;
int ydir = (xga->accel.octant & 0x02) ? -1 : 1;
int y = xga->accel.blt_width;
int x = 0;
int16_t dx;
@@ -1282,6 +1272,7 @@ xga_line_draw_write(svga_t *svga)
dminor = xga->accel.bres_k1;
if (xga->accel.bres_k1 & 0x2000)
dminor |= ~0x1fff;
dminor >>= 1;
destxtmp = xga->accel.bres_k2;
@@ -1305,17 +1296,119 @@ xga_line_draw_write(svga_t *svga)
if ((xga->accel.command & 0x30) == 0x30)
xga_log("Line Draw Write: BLTWIDTH=%d, BLTHEIGHT=%d, FRGDCOLOR=%04x, XDIR=%i, YDIR=%i, steep=%s, ERR=%04x.\n", xga->accel.blt_width, xga->accel.blt_height, xga->accel.frgd_color & 0xffff, xdir, ydir, (xga->accel.octant & 0x01) ? "0" : "1", err);
if (xga->accel.octant & 0x01) {
steep = 0;
SWAP(dx, dy);
SWAP(xdir, ydir);
}
if (xga->accel.pat_src == 8) {
while (y >= 0) {
draw_pixel = 1;
if (xga->accel.command & 0xc0) {
if (steep) {
if ((xga->accel.command & 0x30) == 0x30) {
while (y >= 0) {
draw_pixel = 1;
if (xga->accel.command & 0xc0) {
if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color;
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
if (xga->accel.octant & 0x01) { /*Y Major*/
if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/
if (!x)
draw_pixel = 0;
} else { /*Top-to-Bottom*/
if (!y)
draw_pixel = 0;
}
} else {
if (err >= 0) {
if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/
if (!x)
draw_pixel = 0;
} else { /*Top-to-Bottom*/
if (!y)
draw_pixel = 0;
}
} else
draw_pixel = 0;
}
if (draw_pixel)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
}
}
} else {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color;
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
if (xga->accel.octant & 0x01) { /*Y Major*/
if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/
if (!x)
draw_pixel = 0;
} else { /*Top-to-Bottom*/
if (!y)
draw_pixel = 0;
}
} else {
if (err >= 0) {
if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/
if (!x)
draw_pixel = 0;
} else { /*Top-to-Bottom*/
if (!y)
draw_pixel = 0;
}
} else
draw_pixel = 0;
}
if (draw_pixel)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
}
}
if (!y)
break;
if (xga->accel.octant & 0x01) {
if (xga->accel.octant & 0x02)
dy--;
else
dy++;
while (err >= 0) {
err -= (dmajor << 1);
if (xga->accel.octant & 0x04)
dx--;
else
dx++;
}
err += (dminor << 1);
} else {
if (xga->accel.octant & 0x04)
dx--;
else
dx++;
while (err >= 0) {
err -= (dmajor << 1);
if (xga->accel.octant & 0x02)
dy--;
else
dy++;
}
err += (dminor << 1);
}
y--;
x++;
}
} else {
while (y >= 0) {
if (xga->accel.command & 0xc0) {
if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color;
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0);
@@ -1330,54 +1423,9 @@ xga_line_draw_write(svga_t *svga)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
else if (((xga->accel.command & 0x30) == 0x20) && y)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
else if ((xga->accel.command & 0x30) == 0x30) {
if (err < 0)
draw_pixel = 0;
else {
if (ydir == -1) { /*Bottom-to-Top*/
if (!x)
draw_pixel = 0;
} else { /*Top-to-Bottom*/
if (!y)
draw_pixel = 0;
}
}
if (draw_pixel)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
}
}
}
} else {
if ((dy >= xga->accel.mask_map_origin_x_off) && (dy <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dx >= xga->accel.mask_map_origin_y_off) && (dx <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color;
dest_dat = xga_accel_read_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
if ((xga->accel.command & 0x30) == 0)
xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
else if (((xga->accel.command & 0x30) == 0x10) && x)
xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
else if (((xga->accel.command & 0x30) == 0x20) && y)
xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
else if ((xga->accel.command & 0x30) == 0x30) {
if (xdir == -1) { /*Bottom-to-Top*/
if (!x)
draw_pixel = 0;
} else { /*Top-to-Bottom*/
if (!y)
draw_pixel = 0;
}
if (draw_pixel)
xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
}
}
}
}
} else {
if (steep) {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color;
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0);
@@ -1391,79 +1439,54 @@ xga_line_draw_write(svga_t *svga)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
else if (((xga->accel.command & 0x30) == 0x20) && y)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
else if ((xga->accel.command & 0x30) == 0x30) {
if (err < 0)
draw_pixel = 0;
else {
if (ydir == -1) { /*Bottom-to-Top*/
if (!x)
draw_pixel = 0;
} else { /*Top-to-Bottom*/
if (!y)
draw_pixel = 0;
}
}
if (draw_pixel)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
}
}
} else {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color;
dest_dat = xga_accel_read_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
if ((xga->accel.command & 0x30) == 0)
xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
else if (((xga->accel.command & 0x30) == 0x10) && x)
xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
else if (((xga->accel.command & 0x30) == 0x20) && y)
xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
else if ((xga->accel.command & 0x30) == 0x30) {
if (xdir == -1) { /*Bottom-to-Top*/
if (!x)
draw_pixel = 0;
} else { /*Top-to-Bottom*/
if (!y)
draw_pixel = 0;
}
if (draw_pixel)
xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
}
}
}
if (!y)
break;
if (xga->accel.octant & 0x01) {
if (xga->accel.octant & 0x02)
dy--;
else
dy++;
while (err >= 0) {
err -= (dmajor << 1);
if (xga->accel.octant & 0x04)
dx--;
else
dx++;
}
err += (dminor << 1);
} else {
if (xga->accel.octant & 0x04)
dx--;
else
dx++;
while (err >= 0) {
err -= (dmajor << 1);
if (xga->accel.octant & 0x02)
dy--;
else
dy++;
}
err += (dminor << 1);
}
y--;
x++;
}
if (!y) {
break;
}
while (err >= 0) {
dy += ydir;
err -= (dmajor << 1);
}
dx += xdir;
err += (dminor << 1);
x++;
y--;
}
}
if (steep) {
xga->accel.dst_map_x = dx;
xga->accel.dst_map_y = dy;
} else {
xga->accel.dst_map_x = dy;
xga->accel.dst_map_y = dx;
}
xga->accel.dst_map_x = dx;
xga->accel.dst_map_y = dy;
}
#undef SWAP
static void
xga_bitblt(svga_t *svga)
{
@@ -1641,7 +1664,7 @@ xga_bitblt(svga_t *svga)
while (xga->accel.y >= 0) {
mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, xga->accel.pat_src, patbase, patwidth + 1);
if (mix)
area_state ^= 1;
area_state = !area_state;
if (xga->accel.command & 0xc0) {
if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) {
@@ -1650,9 +1673,6 @@ xga_bitblt(svga_t *svga)
else
src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol;
if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3)
src_dat &= 0xff;
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
old_dest_dat = dest_dat;
@@ -1669,9 +1689,6 @@ xga_bitblt(svga_t *svga)
else
src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol;
if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3)
src_dat &= 0xff;
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
old_dest_dat = dest_dat;
@@ -1715,11 +1732,11 @@ xga_bitblt(svga_t *svga)
if (xga->accel.command & 0xc0) {
if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) {
if (mix) {
if (mix)
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol;
} else {
else
src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol;
}
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
old_dest_dat = dest_dat;
@@ -1730,11 +1747,11 @@ xga_bitblt(svga_t *svga)
}
} else {
if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) {
if (mix) {
if (mix)
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol;
} else {
else
src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol;
}
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
old_dest_dat = dest_dat;
@@ -2422,7 +2439,7 @@ xga_memio_readl(uint32_t addr, void *priv)
temp |= (xga_mem_read(addr + 2, xga, svga) << 16);
temp |= (xga_mem_read(addr + 3, xga, svga) << 24);
xga_log("Read MEMIOL = %04x, temp = %08x\n", addr, temp);
xga_log("[%04X:%08X]: Read MEMIOL = %04x, temp = %08x\n", CS, cpu_state.pc, addr, temp);
return temp;
}

View File

@@ -51,6 +51,7 @@
#include <86box/path.h>
#define GLOBAL
#include <86box/plat.h>
#include <86box/plat_dynld.h>
#include <86box/thread.h>
#include <86box/ui.h>
#ifdef USE_VNC
@@ -1276,6 +1277,35 @@ plat_get_cpu_string(char *outbuf, uint8_t len) {
strncpy(outbuf, cpu_string, len);
}
void
plat_set_thread_name(void *thread, const char *name)
{
/* SetThreadDescription was added in 14393. Revisit if we ever start requiring 10. */
static void *kernel32_handle = NULL;
static HRESULT(WINAPI *pSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription) = NULL;
static dllimp_t kernel32_imports[] = {
// clang-format off
{ "SetThreadDescription", &pSetThreadDescription },
{ NULL, NULL }
// clang-format on
};
if (!kernel32_handle) {
kernel32_handle = dynld_module("kernel32.dll", kernel32_imports);
if (!kernel32_handle) {
kernel32_handle = kernel32_imports; /* store dummy pointer to avoid trying again */
pSetThreadDescription = NULL;
}
}
if (pSetThreadDescription) {
size_t len = strlen(name) + 1;
wchar_t wname[len + 1];
mbstowcs(wname, name, len);
pSetThreadDescription(thread ? (HANDLE) thread : GetCurrentThread(), wname);
}
}
void
take_screenshot(void)
{

View File

@@ -136,6 +136,8 @@ cdrom_mount(uint8_t id, char *fn)
cdrom[id].ops->exit(&(cdrom[id]));
cdrom[id].ops = NULL;
memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path));
if ((fn != NULL) && (strlen(fn) >= 1) && (fn[strlen(fn) - 1] == '/'))
fn[strlen(fn) - 1] = '\\';
cdrom_image_open(&(cdrom[id]), fn);
/* Signal media change to the emulated machine. */
if (cdrom[id].insert)

View File

@@ -37,9 +37,10 @@ typedef struct {
} win_event_t;
thread_t *
thread_create(void (*func)(void *param), void *param)
thread_create_named(void (*func)(void *param), void *param, const char *name)
{
uintptr_t bt = _beginthread(func, 0, param);
plat_set_thread_name((void *) bt, name);
return ((thread_t *) bt);
}