Merge remote-tracking branch 'origin/master' into gm/video-debug-device

This commit is contained in:
GreaseMonkey
2024-01-08 12:08:37 +13:00
22 changed files with 2145 additions and 1158 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -342,6 +342,8 @@ reset_common(int hard)
if (!is286)
reset_808x(hard);
cpu_cpurst_on_sr = 0;
}
/* Hard reset. */

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 = {

View File

@@ -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

View File

@@ -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);

View File

@@ -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 *);

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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,

View File

@@ -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 = ""
}

View File

@@ -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;

View File

@@ -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:

View File

@@ -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;

View File

@@ -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