mirror of
https://github.com/86Box/86Box.git
synced 2026-02-24 02:18:20 -07:00
Merge branch '86Box:master' into machine_23
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
323
src/cpu/x86_ops_flag_2386.h
Normal 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;
|
||||
}
|
||||
414
src/cpu/x86_ops_mov_ctrl_2386.h
Normal file
414
src/cpu/x86_ops_mov_ctrl_2386.h
Normal 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
297
src/cpu/x86_ops_ret_2386.h
Normal 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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -849,3 +849,9 @@ machine_get_config_string(char *s)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const device_t*
|
||||
device_context_get_device(void)
|
||||
{
|
||||
return device_current.dev;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -563,10 +563,8 @@ fdd_poll(void *priv)
|
||||
|
||||
if (fdd_notfound) {
|
||||
fdd_notfound--;
|
||||
#ifdef RETURN_NOIDAM
|
||||
if (!fdd_notfound)
|
||||
fdc_noidam(fdd_fdc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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*/
|
||||
|
||||
162
src/include/86box/vid_ati_mach8.h
Normal file
162
src/include/86box/vid_ati_mach8.h
Normal 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*/
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -2124,7 +2124,6 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
|
||||
|
||||
case 0x66:
|
||||
softresetx86();
|
||||
cpu_set_edx();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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)",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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)*/
|
||||
|
||||
@@ -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)*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user