mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 09:35:32 -07:00
Merge remote-tracking branch 'origin/master' into gm/video-debug-device
This commit is contained in:
@@ -262,7 +262,7 @@ sis_5511_write(UNUSED(int func), int addr, uint8_t val, void *priv)
|
||||
case 0x7a: /* DRAM Bank Register 2-1 */
|
||||
case 0x7c: /* DRAM Bank Register 3-0 */
|
||||
case 0x7e: /* DRAM Bank Register 3-1 */
|
||||
spd_write_drbs(dev->regs, 0x70, 0x7e, 0x82);
|
||||
spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x82);
|
||||
break;
|
||||
|
||||
case 0x71: /* DRAM Bank Register 0-0 */
|
||||
@@ -579,16 +579,19 @@ sis_5513_ide_write(int addr, uint8_t val, sis_5511_t *dev)
|
||||
break;
|
||||
|
||||
case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */
|
||||
case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */
|
||||
case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */
|
||||
case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */
|
||||
case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */
|
||||
case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */
|
||||
case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */
|
||||
case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */
|
||||
case 0x48: /* IDE Command Recovery Time Control */
|
||||
dev->pci_conf_sb[1][addr] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */
|
||||
case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */
|
||||
case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */
|
||||
case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */
|
||||
case 0x49: /* IDE Command Active Time Control */
|
||||
dev->pci_conf_sb[1][addr] = val;
|
||||
dev->pci_conf_sb[1][addr] = val & 0x07;
|
||||
break;
|
||||
|
||||
case 0x4a: /* IDE General Control Register 0 */
|
||||
@@ -659,7 +662,11 @@ sis_5513_read(int func, int addr, void *priv)
|
||||
|
||||
sis_5511_log("SiS 5513 P2I: [R] dev->pci_conf_sb[0][%02X] = %02X\n", addr, ret);
|
||||
} else if (func == 0x01) {
|
||||
ret = dev->pci_conf_sb[func][addr];
|
||||
if (addr == 0x3d)
|
||||
ret = (((dev->pci_conf_sb[0x01][0x4b] & 0xc0) == 0xc0) ||
|
||||
(dev->pci_conf_sb[0x01][0x09] & 0x05)) ? PCI_INTA : 0x00;
|
||||
else
|
||||
ret = dev->pci_conf_sb[func][addr];
|
||||
|
||||
sis_5511_log("SiS 5513 IDE: [R] dev->pci_conf_sb[1][%02X] = %02X\n", addr, ret);
|
||||
}
|
||||
@@ -785,7 +792,9 @@ sis_5511_reset(void *priv)
|
||||
dev->pci_conf[0x74] = dev->pci_conf[0x76] = 0x04;
|
||||
dev->pci_conf[0x78] = dev->pci_conf[0x7a] = 0x04;
|
||||
dev->pci_conf[0x7c] = dev->pci_conf[0x7e] = 0x04;
|
||||
dev->pci_conf[0x71] = dev->pci_conf[0x75] = 0x00;
|
||||
dev->pci_conf[0x73] = dev->pci_conf[0x77] = 0x80;
|
||||
dev->pci_conf[0x79] = dev->pci_conf[0x7d] = 0x00;
|
||||
dev->pci_conf[0x7b] = dev->pci_conf[0x7f] = 0x80;
|
||||
dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
|
||||
dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
|
||||
@@ -873,6 +882,23 @@ sis_5511_reset(void *priv)
|
||||
dev->pci_conf_sb[1][0x20] = 0x01;
|
||||
dev->pci_conf_sb[1][0x21] = 0xf0;
|
||||
dev->pci_conf_sb[1][0x22] = dev->pci_conf_sb[1][0x23] = 0x00;
|
||||
dev->pci_conf_sb[1][0x24] = dev->pci_conf_sb[1][0x25] = 0x00;
|
||||
dev->pci_conf_sb[1][0x26] = dev->pci_conf_sb[1][0x27] = 0x00;
|
||||
dev->pci_conf_sb[1][0x28] = dev->pci_conf_sb[1][0x29] = 0x00;
|
||||
dev->pci_conf_sb[1][0x2a] = dev->pci_conf_sb[1][0x2b] = 0x00;
|
||||
dev->pci_conf_sb[1][0x2c] = dev->pci_conf_sb[1][0x2d] = 0x00;
|
||||
dev->pci_conf_sb[1][0x2e] = dev->pci_conf_sb[1][0x2f] = 0x00;
|
||||
dev->pci_conf_sb[1][0x30] = dev->pci_conf_sb[1][0x31] = 0x00;
|
||||
dev->pci_conf_sb[1][0x32] = dev->pci_conf_sb[1][0x33] = 0x00;
|
||||
dev->pci_conf_sb[1][0x40] = dev->pci_conf_sb[1][0x41] = 0x00;
|
||||
dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00;
|
||||
dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00;
|
||||
dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00;
|
||||
dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00;
|
||||
dev->pci_conf_sb[1][0x4a] = 0x06;
|
||||
dev->pci_conf_sb[1][0x4b] = 0x00;
|
||||
dev->pci_conf_sb[1][0x4c] = dev->pci_conf_sb[1][0x4d] = 0x00;
|
||||
dev->pci_conf_sb[1][0x4e] = dev->pci_conf_sb[1][0x4f] = 0x00;
|
||||
|
||||
sis_5513_ide_irq_handler(dev);
|
||||
sis_5513_ide_handler(dev);
|
||||
@@ -896,8 +922,6 @@ sis_5511_init(UNUSED(const device_t *info))
|
||||
sis_5511_t *dev = (sis_5511_t *) calloc(1, sizeof(sis_5511_t));
|
||||
uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1));
|
||||
|
||||
memset(dev, 0, sizeof(sis_5511_t));
|
||||
|
||||
/* Device 0: SiS 5511 */
|
||||
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev, &dev->nb_slot);
|
||||
/* Device 1: SiS 5513 */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -181,6 +181,7 @@ int cpu_multi;
|
||||
int cpu_16bitbus;
|
||||
int cpu_64bitbus;
|
||||
int cpu_cyrix_alignment;
|
||||
int cpu_cpurst_on_sr;
|
||||
int CPUID;
|
||||
|
||||
int is186;
|
||||
@@ -742,6 +743,7 @@ cpu_set(void)
|
||||
|
||||
timing_misaligned = 0;
|
||||
cpu_cyrix_alignment = 0;
|
||||
cpu_cpurst_on_sr = 0;
|
||||
cpu_CR4_mask = 0;
|
||||
|
||||
switch (cpu_s->cpu_type) {
|
||||
@@ -3018,6 +3020,10 @@ amd_k_invalid_rdmsr:
|
||||
EAX = msr.ecx1002ff & 0xffffffff;
|
||||
EDX = msr.ecx1002ff >> 32;
|
||||
break;
|
||||
case 0x40000020:
|
||||
EAX = msr.ecx40000020 & 0xffffffff;
|
||||
EDX = msr.ecx40000020 >> 32;
|
||||
break;
|
||||
case 0xf0f00250:
|
||||
EAX = msr.ecxf0f00250 & 0xffffffff;
|
||||
EDX = msr.ecxf0f00250 >> 32;
|
||||
@@ -3453,6 +3459,9 @@ amd_k_invalid_wrmsr:
|
||||
case 0x1002ff:
|
||||
msr.ecx1002ff = EAX | ((uint64_t) EDX << 32);
|
||||
break;
|
||||
case 0x40000020:
|
||||
msr.ecx40000020 = EAX | ((uint64_t) EDX << 32);
|
||||
break;
|
||||
case 0xf0f00250:
|
||||
msr.ecxf0f00250 = EAX | ((uint64_t) EDX << 32);
|
||||
break;
|
||||
|
||||
@@ -339,6 +339,9 @@ typedef struct {
|
||||
/* K6-3, K6-2P, and K6-3P MSR's */
|
||||
uint64_t amd_l2aar; /* 0xc0000089 */
|
||||
|
||||
/* Weird long MSR's used by the Hyper-V BIOS. */
|
||||
uint64_t ecx40000020; /* 0x40000020 */
|
||||
|
||||
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
|
||||
uint64_t ecxf0f00250; /* 0xf0f00250 - Some weird long MSR's used by i686 AMI & some Phoenix BIOSes */
|
||||
uint64_t ecxf0f00258; /* 0xf0f00258 */
|
||||
@@ -544,8 +547,9 @@ extern int cpu_multi;
|
||||
extern double cpu_dmulti;
|
||||
extern double fpu_multi;
|
||||
extern double cpu_busspeed;
|
||||
extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment
|
||||
penalties when crossing 8-byte boundaries*/
|
||||
extern int cpu_cyrix_alignment; /* Cyrix 5x86/6x86 only has data misalignment
|
||||
penalties when crossing 8-byte boundaries. */
|
||||
extern int cpu_cpurst_on_sr; /* SiS 551x and 5571: Issue CPURST on soft reset. */
|
||||
|
||||
extern int is8086;
|
||||
extern int is186;
|
||||
|
||||
@@ -342,6 +342,8 @@ reset_common(int hard)
|
||||
|
||||
if (!is286)
|
||||
reset_808x(hard);
|
||||
|
||||
cpu_cpurst_on_sr = 0;
|
||||
}
|
||||
|
||||
/* Hard reset. */
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
#include <86box/video.h>
|
||||
#include <86box/keyboard.h>
|
||||
|
||||
#include <86box/dma.h>
|
||||
#include <86box/pci.h>
|
||||
|
||||
#define STAT_PARITY 0x80
|
||||
#define STAT_RTIMEOUT 0x40
|
||||
#define STAT_TTIMEOUT 0x20
|
||||
@@ -141,8 +144,9 @@ typedef struct atkbc_t {
|
||||
|
||||
uint32_t flags;
|
||||
|
||||
/* Main timer. */
|
||||
pc_timer_t send_delay_timer;
|
||||
/* Main timers. */
|
||||
pc_timer_t kbc_poll_timer;
|
||||
pc_timer_t kbc_dev_poll_timer;
|
||||
|
||||
/* P2 pulse callback timer. */
|
||||
pc_timer_t pulse_cb;
|
||||
@@ -695,10 +699,18 @@ kbc_at_poll(void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC));
|
||||
timer_advance_u64(&dev->kbc_poll_timer, (39ULL * TIMER_USEC));
|
||||
|
||||
/* TODO: Implement the password security state. */
|
||||
kbc_at_do_poll(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
kbc_at_dev_poll(void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
timer_advance_u64(&dev->kbc_dev_poll_timer, (100ULL * TIMER_USEC));
|
||||
|
||||
if ((kbc_at_ports[0] != NULL) && (kbc_at_ports[0]->priv != NULL))
|
||||
kbc_at_ports[0]->poll(kbc_at_ports[0]->priv);
|
||||
@@ -736,7 +748,7 @@ write_p2(atkbc_t *dev, uint8_t val)
|
||||
/* AT, PS/2: Handle reset. */
|
||||
/* 0 holds the CPU in the RESET state, 1 releases it. To simplify this,
|
||||
we just do everything on release. */
|
||||
if ((old ^ val) & 0x01) { /*Reset*/
|
||||
if (!cpu_cpurst_on_sr && ((old ^ val) & 0x01)) { /*Reset*/
|
||||
if (!(val & 0x01)) { /* Pin 0 selected. */
|
||||
/* Pin 0 selected. */
|
||||
kbc_at_log("write_p2(): Pulse reset!\n");
|
||||
@@ -765,6 +777,28 @@ write_p2(atkbc_t *dev, uint8_t val)
|
||||
|
||||
/* Do this here to avoid an infinite reset loop. */
|
||||
dev->p2 = val;
|
||||
|
||||
if (cpu_cpurst_on_sr && ((old ^ val) & 0x01)) { /*Reset*/
|
||||
if (!(val & 0x01)) { /* Pin 0 selected. */
|
||||
/* Pin 0 selected. */
|
||||
pclog("write_p2(): Pulse reset!\n");
|
||||
dma_reset();
|
||||
dma_set_at(1);
|
||||
|
||||
device_reset_all(DEVICE_ALL);
|
||||
|
||||
cpu_alt_reset = 0;
|
||||
|
||||
pci_reset();
|
||||
|
||||
mem_a20_alt = 0;
|
||||
mem_a20_recalc();
|
||||
|
||||
flushmmucache();
|
||||
|
||||
resetx86();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1934,7 +1968,8 @@ kbc_at_close(void *priv)
|
||||
int max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 2 : 1;
|
||||
|
||||
/* Stop timers. */
|
||||
timer_disable(&dev->send_delay_timer);
|
||||
timer_disable(&dev->kbc_dev_poll_timer);
|
||||
timer_disable(&dev->kbc_poll_timer);
|
||||
|
||||
for (int i = 0; i < max_ports; i++) {
|
||||
if (kbc_at_ports[i] != NULL) {
|
||||
@@ -1966,9 +2001,11 @@ kbc_at_init(const device_t *info)
|
||||
io_sethandler(0x0060, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0064, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, dev);
|
||||
|
||||
timer_add(&dev->send_delay_timer, kbc_at_poll, dev, 1);
|
||||
timer_add(&dev->kbc_poll_timer, kbc_at_poll, dev, 1);
|
||||
timer_add(&dev->pulse_cb, pulse_poll, dev, 0);
|
||||
|
||||
timer_add(&dev->kbc_dev_poll_timer, kbc_at_dev_poll, dev, 1);
|
||||
|
||||
dev->write60_ven = NULL;
|
||||
dev->write64_ven = NULL;
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
#define FIFO_SIZE 16
|
||||
|
||||
#define BAT_COUNT 1000
|
||||
|
||||
enum {
|
||||
KBD_84_KEY = 0,
|
||||
KBD_101_KEY,
|
||||
@@ -75,6 +77,8 @@ static atkbc_dev_t *SavedKbd = NULL;
|
||||
|
||||
static uint8_t inv_cmd_response = 0xfa;
|
||||
|
||||
static uint16_t bat_counter = 0;
|
||||
|
||||
static const scancode scancode_set1[512] = {
|
||||
// clang-format off
|
||||
{ { 0},{ 0} }, { { 0x01,0},{ 0x81,0} }, { { 0x02,0},{ 0x82,0} }, { { 0x03,0},{ 0x83,0} }, /*000*/
|
||||
@@ -704,11 +708,16 @@ keyboard_at_bat(void *priv)
|
||||
{
|
||||
atkbc_dev_t *dev = (atkbc_dev_t *) priv;
|
||||
|
||||
keyboard_at_set_defaults(dev);
|
||||
if (bat_counter == 0x0000) {
|
||||
keyboard_at_set_defaults(dev);
|
||||
|
||||
keyboard_scan = 1;
|
||||
keyboard_scan = 1;
|
||||
|
||||
kbc_at_dev_queue_add(dev, 0xaa, 0);
|
||||
kbc_at_dev_queue_add(dev, 0xaa, 0);
|
||||
} else {
|
||||
bat_counter--;
|
||||
dev->state = DEV_STATE_EXECUTE_BAT;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -926,6 +935,7 @@ keyboard_at_write(void *priv)
|
||||
|
||||
case 0xff: /* reset */
|
||||
kbc_at_dev_reset(dev, 1);
|
||||
bat_counter = 1000;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -965,8 +975,10 @@ keyboard_at_init(const device_t *info)
|
||||
|
||||
dev->fifo_mask = FIFO_SIZE - 1;
|
||||
|
||||
if (dev->port != NULL)
|
||||
if (dev->port != NULL) {
|
||||
kbc_at_dev_reset(dev, 0);
|
||||
bat_counter = 0x0000;
|
||||
}
|
||||
|
||||
keyboard_send = add_data_kbd;
|
||||
SavedKbd = dev;
|
||||
|
||||
149
src/floppy/fdc.c
149
src/floppy/fdc.c
@@ -212,6 +212,7 @@ fdc_ctrl_reset(void *priv)
|
||||
fdc->lock = 0;
|
||||
fdc->head = 0;
|
||||
fdc->step = 0;
|
||||
fdc->power_down = 0;
|
||||
if (!(fdc->flags & FDC_FLAG_AT))
|
||||
fdc->rate = 2;
|
||||
}
|
||||
@@ -257,7 +258,7 @@ fdc_set_wrong_am(fdc_t *fdc)
|
||||
int
|
||||
fdc_get_drive(fdc_t *fdc)
|
||||
{
|
||||
return fdc->drive;
|
||||
return (int) fdc->drive;
|
||||
}
|
||||
|
||||
int fdc_get_bitcell_period(fdc_t *fdc);
|
||||
@@ -270,7 +271,7 @@ fdc_get_perp(fdc_t *fdc)
|
||||
if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR))
|
||||
return 0;
|
||||
|
||||
return fdc->perp;
|
||||
return (int) fdc->perp;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -292,7 +293,7 @@ fdc_get_gap2(fdc_t *fdc, int drive)
|
||||
int
|
||||
fdc_get_format_n(fdc_t *fdc)
|
||||
{
|
||||
return fdc->format_n;
|
||||
return (int) fdc->format_n;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -321,7 +322,7 @@ fdc_stop_id_request(fdc_t *fdc)
|
||||
int
|
||||
fdc_get_gap(fdc_t *fdc)
|
||||
{
|
||||
return fdc->gap;
|
||||
return (int) fdc->gap;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -333,7 +334,7 @@ fdc_get_dtl(fdc_t *fdc)
|
||||
int
|
||||
fdc_get_format_sectors(fdc_t *fdc)
|
||||
{
|
||||
return fdc->format_sectors;
|
||||
return (int) fdc->format_sectors;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -418,6 +419,12 @@ fdc_update_rates(fdc_t *fdc)
|
||||
fdc_rate(fdc, 3);
|
||||
}
|
||||
|
||||
void
|
||||
fdc_set_power_down(fdc_t *fdc, uint8_t power_down)
|
||||
{
|
||||
fdc->power_down = power_down;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_update_max_track(fdc_t *fdc, int max_track)
|
||||
{
|
||||
@@ -427,7 +434,7 @@ fdc_update_max_track(fdc_t *fdc, int max_track)
|
||||
void
|
||||
fdc_update_enh_mode(fdc_t *fdc, int enh_mode)
|
||||
{
|
||||
fdc->enh_mode = enh_mode;
|
||||
fdc->enh_mode = !!enh_mode;
|
||||
fdc_update_rates(fdc);
|
||||
}
|
||||
|
||||
@@ -490,7 +497,7 @@ fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate)
|
||||
void
|
||||
fdc_update_drv2en(fdc_t *fdc, int drv2en)
|
||||
{
|
||||
fdc->drv2en = drv2en;
|
||||
fdc->drv2en = !!drv2en;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -500,37 +507,34 @@ fdc_update_rate(fdc_t *fdc, int drive)
|
||||
fdc->bit_rate = 500;
|
||||
else if ((fdc->rwc[drive] == 3) && fdc->enh_mode)
|
||||
fdc->bit_rate = 250;
|
||||
else
|
||||
switch (fdc->rate) {
|
||||
case 0: /*High density*/
|
||||
fdc->bit_rate = 500;
|
||||
break;
|
||||
case 1: /*Double density (360 rpm)*/
|
||||
switch (fdc->drvrate[drive]) {
|
||||
case 0:
|
||||
fdc->bit_rate = 300;
|
||||
break;
|
||||
case 1:
|
||||
fdc->bit_rate = 500;
|
||||
break;
|
||||
case 2:
|
||||
fdc->bit_rate = 2000;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: /*Double density*/
|
||||
fdc->bit_rate = 250;
|
||||
break;
|
||||
case 3: /*Extended density*/
|
||||
fdc->bit_rate = 1000;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else switch (fdc->rate) {
|
||||
default:
|
||||
break;
|
||||
case 0: /*High density*/
|
||||
fdc->bit_rate = 500;
|
||||
break;
|
||||
case 1: /*Double density (360 rpm)*/
|
||||
switch (fdc->drvrate[drive]) {
|
||||
default:
|
||||
break;
|
||||
case 0:
|
||||
fdc->bit_rate = 300;
|
||||
break;
|
||||
case 1:
|
||||
fdc->bit_rate = 500;
|
||||
break;
|
||||
case 2:
|
||||
fdc->bit_rate = 2000;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: /*Double density*/
|
||||
fdc->bit_rate = 250;
|
||||
break;
|
||||
case 3: /*Extended density*/
|
||||
fdc->bit_rate = 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
fdc->bitcell_period = (1000000 / fdc->bit_rate) * 2; /*Bitcell period in ns*/
|
||||
}
|
||||
@@ -688,10 +692,6 @@ fdc_io_command_phase1(fdc_t *fdc, int out)
|
||||
fdc->stat |= 0x20;
|
||||
else
|
||||
dma_set_drq(fdc->dma_ch, 1);
|
||||
if (out)
|
||||
fdc->pos = 0;
|
||||
else
|
||||
fdc->inread = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -741,7 +741,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
|
||||
switch (addr & 7) {
|
||||
if (!fdc->power_down || ((addr & 7) == 2) || ((addr & 7) == 4)) switch (addr & 7) {
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
@@ -776,14 +776,20 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = fdc->ptot = 0;
|
||||
}
|
||||
if ((val & 4) && !(fdc->dor & 4)) {
|
||||
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
||||
fdc->interrupt = -1;
|
||||
fdc->perp &= 0xfc;
|
||||
if (fdc->power_down) {
|
||||
timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC);
|
||||
fdc->interrupt = -5;
|
||||
} else {
|
||||
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
||||
fdc->interrupt = -1;
|
||||
|
||||
for (i = 0; i < FDD_NUM; i++)
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
fdc->perp &= 0xfc;
|
||||
|
||||
fdc_ctrl_reset(fdc);
|
||||
for (i = 0; i < FDD_NUM; i++)
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
|
||||
fdc_ctrl_reset(fdc);
|
||||
}
|
||||
}
|
||||
/* We can now simplify this since each motor now spins separately. */
|
||||
for (i = 0; i < FDD_NUM; i++) {
|
||||
@@ -854,7 +860,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 4;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->format_state = 0;
|
||||
} else
|
||||
fdc_bad_command(fdc);
|
||||
@@ -866,7 +871,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 8;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||
break;
|
||||
case 0x03: /*Specify*/
|
||||
@@ -888,7 +892,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 8;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||
break;
|
||||
case 0x06: /*Read data*/
|
||||
@@ -907,7 +910,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 8;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||
break;
|
||||
case 0x17: /*Powerdown mode*/
|
||||
@@ -924,28 +926,24 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x08: /*Sense interrupt status*/
|
||||
fdc_log("fdc->fintr = %i, fdc->reset_stat = %i\n", fdc->fintr, fdc->reset_stat);
|
||||
fdc->lastdrive = fdc->drive;
|
||||
fdc->pos = 0;
|
||||
fdc_sis(fdc);
|
||||
break;
|
||||
case 0x0a: /*Read sector ID*/
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 1;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||
break;
|
||||
case 0x0d: /*Format track*/
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 5;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||
fdc->format_state = 0;
|
||||
break;
|
||||
case 0x0e: /*Dump registers*/
|
||||
fdc->lastdrive = fdc->drive;
|
||||
fdc->interrupt = 0x0e;
|
||||
fdc->pos = 0;
|
||||
fdc_callback(fdc);
|
||||
break;
|
||||
case 0x0f: /*Seek*/
|
||||
@@ -964,7 +962,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x94: /*Lock*/
|
||||
fdc->lastdrive = fdc->drive;
|
||||
fdc->interrupt = fdc->command;
|
||||
fdc->pos = 0;
|
||||
fdc_callback(fdc);
|
||||
break;
|
||||
case 0x12: /*Set perpendicular mode*/
|
||||
@@ -972,7 +969,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 1;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
} else
|
||||
fdc_bad_command(fdc);
|
||||
break;
|
||||
@@ -980,7 +976,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 3;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
break;
|
||||
default:
|
||||
fdc_bad_command(fdc);
|
||||
@@ -1151,7 +1146,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->format_sectors = fdc->params[2];
|
||||
fdc->format_n = fdc->params[1];
|
||||
fdc->format_state = 1;
|
||||
fdc->pos = 0;
|
||||
fdc->stat = 0x10;
|
||||
break;
|
||||
case 0x0f: /* Seek */
|
||||
@@ -1273,12 +1267,12 @@ uint8_t
|
||||
fdc_read(uint16_t addr, void *priv)
|
||||
{
|
||||
fdc_t *fdc = (fdc_t *) priv;
|
||||
uint8_t ret;
|
||||
uint8_t ret = 0xff;
|
||||
int drive = 0;
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
|
||||
switch (addr & 7) {
|
||||
if (!fdc->power_down || ((addr & 7) == 2)) switch (addr & 7) {
|
||||
case 0: /* STA */
|
||||
if (fdc->flags & FDC_FLAG_PS1) {
|
||||
drive = real_drive(fdc, fdc->dor & 3);
|
||||
@@ -1513,7 +1507,6 @@ fdc_poll_readwrite_finish(fdc_t *fdc, int compare)
|
||||
if ((fdc->interrupt == 5) || (fdc->interrupt == 9))
|
||||
fdd_do_writeback(real_drive(fdc, fdc->drive));
|
||||
|
||||
fdc->inread = 0;
|
||||
fdc->interrupt = -2;
|
||||
|
||||
fdc_poll_common_finish(fdc, compare, 0);
|
||||
@@ -1544,10 +1537,21 @@ fdc_callback(void *priv)
|
||||
case -2: /*End of command*/
|
||||
fdc->stat = (fdc->stat & 0xf) | 0x80;
|
||||
return;
|
||||
case -5: /*Reset in power down mode */
|
||||
fdc->perp &= 0xfc;
|
||||
|
||||
for (uint8_t i = 0; i < FDD_NUM; i++)
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
|
||||
fdc_ctrl_reset(fdc);
|
||||
|
||||
fdc->fintr = 0;
|
||||
memset(fdc->pcn, 0x00, 4 * sizeof(uint16_t));
|
||||
return;
|
||||
case -1: /*Reset*/
|
||||
fdc_int(fdc, 1);
|
||||
fdc->fintr = 0;
|
||||
memset(fdc->pcn, 0, 4 * sizeof(int));
|
||||
memset(fdc->pcn, 0x00, 4 * sizeof(uint16_t));
|
||||
fdc->reset_stat = 4;
|
||||
return;
|
||||
case 0x01: /* Mode */
|
||||
@@ -1570,7 +1574,6 @@ fdc_callback(void *priv)
|
||||
fdc->stat = 0x50;
|
||||
}
|
||||
}
|
||||
fdc->inread = 1;
|
||||
return;
|
||||
case 0x04: /* Sense drive status */
|
||||
fdc->res[10] = (fdc->params[0] & 7) | 0x20;
|
||||
@@ -1715,7 +1718,6 @@ fdc_callback(void *priv)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fdc->inread = 1;
|
||||
return;
|
||||
case 0x07: /* Recalibrate */
|
||||
fdc->pcn[fdc->params[0] & 3] = 0;
|
||||
@@ -2004,18 +2006,11 @@ fdc_data(fdc_t *fdc, uint8_t data, int last)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_finishread(fdc_t *fdc)
|
||||
{
|
||||
fdc->inread = 0;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_track_finishread(fdc_t *fdc, int condition)
|
||||
{
|
||||
fdc->stat = 0x10;
|
||||
fdc->satisfying_sectors |= condition;
|
||||
fdc->inread = 0;
|
||||
fdc_callback(fdc);
|
||||
}
|
||||
|
||||
@@ -2025,7 +2020,6 @@ fdc_sector_finishcompare(fdc_t *fdc, int satisfying)
|
||||
fdc->stat = 0x10;
|
||||
if (satisfying)
|
||||
fdc->satisfying_sectors++;
|
||||
fdc->inread = 0;
|
||||
fdc_callback(fdc);
|
||||
}
|
||||
|
||||
@@ -2033,7 +2027,6 @@ void
|
||||
fdc_sector_finishread(fdc_t *fdc)
|
||||
{
|
||||
fdc->stat = 0x10;
|
||||
fdc->inread = 0;
|
||||
fdc_callback(fdc);
|
||||
}
|
||||
|
||||
@@ -2356,6 +2349,8 @@ fdc_reset(void *priv)
|
||||
|
||||
for (uint8_t i = 0; i < FDD_NUM; i++)
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
|
||||
fdc->power_down = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2418,7 +2413,7 @@ fdc_init(const device_t *info)
|
||||
void
|
||||
fdc_3f1_enable(fdc_t *fdc, int enable)
|
||||
{
|
||||
fdc->enable_3f1 = enable;
|
||||
fdc->enable_3f1 = !!enable;
|
||||
}
|
||||
|
||||
const device_t fdc_xt_device = {
|
||||
|
||||
@@ -1274,18 +1274,19 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui
|
||||
if (dev->last_word[side] == req_am) {
|
||||
dev->calc_crc.word = 0xFFFF;
|
||||
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
|
||||
find->sync_marks = find->bits_obtained = find->bytes_obtained = 0;
|
||||
find->sync_pos = 0xFFFFFFFF;
|
||||
dev->preceding_bit[side] = dev->last_word[side] & 1;
|
||||
find->sync_marks = find->bits_obtained =
|
||||
find->bytes_obtained = 0;
|
||||
find->sync_pos = 0xFFFFFFFF;
|
||||
dev->preceding_bit[side] = dev->last_word[side] & 1;
|
||||
dev->state++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (wrong_am && (dev->last_word[side] == wrong_am)) {
|
||||
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
|
||||
dev->error_condition = 0;
|
||||
dev->state = STATE_IDLE;
|
||||
fdc_finishread(d86f_fdc);
|
||||
dev->data_find.sync_marks = dev->data_find.bits_obtained =
|
||||
dev->data_find.bytes_obtained = 0;
|
||||
dev->error_condition = 0;
|
||||
dev->state = STATE_IDLE;
|
||||
fdc_nodataam(d86f_fdc);
|
||||
return;
|
||||
}
|
||||
@@ -1328,8 +1329,9 @@ d86f_write_find_address_mark_fm(int drive, int side, find_t *find)
|
||||
|
||||
/* If we hadn't found enough set bits but have found a clear bit, null the counter of set bits. */
|
||||
if (!(dev->last_word[side] & 1)) {
|
||||
find->sync_marks = find->bits_obtained = find->bytes_obtained = 0;
|
||||
find->sync_pos = 0xFFFFFFFF;
|
||||
find->sync_marks = find->bits_obtained =
|
||||
find->bytes_obtained = 0;
|
||||
find->sync_pos = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1347,10 +1349,10 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u
|
||||
}
|
||||
|
||||
if (wrong_am && (dev->last_word[side] == wrong_am) && (find->sync_marks >= 3)) {
|
||||
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
|
||||
dev->error_condition = 0;
|
||||
dev->state = STATE_IDLE;
|
||||
fdc_finishread(d86f_fdc);
|
||||
dev->data_find.sync_marks = dev->data_find.bits_obtained =
|
||||
dev->data_find.bytes_obtained = 0;
|
||||
dev->error_condition = 0;
|
||||
dev->state = STATE_IDLE;
|
||||
fdc_nodataam(d86f_fdc);
|
||||
return;
|
||||
}
|
||||
@@ -1433,22 +1435,26 @@ d86f_read_sector_id(int drive, int side, int match)
|
||||
if (!(dev->id_find.bits_obtained & 15)) {
|
||||
/* We've got a byte. */
|
||||
if (dev->id_find.bytes_obtained < 4) {
|
||||
dev->last_sector.byte_array[dev->id_find.bytes_obtained] = decodefm(drive, dev->last_word[side]);
|
||||
dev->last_sector.byte_array[dev->id_find.bytes_obtained] =
|
||||
decodefm(drive, dev->last_word[side]);
|
||||
fdd_calccrc(dev->last_sector.byte_array[dev->id_find.bytes_obtained], &(dev->calc_crc));
|
||||
} else if ((dev->id_find.bytes_obtained >= 4) && (dev->id_find.bytes_obtained < 6)) {
|
||||
dev->track_crc.bytes[(dev->id_find.bytes_obtained & 1) ^ 1] = decodefm(drive, dev->last_word[side]);
|
||||
dev->track_crc.bytes[(dev->id_find.bytes_obtained & 1) ^ 1] =
|
||||
decodefm(drive, dev->last_word[side]);
|
||||
}
|
||||
dev->id_find.bytes_obtained++;
|
||||
|
||||
if (dev->id_find.bytes_obtained == 6) {
|
||||
/* We've got the ID. */
|
||||
if ((dev->calc_crc.word != dev->track_crc.word) && (dev->last_sector.dword == dev->req_sector.dword)) {
|
||||
dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0;
|
||||
d86f_log("86F: ID CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword);
|
||||
if ((dev->calc_crc.word != dev->track_crc.word) &&
|
||||
(dev->last_sector.dword == dev->req_sector.dword)) {
|
||||
dev->id_find.sync_marks = dev->id_find.bits_obtained =
|
||||
dev->id_find.bytes_obtained = 0;
|
||||
d86f_log("86F: ID CRC error: %04X != %04X (%08X)\n", dev->track_crc.word,
|
||||
dev->calc_crc.word, dev->last_sector.dword);
|
||||
if ((dev->state != STATE_02_READ_ID) && (dev->state != STATE_0A_READ_ID)) {
|
||||
dev->error_condition = 0;
|
||||
dev->state = STATE_IDLE;
|
||||
fdc_finishread(d86f_fdc);
|
||||
fdc_headercrcerror(d86f_fdc);
|
||||
} else if (dev->state == STATE_0A_READ_ID)
|
||||
dev->state--;
|
||||
@@ -1458,25 +1464,37 @@ d86f_read_sector_id(int drive, int side, int match)
|
||||
}
|
||||
} else if ((dev->calc_crc.word == dev->track_crc.word) && (dev->state == STATE_0A_READ_ID)) {
|
||||
/* CRC is valid and this is a read sector ID command. */
|
||||
dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0;
|
||||
fdc_sectorid(d86f_fdc, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n, 0, 0);
|
||||
dev->id_find.sync_marks = dev->id_find.bits_obtained =
|
||||
dev->id_find.bytes_obtained = dev->error_condition = 0;
|
||||
fdc_sectorid(d86f_fdc,
|
||||
dev->last_sector.id.c, dev->last_sector.id.h,
|
||||
dev->last_sector.id.r, dev->last_sector.id.n, 0, 0);
|
||||
dev->state = STATE_IDLE;
|
||||
} else {
|
||||
/* CRC is valid. */
|
||||
dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0;
|
||||
dev->id_find.sync_marks = dev->id_find.bits_obtained =
|
||||
dev->id_find.bytes_obtained = 0;
|
||||
dev->id_found |= 1;
|
||||
if ((dev->last_sector.dword == dev->req_sector.dword) || !match) {
|
||||
d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n);
|
||||
d86f_handler[drive].set_sector(drive, side,
|
||||
dev->last_sector.id.c, dev->last_sector.id.h,
|
||||
dev->last_sector.id.r, dev->last_sector.id.n);
|
||||
if (dev->state == STATE_02_READ_ID) {
|
||||
/* READ TRACK command, we need some special handling here. */
|
||||
/* Code corrected: Only the C, H, and N portions of the sector ID are compared, the R portion (the sector number) is ignored. */
|
||||
if ((dev->last_sector.id.c != fdc_get_read_track_sector(d86f_fdc).id.c) || (dev->last_sector.id.h != fdc_get_read_track_sector(d86f_fdc).id.h) || (dev->last_sector.id.n != fdc_get_read_track_sector(d86f_fdc).id.n)) {
|
||||
dev->error_condition |= 4; /* Mark that the sector ID is not the one expected by the FDC. */
|
||||
/* Code corrected: Only the C, H, and N portions of the
|
||||
sector ID are compared, the R portion
|
||||
(the sector number) is ignored. */
|
||||
if ((dev->last_sector.id.c != fdc_get_read_track_sector(d86f_fdc).id.c) ||
|
||||
(dev->last_sector.id.h != fdc_get_read_track_sector(d86f_fdc).id.h) ||
|
||||
(dev->last_sector.id.n != fdc_get_read_track_sector(d86f_fdc).id.n)) {
|
||||
/* Mark that the sector ID is not the one expected by the FDC. */
|
||||
dev->error_condition |= 4;
|
||||
/* Make sure we use the sector size from the FDC. */
|
||||
dev->last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n;
|
||||
}
|
||||
|
||||
/* If the two ID's are identical, then we do not need to do anything regarding the sector size. */
|
||||
/* If the two ID's are identical, then we do not need to do
|
||||
anything regarding the sector size. */
|
||||
}
|
||||
dev->state++;
|
||||
} else {
|
||||
@@ -1576,7 +1594,8 @@ d86f_read_sector_data(int drive, int side)
|
||||
data = d86f_handler[drive].read_data(drive, side, dev->data_find.bytes_obtained);
|
||||
else {
|
||||
#ifdef HACK_FOR_DBASE_III
|
||||
if ((dev->last_sector.id.c == 39) && (dev->last_sector.id.h == 0) && (dev->last_sector.id.r == 5) && (dev->data_find.bytes_obtained >= 272))
|
||||
if ((dev->last_sector.id.c == 39) && (dev->last_sector.id.h == 0) &&
|
||||
(dev->last_sector.id.r == 5) && (dev->data_find.bytes_obtained >= 272))
|
||||
data = (random_generate() & 0xff);
|
||||
else
|
||||
#endif
|
||||
@@ -1589,7 +1608,9 @@ d86f_read_sector_data(int drive, int side)
|
||||
} else {
|
||||
if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) {
|
||||
if (dev->state != STATE_16_VERIFY_DATA) {
|
||||
read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1));
|
||||
read_status = fdc_data(d86f_fdc, data,
|
||||
dev->data_find.bytes_obtained ==
|
||||
(d86f_get_data_len(drive) - 1));
|
||||
if (read_status == -1)
|
||||
dev->dma_over++;
|
||||
}
|
||||
@@ -1597,17 +1618,19 @@ d86f_read_sector_data(int drive, int side)
|
||||
}
|
||||
fdd_calccrc(data, &(dev->calc_crc));
|
||||
} else if (dev->data_find.bytes_obtained < crc_pos)
|
||||
dev->track_crc.bytes[(dev->data_find.bytes_obtained - sector_len) ^ 1] = decodefm(drive, dev->last_word[side]);
|
||||
dev->track_crc.bytes[(dev->data_find.bytes_obtained - sector_len) ^ 1] =
|
||||
decodefm(drive, dev->last_word[side]);
|
||||
dev->data_find.bytes_obtained++;
|
||||
|
||||
if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) {
|
||||
/* We've got the data. */
|
||||
if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state != STATE_02_READ_DATA)) {
|
||||
d86f_log("86F: Data CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword);
|
||||
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
|
||||
dev->error_condition = 0;
|
||||
dev->state = STATE_IDLE;
|
||||
fdc_finishread(d86f_fdc);
|
||||
d86f_log("86F: Data CRC error: %04X != %04X (%08X)\n", dev->track_crc.word,
|
||||
dev->calc_crc.word, dev->last_sector.dword);
|
||||
dev->data_find.sync_marks = dev->data_find.bits_obtained =
|
||||
dev->data_find.bytes_obtained = 0;
|
||||
dev->error_condition = 0;
|
||||
dev->state = STATE_IDLE;
|
||||
fdc_datacrcerror(d86f_fdc);
|
||||
} else if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state == STATE_02_READ_DATA)) {
|
||||
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
|
||||
@@ -2146,7 +2169,8 @@ d86f_turbo_read(int drive, int side)
|
||||
} else {
|
||||
if (dev->turbo_pos < (128UL << dev->req_sector.id.n)) {
|
||||
if (dev->state != STATE_16_VERIFY_DATA) {
|
||||
read_status = fdc_data(d86f_fdc, dat, dev->turbo_pos == ((128UL << dev->req_sector.id.n) - 1));
|
||||
read_status = fdc_data(d86f_fdc, dat,
|
||||
dev->turbo_pos == ((128UL << dev->req_sector.id.n) - 1));
|
||||
if (read_status == -1)
|
||||
dev->dma_over++;
|
||||
}
|
||||
@@ -2163,7 +2187,6 @@ d86f_turbo_read(int drive, int side)
|
||||
#endif
|
||||
dev->error_condition = 0;
|
||||
dev->state = STATE_IDLE;
|
||||
fdc_finishread(d86f_fdc);
|
||||
fdc_datacrcerror(d86f_fdc);
|
||||
} else if ((flags & SECTOR_CRC_ERROR) && (dev->state == STATE_02_READ_DATA)) {
|
||||
#ifdef ENABLE_D86F_LOG
|
||||
|
||||
@@ -65,76 +65,85 @@ typedef struct fdc_t {
|
||||
uint8_t st0;
|
||||
uint8_t swap;
|
||||
uint8_t dtl;
|
||||
|
||||
uint8_t swwp;
|
||||
uint8_t disable_write;
|
||||
uint8_t st5;
|
||||
uint8_t st6;
|
||||
uint8_t error;
|
||||
uint8_t params[8];
|
||||
uint8_t res[11];
|
||||
uint8_t specify[2];
|
||||
uint8_t config;
|
||||
uint8_t pretrk;
|
||||
uint8_t power_down;
|
||||
|
||||
uint8_t head;
|
||||
uint8_t lastdrive;
|
||||
uint8_t sector;
|
||||
uint8_t drive;
|
||||
uint8_t rate;
|
||||
uint8_t tc;
|
||||
uint8_t pnum;
|
||||
uint8_t ptot;
|
||||
|
||||
uint8_t reset_stat;
|
||||
uint8_t seek_dir;
|
||||
uint8_t perp;
|
||||
uint8_t format_state;
|
||||
uint8_t format_n;
|
||||
uint8_t step;
|
||||
uint8_t noprec;
|
||||
uint8_t data_ready;
|
||||
|
||||
uint8_t paramstogo;
|
||||
uint8_t enh_mode;
|
||||
uint8_t dma;
|
||||
uint8_t densel_polarity;
|
||||
uint8_t densel_force;
|
||||
uint8_t fifo;
|
||||
uint8_t tfifo;
|
||||
uint8_t fifobufpos;
|
||||
|
||||
uint8_t drv2en;
|
||||
uint8_t gap;
|
||||
uint8_t enable_3f1;
|
||||
uint8_t format_sectors;
|
||||
uint8_t mfm;
|
||||
uint8_t deleted;
|
||||
uint8_t wrong_am;
|
||||
uint8_t sc;
|
||||
|
||||
uint8_t fintr;
|
||||
uint8_t rw_drive;
|
||||
|
||||
uint8_t lock;
|
||||
uint8_t specify[2];
|
||||
|
||||
uint8_t res[11];
|
||||
|
||||
uint8_t eot[4];
|
||||
uint8_t rwc[4];
|
||||
uint8_t params[8];
|
||||
uint8_t fifobuf[16];
|
||||
|
||||
uint16_t pcn[4];
|
||||
|
||||
uint16_t base_address;
|
||||
uint16_t rw_track;
|
||||
|
||||
int head;
|
||||
int sector;
|
||||
int drive;
|
||||
int lastdrive;
|
||||
int pcn[4];
|
||||
int eot[4];
|
||||
int rw_track;
|
||||
int pos;
|
||||
int pnum;
|
||||
int ptot;
|
||||
int rate;
|
||||
int reset_stat;
|
||||
int lock;
|
||||
int perp;
|
||||
int format_state;
|
||||
int format_n;
|
||||
int step;
|
||||
int seek_dir;
|
||||
int tc;
|
||||
int noprec;
|
||||
int bit_rate; /* Should be 250 at start. */
|
||||
|
||||
int data_ready;
|
||||
int inread;
|
||||
int bitcell_period;
|
||||
int enh_mode;
|
||||
int rwc[4];
|
||||
int drvrate[4];
|
||||
int boot_drive;
|
||||
int dma;
|
||||
int densel_polarity;
|
||||
int densel_force;
|
||||
int fifo;
|
||||
int tfifo;
|
||||
int fifobufpos;
|
||||
int drv2en;
|
||||
|
||||
int gap;
|
||||
int enable_3f1;
|
||||
int format_sectors;
|
||||
int max_track;
|
||||
int mfm;
|
||||
int deleted;
|
||||
int wrong_am;
|
||||
int sc;
|
||||
int satisfying_sectors;
|
||||
int fintr;
|
||||
int rw_drive;
|
||||
|
||||
int flags;
|
||||
int interrupt;
|
||||
|
||||
int irq; /* Should be 6 by default. */
|
||||
int dma_ch; /* Should be 2 by default. */
|
||||
int irq; /* Should be 6 by default. */
|
||||
int dma_ch; /* Should be 2 by default. */
|
||||
|
||||
int bit_rate; /* Should be 250 at start. */
|
||||
int paramstogo;
|
||||
int drvrate[4];
|
||||
|
||||
sector_id_t read_track_sector;
|
||||
sector_id_t format_sector_id;
|
||||
@@ -183,6 +192,7 @@ extern int fdc_get_compare_condition(fdc_t *fdc);
|
||||
extern int fdc_is_deleted(fdc_t *fdc);
|
||||
extern int fdc_is_sk(fdc_t *fdc);
|
||||
extern void fdc_set_wrong_am(fdc_t *fdc);
|
||||
extern void fdc_set_power_down(fdc_t *fdc, uint8_t power_down);
|
||||
extern int fdc_get_drive(fdc_t *fdc);
|
||||
extern int fdc_get_perp(fdc_t *fdc);
|
||||
extern int fdc_get_format_n(fdc_t *fdc);
|
||||
|
||||
@@ -686,6 +686,7 @@ extern int machine_at_ficpa2012_init(const machine_t *);
|
||||
|
||||
extern int machine_at_r534f_init(const machine_t *);
|
||||
extern int machine_at_ms5146_init(const machine_t *);
|
||||
extern int machine_at_cb52x_si_init(const machine_t *);
|
||||
|
||||
extern int machine_at_m560_init(const machine_t *);
|
||||
extern int machine_at_ms5164_init(const machine_t *);
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#define FLAG_CONFIG_M1_IO_ON 0x00000020
|
||||
#define FLAG_NO_IRQ_STEERING 0x00000040
|
||||
#define FLAG_NO_BRIDGES 0x00000080
|
||||
#define FLAG_TRC_CONTROLS_CPURST 0x00000100
|
||||
|
||||
#define FLAG_MECHANISM_MASK FLAG_MECHANISM_1 | FLAG_MECHANISM_2
|
||||
#define FLAG_MASK 0x0000007f
|
||||
|
||||
@@ -1087,9 +1087,9 @@ machine_at_r534f_init(const machine_t *model)
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init(model);
|
||||
machine_at_common_init_ex(model, 2);
|
||||
|
||||
pci_init(PCI_CONFIG_TYPE_1);
|
||||
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
|
||||
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
||||
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
|
||||
pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
@@ -1116,9 +1116,9 @@ machine_at_ms5146_init(const machine_t *model)
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init(model);
|
||||
machine_at_common_init_ex(model, 2);
|
||||
|
||||
pci_init(PCI_CONFIG_TYPE_1);
|
||||
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
|
||||
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
||||
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
|
||||
pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
@@ -1134,6 +1134,35 @@ machine_at_ms5146_init(const machine_t *model)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
machine_at_cb52x_si_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear("roms/machines/cb52x_si/CD5205S.ROM",
|
||||
0x000e0000, 131072, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init_ex(model, 2);
|
||||
|
||||
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
|
||||
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
||||
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
|
||||
pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1);
|
||||
pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2);
|
||||
pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3);
|
||||
|
||||
device_add(&sis_5571_device);
|
||||
device_add(&keyboard_ps2_ami_pci_device);
|
||||
device_add(&fdc37c669_370_device);
|
||||
device_add(&sst_flash_29ee010_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
machine_at_m560_init(const machine_t *model)
|
||||
{
|
||||
|
||||
@@ -752,7 +752,7 @@ machine_at_ap5s_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_TRC_CONTROLS_CPURST);
|
||||
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
||||
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
|
||||
pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
@@ -781,7 +781,7 @@ machine_at_ms5124_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_TRC_CONTROLS_CPURST);
|
||||
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
||||
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0xFE, 0xFF, 0, 0);
|
||||
pci_register_slot(0x10, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
|
||||
@@ -11000,11 +11000,11 @@ const machine_t machines[] = {
|
||||
/* SiS 5571 */
|
||||
/* Has the SiS 5571 chipset with on-chip KBC. */
|
||||
{
|
||||
.name = "[SiS 5571] Rise R534F",
|
||||
.internal_name = "r534f",
|
||||
.name = "[SiS 5571] Daewoo CB52X-SI",
|
||||
.internal_name = "cb52x_si",
|
||||
.type = MACHINE_TYPE_SOCKET7,
|
||||
.chipset = MACHINE_CHIPSET_SIS_5571,
|
||||
.init = machine_at_r534f_init,
|
||||
.init = machine_at_cb52x_si_init,
|
||||
.p1_handler = NULL,
|
||||
.gpio_handler = NULL,
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
@@ -11012,9 +11012,9 @@ const machine_t machines[] = {
|
||||
.cpu = {
|
||||
.package = CPU_PKG_SOCKET5_7,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 55000000,
|
||||
.max_bus = 83333333,
|
||||
.min_voltage = 2500,
|
||||
.min_bus = 50000000,
|
||||
.max_bus = 75000000,
|
||||
.min_voltage = 2800,
|
||||
.max_voltage = 3520,
|
||||
.min_multi = 1.5,
|
||||
.max_multi = 3.0
|
||||
@@ -11023,10 +11023,10 @@ const machine_t machines[] = {
|
||||
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI,
|
||||
.ram = {
|
||||
.min = 8192,
|
||||
.max = 393216,
|
||||
.max = 262144,
|
||||
.step = 8192
|
||||
},
|
||||
.nvrmask = 127,
|
||||
.nvrmask = 255,
|
||||
.kbc_device = NULL,
|
||||
.kbc_p1 = 0xff,
|
||||
.gpio = 0xffffffff,
|
||||
@@ -11066,7 +11066,7 @@ const machine_t machines[] = {
|
||||
.max = 262144,
|
||||
.step = 8192
|
||||
},
|
||||
.nvrmask = 127,
|
||||
.nvrmask = 255,
|
||||
.kbc_device = NULL,
|
||||
.kbc_p1 = 0xff,
|
||||
.gpio = 0xffffffff,
|
||||
@@ -11078,15 +11078,13 @@ const machine_t machines[] = {
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
|
||||
/* ALi ALADDiN IV+ */
|
||||
/* Has the ALi M1543 southbridge with on-chip KBC. */
|
||||
/* Has the SiS 5571 chipset with on-chip KBC. */
|
||||
{
|
||||
.name = "[ALi ALADDiN IV+] PC Chips M560",
|
||||
.internal_name = "m560",
|
||||
.name = "[SiS 5571] Rise R534F",
|
||||
.internal_name = "r534f",
|
||||
.type = MACHINE_TYPE_SOCKET7,
|
||||
.chipset = MACHINE_CHIPSET_ALI_ALADDIN_IV_PLUS,
|
||||
.init = machine_at_m560_init,
|
||||
.chipset = MACHINE_CHIPSET_SIS_5571,
|
||||
.init = machine_at_r534f_init,
|
||||
.p1_handler = NULL,
|
||||
.gpio_handler = NULL,
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
@@ -11094,7 +11092,7 @@ const machine_t machines[] = {
|
||||
.cpu = {
|
||||
.package = CPU_PKG_SOCKET5_7,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 50000000,
|
||||
.min_bus = 55000000,
|
||||
.max_bus = 83333333,
|
||||
.min_voltage = 2500,
|
||||
.max_voltage = 3520,
|
||||
@@ -11105,7 +11103,7 @@ const machine_t machines[] = {
|
||||
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI,
|
||||
.ram = {
|
||||
.min = 8192,
|
||||
.max = 786432,
|
||||
.max = 393216,
|
||||
.step = 8192
|
||||
},
|
||||
.nvrmask = 255,
|
||||
@@ -11120,6 +11118,8 @@ const machine_t machines[] = {
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
|
||||
/* ALi ALADDiN IV+ */
|
||||
/* Has the ALi M1543 southbridge with on-chip KBC. */
|
||||
{
|
||||
.name = "[ALi ALADDiN IV+] MSI MS-5164",
|
||||
@@ -11160,6 +11160,46 @@ const machine_t machines[] = {
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* Has the ALi M1543 southbridge with on-chip KBC. */
|
||||
{
|
||||
.name = "[ALi ALADDiN IV+] PC Chips M560",
|
||||
.internal_name = "m560",
|
||||
.type = MACHINE_TYPE_SOCKET7,
|
||||
.chipset = MACHINE_CHIPSET_ALI_ALADDIN_IV_PLUS,
|
||||
.init = machine_at_m560_init,
|
||||
.p1_handler = NULL,
|
||||
.gpio_handler = NULL,
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
.gpio_acpi_handler = NULL,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_SOCKET5_7,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 50000000,
|
||||
.max_bus = 83333333,
|
||||
.min_voltage = 2500,
|
||||
.max_voltage = 3520,
|
||||
.min_multi = 1.5,
|
||||
.max_multi = 3.0
|
||||
},
|
||||
.bus_flags = MACHINE_PS2_PCI,
|
||||
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI,
|
||||
.ram = {
|
||||
.min = 8192,
|
||||
.max = 786432,
|
||||
.step = 8192
|
||||
},
|
||||
.nvrmask = 255,
|
||||
.kbc_device = NULL,
|
||||
.kbc_p1 = 0xff,
|
||||
.gpio = 0xffffffff,
|
||||
.gpio_acpi = 0xffffffff,
|
||||
.device = NULL,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = NULL,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
|
||||
/* Super Socket 7 machines */
|
||||
/* ALi ALADDiN V */
|
||||
|
||||
@@ -424,6 +424,9 @@ pci_write(uint16_t port, uint8_t val, UNUSED(void *priv))
|
||||
}
|
||||
break;
|
||||
case 0xcf9:
|
||||
if (pci_flags & FLAG_TRC_CONTROLS_CPURST)
|
||||
cpu_cpurst_on_sr = !(val & 0x10);
|
||||
|
||||
if (!(pci_trc_reg & 4) && (val & 4))
|
||||
pci_trc_reset(val);
|
||||
|
||||
|
||||
@@ -12,13 +12,15 @@
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2016-2024 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/timer.h>
|
||||
@@ -45,35 +47,67 @@ typedef struct fdc37c669_t {
|
||||
|
||||
static int next_id = 0;
|
||||
|
||||
static uint16_t
|
||||
make_port(fdc37c669_t *dev, uint8_t reg)
|
||||
#ifdef ENABLE_FDC37C669_LOG
|
||||
int fdc37c669_do_log = ENABLE_FDC37C669_LOG;
|
||||
|
||||
static void
|
||||
fdc37c669_log(const char *fmt, ...)
|
||||
{
|
||||
uint16_t p = 0;
|
||||
uint16_t mask = 0;
|
||||
va_list ap;
|
||||
|
||||
switch (reg) {
|
||||
case 0x20:
|
||||
case 0x21:
|
||||
case 0x22:
|
||||
mask = 0xfc;
|
||||
break;
|
||||
case 0x23:
|
||||
mask = 0xff;
|
||||
break;
|
||||
case 0x24:
|
||||
case 0x25:
|
||||
mask = 0xfe;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
if (fdc37c669_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define fdc37c669_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
p = ((uint16_t) (dev->regs[reg] & mask)) << 2;
|
||||
if (reg == 0x22)
|
||||
p |= 6;
|
||||
static void
|
||||
fdc37c669_fdc_handler(fdc37c669_t *dev)
|
||||
{
|
||||
fdc_remove(dev->fdc);
|
||||
if (dev->regs[0x20] & 0xc0)
|
||||
fdc_set_base(dev->fdc, ((uint16_t) dev->regs[0x20]) << 2);
|
||||
}
|
||||
|
||||
return p;
|
||||
static void
|
||||
fdc37c669_uart_handler(fdc37c669_t *dev, uint8_t uart)
|
||||
{
|
||||
uint8_t uart_reg = 0x24 + uart;
|
||||
uint8_t pwrdn_mask = 0x08 << (uart << 2);
|
||||
uint8_t uart_shift = ((uart ^ 1) << 2);
|
||||
|
||||
serial_remove(dev->uart[uart]);
|
||||
if ((dev->regs[0x02] & pwrdn_mask) && (dev->regs[uart_reg] & 0xc0))
|
||||
serial_setup(dev->uart[0], ((uint16_t) dev->regs[0x24]) << 2,
|
||||
(dev->regs[0x28] >> uart_shift) & 0x0f);
|
||||
}
|
||||
|
||||
static double
|
||||
fdc37c669_uart_get_clock_src(fdc37c669_t *dev, uint8_t uart)
|
||||
{
|
||||
double clock_srcs[4] = { 24000000.0 / 13.0, 24000000.0 / 12.0, 24000000.0 / 3.0, 24000000.0 / 3.0 };
|
||||
double ret;
|
||||
uint8_t clock_src_0 = !!(dev->regs[0x04] & (0x10 << uart));
|
||||
uint8_t clock_src_1 = !!(dev->regs[0x0c] & (0x40 << uart));
|
||||
uint8_t clock_src = clock_src_0 | (clock_src_1 << 1);
|
||||
|
||||
ret = clock_srcs[clock_src];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
fdc37c669_lpt_handler(fdc37c669_t *dev)
|
||||
{
|
||||
uint8_t mask = ~(dev->regs[0x04] & 0x01);
|
||||
|
||||
lpt_port_remove(dev->id);
|
||||
if ((dev->regs[0x01] & 0x04) && (dev->regs[0x23] >= 0x40))
|
||||
lpt_port_init(dev->id, ((uint16_t) (dev->regs[0x23] & mask)) << 2);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -81,149 +115,153 @@ fdc37c669_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
fdc37c669_t *dev = (fdc37c669_t *) priv;
|
||||
uint8_t index = (port & 1) ? 0 : 1;
|
||||
uint8_t valxor = 0;
|
||||
uint8_t max = 42;
|
||||
uint8_t valxor = val ^ dev->regs[dev->cur_reg];
|
||||
|
||||
fdc37c669_log("[%04X:%08X] [W] %04X = %02X (%i, %i)\n", CS, cpu_state.pc, port, val,
|
||||
dev->tries, dev->locked);
|
||||
|
||||
if (index) {
|
||||
if ((val == 0x55) && !dev->locked) {
|
||||
if (dev->tries) {
|
||||
dev->tries = (dev->tries + 1) & 1;
|
||||
|
||||
if (!dev->tries)
|
||||
dev->locked = 1;
|
||||
dev->tries = 0;
|
||||
} else
|
||||
dev->tries++;
|
||||
} else {
|
||||
if (dev->locked) {
|
||||
if (val < max)
|
||||
dev->cur_reg = val;
|
||||
if (val == 0xaa)
|
||||
dev->locked = 0;
|
||||
} else {
|
||||
if (dev->tries)
|
||||
dev->tries = 0;
|
||||
}
|
||||
else
|
||||
dev->cur_reg = val;
|
||||
} else
|
||||
dev->tries = 0;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (dev->locked) {
|
||||
if ((dev->cur_reg < 0x18) && (dev->rw_locked))
|
||||
return;
|
||||
if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27))
|
||||
return;
|
||||
if (dev->cur_reg == 0x29)
|
||||
return;
|
||||
valxor = val ^ dev->regs[dev->cur_reg];
|
||||
} else if (!dev->rw_locked || (dev->cur_reg > 0x0f)) switch (dev->cur_reg) {
|
||||
case 0x00:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x74) | (val & 0x8b);
|
||||
if (!dev->id && (valxor & 8))
|
||||
fdc_set_power_down(dev->fdc, !(val & 0x08));
|
||||
break;
|
||||
case 0x01:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x73) | (val & 0x8c);
|
||||
if (valxor & 0x04)
|
||||
fdc37c669_lpt_handler(dev);
|
||||
if (valxor & 0x80)
|
||||
dev->rw_locked = !(val & 0x80);
|
||||
break;
|
||||
case 0x02:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x77) | (val & 0x88);
|
||||
if (valxor & 0x08)
|
||||
fdc37c669_uart_handler(dev, 0);
|
||||
if (valxor & 0x80)
|
||||
fdc37c669_uart_handler(dev, 1);
|
||||
break;
|
||||
case 0x03:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x08) | (val & 0xf7);
|
||||
if (!dev->id && (valxor & 0x02))
|
||||
fdc_update_enh_mode(dev->fdc, !!(val & 0x02));
|
||||
break;
|
||||
case 0x04:
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dev->cur_reg) {
|
||||
case 0:
|
||||
if (!dev->id && (valxor & 8)) {
|
||||
fdc_remove(dev->fdc);
|
||||
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
|
||||
fdc_set_base(dev->fdc, make_port(dev, 0x20));
|
||||
}
|
||||
if (valxor & 0x03)
|
||||
fdc37c669_lpt_handler(dev);
|
||||
if (valxor & 0x10)
|
||||
serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0));
|
||||
if (valxor & 0x20)
|
||||
serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1));
|
||||
break;
|
||||
case 1:
|
||||
if (valxor & 4) {
|
||||
if (dev->id) {
|
||||
lpt2_remove();
|
||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
||||
lpt2_init(make_port(dev, 0x23));
|
||||
} else {
|
||||
lpt1_remove();
|
||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
||||
lpt1_init(make_port(dev, 0x23));
|
||||
}
|
||||
}
|
||||
if (valxor & 7)
|
||||
dev->rw_locked = (val & 8) ? 0 : 1;
|
||||
break;
|
||||
case 2:
|
||||
if (valxor & 8) {
|
||||
serial_remove(dev->uart[0]);
|
||||
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
||||
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
||||
}
|
||||
if (valxor & 0x80) {
|
||||
serial_remove(dev->uart[1]);
|
||||
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
||||
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (!dev->id && (valxor & 2))
|
||||
fdc_update_enh_mode(dev->fdc, (val & 2) ? 1 : 0);
|
||||
break;
|
||||
case 5:
|
||||
case 0x05:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x83) | (val & 0x7c);
|
||||
if (!dev->id && (valxor & 0x18))
|
||||
fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3);
|
||||
if (!dev->id && (valxor & 0x20))
|
||||
fdc_set_swap(dev->fdc, (val & 0x20) >> 5);
|
||||
break;
|
||||
case 0xB:
|
||||
if (!dev->id && (valxor & 3))
|
||||
fdc_update_rwc(dev->fdc, 0, val & 3);
|
||||
if (!dev->id && (valxor & 0xC))
|
||||
fdc_update_rwc(dev->fdc, 1, (val & 0xC) >> 2);
|
||||
case 0x06:
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
break;
|
||||
case 0x07:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x06) | (val & 0xf9);
|
||||
break;
|
||||
case 0x08:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x0f) | (val & 0xf0);
|
||||
break;
|
||||
case 0x09:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x38) | (val & 0xc7);
|
||||
break;
|
||||
case 0x0a:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0xf0) | (val & 0x0f);
|
||||
break;
|
||||
case 0x0b:
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
if (!dev->id && (valxor & 0x03))
|
||||
fdc_update_rwc(dev->fdc, 0, val & 0x03);
|
||||
if (!dev->id && (valxor & 0x0c))
|
||||
fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2);
|
||||
break;
|
||||
case 0x0c:
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
if (valxor & 0x40)
|
||||
serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0));
|
||||
if (valxor & 0x80)
|
||||
serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1));
|
||||
break;
|
||||
case 0x0f:
|
||||
case 0x12 ... 0x1f:
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
break;
|
||||
case 0x10:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x07) | (val & 0xf8);
|
||||
break;
|
||||
case 0x11:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0xfc) | (val & 0x03);
|
||||
break;
|
||||
case 0x20:
|
||||
if (!dev->id && (valxor & 0xfc)) {
|
||||
fdc_remove(dev->fdc);
|
||||
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
|
||||
fdc_set_base(dev->fdc, make_port(dev, 0x20));
|
||||
}
|
||||
dev->regs[dev->cur_reg] = val & 0xfc;
|
||||
if (!dev->id && (valxor & 0xfc))
|
||||
fdc37c669_fdc_handler(dev);
|
||||
break;
|
||||
case 0x21:
|
||||
dev->regs[dev->cur_reg] = val & 0xfc;
|
||||
break;
|
||||
case 0x22:
|
||||
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x03) | (val & 0xfc);
|
||||
break;
|
||||
case 0x23:
|
||||
if (valxor) {
|
||||
if (dev->id) {
|
||||
lpt2_remove();
|
||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
||||
lpt2_init(make_port(dev, 0x23));
|
||||
} else {
|
||||
lpt1_remove();
|
||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
||||
lpt1_init(make_port(dev, 0x23));
|
||||
}
|
||||
}
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
if (valxor)
|
||||
fdc37c669_lpt_handler(dev);
|
||||
break;
|
||||
case 0x24:
|
||||
if (valxor & 0xfe) {
|
||||
serial_remove(dev->uart[0]);
|
||||
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
||||
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
||||
}
|
||||
dev->regs[dev->cur_reg] = val & 0xfe;
|
||||
if (valxor & 0xfe)
|
||||
fdc37c669_uart_handler(dev, 0);
|
||||
break;
|
||||
case 0x25:
|
||||
if (valxor & 0xfe) {
|
||||
serial_remove(dev->uart[1]);
|
||||
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
||||
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
||||
}
|
||||
dev->regs[dev->cur_reg] = val & 0xfe;
|
||||
if (valxor & 0xfe)
|
||||
fdc37c669_uart_handler(dev, 1);
|
||||
break;
|
||||
case 0x26:
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
if (valxor & 0xf0)
|
||||
fdc_set_dma_ch(dev->fdc, val >> 4);
|
||||
break;
|
||||
case 0x27:
|
||||
if (valxor & 0xf) {
|
||||
if (dev->id)
|
||||
lpt2_irq(val & 0xf);
|
||||
else
|
||||
lpt1_irq(val & 0xf);
|
||||
}
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
if (valxor & 0xf0)
|
||||
fdc_set_irq(dev->fdc, val >> 4);
|
||||
if (valxor & 0x0f)
|
||||
lpt_port_irq(dev->id, val & 0x0f);
|
||||
break;
|
||||
case 0x28:
|
||||
if (valxor & 0xf) {
|
||||
serial_remove(dev->uart[1]);
|
||||
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
||||
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
||||
}
|
||||
if (valxor & 0xf0) {
|
||||
serial_remove(dev->uart[0]);
|
||||
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
||||
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
||||
}
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
if (valxor & 0xf0)
|
||||
fdc37c669_uart_handler(dev, 0);
|
||||
if (valxor & 0x0f)
|
||||
fdc37c669_uart_handler(dev, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
case 0x29:
|
||||
dev->regs[dev->cur_reg] = val & 0x0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -238,23 +276,23 @@ fdc37c669_read(uint16_t port, void *priv)
|
||||
if (dev->locked) {
|
||||
if (index)
|
||||
ret = dev->cur_reg;
|
||||
else if ((dev->cur_reg >= 0x18) || !dev->rw_locked)
|
||||
else if (!dev->rw_locked || (dev->cur_reg > 0x0f))
|
||||
ret = dev->regs[dev->cur_reg];
|
||||
}
|
||||
|
||||
fdc37c669_log("[%04X:%08X] [R] %04X = %02X (%i, %i)\n", CS, cpu_state.pc, port, ret,
|
||||
dev->tries, dev->locked);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
fdc37c669_reset(fdc37c669_t *dev)
|
||||
fdc37c669_reset(void *priv)
|
||||
{
|
||||
serial_remove(dev->uart[0]);
|
||||
serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ);
|
||||
fdc37c669_t *dev = (fdc37c669_t *) priv;
|
||||
|
||||
serial_remove(dev->uart[1]);
|
||||
serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ);
|
||||
memset(dev->regs, 0x00, 42);
|
||||
|
||||
memset(dev->regs, 0, 42);
|
||||
dev->regs[0x00] = 0x28;
|
||||
dev->regs[0x01] = 0x9c;
|
||||
dev->regs[0x02] = 0x88;
|
||||
@@ -262,32 +300,23 @@ fdc37c669_reset(fdc37c669_t *dev)
|
||||
dev->regs[0x06] = 0xff;
|
||||
dev->regs[0x0d] = 0x03;
|
||||
dev->regs[0x0e] = 0x02;
|
||||
dev->regs[0x1e] = 0x80; /* Gameport controller. */
|
||||
dev->regs[0x20] = (FDC_PRIMARY_ADDR >> 2) & 0xfc;
|
||||
dev->regs[0x21] = (0x1f0 >> 2) & 0xfc;
|
||||
dev->regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1;
|
||||
dev->regs[0x1e] = 0x3c; /* Gameport controller. */
|
||||
dev->regs[0x20] = 0x3c;
|
||||
dev->regs[0x21] = 0x3c;
|
||||
dev->regs[0x22] = 0x3d;
|
||||
|
||||
if (dev->id == 1) {
|
||||
dev->regs[0x23] = (LPT2_ADDR >> 2);
|
||||
|
||||
lpt2_remove();
|
||||
lpt2_init(LPT2_ADDR);
|
||||
|
||||
dev->regs[0x24] = (COM3_ADDR >> 2) & 0xfe;
|
||||
dev->regs[0x25] = (COM4_ADDR >> 2) & 0xfe;
|
||||
} else {
|
||||
fdc_reset(dev->fdc);
|
||||
|
||||
lpt1_remove();
|
||||
lpt1_init(LPT1_ADDR);
|
||||
|
||||
dev->regs[0x23] = (LPT1_ADDR >> 2);
|
||||
|
||||
dev->regs[0x24] = (COM1_ADDR >> 2) & 0xfe;
|
||||
dev->regs[0x25] = (COM2_ADDR >> 2) & 0xfe;
|
||||
fdc37c669_fdc_handler(dev);
|
||||
}
|
||||
dev->regs[0x26] = (2 << 4) | 3;
|
||||
dev->regs[0x27] = (6 << 4) | (dev->id ? 5 : 7);
|
||||
dev->regs[0x28] = (4 << 4) | 3;
|
||||
|
||||
fdc37c669_uart_handler(dev, 0);
|
||||
serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0));
|
||||
|
||||
fdc37c669_uart_handler(dev, 1);
|
||||
serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1));
|
||||
|
||||
fdc37c669_lpt_handler(dev);
|
||||
|
||||
dev->locked = 0;
|
||||
dev->rw_locked = 0;
|
||||
@@ -317,8 +346,8 @@ fdc37c669_init(const device_t *info)
|
||||
dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1);
|
||||
dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2);
|
||||
|
||||
io_sethandler(info->local ? FDC_SECONDARY_ADDR : (next_id ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR), 0x0002,
|
||||
fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev);
|
||||
io_sethandler(info->local ? FDC_SECONDARY_ADDR : (next_id ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR),
|
||||
0x0002, fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev);
|
||||
|
||||
fdc37c669_reset(dev);
|
||||
|
||||
@@ -334,7 +363,7 @@ const device_t fdc37c669_device = {
|
||||
.local = 0,
|
||||
.init = fdc37c669_init,
|
||||
.close = fdc37c669_close,
|
||||
.reset = NULL,
|
||||
.reset = fdc37c669_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
@@ -348,7 +377,7 @@ const device_t fdc37c669_370_device = {
|
||||
.local = 1,
|
||||
.init = fdc37c669_init,
|
||||
.close = fdc37c669_close,
|
||||
.reset = NULL,
|
||||
.reset = fdc37c669_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
|
||||
@@ -43,11 +43,29 @@
|
||||
#define COMPOSITE_OLD 0
|
||||
#define COMPOSITE_NEW 1
|
||||
|
||||
#define DOUBLE_NONE 0
|
||||
#define DOUBLE_SIMPLE 1
|
||||
#define DOUBLE_INTERPOLATE_SRGB 2
|
||||
#define DOUBLE_INTERPOLATE_LINEAR 3
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint32_t color;
|
||||
struct {
|
||||
uint8_t b;
|
||||
uint8_t g;
|
||||
uint8_t r;
|
||||
uint8_t a;
|
||||
};
|
||||
} color_t;
|
||||
|
||||
static uint8_t crtcmask[32] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static uint8_t interp_lut[2][256][256];
|
||||
|
||||
static video_timings_t timing_cga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
|
||||
|
||||
void cga_recalctimings(cga_t *cga);
|
||||
@@ -201,24 +219,269 @@ cga_recalctimings(cga_t *cga)
|
||||
cga->dispofftime = (uint64_t) (_dispofftime);
|
||||
}
|
||||
|
||||
void
|
||||
cga_poll(void *priv)
|
||||
static void
|
||||
cga_render(cga_t *cga, int line)
|
||||
{
|
||||
cga_t *cga = (cga_t *) priv;
|
||||
uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff;
|
||||
int drawcursor;
|
||||
int x;
|
||||
int c;
|
||||
int xs_temp;
|
||||
int ys_temp;
|
||||
int oldvc;
|
||||
uint8_t chr;
|
||||
uint8_t attr;
|
||||
uint8_t border;
|
||||
uint16_t dat;
|
||||
int cols[4];
|
||||
int col;
|
||||
|
||||
if ((cga->cgamode & 0x12) == 0x12) {
|
||||
for (c = 0; c < 8; ++c) {
|
||||
buffer32->line[line][c] = 0;
|
||||
if (cga->cgamode & 1)
|
||||
buffer32->line[line][c + (cga->crtc[1] << 3) + 8] = 0;
|
||||
else
|
||||
buffer32->line[line][c + (cga->crtc[1] << 4) + 8] = 0;
|
||||
}
|
||||
} else {
|
||||
for (c = 0; c < 8; ++c) {
|
||||
buffer32->line[line][c] = (cga->cgacol & 15) + 16;
|
||||
if (cga->cgamode & 1)
|
||||
buffer32->line[line][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16;
|
||||
else
|
||||
buffer32->line[line][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16;
|
||||
}
|
||||
}
|
||||
if (cga->cgamode & 1) {
|
||||
for (x = 0; x < cga->crtc[1]; x++) {
|
||||
if (cga->cgamode & 8) {
|
||||
chr = cga->charbuffer[x << 1];
|
||||
attr = cga->charbuffer[(x << 1) + 1];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
|
||||
cols[1] = (attr & 15) + 16;
|
||||
if (cga->cgamode & 0x20) {
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor)
|
||||
cols[1] = cols[0];
|
||||
} else
|
||||
cols[0] = (attr >> 4) + 16;
|
||||
if (drawcursor) {
|
||||
for (c = 0; c < 8; c++) {
|
||||
buffer32->line[line][(x << 3) + c + 8]
|
||||
= cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
||||
}
|
||||
} else {
|
||||
for (c = 0; c < 8; c++) {
|
||||
buffer32->line[line][(x << 3) + c + 8]
|
||||
= cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
}
|
||||
cga->ma++;
|
||||
}
|
||||
} else if (!(cga->cgamode & 2)) {
|
||||
for (x = 0; x < cga->crtc[1]; x++) {
|
||||
if (cga->cgamode & 8) {
|
||||
chr = cga->vram[(cga->ma << 1) & 0x3fff];
|
||||
attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
|
||||
cols[1] = (attr & 15) + 16;
|
||||
if (cga->cgamode & 0x20) {
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
if ((cga->cgablink & 8) && (attr & 0x80))
|
||||
cols[1] = cols[0];
|
||||
} else
|
||||
cols[0] = (attr >> 4) + 16;
|
||||
cga->ma++;
|
||||
if (drawcursor) {
|
||||
for (c = 0; c < 8; c++) {
|
||||
buffer32->line[line][(x << 4) + (c << 1) + 8]
|
||||
= buffer32->line[line][(x << 4) + (c << 1) + 9]
|
||||
= cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
||||
}
|
||||
} else {
|
||||
for (c = 0; c < 8; c++) {
|
||||
buffer32->line[line][(x << 4) + (c << 1) + 8]
|
||||
= buffer32->line[line][(x << 4) + (c << 1) + 9]
|
||||
= cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!(cga->cgamode & 16)) {
|
||||
cols[0] = (cga->cgacol & 15) | 16;
|
||||
col = (cga->cgacol & 16) ? 24 : 16;
|
||||
if (cga->cgamode & 4) {
|
||||
cols[1] = col | 3; /* Cyan */
|
||||
cols[2] = col | 4; /* Red */
|
||||
cols[3] = col | 7; /* White */
|
||||
} else if (cga->cgacol & 32) {
|
||||
cols[1] = col | 3; /* Cyan */
|
||||
cols[2] = col | 5; /* Magenta */
|
||||
cols[3] = col | 7; /* White */
|
||||
} else {
|
||||
cols[1] = col | 2; /* Green */
|
||||
cols[2] = col | 4; /* Red */
|
||||
cols[3] = col | 6; /* Yellow */
|
||||
}
|
||||
for (x = 0; x < cga->crtc[1]; x++) {
|
||||
if (cga->cgamode & 8)
|
||||
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) |
|
||||
cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
|
||||
else
|
||||
dat = 0;
|
||||
cga->ma++;
|
||||
for (c = 0; c < 8; c++) {
|
||||
buffer32->line[line][(x << 4) + (c << 1) + 8]
|
||||
= buffer32->line[line][(x << 4) + (c << 1) + 9]
|
||||
= cols[dat >> 14];
|
||||
dat <<= 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cols[0] = 0;
|
||||
cols[1] = (cga->cgacol & 15) + 16;
|
||||
for (x = 0; x < cga->crtc[1]; x++) {
|
||||
if (cga->cgamode & 8)
|
||||
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) |
|
||||
cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
|
||||
else
|
||||
dat = 0;
|
||||
cga->ma++;
|
||||
for (c = 0; c < 16; c++) {
|
||||
buffer32->line[line][(x << 4) + c + 8] = cols[dat >> 15];
|
||||
dat <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cga_render_blank(cga_t *cga, int line)
|
||||
{
|
||||
int col = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16;
|
||||
|
||||
if (cga->cgamode & 1)
|
||||
hline(buffer32, 0, line, (cga->crtc[1] << 3) + 16, col);
|
||||
else
|
||||
hline(buffer32, 0, line, (cga->crtc[1] << 4) + 16, col);
|
||||
}
|
||||
|
||||
static void
|
||||
cga_render_process(cga_t *cga, int line)
|
||||
{
|
||||
int x;
|
||||
uint8_t border;
|
||||
|
||||
if (cga->cgamode & 1)
|
||||
x = (cga->crtc[1] << 3) + 16;
|
||||
else
|
||||
x = (cga->crtc[1] << 4) + 16;
|
||||
|
||||
if (cga->composite) {
|
||||
border = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15);
|
||||
|
||||
Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[line]);
|
||||
} else
|
||||
video_process_8(x, line);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
cga_interpolate_srgb(uint8_t co1, uint8_t co2, double fraction)
|
||||
{
|
||||
uint8_t ret = ((co2 - co1) * fraction + co1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
cga_interpolate_linear(uint8_t co1, uint8_t co2, double fraction)
|
||||
{
|
||||
double c1, c2;
|
||||
double r1, r2;
|
||||
uint8_t ret;
|
||||
|
||||
c1 = ((double) co1) / 255.0;
|
||||
c1 = pow((co1 >= 0) ? c1 : -c1, 2.19921875);
|
||||
if (co1 <= 0)
|
||||
c1 = -c1;
|
||||
c2 = ((double) co2) / 255.0;
|
||||
c2 = pow((co2 >= 0) ? c2 : -c2, 2.19921875);
|
||||
if (co2 <= 0)
|
||||
c2 = -c2;
|
||||
r1 = ((c2 - c1) * fraction + c1);
|
||||
r2 = pow((r1 >= 0.0) ? r1 : -r1, 1.0 / 2.19921875);
|
||||
if (r1 <= 0.0)
|
||||
r2 = -r2;
|
||||
ret = (uint8_t) (r2 * 255.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static color_t
|
||||
cga_interpolate_lookup(cga_t *cga, color_t color1, color_t color2, double fraction)
|
||||
{
|
||||
color_t ret;
|
||||
uint8_t dt = cga->double_type - DOUBLE_INTERPOLATE_SRGB;
|
||||
|
||||
ret.a = 0x00;
|
||||
ret.r = interp_lut[dt][color1.r][color2.r];
|
||||
ret.g = interp_lut[dt][color1.g][color2.g];
|
||||
ret.b = interp_lut[dt][color1.b][color2.b];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
cga_interpolate(cga_t *cga, int x, int y, int w, int h)
|
||||
{
|
||||
double quotient = 0.5;
|
||||
|
||||
for (int i = y; i < (y + h); i++) {
|
||||
if (i & 1) for (int j = x; j < (x + w); j++) {
|
||||
int prev = i - 1;
|
||||
int next = i + 1;
|
||||
color_t prev_color, next_color;
|
||||
color_t black;
|
||||
color_t interim_1, interim_2;
|
||||
color_t final;
|
||||
|
||||
black.color = 0x00000000;
|
||||
|
||||
prev_color.color = buffer32->line[prev][j];
|
||||
|
||||
if (next < (y + h))
|
||||
next_color.color = buffer32->line[next][j];
|
||||
else
|
||||
next_color.color = 0x00000000;
|
||||
|
||||
interim_1 = cga_interpolate_lookup(cga, prev_color, black, quotient);
|
||||
interim_2 = cga_interpolate_lookup(cga, black, next_color, quotient);
|
||||
final = cga_interpolate_lookup(cga, interim_1, interim_2, quotient);
|
||||
|
||||
buffer32->line[i][j] = final.color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cga_blit_memtoscreen(cga_t *cga, int x, int y, int w, int h)
|
||||
{
|
||||
if (cga->double_type > DOUBLE_SIMPLE)
|
||||
cga_interpolate(cga, x, y, w, h);
|
||||
|
||||
video_blit_memtoscreen(x, y, w, h);
|
||||
}
|
||||
|
||||
void
|
||||
cga_poll(void *priv)
|
||||
{
|
||||
cga_t *cga = (cga_t *) priv;
|
||||
int x;
|
||||
int oldsc;
|
||||
int oldvc;
|
||||
int xs_temp;
|
||||
int ys_temp;
|
||||
int old_ma;
|
||||
|
||||
if (!cga->linepos) {
|
||||
timer_advance_u64(&cga->timer, cga->dispofftime);
|
||||
@@ -233,143 +496,44 @@ cga_poll(void *priv)
|
||||
video_wait_for_buffer();
|
||||
}
|
||||
cga->lastline = cga->displine;
|
||||
if ((cga->cgamode & 0x12) == 0x12) {
|
||||
for (c = 0; c < 8; ++c) {
|
||||
buffer32->line[cga->displine][c] = 0;
|
||||
if (cga->cgamode & 1)
|
||||
buffer32->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = 0;
|
||||
else
|
||||
buffer32->line[cga->displine][c + (cga->crtc[1] << 4) + 8] = 0;
|
||||
}
|
||||
} else {
|
||||
for (c = 0; c < 8; ++c) {
|
||||
buffer32->line[cga->displine][c] = (cga->cgacol & 15) + 16;
|
||||
if (cga->cgamode & 1)
|
||||
buffer32->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16;
|
||||
else
|
||||
buffer32->line[cga->displine][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16;
|
||||
}
|
||||
}
|
||||
if (cga->cgamode & 1) {
|
||||
for (x = 0; x < cga->crtc[1]; x++) {
|
||||
if (cga->cgamode & 8) {
|
||||
chr = cga->charbuffer[x << 1];
|
||||
attr = cga->charbuffer[(x << 1) + 1];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
|
||||
cols[1] = (attr & 15) + 16;
|
||||
if (cga->cgamode & 0x20) {
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor)
|
||||
cols[1] = cols[0];
|
||||
} else
|
||||
cols[0] = (attr >> 4) + 16;
|
||||
if (drawcursor) {
|
||||
for (c = 0; c < 8; c++) {
|
||||
buffer32->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
||||
}
|
||||
} else {
|
||||
for (c = 0; c < 8; c++) {
|
||||
buffer32->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
}
|
||||
cga->ma++;
|
||||
}
|
||||
} else if (!(cga->cgamode & 2)) {
|
||||
for (x = 0; x < cga->crtc[1]; x++) {
|
||||
if (cga->cgamode & 8) {
|
||||
chr = cga->vram[(cga->ma << 1) & 0x3fff];
|
||||
attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
|
||||
cols[1] = (attr & 15) + 16;
|
||||
if (cga->cgamode & 0x20) {
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
if ((cga->cgablink & 8) && (attr & 0x80))
|
||||
cols[1] = cols[0];
|
||||
} else
|
||||
cols[0] = (attr >> 4) + 16;
|
||||
cga->ma++;
|
||||
if (drawcursor) {
|
||||
for (c = 0; c < 8; c++) {
|
||||
buffer32->line[cga->displine][(x << 4) + (c << 1) + 8]
|
||||
= buffer32->line[cga->displine][(x << 4) + (c << 1) + 9]
|
||||
= cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
||||
}
|
||||
} else {
|
||||
for (c = 0; c < 8; c++) {
|
||||
buffer32->line[cga->displine][(x << 4) + (c << 1) + 8]
|
||||
= buffer32->line[cga->displine][(x << 4) + (c << 1) + 9]
|
||||
= cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!(cga->cgamode & 16)) {
|
||||
cols[0] = (cga->cgacol & 15) | 16;
|
||||
col = (cga->cgacol & 16) ? 24 : 16;
|
||||
if (cga->cgamode & 4) {
|
||||
cols[1] = col | 3; /* Cyan */
|
||||
cols[2] = col | 4; /* Red */
|
||||
cols[3] = col | 7; /* White */
|
||||
} else if (cga->cgacol & 32) {
|
||||
cols[1] = col | 3; /* Cyan */
|
||||
cols[2] = col | 5; /* Magenta */
|
||||
cols[3] = col | 7; /* White */
|
||||
} else {
|
||||
cols[1] = col | 2; /* Green */
|
||||
cols[2] = col | 4; /* Red */
|
||||
cols[3] = col | 6; /* Yellow */
|
||||
}
|
||||
for (x = 0; x < cga->crtc[1]; x++) {
|
||||
if (cga->cgamode & 8)
|
||||
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
|
||||
else
|
||||
dat = 0;
|
||||
cga->ma++;
|
||||
for (c = 0; c < 8; c++) {
|
||||
buffer32->line[cga->displine][(x << 4) + (c << 1) + 8]
|
||||
= buffer32->line[cga->displine][(x << 4) + (c << 1) + 9]
|
||||
= cols[dat >> 14];
|
||||
dat <<= 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cols[0] = 0;
|
||||
cols[1] = (cga->cgacol & 15) + 16;
|
||||
for (x = 0; x < cga->crtc[1]; x++) {
|
||||
if (cga->cgamode & 8)
|
||||
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
|
||||
else
|
||||
dat = 0;
|
||||
cga->ma++;
|
||||
for (c = 0; c < 16; c++) {
|
||||
buffer32->line[cga->displine][(x << 4) + c + 8] = cols[dat >> 15];
|
||||
dat <<= 1;
|
||||
}
|
||||
}
|
||||
switch (cga->double_type) {
|
||||
default:
|
||||
cga_render(cga, cga->displine << 1);
|
||||
cga_render_blank(cga, (cga->displine << 1) + 1);
|
||||
break;
|
||||
case DOUBLE_NONE:
|
||||
cga_render(cga, cga->displine);
|
||||
break;
|
||||
case DOUBLE_SIMPLE:
|
||||
old_ma = cga->ma;
|
||||
cga_render(cga, cga->displine << 1);
|
||||
cga->ma = old_ma;
|
||||
cga_render(cga, (cga->displine << 1) + 1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
cols[0] = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16;
|
||||
if (cga->cgamode & 1) {
|
||||
hline(buffer32, 0, cga->displine, (cga->crtc[1] << 3) + 16, cols[0]);
|
||||
} else {
|
||||
hline(buffer32, 0, cga->displine, (cga->crtc[1] << 4) + 16, cols[0]);
|
||||
switch (cga->double_type) {
|
||||
default:
|
||||
cga_render_blank(cga, cga->displine << 1);
|
||||
break;
|
||||
case DOUBLE_NONE:
|
||||
cga_render_blank(cga, cga->displine);
|
||||
break;
|
||||
case DOUBLE_SIMPLE:
|
||||
cga_render_blank(cga, cga->displine << 1);
|
||||
cga_render_blank(cga, (cga->displine << 1) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cga->cgamode & 1)
|
||||
x = (cga->crtc[1] << 3) + 16;
|
||||
else
|
||||
x = (cga->crtc[1] << 4) + 16;
|
||||
|
||||
if (cga->composite) {
|
||||
border = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15);
|
||||
|
||||
Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[cga->displine]);
|
||||
} else {
|
||||
video_process_8(x, cga->displine);
|
||||
switch (cga->double_type) {
|
||||
default:
|
||||
cga_render_process(cga, cga->displine << 1);
|
||||
cga_render_process(cga, (cga->displine << 1) + 1);
|
||||
break;
|
||||
case DOUBLE_NONE:
|
||||
cga_render_process(cga, cga->displine);
|
||||
break;
|
||||
}
|
||||
|
||||
cga->sc = oldsc;
|
||||
@@ -386,7 +550,8 @@ cga_poll(void *priv)
|
||||
if (!cga->vsynctime)
|
||||
cga->cgastat &= ~8;
|
||||
}
|
||||
if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) {
|
||||
if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 &&
|
||||
cga->sc == ((cga->crtc[11] & 31) >> 1))) {
|
||||
cga->con = 0;
|
||||
cga->coff = 1;
|
||||
}
|
||||
@@ -445,6 +610,8 @@ cga_poll(void *priv)
|
||||
|
||||
xs_temp = x;
|
||||
ys_temp = cga->lastline - cga->firstline;
|
||||
if (cga->double_type > DOUBLE_NONE)
|
||||
ys_temp <<= 1;
|
||||
|
||||
if ((xs_temp > 0) && (ys_temp > 0)) {
|
||||
if (xs_temp < 64)
|
||||
@@ -454,21 +621,33 @@ cga_poll(void *priv)
|
||||
if (!enable_overscan)
|
||||
xs_temp -= 16;
|
||||
|
||||
if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
|
||||
if ((cga->cgamode & 8) && ((xs_temp != xsize) ||
|
||||
(ys_temp != ysize) || video_force_resize_get())) {
|
||||
xsize = xs_temp;
|
||||
ysize = ys_temp;
|
||||
set_screen_size(xsize, ysize + (enable_overscan ? 8 : 0));
|
||||
if (cga->double_type > DOUBLE_NONE)
|
||||
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
|
||||
else
|
||||
set_screen_size(xsize, ysize + (enable_overscan ? 8 : 0));
|
||||
|
||||
if (video_force_resize_get())
|
||||
video_force_resize_set(0);
|
||||
}
|
||||
|
||||
if (enable_overscan) {
|
||||
video_blit_memtoscreen(0, cga->firstline - 4,
|
||||
xsize, (cga->lastline - cga->firstline) + 8);
|
||||
if (cga->double_type > DOUBLE_NONE) {
|
||||
if (enable_overscan)
|
||||
cga_blit_memtoscreen(cga, 0, (cga->firstline - 4) << 1,
|
||||
xsize, ((cga->lastline - cga->firstline) << 1) + 16);
|
||||
else
|
||||
cga_blit_memtoscreen(cga, 8, cga->firstline << 1,
|
||||
xsize, (cga->lastline - cga->firstline) << 1);
|
||||
} else {
|
||||
video_blit_memtoscreen(8, cga->firstline,
|
||||
xsize, cga->lastline - cga->firstline);
|
||||
if (enable_overscan)
|
||||
video_blit_memtoscreen(0, cga->firstline - 4,
|
||||
xsize, (cga->lastline - cga->firstline) + 8);
|
||||
else
|
||||
video_blit_memtoscreen(8, cga->firstline,
|
||||
xsize, cga->lastline - cga->firstline);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,7 +681,8 @@ cga_poll(void *priv)
|
||||
}
|
||||
if (cga->cgadispon)
|
||||
cga->cgastat &= ~1;
|
||||
if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1)))
|
||||
if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 &&
|
||||
cga->sc == ((cga->crtc[10] & 31) >> 1)))
|
||||
cga->con = 1;
|
||||
if (cga->cgadispon && (cga->cgamode & 1)) {
|
||||
for (x = 0; x < (cga->crtc[1] << 1); x++)
|
||||
@@ -546,6 +726,15 @@ cga_standalone_init(UNUSED(const device_t *info))
|
||||
cgapal_rebuild();
|
||||
update_cga16_color(cga->cgamode);
|
||||
|
||||
cga->double_type = device_get_config_int("double_type");
|
||||
|
||||
for (uint16_t i = 0; i < 256; i++) {
|
||||
for (uint16_t j = 0; j < 256; j++) {
|
||||
interp_lut[0][i][j] = cga_interpolate_srgb(i, j, 0.5);
|
||||
interp_lut[1][i][j] = cga_interpolate_linear(i, j, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
return cga;
|
||||
}
|
||||
|
||||
@@ -625,10 +814,10 @@ const device_config_t cga_config[] = {
|
||||
.name = "rgb_type",
|
||||
.description = "RGB type",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_int = 0,
|
||||
.default_int = 5,
|
||||
.selection = {
|
||||
{
|
||||
.description = "Color",
|
||||
.description = "Color (generic)",
|
||||
.value = 0
|
||||
},
|
||||
{
|
||||
@@ -647,6 +836,37 @@ const device_config_t cga_config[] = {
|
||||
.description = "Color (no brown)",
|
||||
.value = 4
|
||||
},
|
||||
{
|
||||
.description = "Color (IBM 5153)",
|
||||
.value = 5
|
||||
},
|
||||
{
|
||||
.description = ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "double_type",
|
||||
.description = "Line doubling type",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_int = DOUBLE_NONE,
|
||||
.selection = {
|
||||
{
|
||||
.description = "None",
|
||||
.value = DOUBLE_NONE
|
||||
},
|
||||
{
|
||||
.description = "Simple doubling",
|
||||
.value = DOUBLE_SIMPLE
|
||||
},
|
||||
{
|
||||
.description = "sRGB interpolation",
|
||||
.value = DOUBLE_INTERPOLATE_SRGB
|
||||
},
|
||||
{
|
||||
.description = "Linear interpolation",
|
||||
.value = DOUBLE_INTERPOLATE_LINEAR
|
||||
},
|
||||
{
|
||||
.description = ""
|
||||
}
|
||||
|
||||
@@ -555,7 +555,7 @@ ega_recalctimings(ega_t *ega)
|
||||
if (ega->seqregs[1] & 8)
|
||||
overscan_x <<= 1;
|
||||
|
||||
ega->y_add = (overscan_y >> 1) - (ega->crtc[8] & 0x1f);
|
||||
ega->y_add = (overscan_y >> 1);
|
||||
ega->x_add = (overscan_x >> 1);
|
||||
|
||||
if (ega->seqregs[1] & 8) {
|
||||
@@ -769,6 +769,7 @@ ega_poll(void *priv)
|
||||
if ((ega->sc == (ega->crtc[11] & 31)) || (ega->sc == ega->rowcount))
|
||||
ega->con = 0;
|
||||
if (ega->dispon) {
|
||||
/* TODO: Verify real hardware behaviour for out-of-range fine vertical scroll */
|
||||
if (ega->linedbl && !ega->linecountff) {
|
||||
ega->linecountff = 1;
|
||||
ega->ma = ega->maback;
|
||||
@@ -881,7 +882,7 @@ ega_poll(void *priv)
|
||||
}
|
||||
if (ega->vc == ega->vtotal) {
|
||||
ega->vc = 0;
|
||||
ega->sc = 0;
|
||||
ega->sc = (ega->crtc[0x8] & 0x1f);
|
||||
ega->dispon = 1;
|
||||
ega->displine = (ega->interlace && ega->oddeven) ? 1 : 0;
|
||||
|
||||
@@ -916,7 +917,7 @@ ega_doblit(int wx, int wy, ega_t *ega)
|
||||
int x_add = enable_overscan ? overscan_x : 0;
|
||||
int y_start = enable_overscan ? 0 : (overscan_y >> 1);
|
||||
int x_start = enable_overscan ? 0 : (overscan_x >> 1);
|
||||
int bottom = (overscan_y >> 1) + (ega->crtc[8] & 0x1f);
|
||||
int bottom = (overscan_y >> 1);
|
||||
uint32_t *p;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@@ -23,6 +24,7 @@
|
||||
#include <math.h>
|
||||
#include <wchar.h>
|
||||
#include <stdatomic.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/io.h>
|
||||
@@ -413,6 +415,24 @@ static uint32_t s3_accel_in_l(uint16_t port, void *priv);
|
||||
static uint8_t s3_pci_read(int func, int addr, void *priv);
|
||||
static void s3_pci_write(int func, int addr, uint8_t val, void *priv);
|
||||
|
||||
#ifdef ENABLE_S3_LOG
|
||||
int s3_do_log = ENABLE_S3_LOG;
|
||||
|
||||
static void
|
||||
s3_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (s3_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define s3_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
/*Remap address for chain-4/doubleword style layout.
|
||||
These will stay for convenience.*/
|
||||
static __inline uint32_t
|
||||
@@ -581,7 +601,9 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
|
||||
const svga_t *svga = &s3->svga;
|
||||
|
||||
if (s3->accel.cmd & 0x100) {
|
||||
//pclog("S3 PIXTRANS_W write: cmd=%03x, pixelcntl=%02x, frgdmix=%02x, bkgdmix=%02x, curx=%d, val=%04x.\n", s3->accel.cmd, s3->accel.multifunc[0x0a], s3->accel.frgd_mix, s3->accel.bkgd_mix, s3->accel.cur_x, val);
|
||||
s3_log("S3 PIXTRANS_W write: cmd=%03x, pixelcntl=%02x, frgdmix=%02x, bkgdmix=%02x, "
|
||||
"curx=%d, val=%04x.\n", s3->accel.cmd, s3->accel.multifunc[0x0a],
|
||||
s3->accel.frgd_mix, s3->accel.bkgd_mix, s3->accel.cur_x, val);
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
@@ -595,7 +617,9 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
|
||||
if (s3->accel.color_16bit_check_rectfill) {
|
||||
if (s3->accel.color_16bit_check) {
|
||||
if (s3->accel.pix_trans_x_count < s3->accel.pix_trans_ptr_cnt) {
|
||||
//pclog("Word: CPU data CMD=%04x, byte write=%02x, cnt=%d, check=%d.\n", s3->accel.cmd, val & 0xff, s3->accel.pix_trans_x_count, s3->accel.color_16bit_check);
|
||||
s3_log("Word: CPU data CMD=%04x, byte write=%02x, "
|
||||
"cnt=%d, check=%d.\n", s3->accel.cmd, val & 0xff,
|
||||
s3->accel.pix_trans_x_count, s3->accel.color_16bit_check);
|
||||
s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count] = val & 0xff;
|
||||
s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count + 1] = val >> 8;
|
||||
s3->accel.pix_trans_x_count += 2;
|
||||
@@ -618,7 +642,10 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
|
||||
if (s3->accel.color_16bit_check_rectfill) {
|
||||
if (s3->accel.color_16bit_check) {
|
||||
if (s3->accel.pix_trans_x_count < s3->accel.pix_trans_ptr_cnt) {
|
||||
//pclog("Word: CPU data CMD=%04x, word write=%04x, cnt=%d, check=%d, totalptrcnt=%d.\n", s3->accel.cmd, val, s3->accel.pix_trans_x_count, s3->accel.color_16bit_check, s3->accel.pix_trans_ptr_cnt);
|
||||
s3_log("Word: CPU data CMD=%04x, word write=%04x, cnt=%d, check=%d, "
|
||||
"totalptrcnt=%d.\n", s3->accel.cmd, val,
|
||||
s3->accel.pix_trans_x_count, s3->accel.color_16bit_check,
|
||||
s3->accel.pix_trans_ptr_cnt);
|
||||
s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count] = val & 0xff;
|
||||
s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count + 1] = val >> 8;
|
||||
s3->accel.pix_trans_x_count += 2;
|
||||
@@ -626,15 +653,23 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
|
||||
}
|
||||
} else {
|
||||
if (s3->accel.pix_trans_x_count < s3->accel.pix_trans_ptr_cnt) {
|
||||
//pclog("Word: CPU data CMD=%04x, word write=%04x, cnt=%d, check=%d, totalptrcnt=%d.\n", s3->accel.cmd, val, s3->accel.pix_trans_x_count, s3->accel.color_16bit_check, s3->accel.pix_trans_ptr_cnt);
|
||||
s3_log("Word: CPU data CMD=%04x, word write=%04x, cnt=%d, check=%d, "
|
||||
"totalptrcnt=%d.\n", s3->accel.cmd, val,
|
||||
s3->accel.pix_trans_x_count, s3->accel.color_16bit_check,
|
||||
s3->accel.pix_trans_ptr_cnt);
|
||||
s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count2] = val & 0xff;
|
||||
s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count2 + 1] = val >> 8;
|
||||
s3->accel.pix_trans_x_count += 2;
|
||||
}
|
||||
if (s3->accel.pix_trans_x_count2 == s3->accel.pix_trans_ptr_cnt) {
|
||||
for (int i = 0; i < s3->accel.pix_trans_ptr_cnt; i += 2) {
|
||||
//pclog("Transferring write count=%d, bytes=%08x.\n", i, s3->accel.pix_trans_ptr[i] | (s3->accel.pix_trans_ptr[i + 1] << 8) | (s3->accel.pix_trans_ptr[i + 2] << 16) | (s3->accel.pix_trans_ptr[i + 3] << 24));
|
||||
s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans_ptr[i] | (s3->accel.pix_trans_ptr[i + 1] << 8), s3);
|
||||
s3_log("Transferring write count=%d, bytes=%08x.\n", i,
|
||||
s3->accel.pix_trans_ptr[i] |
|
||||
(s3->accel.pix_trans_ptr[i + 1] << 8) |
|
||||
(s3->accel.pix_trans_ptr[i + 2] << 16) |
|
||||
(s3->accel.pix_trans_ptr[i + 3] << 24));
|
||||
s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans_ptr[i] |
|
||||
(s3->accel.pix_trans_ptr[i + 1] << 8), s3);
|
||||
}
|
||||
|
||||
s3->accel.pix_trans_x_count2 = 0;
|
||||
@@ -911,7 +946,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
s3->accel.ssv_state = 0;
|
||||
s3->accel_start(-1, 0, 0xffffffff, 0, s3);
|
||||
if (s3->bpp == 3) {
|
||||
if (!(s3->accel.multifunc[0xe] & 0x200))
|
||||
if (!(s3->accel.multifunc[0xe] & 0x200) && !(svga->crtc[0x32] & 0x40))
|
||||
s3->accel.multifunc[0xe] &= ~0x10;
|
||||
}
|
||||
break;
|
||||
@@ -1253,22 +1288,30 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
if (s3->accel.color_16bit_check_rectfill) {
|
||||
if (s3->accel.color_16bit_check) {
|
||||
if (s3->accel.pix_trans_x_count < s3->accel.pix_trans_ptr_cnt) {
|
||||
//pclog("Byte: CPU data CMD=%04x, byte write=%02x, cnt=%d, check=%d.\n", s3->accel.cmd, val, s3->accel.pix_trans_x_count, s3->accel.color_16bit_check);
|
||||
s3_log("Byte: CPU data CMD=%04x, byte write=%02x, cnt=%d, "
|
||||
"check=%d.\n", s3->accel.cmd, val,
|
||||
s3->accel.pix_trans_x_count, s3->accel.color_16bit_check);
|
||||
s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count] = val;
|
||||
s3->accel.pix_trans_x_count++;
|
||||
s3->accel.pix_trans_x_count2 = s3->accel.pix_trans_x_count;
|
||||
}
|
||||
} else {
|
||||
if (s3->accel.pix_trans_x_count2 < s3->accel.pix_trans_ptr_cnt) {
|
||||
//pclog("Byte: CPU data CMD=%04x, byte write=%02x, cnt=%d, check=%d.\n", s3->accel.cmd, val, s3->accel.pix_trans_x_count2, s3->accel.color_16bit_check);
|
||||
s3_log("Byte: CPU data CMD=%04x, byte write=%02x, cnt=%d, "
|
||||
"check=%d.\n", s3->accel.cmd, val,
|
||||
s3->accel.pix_trans_x_count2, s3->accel.color_16bit_check);
|
||||
s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count2] = val;
|
||||
s3->accel.pix_trans_x_count2++;
|
||||
}
|
||||
//pclog("WriteCNT=%d, TotalCNT=%d.\n", s3->accel.pix_trans_x_count2, s3->accel.pix_trans_ptr_cnt);
|
||||
s3_log("WriteCNT=%d, TotalCNT=%d.\n", s3->accel.pix_trans_x_count2,
|
||||
s3->accel.pix_trans_ptr_cnt);
|
||||
if (s3->accel.pix_trans_x_count2 == s3->accel.pix_trans_ptr_cnt) {
|
||||
for (int i = 0; i < s3->accel.pix_trans_ptr_cnt; i += 2) {
|
||||
//pclog("Transferring write count=%d, bytes=%04x.\n", i, s3->accel.pix_trans_ptr[i] | (s3->accel.pix_trans_ptr[i + 1] << 8));
|
||||
s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans_ptr[i] | (s3->accel.pix_trans_ptr[i + 1] << 8), s3);
|
||||
s3_log("Transferring write count=%d, bytes=%04x.\n", i,
|
||||
s3->accel.pix_trans_ptr[i] |
|
||||
(s3->accel.pix_trans_ptr[i + 1] << 8));
|
||||
s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans_ptr[i] |
|
||||
(s3->accel.pix_trans_ptr[i + 1] << 8), s3);
|
||||
}
|
||||
|
||||
s3->accel.pix_trans_x_count2 = 0;
|
||||
@@ -1297,35 +1340,48 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
break;
|
||||
s3->accel.pix_trans[1] = val;
|
||||
if (s3->accel.cmd & 0x100) {
|
||||
//pclog("S3 PIXTRANS_B write (E2E9): cmd=%03x, pixelcntl=%02x, frgdmix=%02x, bkgdmix=%02x, curx=%d, val=%04x.\n", s3->accel.cmd, s3->accel.multifunc[0x0a], s3->accel.frgd_mix, s3->accel.bkgd_mix, s3->accel.cur_x, val);
|
||||
s3_log("S3 PIXTRANS_B write (E2E9): cmd=%03x, pixelcntl=%02x, frgdmix=%02x, "
|
||||
"bkgdmix=%02x, curx=%d, val=%04x.\n", s3->accel.cmd, s3->accel.multifunc[0x0a],
|
||||
s3->accel.frgd_mix, s3->accel.bkgd_mix, s3->accel.cur_x, val);
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3->accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) ||
|
||||
((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3->accel_start(8, 1, s3->accel.pix_trans[0] |
|
||||
(s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
else
|
||||
s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] |
|
||||
(s3->accel.pix_trans[1] << 8), s3);
|
||||
} else
|
||||
s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] |
|
||||
(s3->accel.pix_trans[1] << 8), s3);
|
||||
break;
|
||||
case 0x200:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) ||
|
||||
((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
s3->accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3);
|
||||
s3->accel_start(16, 1, s3->accel.pix_trans[1] |
|
||||
(s3->accel.pix_trans[0] << 8), 0, s3);
|
||||
else
|
||||
s3->accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
s3->accel_start(16, 1, s3->accel.pix_trans[0] |
|
||||
(s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
} else {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3);
|
||||
s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] |
|
||||
(s3->accel.pix_trans[0] << 8), s3);
|
||||
else
|
||||
s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] |
|
||||
(s3->accel.pix_trans[1] << 8), s3);
|
||||
}
|
||||
} else {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3);
|
||||
s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] |
|
||||
(s3->accel.pix_trans[0] << 8), s3);
|
||||
else
|
||||
s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] |
|
||||
(s3->accel.pix_trans[1] << 8), s3);
|
||||
}
|
||||
break;
|
||||
case 0x400:
|
||||
@@ -2717,11 +2773,6 @@ s3_out(uint16_t addr, uint8_t val, void *priv)
|
||||
s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4);
|
||||
svga->force_dword_mode = !!(val & 0x08);
|
||||
break;
|
||||
case 0x32:
|
||||
svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask;
|
||||
if (s3->color_16bit)
|
||||
svga->vram_display_mask = s3->vram_mask;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
s3->enable_8514 = (val & 0x01);
|
||||
@@ -3101,15 +3152,6 @@ s3_recalctimings(svga_t *svga)
|
||||
int clk_sel = (svga->miscout >> 2) & 3;
|
||||
uint8_t mask = 0xc0;
|
||||
|
||||
if (!svga->scrblank && svga->attr_palette_enable) {
|
||||
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
|
||||
if (svga->crtc[0x3a] & 0x10) { /*256+ color register*/
|
||||
svga->gdcreg[5] |= 0x40;
|
||||
svga->attrregs[0x10] |= 0x40;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
svga->ma_latch |= (s3->ma_ext << 16);
|
||||
if (s3->chip >= S3_86C928) {
|
||||
svga->hdisp = svga->hdisp_old;
|
||||
@@ -3173,7 +3215,7 @@ s3_recalctimings(svga_t *svga)
|
||||
break;
|
||||
}
|
||||
|
||||
svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10));
|
||||
svga->lowres = (!!(svga->attrregs[0x10] & 0x40) && !(svga->crtc[0x3a] & 0x10));
|
||||
|
||||
if (s3->chip != S3_86C801)
|
||||
mask |= 0x01;
|
||||
@@ -3232,8 +3274,12 @@ s3_recalctimings(svga_t *svga)
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) {
|
||||
pclog("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, attr=%02x.\n", svga->bpp, s3->width, svga->crtc[0x50], svga->crtc[0x31] & 0x02, s3->color_16bit, s3->accel.advfunc_cntl & 4, svga->attrregs[0x10] & 0x40);
|
||||
if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) {
|
||||
svga->vram_display_mask = s3->vram_mask;
|
||||
s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, "
|
||||
"attr=%02x.\n", svga->bpp, s3->width, svga->crtc[0x50],
|
||||
svga->crtc[0x31] & 0x02, s3->color_16bit, s3->accel.advfunc_cntl & 4,
|
||||
svga->attrregs[0x10] & 0x40);
|
||||
switch (svga->bpp) {
|
||||
case 8:
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
@@ -3920,9 +3966,11 @@ s3_recalctimings(svga_t *svga)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask;
|
||||
if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) {
|
||||
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
|
||||
if ((svga->crtc[0x31] & 0x08) && (svga->attrregs[0x10] & 0x40) == 0x00) {
|
||||
if (svga->crtc[0x31] & 0x08) {
|
||||
svga->vram_display_mask = s3->vram_mask;
|
||||
if (svga->bpp == 8) {
|
||||
svga->render = svga_render_8bpp_highres; /*Enhanced 4bpp mode, just like the 8bpp mode per spec.*/
|
||||
svga->rowoffset <<= 1;
|
||||
@@ -3939,14 +3987,6 @@ 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) {
|
||||
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
|
||||
if (svga->crtc[0x3a] & 0x10) { /*256+ color register*/
|
||||
svga->gdcreg[5] |= 0x40;
|
||||
svga->attrregs[0x10] |= 0x40;
|
||||
}
|
||||
}
|
||||
}
|
||||
svga->hdisp = svga->hdisp_old;
|
||||
if (svga->crtc[0x5d] & 0x01)
|
||||
svga->htotal |= 0x100;
|
||||
@@ -4002,9 +4042,10 @@ s3_trio64v_recalctimings(svga_t *svga)
|
||||
if (!svga->rowoffset)
|
||||
svga->rowoffset = 256;
|
||||
|
||||
svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10));
|
||||
svga->lowres = (!!(svga->attrregs[0x10] & 0x40) && !(svga->crtc[0x3a] & 0x10));
|
||||
|
||||
if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) {
|
||||
if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) {
|
||||
svga->vram_display_mask = s3->vram_mask;
|
||||
switch (svga->bpp) {
|
||||
case 8:
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
@@ -4028,7 +4069,9 @@ s3_trio64v_recalctimings(svga_t *svga)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask;
|
||||
|
||||
} else /*Streams mode*/
|
||||
{
|
||||
if (s3->streams.buffer_ctrl & 1)
|
||||
@@ -4053,6 +4096,7 @@ s3_trio64v_recalctimings(svga_t *svga)
|
||||
svga->overlay.v_acc = s3->streams.dda_vert_accumulator;
|
||||
svga->rowoffset = s3->streams.pri_stride >> 3;
|
||||
|
||||
svga->vram_display_mask = s3->vram_mask;
|
||||
switch ((s3->streams.pri_ctrl >> 24) & 0x7) {
|
||||
case 0: /*RGB-8 (CLUT)*/
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
@@ -7180,27 +7224,32 @@ s3_911_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat,
|
||||
}
|
||||
}
|
||||
|
||||
//pclog("CMD=%04x, curx=%d, lwrtmask=%04x, actual wrtmask=%04x, frgdmix=%d, bkgdmix=%d, input=%d, cnt=%d.\n", s3->accel.cmd, s3->accel.cur_x, wrt_mask, s3->accel.wrt_mask, frgd_mix, bkgd_mix, cpu_input, count);
|
||||
s3_log("CMD=%04x, curx=%d, lwrtmask=%04x, actual wrtmask=%04x, frgdmix=%d, "
|
||||
"bkgdmix=%d, input=%d, cnt=%d.\n", s3->accel.cmd, s3->accel.cur_x,
|
||||
wrt_mask, s3->accel.wrt_mask, frgd_mix, bkgd_mix, cpu_input, count);
|
||||
while (count-- && s3->accel.sy >= 0) {
|
||||
if (s3->accel.b2e8_pix && s3_cpu_src(s3) && !s3->accel.temp_cnt) {
|
||||
mix_dat >>= 16;
|
||||
s3->accel.temp_cnt = 16;
|
||||
}
|
||||
|
||||
if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) {
|
||||
if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r &&
|
||||
(s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) {
|
||||
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
|
||||
case 0:
|
||||
src_dat = bkgd_color;
|
||||
if (s3->color_16bit && (svga->bpp < 24) && !s3->accel.b2e8_pix) {
|
||||
if (!s3->accel.color_16bit_check)
|
||||
src_dat = s3->accel.bkgd_color_actual[0] | (s3->accel.bkgd_color_actual[1] << 8);
|
||||
src_dat = s3->accel.bkgd_color_actual[0] |
|
||||
(s3->accel.bkgd_color_actual[1] << 8);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
src_dat = frgd_color;
|
||||
if (s3->color_16bit && (svga->bpp < 24) && !s3->accel.b2e8_pix) {
|
||||
if (!s3->accel.color_16bit_check)
|
||||
src_dat = s3->accel.frgd_color_actual[0] | (s3->accel.frgd_color_actual[1] << 8);
|
||||
src_dat = s3->accel.frgd_color_actual[0] |
|
||||
(s3->accel.frgd_color_actual[1] << 8);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
|
||||
@@ -741,7 +741,7 @@ svga_recalctimings(svga_t *svga)
|
||||
if (svga->hdisp >= 2048)
|
||||
svga->monitor->mon_overscan_x = 0;
|
||||
|
||||
svga->y_add = (svga->monitor->mon_overscan_y >> 1) - (svga->crtc[8] & 0x1f);
|
||||
svga->y_add = (svga->monitor->mon_overscan_y >> 1);
|
||||
svga->x_add = (svga->monitor->mon_overscan_x >> 1);
|
||||
|
||||
if (svga->vblankstart < svga->dispend)
|
||||
@@ -942,6 +942,8 @@ svga_poll(void *priv)
|
||||
if ((svga->sc == (svga->crtc[11] & 31)) || (svga->sc == svga->rowcount))
|
||||
svga->con = 0;
|
||||
if (svga->dispon) {
|
||||
/* TODO: Verify real hardware behaviour for out-of-range fine vertical scroll
|
||||
- S3 Trio64V2/DX: sc == rowcount, wrapping 5-bit counter. */
|
||||
if (svga->linedbl && !svga->linecountff) {
|
||||
svga->linecountff = 1;
|
||||
svga->ma = svga->maback;
|
||||
@@ -1065,7 +1067,7 @@ svga_poll(void *priv)
|
||||
}
|
||||
if (svga->vc == svga->vtotal) {
|
||||
svga->vc = 0;
|
||||
svga->sc = 0;
|
||||
svga->sc = (svga->crtc[0x8] & 0x1f);
|
||||
svga->dispon = 1;
|
||||
svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0;
|
||||
|
||||
@@ -1642,7 +1644,7 @@ svga_doblit(int wx, int wy, svga_t *svga)
|
||||
x_add = enable_overscan ? svga->monitor->mon_overscan_x : 0;
|
||||
y_start = enable_overscan ? 0 : (svga->monitor->mon_overscan_y >> 1);
|
||||
x_start = enable_overscan ? 0 : (svga->monitor->mon_overscan_x >> 1);
|
||||
bottom = (svga->monitor->mon_overscan_y >> 1) + (svga->crtc[8] & 0x1f);
|
||||
bottom = (svga->monitor->mon_overscan_y >> 1);
|
||||
|
||||
if (svga->vertical_linedbl) {
|
||||
y_add <<= 1;
|
||||
|
||||
@@ -601,8 +601,27 @@ cgapal_rebuild_monitor(int monitor_index)
|
||||
}
|
||||
}
|
||||
|
||||
if (cga_palette_monitor == 7)
|
||||
if (cga_palette_monitor == 8)
|
||||
palette_lookup[0x16] = makecol(video_6to8[42], video_6to8[42], video_6to8[0]);
|
||||
else if (cga_palette_monitor == 10) {
|
||||
/* IBM 5153 CRT, colors by VileR */
|
||||
palette_lookup[0x10] = 0x00000000;
|
||||
palette_lookup[0x11] = 0x000000c4;
|
||||
palette_lookup[0x12] = 0x0000c400;
|
||||
palette_lookup[0x13] = 0x0000c4c4;
|
||||
palette_lookup[0x14] = 0x00c40000;
|
||||
palette_lookup[0x15] = 0x00c400c4;
|
||||
palette_lookup[0x16] = 0x00c47e00;
|
||||
palette_lookup[0x17] = 0x00c4c4c4;
|
||||
palette_lookup[0x18] = 0x004e4e4e;
|
||||
palette_lookup[0x19] = 0x004e4edc;
|
||||
palette_lookup[0x1a] = 0x004edc4e;
|
||||
palette_lookup[0x1b] = 0x004ef3f3;
|
||||
palette_lookup[0x1c] = 0x00dc4e4e;
|
||||
palette_lookup[0x1d] = 0x00f34ef3;
|
||||
palette_lookup[0x1e] = 0x00f3f34e;
|
||||
palette_lookup[0x1f] = 0x00ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user