Rewritten 808x CPU emulation core based on reenigne's XTCE, VisiOn, SnatchIt, and 8088 MPH now work correctly;

Fixed PC speaker sound volume in PIT mode 0;
A few CPU emulation clean-ups;
Hard disk controller changing redone in a less messy way;
Re-added the long-missing key send delay handling to the XT keyboard handler;
Fixed a bug that was causing SLiRP not to work when compiled with MingW/GCC 7.3.0-2 or newer;
Some serial mouse and port fixes;
A lot of changes to printer emulation, mostly based on DOSBox-X;
Printer PNG writer now uses statically linked libpng;
Added support for the HxC MFM floppy image format and upped 86F format version to 2.12;
Ported various things from PCem and some from VARCem;
Added the S3 86c801/805 emulation (patch from TheCollector1995);
Fixed and renamed the EGA monitor options;
Better synchronized the 808x to the PIT and the CGA;
Fixed the CGA wait state calculation;
Cleaned up some things in mem.c;
Fixed some things in the floppy emulation to make VisiOn get the correct errors from the copy protection disk;
Fixed several renderer-related bugs, including the SDL2 renderer's failure to take screenshots;
The Jenkins builds are now compiled with MingW/GCC 7.4.0-1 and include all the required DLL's.
This commit is contained in:
OBattler
2019-02-06 03:34:39 +01:00
parent c91b1f2b8e
commit 46d0ed2baa
104 changed files with 7749 additions and 6608 deletions

View File

@@ -8,7 +8,7 @@
*
* Main include file for the application.
*
* Version: @(#)86box.h 1.0.25 2018/10/02
* Version: @(#)86box.h 1.0.27 2019/01/13
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -98,7 +98,7 @@ extern int serial_enabled[], /* (C) enable serial ports */
isartc_type; /* (C) enable ISA RTC card */
extern int sound_is_float, /* (C) sound uses FP values */
GAMEBLASTER, /* (C) sound option */
GUS, /* (C) sound option */
GUS, GUSMAX, /* (C) sound option */
SSI2001, /* (C) sound option */
voodoo_enabled; /* (C) video option */
extern uint32_t mem_size; /* (C) memory size */
@@ -109,8 +109,8 @@ extern int cpu_manufacturer, /* (C) cpu manufacturer */
extern int time_sync; /* (C) enable time sync */
extern int network_type; /* (C) net provider type */
extern int network_card; /* (C) net interface num */
extern char network_host[512]; /* (C) host network intf */
extern char network_host[522]; /* (C) host network intf */
extern int hdd_format_type; /* (C) hard disk file format */
extern int is_pentium; /* TODO: Move back to cpu/cpu.h when it's figured out,
how to remove that hack from the ET4000/W32p. */

View File

@@ -10,7 +10,7 @@
# settings, so we can avoid changing the main one for all of
# our local setups.
#
# Version: @(#)Makefile.local 1.0.19 2018/10/22
# Version: @(#)Makefile.local 1.0.20 2018/11/18
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
#
@@ -133,6 +133,7 @@ STUFF :=
# -DENABLE_DYNLD_LOG=N sets logging level at N.
# -DENABLE_JOYSTICK_LOG=N sets logging level at N.
# -DENABLE_SDL_LOG=N sets logging level at N.
# -DENABLE_SETTINGS_LOG=N sets logging level at N.
# -DENABLE_WIN_LOG=N sets logging level at N.
EXTRAS :=

View File

@@ -8,7 +8,7 @@
*
* CD-ROM image support.
*
* Version: @(#)cdrom_image.cc 1.0.7 2018/10/28
* Version: @(#)cdrom_image.cc 1.0.9 2019/02/01
*
* Author: RichardG867,
* Miran Grca, <mgrca8@gmail.com>
@@ -292,6 +292,6 @@ cdrom_image_close(cdrom_t *dev)
{
cdrom_image_log("CDROM: image_close(%ls)\n", dev->image_path);
if (dev->ops->exit)
if (dev && dev->ops && dev->ops->exit)
dev->ops->exit(dev);
}

View File

@@ -8,7 +8,7 @@
*
* Configuration file handler.
*
* Version: @(#)config.c 1.0.58 2018/10/17
* Version: @(#)config.c 1.0.60 2019/01/13
*
* Authors: Sarah Walker,
* Miran Grca, <mgrca8@gmail.com>
@@ -208,7 +208,7 @@ create_section(char *name)
section_t *ns = malloc(sizeof(section_t));
memset(ns, 0x00, sizeof(section_t));
strncpy(ns->name, name, sizeof(ns->name));
memcpy(ns->name, name, strlen(name) + 1);
list_add(&ns->list, &config_head);
return(ns);
@@ -221,7 +221,7 @@ create_entry(section_t *section, char *name)
entry_t *ne = malloc(sizeof(entry_t));
memset(ne, 0x00, sizeof(entry_t));
strncpy(ne->name, name, sizeof(ne->name));
memcpy(ne->name, name, strlen(name) + 1);
list_add(&ne->list, &section->entry_head);
return(ne);
@@ -652,7 +652,7 @@ load_sound(void)
SSI2001 = !!config_get_int(cat, "ssi2001", 0);
GAMEBLASTER = !!config_get_int(cat, "gameblaster", 0);
GUS = !!config_get_int(cat, "gus", 0);
memset(temp, '\0', sizeof(temp));
p = config_get_string(cat, "opl_type", "dbopl");
strcpy(temp, p);
@@ -766,29 +766,17 @@ load_other_peripherals(void)
else
scsi_card_current = 0;
if (hdc_name) {
free(hdc_name);
hdc_name = NULL;
}
p = config_get_string(cat, "hdc", NULL);
if (p == NULL) {
p = config_get_string(cat, "hdd_controller", NULL);
if (p != NULL)
config_delete_var(cat, "hdd_controller");
}
if (p == NULL) {
if (machines[machine].flags & MACHINE_HDC) {
hdc_name = (char *) malloc((strlen("internal") + 1) * sizeof(char));
strcpy(hdc_name, "internal");
p = (char *)malloc((strlen("internal")+1)*sizeof(char));
strcpy(p, "internal");
} else {
hdc_name = (char *) malloc((strlen("none") + 1) * sizeof(char));
strcpy(hdc_name, "none");
p = (char *)malloc((strlen("none")+1)*sizeof(char));
strcpy(p, "none");
}
} else {
hdc_name = (char *) malloc((strlen(p) + 1) * sizeof(char));
strcpy(hdc_name, p);
}
config_set_string(cat, "hdc", hdc_name);
hdc_current = hdc_get_from_internal_name(p);
ide_ter_enabled = !!config_get_int(cat, "ide_ter", 0);
ide_qua_enabled = !!config_get_int(cat, "ide_qua", 0);
@@ -1249,12 +1237,7 @@ config_load(void)
vid_api = plat_vidapi("default");
time_sync = TIME_SYNC_ENABLED;
joystick_type = 7;
if (hdc_name) {
free(hdc_name);
hdc_name = NULL;
}
hdc_name = (char *) malloc((strlen("none")+1) * sizeof(char));
strcpy(hdc_name, "none");
hdc_current = hdc_get_from_internal_name("none");
serial_enabled[0] = 1;
serial_enabled[1] = 1;
lpt_enabled = 1;
@@ -1652,7 +1635,8 @@ save_other_peripherals(void)
config_set_string(cat, "scsicard",
scsi_card_get_internal_name(scsi_card_current));
config_set_string(cat, "hdc", hdc_name);
config_set_string(cat, "hdc",
hdc_get_internal_name(hdc_current));
if (ide_ter_enabled == 0)
config_delete_var(cat, "ide_ter");
@@ -2170,7 +2154,7 @@ config_set_string(char *head, char *name, char *val)
if (ent == NULL)
ent = create_entry(section, name);
strncpy(ent->data, val, sizeof(ent->data));
memcpy(ent->data, val, sizeof(ent->data));
mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata));
}

View File

@@ -27,53 +27,33 @@
extern int codegen_flags_changed;
extern int nmi_enable;
int cpl_override = 0, fpucount = 0;
int tempc, oldcpl, optype, inttype, oddeven = 0;
int use32, stack32;
int inscounts[256];
uint32_t oldpc2;
uint16_t flags, eflags;
uint16_t rds, ea_rseg;
uint16_t oldcs;
int trap;
uint16_t flags,eflags;
uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw;
uint32_t oldds, oldss, olddslimit, oldsslimit,
olddslimitw, oldsslimitw;
uint32_t *eal_r, *eal_w;
uint32_t oxpc, cr2, cr3, cr4;
uint32_t dr[8];
uint32_t rmdat32;
uint32_t backupregs[16];
x86seg gdt,ldt,idt,tr;
x86seg _cs,_ds,_es,_ss,_fs,_gs;
x86seg _oldds;
extern int cpl_override;
extern int fpucount;
uint16_t rds;
uint16_t ea_rseg;
int cgate32;
uint32_t cr2, cr3, cr4;
uint32_t dr[8];
uint32_t rmdat32;
#define rmdat rmdat32
#define fetchdat rmdat32
uint32_t backupregs[16];
extern int oddeven;
int inttype;
uint32_t oldcs2;
uint32_t oldecx;
uint32_t *eal_r, *eal_w;
uint16_t *mod1add[2][8];
uint32_t *mod1seg[8];
#define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 0; }
#define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 0
#include "x86_flags.h"
#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++
@@ -149,11 +129,6 @@ void exec386(int cycs)
timer_start_period(cycles << TIMER_SHIFT);
while (cycdiff < cycle_period)
{
/* testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX;
testr[4]=ESI; testr[5]=EDI; testr[6]=EBP; testr[7]=ESP;*/
/* testr[8]=flags;*/
/* oldcs2=oldcs; */
/* oldpc2=oldpc; */
oldcs=CS;
cpu_state.oldpc = cpu_state.pc;
oldcpl=CPL;

View File

@@ -34,43 +34,10 @@ uint32_t cpu_cur_status = 0;
int cpu_reps, cpu_reps_latched;
int cpu_notreps, cpu_notreps_latched;
int inrecomp = 0;
int inrecomp = 0, cpu_block_end = 0;
int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks;
int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched;
int cpu_block_end = 0;
int nmi_enable = 1;
int inscounts[256];
uint32_t oldpc2;
int trap;
int cpl_override=0;
int fpucount=0;
uint16_t rds;
uint16_t ea_rseg;
int cgate32;
uint32_t rmdat32;
uint32_t backupregs[16];
int oddeven=0;
int inttype;
uint32_t oldcs2;
uint32_t oldecx;
uint32_t *eal_r, *eal_w;
uint16_t *mod1add[2][8];
uint32_t *mod1seg[8];
#ifdef ENABLE_386_DYNAREC_LOG
int x386_dynarec_do_log = ENABLE_386_DYNAREC_LOG;#endif

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
*
* CPU type handler.
*
* Version: @(#)cpu.h 1.0.12 2018/10/02
* Version: @(#)cpu.h 1.0.13 2018/11/14
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* leilei,
@@ -442,7 +442,6 @@ extern void codegen_block_end(void);
extern void codegen_reset(void);
extern void cpu_set_edx(void);
extern int divl(uint32_t val);
extern void dumpregs(int __force);
extern void execx86(int cycs);
extern void exec386(int cycs);
extern void exec386_dynarec(int cycs);
@@ -463,8 +462,12 @@ extern void x86gpf(char *s, uint16_t error);
extern void x86np(char *s, uint16_t error);
extern void x86ss(char *s, uint16_t error);
extern void x86ts(char *s, uint16_t error);
#ifdef ENABLE_808X_LOG
extern void dumpregs(int __force);
extern void x87_dumpregs(void);
extern void x87_reset(void);
#endif
extern int cpu_effective;
extern void cpu_dynamic_switch(int new_cpu);

View File

@@ -53,7 +53,7 @@
CPU cpus_8088[] = {
/*8088 standard*/
{"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/7.16", CPU_8088, 1, 7159092, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0}
};
@@ -67,16 +67,16 @@ CPU cpus_pcjr[] = {
CPU cpus_europc[] = {
/*8088 EuroPC*/
{"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/9.54", CPU_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/7.16", CPU_8088, 1, 7159092, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/9.54", CPU_8088, 1, 9545456, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0}
};
CPU cpus_8086[] = {
/*8086 standard*/
{"8086/7.16", CPU_8086, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/7.16", CPU_8086, 1, 7159092, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/9.54", CPU_8086, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/9.54", CPU_8086, 1, 9545456, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/10", CPU_8086, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0}
};

View File

@@ -1,23 +1,28 @@
uint16_t oldcs;
extern uint32_t rmdat32;
int oldcpl;
extern uint8_t opcode, opcode2;
extern uint8_t flags_p;
extern uint8_t znptable8[256];
extern int nmi_enable;
extern uint16_t zero, oldcs;
extern uint16_t lastcs, lastpc;
extern uint16_t rds, ea_rseg;
extern uint16_t znptable16[65536];
extern uint16_t *mod1add[2][8];
int tempc;
int output;
int firstrepcycle;
extern int x86_was_reset, codegen_flat_ds;
extern int codegen_flat_ss, nmi_enable;
extern int timetolive, keyboardtimer, trap;
extern int tempc, optype, use32, stack32;
extern int oldcpl, cgate32, cpl_override, fpucount;
extern int gpf, nmi_enable;
extern int oddeven, inttype;
uint32_t easeg,ealimit,ealimitw;
extern uint32_t rmdat32, easeg;
extern uint32_t oxpc, flags_zn;
extern uint32_t abrt_error;
extern uint32_t backupregs[16];
extern uint32_t *mod1seg[8];
extern uint32_t *eal_r, *eal_w;
int skipnextprint;
int inhlt;
uint8_t opcode;
int noint;
uint16_t lastcs,lastpc;
extern int timetolive,keyboardtimer;
#define setznp168 setznp16
@@ -30,47 +35,25 @@ extern int timetolive,keyboardtimer;
#define setr16(r,v) cpu_state.regs[r].w=v
#define setr32(r,v) cpu_state.regs[r].l=v
uint8_t znptable8[256];
uint16_t znptable16[65536];
#define fetchea() { \
rmdat = readmemb(cs + pc); \
pc++; \
reg = (rmdat >> 3) & 7; \
mod = (rmdat >> 6) & 3; \
rm = rmdat & 7; \
if (mod!=3) \
fetcheal(); \
}
int use32;
int stack32;
#define fetchea() { rmdat=readmemb(cs+pc); pc++; \
reg=(rmdat>>3)&7; \
mod=(rmdat>>6)&3; \
rm=rmdat&7; \
if (mod!=3) fetcheal(); }
int optype;
#define JMP 1
#define CALL 2
#define IRET 3
#define OPTYPE_INT 4
uint32_t oxpc;
extern uint16_t *mod1add[2][8];
extern uint32_t *mod1seg[8];
#define IRQTEST ((flags&I_FLAG) && (pic.pend&~pic.mask) && !noint)
extern int cgate32;
extern uint32_t *eal_r, *eal_w;
extern uint32_t flags_zn;
extern uint8_t flags_p;
#define FLAG_N (flags_zn>>31)
#define FLAG_Z (flags_zn)
#define FLAG_P (znptable8[flags_p]&P_FLAG)
extern int gpf;
enum
{
@@ -83,25 +66,8 @@ enum
ABRT_PF = 0xE
};
extern uint32_t abrt_error;
void x86_doabrt(int x86_abrt);
extern uint8_t opcode2;
extern uint16_t rds;
extern uint32_t rmdat32;
extern int inscounts[256];
void x86illegal();
void x86seg_reset();
void x86gpf(char *s, uint16_t error);
extern uint16_t zero;
extern int x86_was_reset;
extern int codegen_flat_ds;
extern int codegen_flat_ss;
extern void x86_doabrt(int x86_abrt);
extern void x86illegal();
extern void x86seg_reset();
extern void x86gpf(char *s, uint16_t error);

View File

@@ -8,7 +8,7 @@
*
* x86 CPU segment emulation.
*
* Version: @(#)x86seg.c 1.0.8 2018/10/17
* Version: @(#)x86seg.c 1.0.9 2018/11/14
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -46,7 +46,7 @@ int dtimes = 0;
int btimes = 0;
uint32_t abrt_error;
int cgate16,cgate32;
int cgate16, cgate32;
#define breaknullsegs 0
@@ -55,7 +55,6 @@ int intgatesize;
void taskswitch286(uint16_t seg, uint16_t *segdat, int is32);
void taskswitch386(uint16_t seg, uint16_t *segdat);
int output;
void pmodeint(int num, int soft);
/*NOT PRESENT is INT 0B
GPF is INT 0D*/
@@ -89,7 +88,9 @@ void x86abort(const char *format, ...)
va_end(ap);
fflush(stdlog);
nvr_save();
#ifdef ENABLE_808X_LOG
dumpregs(1);
#endif
fflush(stdlog);
exit(-1);
}

View File

@@ -65,6 +65,7 @@ void x87_settag(uint16_t new_tag)
cpu_state.tag[7] = (new_tag >> 14) & 3;
}
#ifdef ENABLE_808X_LOG
void x87_dumpregs()
{
if (cpu_state.ismmx)
@@ -79,21 +80,4 @@ void x87_dumpregs()
}
fpu_log("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag());
}
void x87_print()
{
if (cpu_state.ismmx)
{
fpu_log("\tMM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\t", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q);
fpu_log("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q);
}
else
{
fpu_log("\tST(0)=%.20f\tST(1)=%.20f\tST(2)=%f\tST(3)=%f\t",cpu_state.ST[cpu_state.TOP&7],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]);
fpu_log("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\tTOP=%i CR=%04X SR=%04X TAG=%04X\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7], cpu_state.TOP, cpu_state.npxc, cpu_state.npxs, x87_gettag());
}
}
void x87_reset()
{
}
#endif

View File

@@ -8,7 +8,7 @@
*
* Definitions for the device handler.
*
* Version: @(#)device.h 1.0.10 2018/10/23
* Version: @(#)device.h 1.0.11 2018/11/12
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -54,15 +54,16 @@
enum {
DEVICE_NOT_WORKING = 1, /* does not currently work correctly and will be disabled in a release build */
DEVICE_AT = 2, /* requires an AT-compatible system */
DEVICE_PS2 = 4, /* requires a PS/1 or PS/2 system */
DEVICE_ISA = 8, /* requires the ISA bus */
DEVICE_CBUS = 0x10, /* requires the C-BUS bus */
DEVICE_MCA = 0x20, /* requires the MCA bus */
DEVICE_EISA = 0x40, /* requires the EISA bus */
DEVICE_VLB = 0x80, /* requires the PCI bus */
DEVICE_PCI = 0x100, /* requires the VLB bus */
DEVICE_AGP = 0x200 /* requires the AGP bus */
DEVICE_PCJR = 2, /* requires an IBM PCjr */
DEVICE_AT = 4, /* requires an AT-compatible system */
DEVICE_PS2 = 8, /* requires a PS/1 or PS/2 system */
DEVICE_ISA = 0x10, /* requires the ISA bus */
DEVICE_CBUS = 0x20, /* requires the C-BUS bus */
DEVICE_MCA = 0x40, /* requires the MCA bus */
DEVICE_EISA = 0x80, /* requires the EISA bus */
DEVICE_VLB = 0x100, /* requires the PCI bus */
DEVICE_PCI = 0x200, /* requires the VLB bus */
DEVICE_AGP = 0x400 /* requires the AGP bus */
};

View File

@@ -8,7 +8,7 @@
*
* Common code to handle all sorts of disk controllers.
*
* Version: @(#)hdc.c 1.0.16 2018/10/17
* Version: @(#)hdc.c 1.0.17 2018/11/18
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -30,7 +30,6 @@
#include "hdd.h"
char *hdc_name; /* configured HDC name */
int hdc_current;
@@ -160,19 +159,10 @@ static const struct {
/* Initialize the 'hdc_current' value based on configured HDC name. */
void
hdc_init(char *name)
hdc_init(void)
{
int c;
hdc_log("HDC: initializing..\n");
for (c = 0; controllers[c].device; c++) {
if (! strcmp(name, (char *) controllers[c].internal_name)) {
hdc_current = c;
break;
}
}
/* Zero all the hard disk image arrays. */
hdd_image_init();
}
@@ -211,6 +201,22 @@ hdc_get_internal_name(int hdc)
}
int
hdc_get_id(char *s)
{
int c = 0;
while (strlen((char *) controllers[c].name))
{
if (!strcmp((char *) controllers[c].name, s))
return c;
c++;
}
return 0;
}
int
hdc_get_from_internal_name(char *s)
{

View File

@@ -8,7 +8,7 @@
*
* Definitions for the common disk controller handler.
*
* Version: @(#)hdc.h 1.0.9 2018/09/24
* Version: @(#)hdc.h 1.0.10 2018/11/18
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -28,7 +28,6 @@
* least 7 devices, with each device being
* able to support 8 units, but hey... */
extern char *hdc_name;
extern int hdc_current;
@@ -59,11 +58,12 @@ extern const device_t xtide_acculogic_device; /* xtide_ps2 */
extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */
extern void hdc_init(char *name);
extern void hdc_init(void);
extern void hdc_reset(void);
extern char *hdc_get_name(int hdc);
extern char *hdc_get_internal_name(int hdc);
extern int hdc_get_id(char *s);
extern int hdc_get_from_internal_name(char *s);
extern int hdc_has_config(int hdc);
extern const device_t *hdc_get_device(int hdc);

View File

@@ -8,7 +8,7 @@
*
* Implementation of the Intel DMA controllers.
*
* Version: @(#)dma.c 1.0.3 2018/03/13
* Version: @(#)dma.c 1.0.4 2018/11/18
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -625,7 +625,7 @@ ps2_dma_init(void)
uint8_t
_dma_read(uint32_t addr)
{
uint8_t temp = mem_readb_phys_dma(addr);
uint8_t temp = mem_readb_phys(addr);
return(temp);
}
@@ -634,7 +634,7 @@ _dma_read(uint32_t addr)
void
_dma_write(uint32_t addr, uint8_t val)
{
mem_writeb_phys_dma(addr, val);
mem_writeb_phys(addr, val);
mem_invalidate_range(addr, addr);
}
@@ -654,14 +654,14 @@ dma_channel_read(int channel)
return(DMA_NODATA);
}
if (! AT)
refreshread();
if (dma_m & (1 << channel))
return(DMA_NODATA);
if ((dma_c->mode & 0xC) != 8)
return(DMA_NODATA);
if ((!AT) && !channel)
refreshread();
if (! dma_c->size) {
temp = _dma_read(dma_c->ac);
@@ -725,14 +725,14 @@ dma_channel_write(int channel, uint16_t val)
return(DMA_NODATA);
}
if (! AT)
refreshread();
if (dma_m & (1 << channel))
return(DMA_NODATA);
if ((dma_c->mode & 0xC) != 4)
return(DMA_NODATA);
if ((!AT) && !channel)
refreshread();
if (! dma_c->size) {
_dma_write(dma_c->ac, val & 0xff);
@@ -895,7 +895,7 @@ DMAPageRead(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize)
memcpy(DataRead, &ram[PhysAddress], TotalSize);
#else
for (i = 0; i < TotalSize; i++)
DataRead[i] = mem_readb_phys_dma(PhysAddress + i);
DataRead[i] = mem_readb_phys(PhysAddress + i);
#endif
}
@@ -910,7 +910,7 @@ DMAPageWrite(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize)
memcpy(&ram[PhysAddress], DataWrite, TotalSize);
#else
for (i = 0; i < TotalSize; i++)
mem_writeb_phys_dma(PhysAddress + i, DataWrite[i]);
mem_writeb_phys(PhysAddress + i, DataWrite[i]);
mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1);
#endif

View File

@@ -9,7 +9,7 @@
* Implementation of the NEC uPD-765 and compatible floppy disk
* controller.
*
* Version: @(#)fdc.c 1.0.12 2018/10/18
* Version: @(#)fdc.c 1.0.15 2019/01/26
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
@@ -156,7 +156,7 @@ fdc_ctrl_reset(void *p)
fdc->head = 0;
fdc->abort = 0;
fdc->step = 0;
if (!(fdc->flags & FDC_FLAG_AT))
if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PS1))
fdc->rate = 2;
}
@@ -383,20 +383,6 @@ fdc_update_rates(fdc_t *fdc)
}
void
fdc_update_is_nsc(fdc_t *fdc, int is_nsc)
{
int old_is_nsc = fdc->flags & FDC_FLAG_NSC;
if (is_nsc)
fdc->flags |= FDC_FLAG_NSC;
else
fdc->flags &= ~FDC_FLAG_NSC;
if ((old_is_nsc ^ fdc->flags) & FDC_FLAG_NSC)
fdc->densel_force = fdc->densel_force ^ 3;
fdc_update_rates(fdc);
}
void
fdc_update_max_track(fdc_t *fdc, int max_track)
{
@@ -613,7 +599,7 @@ void
fdc_seek(fdc_t *fdc, int drive, int params)
{
fdd_seek(real_drive(fdc, drive), params);
fdc->time = 5000LL * (1 << TIMER_SHIFT);
fdc->time = 2048LL * (1 << TIMER_SHIFT);
fdc->stat |= (1 << fdc->drive);
}
@@ -636,7 +622,7 @@ fdc_bad_command(fdc_t *fdc)
{
fdc->stat = 0x10;
fdc->interrupt = 0xfc;
timer_clock();
timer_process();
fdc->time = 200LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
}
@@ -713,6 +699,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc_log("Write FDC %04X %02X\n", addr, val);
cycles -= ISA_CYCLES(8);
// pclog("fdc_write(): cycles -= ISA_CYCLES(8);\n");
switch (addr&7) {
case 0:
@@ -727,7 +714,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
picintc(1 << fdc->irq);
}
if ((val & 0x80) && !(fdc->dor & 0x80)) {
timer_clock();
timer_process();
fdc->time = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc->interrupt = -1;
@@ -758,7 +745,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc->pnum = fdc->ptot = 0;
}
if ((val&4) && !(fdc->dor&4)) {
timer_clock();
timer_process();
fdc->time = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc->interrupt = -1;
@@ -769,7 +756,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc_ctrl_reset(fdc);
}
timer_clock();
timer_process();
timer_update_outstanding();
/* We can now simplify this since each motor now spins separately. */
for (i = 0; i < FDD_NUM; i++) {
@@ -795,15 +782,13 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
return;
case 4:
if (val & 0x80) {
timer_clock();
timer_process();
fdc->time = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc->interrupt = -1;
fdc->perp &= 0xfc;
fdc_ctrl_reset(fdc);
}
/* if (fdc->flags & FDC_FLAG_PS1)
fdc->rate = val & 0x03; */
return;
case 5: /*Command register*/
if ((fdc->stat & 0xf0) == 0xb0) {
@@ -981,7 +966,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
if (fdc->pnum==fdc->ptot) {
fdc_log("Got all params %02X\n", fdc->command);
fdc->interrupt = fdc->command & 0x1F;
timer_clock();
timer_process();
fdc->time = 1024LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc->reset_stat = 0;
@@ -1073,7 +1058,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc->st0 = 0x20 | (fdc->params[0] & 3);
fdc->pcn[fdc->params[0] & 3] = 0;
fdc->interrupt = -3;
timer_clock();
timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
@@ -1081,8 +1066,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en)
fdc_seek(fdc, fdc->drive, -fdc->max_track);
fdc_log("Recalibrating...\n");
fdc->time = 5000LL * (1 << TIMER_SHIFT);
fdc->step = fdc->seek_dir = 1;
fdc->time = 2048LL * (1 << TIMER_SHIFT);
fdc->seek_dir = fdc->step = 1;
break;
case 0x0d: /*Format*/
fdc_rate(fdc, fdc->drive);
@@ -1117,7 +1102,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
} else
fdc->pcn[fdc->params[0] & 3] = fdc->params[1];
fdc->interrupt = -3;
timer_clock();
timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
@@ -1135,12 +1120,12 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc_seek(fdc, fdc->drive, -fdc->params[1]);
fdc->pcn[fdc->params[0] & 3] -= fdc->params[1];
}
fdc->time = 5000LL * (1 << TIMER_SHIFT);
fdc->time = 2048LL * (1 << TIMER_SHIFT);
fdc->step = 1;
} else {
fdc->st0 = 0x20 | (fdc->params[0] & 7);
fdc->interrupt = -3;
timer_clock();
timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
@@ -1151,7 +1136,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc_log("Failed seek\n");
fdc->st0 = 0x20 | (fdc->params[0] & 7);
fdc->interrupt = -3;
timer_clock();
timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
@@ -1162,7 +1147,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc->seek_dir = 1;
fdc_seek(fdc, fdc->drive, fdc->params[1] - fdc->pcn[fdc->params[0] & 3]);
fdc->pcn[fdc->params[0] & 3] = fdc->params[1];
fdc->time = 5000LL * (1 << TIMER_SHIFT);
fdc->time = 2048LL * (1 << TIMER_SHIFT);
fdc->step = 1;
fdc_log("fdc->time = %i\n", fdc->time);
}
@@ -1206,8 +1191,9 @@ fdc_read(uint16_t addr, void *priv)
int drive;
cycles -= ISA_CYCLES(8);
// pclog("fdc_read(): cycles -= ISA_CYCLES(8);\n");
switch (addr&7) {
switch (addr & 7) {
case 0: /* STA */
if (fdc->flags & FDC_FLAG_PS1) {
drive = real_drive(fdc, fdc->dor & 3);
@@ -1216,9 +1202,9 @@ fdc_read(uint16_t addr, void *priv)
Bit 2: INDEX (best return always 0 as it goes by very fast)
Bit 6: DRQ
*/
if (writeprot[drive]) /* WRITEPROT */
ret |= 0x01;
if (fdc->seek_dir) /* nDIRECTION */
ret |= 0x01;
if (writeprot[drive]) /* WRITEPROT */
ret |= 0x02;
if (!fdd_get_head(drive)) /* nHDSEL */
ret |= 0x08;
@@ -1239,10 +1225,20 @@ fdc_read(uint16_t addr, void *priv)
if (!fdd_get_type(1))
ret |= 80;
/* -Drive Select 1,0 */
if (drive)
ret |= 0x20;
else
ret |= 0x40;
switch (drive) {
case 0:
ret |= 0x43;
break;
case 1:
ret |= 0x23;
break;
case 2:
ret |= 0x62;
break;
case 3:
ret |= 0x61;
break;
}
} else {
if (is486)
return 0xff;
@@ -1326,6 +1322,7 @@ fdc_read(uint16_t addr, void *priv)
drive = real_drive(fdc, fdc->dor & 3);
if (fdc->flags & FDC_FLAG_PS1) {
fdc->step = 0;
if (fdc->dor & (0x10 << drive)) {
ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x00 : 0x80;
ret |= (fdc->dor & 0x08);
@@ -1613,7 +1610,7 @@ fdc_callback(void *priv)
if (!fdd_track0(drive_num))
fdc->st0 |= 0x50;
fdc->interrupt = -3;
timer_clock();
timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc->stat = 0x80 | (1 << fdc->drive);
@@ -1621,7 +1618,7 @@ fdc_callback(void *priv)
case 0x0d: /*Format track*/
if (fdc->format_state == 1) {
fdc->format_state = 2;
timer_clock();
timer_process();
fdc->time = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
} else if (fdc->format_state == 2) {
@@ -1664,7 +1661,7 @@ fdc_callback(void *priv)
drive_num = real_drive(fdc, fdc->rw_drive);
fdc->st0 = 0x20 | (fdc->params[0] & 7);
fdc->interrupt = -3;
/* timer_clock();
/* timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding(); */
fdc->stat = 0x80 | (1 << fdc->drive);
@@ -2083,13 +2080,15 @@ fdc_reset(void *priv)
fdc->enable_3f1 = 1;
fdc_update_is_nsc(fdc, 0);
fdc_update_enh_mode(fdc, 0);
if (fdc->flags & FDC_FLAG_PS1)
fdc_update_densel_polarity(fdc, 0);
else
fdc_update_densel_polarity(fdc, 1);
fdc_update_densel_force(fdc, 0);
if (fdc->flags & FDC_FLAG_NSC)
fdc_update_densel_force(fdc, 3);
else
fdc_update_densel_force(fdc, 0);
fdc_update_rwc(fdc, 0, default_rwc);
fdc_update_rwc(fdc, 1, default_rwc);
fdc_update_rwc(fdc, 2, default_rwc);
@@ -2099,6 +2098,7 @@ fdc_reset(void *priv)
fdc_update_drvrate(fdc, 2, 0);
fdc_update_drvrate(fdc, 3, 0);
fdc_update_drv2en(fdc, 1);
fdc_update_rates(fdc);
fdc->fifo = 0;
fdc->tfifo = 1;
@@ -2172,6 +2172,7 @@ fdc_init(const device_t *info)
fdd_set_fdc(fdc);
imd_set_fdc(fdc);
img_set_fdc(fdc);
mfm_set_fdc(fdc);
fdc_reset(fdc);

View File

@@ -8,7 +8,7 @@
*
* Implementation of the floppy drive emulation.
*
* Version: @(#)fdd.c 1.0.12 2018/10/18
* Version: @(#)fdd.c 1.0.13 2018/11/12
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -52,6 +52,7 @@
#include "fdd_imd.h"
#include "fdd_img.h"
#include "fdd_json.h"
#include "fdd_mfm.h"
#include "fdd_td0.h"
#include "fdc.h"
@@ -122,6 +123,7 @@ static const struct
{L"IMD", imd_load, imd_close, -1},
{L"IMG", img_load, img_close, -1},
{L"JSON", json_load, json_close, -1},
{L"MFM", mfm_load, mfm_close, -1},
{L"TD0", td0_load, td0_close, -1},
{L"VFD", img_load, img_close, -1},
{L"XDF", img_load, img_close, -1},
@@ -464,14 +466,7 @@ int fdd_get_check_bpb(int drive)
int fdd_get_densel(int drive)
{
if (drive_types[fdd[drive].type].flags & FLAG_INVERT_DENSEL)
{
return fdd[drive].densel ^ 1;
}
else
{
return fdd[drive].densel;
}
return fdd[drive].densel;
}
void fdd_load(int drive, wchar_t *fn)

View File

@@ -8,7 +8,7 @@
*
* Definitions for the floppy drive emulation.
*
* Version: @(#)fdd.h 1.0.4 2018/04/12
* Version: @(#)fdd.h 1.0.5 2018/11/12
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -254,6 +254,7 @@ void fdi_set_fdc(void *fdc);
void fdd_set_fdc(void *fdc);
void imd_set_fdc(void *fdc);
void img_set_fdc(void *fdc);
void mfm_set_fdc(void *fdc);
#ifdef __cplusplus

View File

@@ -10,7 +10,7 @@
* data in the form of FM/MFM-encoded transitions) which also
* forms the core of the emulator's floppy disk emulation.
*
* Version: @(#)fdd_86f.c 1.0.16 2018/10/17
* Version: @(#)fdd_86f.c 1.0.17 2018/11/12
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -190,6 +190,10 @@ typedef struct {
* Bits 10, 9 Zone type (3 = Commodore 64 zoned, 2 = Apple zoned,
* 1 = Pre-Apple zoned #2, 0 = Pre-Apple zoned #1)
* Bit 11 Data and surface bits are stored in reverse byte endianness
* Bit 12 If bits 6, 5 are not 0, they specify % of speedup instead
* of slowdown;
* If bits 6, 5 are 0, and bit 7 is 1, the extra bitcell count
* specifies the entire bitcell count
*/
typedef struct {
FILE *f;
@@ -360,6 +364,14 @@ d86f_get_rpm_mode(int drive)
return (d86f_handler[drive].disk_flags(drive) & 0x60) >> 5;
}
int
d86f_get_speed_shift_dir(int drive)
{
return (d86f_handler[drive].disk_flags(drive) & 0x1000) >> 12;
}
int
d86f_reverse_bytes(int drive)
{
@@ -521,12 +533,15 @@ common_get_raw_size(int drive, int side)
double rpm, rpm_diff;
double size = 100000.0;
int mfm;
int rm, ssd;
mfm = d86f_is_mfm(drive);
rpm = ((d86f_track_flags(drive) & 0xE0) == 0x20) ? 360.0 : 300.0;
rpm_diff = 1.0;
rm = d86f_get_rpm_mode(drive);
ssd = d86f_get_speed_shift_dir(drive);
switch (d86f_get_rpm_mode(drive)) {
switch (rm) {
case 1:
rpm_diff = 1.01;
break;
@@ -544,6 +559,9 @@ common_get_raw_size(int drive, int side)
break;
}
if (ssd)
rpm_diff = 1.0 / rpm_diff;
switch (d86f_track_flags(drive) & 7) {
case 0:
rate = 500.0;
@@ -572,9 +590,13 @@ common_get_raw_size(int drive, int side)
if (! mfm) rate /= 2.0;
size = (size / 250.0) * rate;
size = (size * 300.0) / rpm;
size *= rpm_diff;
if (!rm && ssd)
size = 0.0;
else {
size = (size / 250.0) * rate;
size = (size * 300.0) / rpm;
size *= rpm_diff;
}
/*
* Round down to a multiple of 16 and add the extra bit cells,
@@ -640,25 +662,30 @@ d86f_get_array_size(int drive, int side)
{
int array_size;
int hole, rm;
int ssd;
rm = d86f_get_rpm_mode(drive);
ssd = d86f_get_speed_shift_dir(drive);
hole = (d86f_handler[drive].disk_flags(drive) & 6) >> 1;
switch (hole) {
if (!rm && ssd) /* Special case - extra bit cells size specifies entire array size. */
array_size = 0;
else switch (hole) {
case 0:
case 1:
default:
array_size = 12500;
switch (rm) {
case 1:
array_size = 12625;
array_size = ssd ? 12376 : 12625;
break;
case 2:
array_size = 12687;
array_size = ssd ? 12315 : 12687;
break;
case 3:
array_size = 12750;
array_size = ssd ? 12254 : 12750;
break;
default:
@@ -670,15 +697,15 @@ d86f_get_array_size(int drive, int side)
array_size = 25000;
switch (rm) {
case 1:
array_size = 25250;
array_size = ssd ? 24752 : 25250;
break;
case 2:
array_size = 25375;
array_size = ssd ? 24630 : 25375;
break;
case 3:
array_size = 25500;
array_size = ssd ? 24509 : 25500;
break;
default:
@@ -690,15 +717,15 @@ d86f_get_array_size(int drive, int side)
array_size = 50000;
switch (rm) {
case 1:
array_size = 50500;
array_size = ssd ? 49504 : 50500;
break;
case 2:
array_size = 50750;
array_size = ssd ? 49261 : 50750;
break;
case 3:
array_size = 51000;
array_size = ssd ? 49019 : 51000;
break;
default:
@@ -1099,23 +1126,16 @@ d86f_get_bit(int drive, int side)
if (d86f_has_surface_desc(drive) && dev->track_surface_data && dev->track_surface_data[side]) {
surface_bit = (surface_data >> track_bit) & 1;
if (! surface_bit) {
if (! current_bit) {
/* Bit is 0 and is not set to fuzzy, we add it as read. */
dev->last_word[side] |= 1;
} else {
/* Bit is 1 and is not set to fuzzy, we add it as read. */
dev->last_word[side] |= 1;
}
} else {
if (! surface_bit)
dev->last_word[side] |= current_bit;
else {
if (current_bit) {
/* Bit is 1 and is set to fuzzy, we randomly generate it. */
dev->last_word[side] |= (random_generate() & 1);
}
}
} else {
} else
dev->last_word[side] |= current_bit;
}
}
@@ -1267,7 +1287,7 @@ d86f_word_is_aligned(int drive, int side, uint32_t base_pos)
/* State 1: Find sector ID */
void
d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t ignore_other_am)
d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t wrong_am, uint16_t ignore_other_am)
{
d86f_t *dev = d86f[drive];
@@ -1283,6 +1303,15 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui
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);
fdc_nodataam(d86f_fdc);
return;
}
if ((ignore_other_am & 2) && (dev->last_word[side] == other_am)) {
dev->calc_crc.word = 0xFFFF;
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
@@ -1329,7 +1358,7 @@ d86f_write_find_address_mark_fm(int drive, int side, find_t *find)
void
d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t ignore_other_am)
d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t wrong_am, uint16_t ignore_other_am)
{
d86f_t *dev = d86f[drive];
@@ -1341,6 +1370,15 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u
return;
}
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);
fdc_nodataam(d86f_fdc);
return;
}
if ((dev->last_word[side] == req_am) && (find->sync_marks >= 3)) {
if (d86f_word_is_aligned(drive, side, find->sync_pos)) {
dev->calc_crc.word = 0xCDB4;
@@ -1430,7 +1468,7 @@ d86f_read_sector_id(int drive, int side, int match)
if (dev->id_find.bytes_obtained == 6) {
/* We've got the ID. */
if (dev->calc_crc.word != dev->track_crc.word) {
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)) {
@@ -2401,9 +2439,9 @@ d86f_poll(int drive)
case STATE_11_FIND_ID:
case STATE_16_FIND_ID:
if (mfm)
d86f_find_address_mark_mfm(drive, side, &(dev->id_find), 0x5554, 0, 0);
d86f_find_address_mark_mfm(drive, side, &(dev->id_find), 0x5554, 0, 0, 0);
else
d86f_find_address_mark_fm(drive, side, &(dev->id_find), 0xF57E, 0, 0);
d86f_find_address_mark_fm(drive, side, &(dev->id_find), 0xF57E, 0, 0, 0);
break;
case STATE_0A_READ_ID:
@@ -2422,18 +2460,18 @@ d86f_poll(int drive)
case STATE_02_FIND_DATA:
if (mfm)
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, 2);
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, 0x5554, 2);
else
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, 2);
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, 0xF57E, 2);
break;
case STATE_06_FIND_DATA:
case STATE_11_FIND_DATA:
case STATE_16_FIND_DATA:
if (mfm)
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, fdc_is_sk(d86f_fdc) | 2);
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, 0x5554, fdc_is_sk(d86f_fdc) | 2);
else
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, fdc_is_sk(d86f_fdc) | 2);
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, 0xF57E, fdc_is_sk(d86f_fdc) | 2);
break;
case STATE_05_FIND_DATA:
@@ -2446,9 +2484,9 @@ d86f_poll(int drive)
case STATE_0C_FIND_DATA:
if (mfm)
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x554A, 0x5545, fdc_is_sk(d86f_fdc) | 2);
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x554A, 0x5545, 0x5554, fdc_is_sk(d86f_fdc) | 2);
else
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56A, 0xF56F, fdc_is_sk(d86f_fdc) | 2);
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56A, 0xF56F, 0xF57E, fdc_is_sk(d86f_fdc) | 2);
break;
case STATE_02_READ_DATA:
@@ -2808,6 +2846,7 @@ d86f_decompose_encoded_buffer(int drive, int side)
uint16_t *src1_s = dev->thin_track_surface_data[0][side];
uint16_t *src2 = dev->thin_track_encoded_data[1][side];
uint16_t *src2_s = dev->thin_track_surface_data[1][side];
dst = d86f_handler[drive].encoded_data(drive, side);
len = d86f_get_array_size(drive, side);
for (i = 0; i < len; i++) {
@@ -2857,17 +2896,19 @@ d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *da, ui
fread(&(dev->side_flags[side]), 2, 1, dev->f);
if (d86f_has_extra_bit_cells(drive)) {
fread(&(dev->extra_bit_cells[side]), 4, 1, dev->f);
if (dev->extra_bit_cells[side] < -32768)
dev->extra_bit_cells[side] = -32768;
if (dev->extra_bit_cells[side] > 32768)
dev->extra_bit_cells[side] = 32768;
} else {
/* If RPM shift is 0% and direction is 1, do not adjust extra bit cells,
as that is the whole track length. */
if (d86f_get_rpm_mode(drive) || !d86f_get_speed_shift_dir(drive)) {
if (dev->extra_bit_cells[side] < -32768)
dev->extra_bit_cells[side] = -32768;
if (dev->extra_bit_cells[side] > 32768)
dev->extra_bit_cells[side] = 32768;
}
} else
dev->extra_bit_cells[side] = 0;
}
fread(&(dev->index_hole_pos[side]), 4, 1, dev->f);
} else {
} else
fseek(dev->f, dev->track_offset[logical_track] + d86f_track_header_size(drive), SEEK_SET);
}
array_size = d86f_get_array_size(drive, side) << 1;
if (d86f_has_surface_desc(drive))
fread(sa, 1, array_size, dev->f);
@@ -3009,11 +3050,14 @@ d86f_write_tracks(int drive, FILE **f, uint32_t *track_table)
tbl = track_table;
if (! fdd_doublestep_40(drive)) {
for (side = 0; side < sides; side++) {
fdd_set_head(drive, side);
d86f_decompose_encoded_buffer(drive, side);
d86f_decompose_encoded_buffer(drive, 0);
if (sides == 2)
d86f_decompose_encoded_buffer(drive, 1);
for (thin_track = 0; thin_track < 2; thin_track++) {
for (side = 0; side < sides; side++) {
fdd_set_head(drive, side);
for (thin_track = 0; thin_track < 2; thin_track++) {
if (sides == 2)
logical_track = ((dev->cur_track + thin_track) << 1) + side;
else
@@ -3021,8 +3065,9 @@ d86f_write_tracks(int drive, FILE **f, uint32_t *track_table)
if (track_table && !tbl[logical_track]) {
fseek(*f, 0, SEEK_END);
track_table[logical_track] = ftell(*f);
tbl[logical_track] = ftell(*f);
}
if (tbl[logical_track]) {
fseek(*f, tbl[logical_track], SEEK_SET);
d86f_write_track(drive, f, side, dev->thin_track_encoded_data[thin_track][side], dev->thin_track_surface_data[thin_track][side]);
@@ -3039,12 +3084,12 @@ d86f_write_tracks(int drive, FILE **f, uint32_t *track_table)
if (track_table && !tbl[logical_track]) {
fseek(*f, 0, SEEK_END);
track_table[logical_track] = ftell(*f);
tbl[logical_track] = ftell(*f);
}
if (tbl[logical_track]) {
fseek(*f, tbl[logical_track], SEEK_SET);
d86f_write_track(drive, f, side, dev->track_encoded_data[side], dev->track_surface_data[side]);
d86f_write_track(drive, f, side, d86f_handler[drive].encoded_data(drive, side), dev->track_surface_data[side]);
}
}
}
@@ -3376,7 +3421,7 @@ d86f_export(int drive, wchar_t *fn)
int i;
int inc = 1;
uint32_t magic = 0x46423638;
uint16_t version = 0x020B;
uint16_t version = 0x020C;
uint16_t disk_flags = d86f_handler[drive].disk_flags(drive);
memset(tt, 0, 512 * sizeof(uint32_t));

View File

@@ -8,7 +8,7 @@
*
* Definitions for the 86F floppy image format.
*
* Version: @(#)floppy_86f.h 1.0.4 2018/03/17
* Version: @(#)floppy_86f.h 1.0.5 2018/11/14
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -38,7 +38,7 @@
# define EMU_FLOPPY_86F_H
#define D86FVER 0x020B
#define D86FVER 0x020C
extern void d86f_init(void);

469
src/floppy/fdd_mfm.c Normal file
View File

@@ -0,0 +1,469 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the HxC MFM image format.
*
* Version: @(#)fdd_mfm.c 1.0.0 2018/11/12
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2018 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "../plat.h"
#include "fdd.h"
#include "fdd_86f.h"
#include "fdd_img.h"
#include "fdd_mfm.h"
#include "fdc.h"
#pragma pack(push,1)
typedef struct {
uint8_t hdr_name[7];
uint16_t tracks_no;
uint8_t sides_no;
uint16_t rpm;
uint16_t bit_rate;
uint8_t if_type;
uint32_t track_list_offset;
} mfm_header_t;
typedef struct {
uint16_t track_no;
uint8_t side_no;
uint32_t track_size;
uint32_t track_offset;
} mfm_track_t;
typedef struct {
uint16_t track_no;
uint8_t side_no;
uint16_t rpm;
uint16_t bit_rate;
uint32_t track_size;
uint32_t track_offset;
} mfm_adv_track_t;
#pragma pack(pop)
typedef struct {
FILE *f;
mfm_header_t hdr;
mfm_track_t *tracks;
mfm_adv_track_t *adv_tracks;
int br_rounded, rpm_rounded,
total_tracks, cur_track;
uint8_t track_data[2][256*1024];
} mfm_t;
static mfm_t *mfm[FDD_NUM];
static fdc_t *mfm_fdc;
#ifdef ENABLE_MFM_LOG
int mfm_do_log = ENABLE_MFM_LOG;
static void
mfm_log(const char *fmt, ...)
{
va_list ap;
if (mfm_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define mfm_log(fmt, ...)
#endif
static uint16_t
disk_flags(int drive)
{
mfm_t *dev = mfm[drive];
uint16_t temp_disk_flags = 0x1080; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0;
Bit 12 = 1, bits 6, 5 = 0 - extra bit cells field specifies the entire
amount of bit cells per track. */
switch (dev->br_rounded) {
case 500:
temp_disk_flags |= 2;
break;
case 300:
case 250:
default:
temp_disk_flags |= 0;
break;
case 1000:
temp_disk_flags |= 4;
break;
}
if (dev->hdr.sides_no == 2)
temp_disk_flags |= 8;
return(temp_disk_flags);
}
static int
get_track_index(int drive, int side)
{
mfm_t *dev = mfm[drive];
int i, ret = -1;
for (i = 0; i < dev->total_tracks; i++) {
if ((dev->tracks[i].track_no == dev->cur_track) &&
(dev->tracks[i].side_no == side)) {
ret = i;
break;
}
}
return ret;
}
static int
get_adv_track_index(int drive, int side)
{
mfm_t *dev = mfm[drive];
int i, ret = -1;
for (i = 0; i < dev->total_tracks; i++) {
if ((dev->adv_tracks[i].track_no == dev->cur_track) &&
(dev->adv_tracks[i].side_no == side)) {
ret = i;
break;
}
}
return ret;
}
static void
get_adv_track_bitrate(int drive, int side, int *br, int *rpm)
{
mfm_t *dev = mfm[drive];
int track_index;
double dbr;
track_index = get_adv_track_index(drive, side);
if (track_index == -1) {
*br = 250;
*rpm = 300;
} else {
dbr = round(((double) dev->adv_tracks[track_index].bit_rate) / 50.0) * 50.0;
*br = ((int) dbr);
dbr = round(((double) dev->adv_tracks[track_index].rpm) / 60.0) * 60.0;
*rpm = ((int) dbr);
}
}
static uint16_t
side_flags(int drive)
{
mfm_t *dev = mfm[drive];
uint16_t temp_side_flags = 0;
int side, br = 250, rpm = 300;
if (dev->hdr.if_type & 0x80) {
side = fdd_get_head(drive);
get_adv_track_bitrate(drive, side, &br, &rpm);
} else {
br = dev->br_rounded;
rpm = dev->rpm_rounded;
}
/* 300 kbps @ 360 rpm = 250 kbps @ 200 rpm */
if ((rpm >= 352) && (rpm <= 367) && (br == 300)) {
br = 250;
rpm = 300;
}
switch (br) {
case 500:
temp_side_flags = 0;
break;
case 300:
temp_side_flags = 1;
break;
case 250:
default:
temp_side_flags = 2;
break;
case 1000:
temp_side_flags = 3;
break;
}
if ((rpm >= 352) && (rpm <= 367))
temp_side_flags |= 0x20;
/*
* Set the encoding value to match that provided by the FDC.
* Then if it's wrong, it will sector not found anyway.
*/
temp_side_flags |= 0x08;
return(temp_side_flags);
}
static uint32_t
get_raw_size(int drive, int side)
{
mfm_t *dev = mfm[drive];
int track_index, is_300_rpm;
if (dev->hdr.if_type & 0x80)
track_index = get_adv_track_index(drive, side);
else
track_index = get_track_index(drive, side);
is_300_rpm = (dev->hdr.rpm < 352);
if (track_index == -1) {
mfm_log("MFM: Unable to find track (%i, %i)\n", dev->cur_track, side);
return is_300_rpm ? 100000 : 83333;
}
/* Bit 7 on - my extension of the HxC MFM format to output exact bitcell counts
for each track instead of rounded byte counts. */
if (dev->hdr.if_type & 0x80)
return dev->adv_tracks[track_index].track_size;
else
return dev->tracks[track_index].track_size * 8;
}
static int32_t
extra_bit_cells(int drive, int side)
{
return (int32_t) get_raw_size(drive, side);
}
static uint16_t *
encoded_data(int drive, int side)
{
mfm_t *dev = mfm[drive];
return((uint16_t *)dev->track_data[side]);
}
void
mfm_read_side(int drive, int side)
{
mfm_t *dev = mfm[drive];
int track_index, track_size;
int track_bytes;
if (dev->hdr.if_type & 0x80)
track_index = get_adv_track_index(drive, side);
else
track_index = get_track_index(drive, side);
track_size = get_raw_size(drive, side);
track_bytes = track_size >> 3;
if (track_size & 0x07)
track_bytes++;
if (track_index == -1)
memset(dev->track_data[side], 0x00, track_bytes);
else {
if (dev->hdr.if_type & 0x80)
fseek(dev->f, dev->adv_tracks[track_index].track_offset, SEEK_SET);
else
fseek(dev->f, dev->tracks[track_index].track_offset, SEEK_SET);
fread(dev->track_data[side], 1, track_size, dev->f);
}
mfm_log("drive = %i, side = %i, dev->cur_track = %i, track_index = %i, track_size = %i\n",
drive, side, dev->cur_track, track_index, track_size);
}
void
mfm_seek(int drive, int track)
{
mfm_t *dev = mfm[drive];
mfm_log("mfm_seek(%i, %i)\n", drive, track);
if (fdd_doublestep_40(drive)) {
if (dev->hdr.tracks_no <= 43)
track /= 2;
}
dev->cur_track = track;
d86f_set_cur_track(drive, track);
if (dev->f == NULL)
return;
if (track < 0)
track = 0;
mfm_read_side(drive, 0);
mfm_read_side(drive, 1);
}
void
mfm_load(int drive, wchar_t *fn)
{
mfm_t *dev;
double dbr;
int i;
writeprot[drive] = fwriteprot[drive] = 1;
/* Allocate a drive block. */
dev = (mfm_t *)malloc(sizeof(mfm_t));
memset(dev, 0x00, sizeof(mfm_t));
dev->f = plat_fopen(fn, L"rb");
if (dev->f == NULL) {
free(dev);
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
return;
}
d86f_unregister(drive);
/* Read the header. */
fread(&dev->hdr, 1, sizeof(mfm_header_t), dev->f);
/* Calculate tracks * sides, allocate the tracks array, and read it. */
dev->total_tracks = dev->hdr.tracks_no * dev->hdr.sides_no;
if (dev->hdr.if_type & 0x80) {
dev->adv_tracks = (mfm_adv_track_t *) malloc(dev->total_tracks * sizeof(mfm_adv_track_t));
fread(dev->adv_tracks, 1, dev->total_tracks * sizeof(mfm_adv_track_t), dev->f);
} else {
dev->tracks = (mfm_track_t *) malloc(dev->total_tracks * sizeof(mfm_track_t));
fread(dev->tracks, 1, dev->total_tracks * sizeof(mfm_track_t), dev->f);
}
/* The chances of finding a HxC MFM image of a single-sided thin track
disk are much smaller than the chances of finding a HxC MFM image
incorrectly converted from a SCP image, erroneously indicating 1
side and 80+ tracks instead of 2 sides and <= 43 tracks, so if we
have detected such an image, convert the track numbers. */
if ((dev->hdr.tracks_no > 43) && (dev->hdr.sides_no == 1)) {
dev->hdr.tracks_no >>= 1;
dev->hdr.sides_no <<= 1;
for (i = 0; i < dev->total_tracks; i++) {
if (dev->hdr.if_type & 0x80) {
dev->adv_tracks[i].side_no <<= 1;
dev->adv_tracks[i].side_no |= (dev->adv_tracks[i].track_no & 1);
dev->adv_tracks[i].track_no >>= 1;
} else {
dev->tracks[i].side_no <<= 1;
dev->tracks[i].side_no |= (dev->tracks[i].track_no & 1);
dev->tracks[i].track_no >>= 1;
}
}
}
if (!(dev->hdr.if_type & 0x80)) {
dbr = round(((double) dev->hdr.bit_rate) / 50.0) * 50.0;
dev->br_rounded = (int) dbr;
mfm_log("Round bit rate: %i kbps\n", dev->br_rounded);
dbr = round(((double) dev->hdr.rpm) / 60.0) * 60.0;
dev->rpm_rounded = (int) dbr;
mfm_log("Round RPM: %i kbps\n", dev->rpm_rounded);
}
/* Set up the drive unit. */
mfm[drive] = dev;
/* Attach this format to the D86F engine. */
d86f_handler[drive].disk_flags = disk_flags;
d86f_handler[drive].side_flags = side_flags;
d86f_handler[drive].writeback = null_writeback;
d86f_handler[drive].set_sector = null_set_sector;
d86f_handler[drive].write_data = null_write_data;
d86f_handler[drive].format_conditions = null_format_conditions;
d86f_handler[drive].extra_bit_cells = extra_bit_cells;
d86f_handler[drive].encoded_data = encoded_data;
d86f_handler[drive].read_revolution = common_read_revolution;
d86f_handler[drive].index_hole_pos = null_index_hole_pos;
d86f_handler[drive].get_raw_size = get_raw_size;
d86f_handler[drive].check_crc = 1;
d86f_set_version(drive, D86FVER);
d86f_common_handlers(drive);
drives[drive].seek = mfm_seek;
mfm_log("Loaded as MFM\n");
}
void
mfm_close(int drive)
{
mfm_t *dev = mfm[drive];
if (dev == NULL) return;
d86f_unregister(drive);
drives[drive].seek = NULL;
if (dev->tracks)
free(dev->tracks);
if (dev->adv_tracks)
free(dev->adv_tracks);
if (dev->f)
fclose(dev->f);
/* Release the memory. */
free(dev);
mfm[drive] = NULL;
}
void
mfm_set_fdc(void *fdc)
{
mfm_fdc = (fdc_t *)fdc;
}

26
src/floppy/fdd_mfm.h Normal file
View File

@@ -0,0 +1,26 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the HxC MFM image format.
*
* Version: @(#)fdd_mfm.h 1.0.0 2018/11/12
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2018 Miran Grca.
*/
#ifndef EMU_FLOPPY_MFM_H
# define EMU_FLOPPY_MFM_H
extern void mfm_seek(int drive, int track);
extern void mfm_load(int drive, wchar_t *fn);
extern void mfm_close(int drive);
#endif /*EMU_FLOPPY_MFM_H*/

View File

@@ -10,7 +10,7 @@
*
* NOTE: This module needs a good cleanup someday.
*
* Version: @(#)gameport.h 1.0.3 2018/03/15
* Version: @(#)gameport.h 1.0.4 2018/11/11
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
@@ -52,24 +52,24 @@
typedef struct {
char name[64];
char name[260];
int a[8];
int b[32];
int p[4];
struct {
char name[32];
char name[260];
int id;
} axis[8];
struct {
char name[32];
char name[260];
int id;
} button[32];
struct {
char name[32];
char name[260];
int id;
} pov[4];

View File

@@ -8,7 +8,7 @@
*
* Implementation of the XT-style keyboard.
*
* Version: @(#)keyboard_xt.c 1.0.14 2018/11/02
* Version: @(#)keyboard_xt.c 1.0.15 2019/01/24
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -50,13 +50,14 @@
typedef struct {
int want_irq;
int blocked;
int tandy;
uint8_t pa;
uint8_t pb;
int tandy;
int type;
uint8_t key_waiting;
uint8_t type;
} xtkbd_t;
@@ -333,15 +334,24 @@ kbd_poll(void *priv)
keyboard_delay += (1000LL * TIMER_USEC);
if (key_queue_start != key_queue_end && !kbd->blocked) {
kbd->pa = key_queue[key_queue_start];
if (!(kbd->pb & 0x40) && (romset != ROM_TANDY))
return;
if (kbd->want_irq) {
kbd->want_irq = 0;
kbd->pa = kbd->key_waiting;
kbd->blocked = 1;
picint(2);
}
if (key_queue_start != key_queue_end && !kbd->blocked) {
kbd->key_waiting = key_queue[key_queue_start];
#if ENABLE_KEYBOARD_LOG
pclog("XTkbd: reading %02X from the key queue at %i\n",
kbd->pa, key_queue_start);
#endif
key_queue_start = (key_queue_start + 1) & 0x0f;
kbd->blocked = 1;
kbd->want_irq = 1;
}
}
@@ -423,33 +433,34 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
{
xtkbd_t *kbd = (xtkbd_t *)priv;
if (port != 0x61) return;
switch (port) {
case 0x61:
if (!(kbd->pb & 0x40) && (val & 0x40)) {
key_queue_start = key_queue_end = 0;
kbd->want_irq = 0;
kbd->blocked = 0;
kbd_adddata(0xaa);
}
kbd->pb = val;
ppi.pb = val;
if (!(kbd->pb & 0x40) && (val & 0x40)) { /*Reset keyboard*/
#if ENABLE_KEYBOARD_LOG
pclog("XTkbd: reset keyboard\n");
#endif
key_queue_end = key_queue_start;
kbd_adddata(0xaa);
timer_process();
timer_update_outstanding();
speaker_update();
speaker_gated = val & 1;
speaker_enable = val & 2;
if (speaker_enable)
was_speaker_enable = 1;
pit_set_gate(&pit, 2, val & 1);
if (val & 0x80) {
kbd->pa = 0;
kbd->blocked = 0;
picintc(2);
}
break;
}
if ((kbd->pb & 0x80)==0 && (val & 0x80)!=0) {
kbd->pa = 0;
kbd->blocked = 0;
picintc(2);
}
kbd->pb = val;
ppi.pb = val;
timer_process();
timer_update_outstanding();
speaker_update();
speaker_gated = val & 1;
speaker_enable = val & 2;
if (speaker_enable)
was_speaker_enable = 1;
pit_set_gate(&pit, 2, val & 1);
}
@@ -468,7 +479,9 @@ kbd_read(uint16_t port, void *priv)
ret = 0x7d;
else
ret = 0x6d;
} else
} else if ((kbd->type == 1) && (kbd->pb & 0x80))
ret = 0xff; /* According to Ruud on the PCem forum, this is supposed to return 0xFF on the XT. */
else
ret = kbd->pa;
break;
@@ -521,10 +534,13 @@ kbd_reset(void *priv)
{
xtkbd_t *kbd = (xtkbd_t *)priv;
kbd->want_irq = 0;
kbd->blocked = 0;
kbd->pa = 0x00;
kbd->pb = 0x00;
keyboard_scan = 1;
key_queue_start = 0,
key_queue_end = 0;
}
@@ -538,17 +554,16 @@ kbd_init(const device_t *info)
kbd = (xtkbd_t *)malloc(sizeof(xtkbd_t));
memset(kbd, 0x00, sizeof(xtkbd_t));
keyboard_set_table(scancode_xt);
kbd->type = info->local;
keyboard_scan = 1;
io_sethandler(0x0060, 4,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
keyboard_send = kbd_adddata_ex;
kbd_reset(kbd);
kbd->type = info->local;
timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, kbd);
keyboard_set_table(scancode_xt);
return(kbd);
}

View File

@@ -10,7 +10,7 @@
*
* NOTE: FIXME: Strings 2176 and 2193 are same.
*
* Version: @(#)language.h 1.0.9 2018/09/06
* Version: @(#)language.h 1.0.10 2018/11/19
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -93,6 +93,8 @@
#define IDS_2117 2117 // "Floppy %i (%s): %ls"
#define IDS_2118 2118 // "All floppy images (*.0??;*.."
#define IDS_2119 2119 // "You must save the settings.."
#define IDS_2120 2120 // "Unable to initialize Free.."
#define IDS_2121 2121 // "Unable to initialize SDL..."
#define IDS_4096 4096 // "Hard disk (%s)"
#define IDS_4097 4097 // "%01i:%01i"
@@ -171,7 +173,7 @@
#define IDS_LANG_ENUS IDS_7168
#define STR_NUM_2048 72
#define STR_NUM_2048 74
#define STR_NUM_3072 11
#define STR_NUM_4096 18
#define STR_NUM_4352 7

View File

@@ -12,6 +12,7 @@
#include "sound/snd_lpt_dss.h"
#include "printer/prt_devs.h"
char lpt_device_names[3][16];
@@ -64,7 +65,7 @@ void lpt_devices_init()
{
lpt_device_ts[i] = (lpt_device_t *) lpt_devices[c].device;
if (lpt_device_ts[i])
lpt_device_ps[i] = lpt_device_ts[i]->init();
lpt_device_ps[i] = lpt_device_ts[i]->init(lpt_device_ts[i]);
}
}
}
@@ -87,12 +88,16 @@ void lpt_write(int i, uint16_t port, uint8_t val, void *priv)
switch (port & 3)
{
case 0:
if (lpt_device_ts[i])
if (lpt_device_ts[i] && lpt_device_ts[i]->write_data)
lpt_device_ts[i]->write_data(val, lpt_device_ps[i]);
lpt_dats[i] = val;
break;
case 1:
break;
case 2:
if (lpt_device_ts[i])
if (lpt_device_ts[i] && lpt_device_ts[i]->write_ctrl)
lpt_device_ts[i]->write_ctrl(val, lpt_device_ps[i]);
lpt_ctrls[i] = val;
break;
@@ -100,18 +105,35 @@ void lpt_write(int i, uint16_t port, uint8_t val, void *priv)
}
uint8_t lpt_read(int i, uint16_t port, void *priv)
{
uint8_t retval = 0xff;
switch (port & 3)
{
case 0:
return lpt_dats[i];
if (lpt_device_ts[i] && lpt_device_ts[i]->read_data) {
retval = lpt_device_ts[i]->read_data(lpt_device_ps[i]);
break;
}
retval = lpt_dats[i];
break;
case 1:
if (lpt_device_ts[i])
return lpt_device_ts[i]->read_status(lpt_device_ps[i]);
return 0;
if (lpt_device_ts[i] && lpt_device_ts[i]->read_status) {
retval = lpt_device_ts[i]->read_status(lpt_device_ps[i]);
break;
}
retval = 0xdf;
break;
case 2:
return lpt_ctrls[i];
if (lpt_device_ts[i] && lpt_device_ts[i]->read_ctrl) {
retval = lpt_device_ts[i]->read_ctrl(lpt_device_ps[i]);
break;
}
retval = 0xe0 | lpt_ctrls[i];
break;
}
return 0xff;
return retval;
}
void lpt1_write(uint16_t port, uint8_t val, void *priv)
@@ -124,6 +146,7 @@ uint8_t lpt1_read(uint16_t port, void *priv)
return lpt_read(0, port, priv);
}
void lpt2_write(uint16_t port, uint8_t val, void *priv)
{
lpt_write(1, port, val, priv);

View File

@@ -17,10 +17,12 @@ extern char lpt_device_names[3][16];
typedef struct
{
char name[80];
const char *name;
void *(*init)();
void (*close)(void *p);
void (*write_data)(uint8_t val, void *p);
void (*write_ctrl)(uint8_t val, void *p);
uint8_t (*read_data)(void *p);
uint8_t (*read_status)(void *p);
uint8_t (*read_ctrl)(void *p);
} lpt_device_t;

View File

@@ -8,7 +8,7 @@
*
* Implementation of the Commodore PC3 system.
*
* Version: @(#)m_at_commodore.c 1.0.1 2018/11/06
* Version: @(#)m_at_commodore.c 1.0.2 2018/11/12
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -51,49 +51,54 @@
#include "machine.h"
static void cbm_io_write(uint16_t port, uint8_t val, void *p)
{
serial_t *uart = machine_get_serial(0);
static serial_t *cmd_uart;
lpt1_remove();
lpt2_remove();
switch (val & 3)
{
case 1:
lpt1_init(0x3bc);
break;
case 2:
lpt1_init(0x378);
break;
case 3:
lpt1_init(0x278);
break;
}
switch (val & 0xc)
{
case 0x4:
serial_setup(uart, 0x2f8, 3);
break;
case 0x8:
serial_setup(uart, 0x3f8, 4);
break;
}
static void
cbm_io_write(uint16_t port, uint8_t val, void *p)
{
lpt1_remove();
lpt2_remove();
switch (val & 3) {
case 1:
lpt1_init(0x3bc);
break;
case 2:
lpt1_init(0x378);
break;
case 3:
lpt1_init(0x278);
break;
}
switch (val & 0xc) {
case 0x4:
serial_setup(cmd_uart, 0x2f8, 3);
break;
case 0x8:
serial_setup(cmd_uart, 0x3f8, 4);
break;
}
}
static void cbm_io_init()
static void
cbm_io_init()
{
io_sethandler(0x0230, 0x0001, NULL,NULL,NULL, cbm_io_write,NULL,NULL, NULL);
io_sethandler(0x0230, 0x0001, NULL,NULL,NULL, cbm_io_write,NULL,NULL, NULL);
}
void
machine_at_cmdpc_init(const machine_t *model)
{
machine_at_ide_init(model);
mem_remap_top(384);
device_add(&fdc_at_device);
machine_at_ide_init(model);
cbm_io_init();
mem_remap_top(384);
device_add(&fdc_at_device);
cmd_uart = device_add(&i8250_device);
cbm_io_init();
}

View File

@@ -9,7 +9,7 @@
* SiS sis85c471 Super I/O Chip
* Used by DTK PKM-0038S E-2
*
* Version: @(#)m_at_sis85c471.c 1.0.12 2018/11/09
* Version: @(#)m_at_sis85c471.c 1.0.13 2018/11/12
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
@@ -36,6 +36,7 @@
typedef struct {
uint8_t cur_reg,
regs[39];
serial_t *uart[2];
} sis_85c471_t;
@@ -45,7 +46,6 @@ sis_85c471_write(uint16_t port, uint8_t val, void *priv)
sis_85c471_t *dev = (sis_85c471_t *) priv;
uint8_t index = (port & 1) ? 0 : 1;
uint8_t valxor;
serial_t *uart[2];
if (index) {
if ((val >= 0x50) && (val <= 0x76))
@@ -68,13 +68,11 @@ sis_85c471_write(uint16_t port, uint8_t val, void *priv)
ide_pri_enable();
}
if (valxor & 0x20) {
uart[0] = machine_get_serial(0);
uart[1] = machine_get_serial(1);
serial_remove(uart[0]);
serial_remove(uart[1]);
serial_remove(dev->uart[0]);
serial_remove(dev->uart[1]);
if (val & 0x20) {
serial_setup(uart[0], SERIAL1_ADDR, SERIAL1_IRQ);
serial_setup(uart[0], SERIAL2_ADDR, SERIAL2_IRQ);
serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ);
serial_setup(dev->uart[0], SERIAL2_ADDR, SERIAL2_IRQ);
}
}
if (valxor & 0x10) {
@@ -204,6 +202,9 @@ sis_85c471_init(const device_t *info)
dev->regs[0x23] = 0xF0;
dev->regs[0x26] = 1;
dev->uart[0] = device_add_inst(&i8250_device, 1);
dev->uart[1] = device_add_inst(&i8250_device, 2);
io_sethandler(0x0022, 0x0002,
sis_85c471_read, NULL, NULL, sis_85c471_write, NULL, NULL, dev);

View File

@@ -22,6 +22,8 @@ static uint16_t wd76c10_2072;
static uint16_t wd76c10_2872;
static uint16_t wd76c10_5872;
static serial_t *wd76c10_uart[2];
static fdc_t *wd76c10_fdc;
@@ -50,11 +52,6 @@ wd76c10_read(uint16_t port, void *priv)
static void
wd76c10_write(uint16_t port, uint16_t val, void *priv)
{
serial_t *uart[2];
uart[0] = machine_get_serial(0);
uart[1] = machine_get_serial(1);
switch (port)
{
case 0x0092:
@@ -67,27 +64,27 @@ wd76c10_write(uint16_t port, uint16_t val, void *priv)
case 0x2072:
wd76c10_2072 = val;
serial_remove(uart[0]);
serial_remove(wd76c10_uart[0]);
if (!(val & 0x10))
{
switch ((val >> 5) & 7)
{
case 1: serial_setup(uart[0], 0x3f8, 4); break;
case 2: serial_setup(uart[0], 0x2f8, 4); break;
case 3: serial_setup(uart[0], 0x3e8, 4); break;
case 4: serial_setup(uart[0], 0x2e8, 4); break;
case 1: serial_setup(wd76c10_uart[0], 0x3f8, 4); break;
case 2: serial_setup(wd76c10_uart[0], 0x2f8, 4); break;
case 3: serial_setup(wd76c10_uart[0], 0x3e8, 4); break;
case 4: serial_setup(wd76c10_uart[0], 0x2e8, 4); break;
default: break;
}
}
serial_remove(uart[1]);
serial_remove(wd76c10_uart[1]);
if (!(val & 0x01))
{
switch ((val >> 1) & 7)
{
case 1: serial_setup(uart[1], 0x3f8, 3); break;
case 2: serial_setup(uart[1], 0x2f8, 3); break;
case 3: serial_setup(uart[1], 0x3e8, 3); break;
case 4: serial_setup(uart[1], 0x2e8, 3); break;
case 1: serial_setup(wd76c10_uart[1], 0x3f8, 3); break;
case 2: serial_setup(wd76c10_uart[1], 0x2f8, 3); break;
case 3: serial_setup(wd76c10_uart[1], 0x3e8, 3); break;
case 4: serial_setup(wd76c10_uart[1], 0x2e8, 3); break;
default: break;
}
}
@@ -152,6 +149,8 @@ machine_at_wd76c10_init(const machine_t *model)
device_add(&keyboard_ps2_quadtel_device);
wd76c10_fdc = device_add(&fdc_at_device);
wd76c10_uart[0] = device_add_inst(&i8250_device, 1);
wd76c10_uart[1] = device_add_inst(&i8250_device, 2);
wd76c10_init();

View File

@@ -8,7 +8,7 @@
*
* Emulation of the IBM PCjr.
*
* Version: @(#)m_pcjr.c 1.0.11 2018/11/06
* Version: @(#)m_pcjr.c 1.0.12 2018/11/12
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -756,9 +756,6 @@ machine_pcjr_init(const machine_t *model)
else
setrtcconst(14318184.0);
if (serial_enabled[0])
serial_setup(machine_get_serial(0), 0x2f8, 3);
/* Initialize the video controller. */
mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000,
vid_read, NULL, NULL,

View File

@@ -28,7 +28,7 @@
* boot. Sometimes, they do, and then it shows an "Incorrect
* DOS" error message?? --FvK
*
* Version: @(#)m_ps1.c 1.0.13 2018/11/06
* Version: @(#)m_ps1.c 1.0.14 2018/11/12
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -98,6 +98,8 @@ typedef struct {
ps1_190;
int ps1_e0_addr;
uint8_t ps1_e0_regs[256];
serial_t *uart;
} ps1_t;
@@ -292,7 +294,6 @@ static void
ps1_write(uint16_t port, uint8_t val, void *priv)
{
ps1_t *ps = (ps1_t *)priv;
serial_t *uart;
switch (port) {
case 0x0092:
@@ -328,11 +329,10 @@ ps1_write(uint16_t port, uint8_t val, void *priv)
case 0x0102:
lpt1_remove();
uart = machine_get_serial(0);
if (val & 0x04)
serial_setup(uart, SERIAL1_ADDR, SERIAL1_IRQ);
serial_setup(ps->uart, SERIAL1_ADDR, SERIAL1_IRQ);
else
serial_remove(uart);
serial_remove(ps->uart);
if (val & 0x10) {
switch ((val >> 5) & 3) {
case 0:
@@ -449,6 +449,8 @@ ps1_setup(int model)
io_sethandler(0x0190, 1,
ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps);
ps->uart = device_add_inst(&i8250_device, 1);
lpt1_remove();
lpt1_init(0x3bc);
@@ -459,9 +461,6 @@ ps1_setup(int model)
lpt2_remove();
serial_remove(machine_get_serial(0));
serial_remove(machine_get_serial(1));
/* Enable the PS/1 VGA controller. */
if (model == 2011)
device_add(&ps1vga_device);

View File

@@ -22,6 +22,7 @@
static uint8_t ps2_94, ps2_102, ps2_103, ps2_104, ps2_105, ps2_190;
static serial_t *ps2_uart;
static struct
@@ -70,8 +71,6 @@ static uint8_t ps2_read(uint16_t port, void *p)
static void ps2_write(uint16_t port, uint8_t val, void *p)
{
serial_t *uart = machine_get_serial(0);
switch (port)
{
case 0x94:
@@ -80,9 +79,9 @@ static void ps2_write(uint16_t port, uint8_t val, void *p)
case 0x102:
lpt1_remove();
if (val & 0x04)
serial_setup(uart, SERIAL1_ADDR, SERIAL1_IRQ);
serial_setup(ps2_uart, SERIAL1_ADDR, SERIAL1_IRQ);
else
serial_remove(uart);
serial_remove(ps2_uart);
if (val & 0x10)
{
switch ((val >> 5) & 3)
@@ -143,6 +142,8 @@ static void ps2board_init(void)
ps2_190 = 0;
ps2_uart = device_add_inst(&i8250_device, 1);
lpt1_init(0x3bc);
memset(&ps2_hd, 0, sizeof(ps2_hd));

View File

@@ -8,7 +8,7 @@
*
* Implementation of MCA-based PS/2 machines.
*
* Version: @(#)m_ps2_mca.c 1.0.4 2018/11/06
* Version: @(#)m_ps2_mca.c 1.0.5 2018/11/12
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -97,6 +97,8 @@ static struct
uint8_t mem_2mb_pos_regs[8];
int pending_cache_miss;
serial_t *uart;
} ps2;
/*The model 70 type 3/4 BIOS performs cache testing. Since 86Box doesn't have any
@@ -372,8 +374,6 @@ static uint8_t model_80_read(uint16_t port)
static void model_50_write(uint16_t port, uint8_t val)
{
serial_t *uart = machine_get_serial(0);
switch (port)
{
case 0x100:
@@ -383,13 +383,13 @@ static void model_50_write(uint16_t port, uint8_t val)
break;
case 0x102:
lpt1_remove();
serial_remove(uart);
serial_remove(ps2.uart);
if (val & 0x04)
{
if (val & 0x08)
serial_setup(uart, SERIAL1_ADDR, SERIAL1_IRQ);
serial_setup(ps2.uart, SERIAL1_ADDR, SERIAL1_IRQ);
else
serial_setup(uart, SERIAL2_ADDR, SERIAL2_IRQ);
serial_setup(ps2.uart, SERIAL2_ADDR, SERIAL2_IRQ);
}
if (val & 0x10)
{
@@ -428,8 +428,6 @@ static void model_50_write(uint16_t port, uint8_t val)
static void model_55sx_write(uint16_t port, uint8_t val)
{
serial_t *uart = machine_get_serial(0);
switch (port)
{
case 0x100:
@@ -439,13 +437,13 @@ static void model_55sx_write(uint16_t port, uint8_t val)
break;
case 0x102:
lpt1_remove();
serial_remove(uart);
serial_remove(ps2.uart);
if (val & 0x04)
{
if (val & 0x08)
serial_setup(uart, SERIAL1_ADDR, SERIAL1_IRQ);
serial_setup(ps2.uart, SERIAL1_ADDR, SERIAL1_IRQ);
else
serial_setup(uart, SERIAL2_ADDR, SERIAL2_IRQ);
serial_setup(ps2.uart, SERIAL2_ADDR, SERIAL2_IRQ);
}
if (val & 0x10)
{
@@ -505,8 +503,6 @@ static void model_55sx_write(uint16_t port, uint8_t val)
static void model_70_type3_write(uint16_t port, uint8_t val)
{
serial_t *uart = machine_get_serial(0);
switch (port)
{
case 0x100:
@@ -515,13 +511,13 @@ static void model_70_type3_write(uint16_t port, uint8_t val)
break;
case 0x102:
lpt1_remove();
serial_remove(uart);
serial_remove(ps2.uart);
if (val & 0x04)
{
if (val & 0x08)
serial_setup(uart, SERIAL1_ADDR, SERIAL1_IRQ);
serial_setup(ps2.uart, SERIAL1_ADDR, SERIAL1_IRQ);
else
serial_setup(uart, SERIAL2_ADDR, SERIAL2_IRQ);
serial_setup(ps2.uart, SERIAL2_ADDR, SERIAL2_IRQ);
}
if (val & 0x10)
{
@@ -555,8 +551,6 @@ static void model_70_type3_write(uint16_t port, uint8_t val)
static void model_80_write(uint16_t port, uint8_t val)
{
serial_t *uart = machine_get_serial(0);
switch (port)
{
case 0x100:
@@ -565,13 +559,13 @@ static void model_80_write(uint16_t port, uint8_t val)
break;
case 0x102:
lpt1_remove();
serial_remove(uart);
serial_remove(ps2.uart);
if (val & 0x04)
{
if (val & 0x08)
serial_setup(uart, SERIAL1_ADDR, SERIAL1_IRQ);
serial_setup(ps2.uart, SERIAL1_ADDR, SERIAL1_IRQ);
else
serial_setup(uart, SERIAL2_ADDR, SERIAL2_IRQ);
serial_setup(ps2.uart, SERIAL2_ADDR, SERIAL2_IRQ);
}
if (val & 0x10)
{
@@ -1246,6 +1240,8 @@ machine_ps2_common_init(const machine_t *model)
pit_ps2_init();
nmi_mask = 0x80;
ps2.uart = device_add_inst(&i8250_device, 1);
}

View File

@@ -115,7 +115,7 @@ static uint8_t mem_read_laserxtems(uint32_t addr, void *priv)
}
static void laserxt_init(is_lxt3)
static void laserxt_init(int is_lxt3)
{
int i;

113
src/machine/m_xt_zenith.c Normal file
View File

@@ -0,0 +1,113 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of various Zenith PC compatible machines.
* Currently only the Zenith Data Systems Supersport is emulated.
*
* Version: @(#)m_xt_compaq.c 1.0.0 2019/01/13
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../86box.h"
#include "../cpu/cpu.h"
#include "../nmi.h"
#include "../pit.h"
#include "../mem.h"
#include "../rom.h"
#include "../device.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "../game/gameport.h"
#include "../keyboard.h"
#include "../lpt.h"
#include "machine.h"
typedef struct {
mem_mapping_t scratchpad_mapping;
uint8_t *scratchpad_ram;
} zenith_t;
static uint8_t zenith_scratchpad_read(uint32_t addr, void *p)
{
zenith_t *dev = (zenith_t *)p;
return dev->scratchpad_ram[addr & 0x3fff];
}
static void zenith_scratchpad_write(uint32_t addr, uint8_t val, void *p)
{
zenith_t *dev = (zenith_t *)p;
dev->scratchpad_ram[addr & 0x3fff] = val;
}
static void *
zenith_scratchpad_init(const device_t *info)
{
zenith_t *dev;
dev = (zenith_t *)malloc(sizeof(zenith_t));
memset(dev, 0x00, sizeof(zenith_t));
dev->scratchpad_ram = malloc(0x4000);
mem_mapping_disable(&bios_mapping[4]);
mem_mapping_disable(&bios_mapping[5]);
mem_mapping_add(&dev->scratchpad_mapping, 0xf0000, 0x4000,
zenith_scratchpad_read, NULL, NULL,
zenith_scratchpad_write, NULL, NULL,
dev->scratchpad_ram, MEM_MAPPING_EXTERNAL, dev);
return dev;
}
static void
zenith_scratchpad_close(void *p)
{
zenith_t *dev = (zenith_t *)p;
free(dev->scratchpad_ram);
free(dev);
}
static const device_t zenith_scratchpad_device = {
"Zenith scratchpad RAM",
0, 0,
zenith_scratchpad_init, zenith_scratchpad_close, NULL,
NULL,
NULL,
NULL
};
void
machine_xt_zenith_init(const machine_t *model)
{
machine_common_init(model);
lpt2_remove(); /* only one parallel port */
device_add(&zenith_scratchpad_device);
pit_set_out_func(&pit, 1, pit_refresh_timer_xt);
device_add(&keyboard_xt_device);
device_add(&fdc_xt_device);
nmi_init();
if (joystick_type != 7)
device_add(&gameport_device);
}

View File

@@ -8,7 +8,7 @@
*
* Handling of the emulated machines.
*
* Version: @(#)machine.c 1.0.36 2018/11/05
* Version: @(#)machine.c 1.0.37 2018/11/12
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -42,8 +42,6 @@ int machine;
int AT, PCI;
int romset;
static serial_t *uart[2];
#ifdef ENABLE_MACHINE_LOG
int machine_do_log = ENABLE_MACHINE_LOG;
@@ -92,12 +90,6 @@ machine_init(void)
/* All good, boot the machine! */
machines[machine].init(&machines[machine]);
/* For non-PCI machines, add two regular 8250 UART's. */
if (!PCI) {
uart[0] = device_add_inst(&i8250_device, 1);
uart[1] = device_add_inst(&i8250_device, 2);
}
/* If it's a PCI or MCA machine, reset the video card
after initializing the machine, so the slots work correctly. */
if (PCI || MCA)
@@ -105,13 +97,6 @@ machine_init(void)
}
serial_t *
machine_get_serial(int port)
{
return uart[port];
}
void
machine_common_init(const machine_t *model)
{

View File

@@ -8,7 +8,7 @@
*
* Handling of the emulated machines.
*
* Version: @(#)machine.h 1.0.30 2018/09/15
* Version: @(#)machine.h 1.0.32 2019/01/13
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -82,9 +82,6 @@ extern int machine_getmachine(int romset);
extern char *machine_getname(void);
extern char *machine_get_internal_name(void);
extern int machine_get_machine_from_internal_name(char *s);
#ifdef EMU_SERIAL_H
extern serial_t *machine_get_serial(int port);
#endif
extern void machine_init(void);
#ifdef EMU_DEVICE_H
extern const device_t *machine_getdevice(int machine);
@@ -199,6 +196,7 @@ extern void machine_xt_t1000_init(const machine_t *);
extern void machine_xt_t1200_init(const machine_t *);
extern void machine_xt_xi8088_init(const machine_t *);
extern void machine_xt_zenith_init(const machine_t *);
#ifdef EMU_DEVICE_H
extern const device_t *xi8088_get_device(void);

View File

@@ -11,7 +11,7 @@
* NOTES: OpenAT wip for 286-class machine with open BIOS.
* PS2_M80-486 wip, pending receipt of TRM's for machine.
*
* Version: @(#)machine_table.c 1.0.44 2018/11/03
* Version: @(#)machine_table.c 1.0.45 2019/01/13
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -51,7 +51,8 @@ const machine_t machines[] = {
{ "[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 512, 512, 256, 0, machine_xt_laserxt_init, NULL },
#endif
{ "[8088] Xi8088", ROM_XI8088, "xi8088", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, NULL },
{ "[8088] Zenith Data SupersPort", ROM_ZD_SUPERS, "zdsupers", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 128, 640, 128, 0, machine_xt_zenith_init, NULL },
{ "[8086] Amstrad PC1512", ROM_PC1512, "pc1512", {{"Intel", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL },
{ "[8086] Amstrad PC1640", ROM_PC1640, "pc1640", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL },
{ "[8086] Amstrad PC2086", ROM_PC2086, "pc2086", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL },

View File

@@ -12,7 +12,7 @@
* the DYNAMIC_TABLES=1 enables this. Will eventually go
* away, either way...
*
* Version: @(#)mem.c 1.0.18 2018/10/17
* Version: @(#)mem.c 1.0.19 2018/11/18
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -494,10 +494,12 @@ getpccache(uint32_t a)
a &= rammask;
if (_mem_exec[a >> 14]) {
if (_mem_mapping_r[a >> 14]->flags & MEM_MAPPING_ROM)
cpu_prefetch_cycles = cpu_rom_prefetch_cycles;
else
cpu_prefetch_cycles = cpu_mem_prefetch_cycles;
if (is286) {
if (_mem_mapping_r[a >> 14]->flags & MEM_MAPPING_ROM)
cpu_prefetch_cycles = cpu_rom_prefetch_cycles;
else
cpu_prefetch_cycles = cpu_mem_prefetch_cycles;
}
return &_mem_exec[a >> 14][(uintptr_t)(a & 0x3000) - (uintptr_t)(a2 & ~0xfff)];
}
@@ -996,26 +998,6 @@ writememql(uint32_t seg, uint32_t addr, uint64_t val)
uint8_t
mem_readb_phys(uint32_t addr)
{
mem_logical_addr = 0xffffffff;
if (_mem_read_b[addr >> 14])
return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]);
return 0xff;
}
/*
* Version of mem_readby_phys that doesn't go through
* the CPU paging mechanism.
*/
uint8_t
mem_readb_phys_dma(uint32_t addr)
{
#if 0
mem_logical_addr = 0xffffffff;
#endif
{
if (_mem_exec[addr >> 14])
return _mem_exec[addr >> 14][addr & 0x3fff];
@@ -1028,36 +1010,24 @@ mem_readb_phys_dma(uint32_t addr)
uint16_t
mem_readw_phys(uint32_t addr)
{
{
uint16_t temp;
if (_mem_read_w[addr >> 14])
if (_mem_exec[addr >> 14])
return ((uint16_t *) _mem_exec[addr >> 14])[(addr >> 1) & 0x1fff];
else if (_mem_read_w[addr >> 14])
return _mem_read_w[addr >> 14](addr, _mem_priv_r[addr >> 14]);
else {
temp = mem_readb_phys(addr + 1) << 8;
temp |= mem_readb_phys(addr);
}
return temp;
}
void
mem_writeb_phys(uint32_t addr, uint8_t val)
{
mem_logical_addr = 0xffffffff;
if (_mem_write_b[addr >> 14])
_mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
}
/*
* Version of mem_readby_phys that doesn't go through
* the CPU paging mechanism.
*/
void
mem_writeb_phys_dma(uint32_t addr, uint8_t val)
{
#if 0
mem_logical_addr = 0xffffffff;
#endif
{
if (_mem_exec[addr >> 14])
_mem_exec[addr >> 14][addr & 0x3fff] = val;
@@ -1065,16 +1035,6 @@ mem_writeb_phys_dma(uint32_t addr, uint8_t val)
_mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
}
void
mem_writew_phys(uint32_t addr, uint16_t val)
{
mem_logical_addr = 0xffffffff;
if (_mem_write_w[addr >> 14])
_mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
}
uint8_t
mem_read_ram(uint32_t addr, void *priv)

View File

@@ -8,7 +8,7 @@
*
* Definitions for the memory interface.
*
* Version: @(#)mem.h 1.0.6 2018/09/15
* Version: @(#)mem.h 1.0.8 2018/11/18
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
@@ -139,7 +139,6 @@ extern int shadowbios,
extern int readlnum,
writelnum;
extern int nopageerrors;
extern int memspeed[11];
extern int mmu_perm;
@@ -209,11 +208,8 @@ extern void mem_set_mem_state(uint32_t base, uint32_t size, int state);
extern uint8_t mem_readb_phys(uint32_t addr);
extern uint8_t mem_readb_phys_dma(uint32_t addr);
extern uint16_t mem_readw_phys(uint32_t addr);
extern uint32_t mem_readl_phys(uint32_t addr);
extern void mem_writeb_phys(uint32_t addr, uint8_t val);
extern void mem_writeb_phys_dma(uint32_t addr, uint8_t val);
extern void mem_writew_phys(uint32_t addr, uint16_t val);
extern void mem_writel_phys(uint32_t addr, uint32_t val);
extern uint8_t mem_read_ram(uint32_t addr, void *priv);
extern uint16_t mem_read_ramw(uint32_t addr, void *priv);

View File

@@ -10,7 +10,7 @@
*
* TODO: Add the Genius Serial Mouse.
*
* Version: @(#)mouse_serial.c 1.0.26 2018/11/05
* Version: @(#)mouse_serial.c 1.0.27 2018/11/11
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*/
@@ -30,12 +30,21 @@
#define SERMOUSE_PORT 0 /* attach to Serial0 */
#define PHASE_IDLE 0
#define PHASE_ID 1
#define PHASE_DATA 2
#define PHASE_STATUS 3
#define PHASE_DIAGNOSTIC 4
#define PHASE_FORMAT_AND_REVISION 5
enum {
PHASE_IDLE,
PHASE_ID,
PHASE_DATA,
PHASE_STATUS,
PHASE_DIAGNOSTIC,
PHASE_FORMAT_AND_REVISION,
PHASE_COPYRIGHT_STRING,
PHASE_BUTTONS
};
enum {
REPORT_PHASE_PREPARE,
REPORT_PHASE_TRANSMIT
};
typedef struct {
@@ -45,16 +54,18 @@ typedef struct {
uint8_t flags, but, /* device flags */
want_data,
status, format,
prompt, continuous,
prompt, on_change,
id_len, id[255],
data_len, data[5];
int abs_x, abs_y;
int abs_x, abs_y,
rel_x, rel_y,
rel_z,
oldb, lastb;
int pos;
int64_t delay;
int64_t period;
int oldb;
int phase;
int command_pos, command_phase,
report_pos, report_phase;
int64_t command_delay, transmit_period,
report_delay, report_period;
serial_t *serial;
} mouse_t;
@@ -93,9 +104,9 @@ sermouse_callback(struct serial_s *serial, void *priv)
mouse_t *dev = (mouse_t *)priv;
/* Start a timer to wake us up in a little while. */
dev->pos = 0;
dev->phase = PHASE_ID;
dev->delay = dev->period;
dev->command_pos = 0;
dev->command_phase = PHASE_ID;
dev->command_delay = dev->transmit_period;
}
@@ -234,114 +245,256 @@ sermouse_report(int x, int y, int z, int b, mouse_t *dev)
memset(dev->data, 0, 5);
switch(dev->type) {
case MOUSE_TYPE_MSYSTEMS:
switch (dev->format) {
case 0:
len = sermouse_data_msystems(dev, x, y, b);
break;
case MOUSE_TYPE_MICROSOFT:
case MOUSE_TYPE_MS3BUTTON:
case MOUSE_TYPE_MSWHEEL:
len = sermouse_data_ms(dev, x, y, z, b);
case 1:
len = sermouse_data_3bp(dev, x, y, b);
break;
case MOUSE_TYPE_LOGITECH:
case MOUSE_TYPE_LT3BUTTON:
switch (dev->format) {
case 0:
len = sermouse_data_msystems(dev, x, y, b);
break;
case 1:
len = sermouse_data_3bp(dev, x, y, b);
break;
case 2:
len = sermouse_data_hex(dev, x, y, b);
break;
case 3: /* Relative */
len = sermouse_data_bp1(dev, x, y, b);
break;
case 5:
len = sermouse_data_mmseries(dev, x, y, b);
break;
case 6: /* Absolute */
len = sermouse_data_bp1(dev, dev->abs_x, dev->abs_y, b);
break;
case 7:
len = sermouse_data_ms(dev, x, y, z, b);
break;
}
case 2:
len = sermouse_data_hex(dev, x, y, b);
break;
case 3: /* Relative */
len = sermouse_data_bp1(dev, x, y, b);
break;
case 5:
len = sermouse_data_mmseries(dev, x, y, b);
break;
case 6: /* Absolute */
len = sermouse_data_bp1(dev, dev->abs_x, dev->abs_y, b);
break;
case 7:
len = sermouse_data_ms(dev, x, y, z, b);
break;
}
dev->oldb = b;
dev->data_len = len;
}
dev->pos = 0;
if (dev->phase != PHASE_DATA)
dev->phase = PHASE_DATA;
static void
sermouse_command_phase_idle(mouse_t *dev)
{
dev->command_delay = 0LL;
dev->command_pos = 0;
dev->command_phase = PHASE_IDLE;
}
if (!dev->delay)
dev->delay = dev->period;
static void
sermouse_command_pos_check(mouse_t *dev, int len)
{
if (++dev->command_pos == len)
sermouse_command_phase_idle(dev);
else
dev->command_delay += dev->transmit_period;
}
static uint8_t
sermouse_last_button_status(mouse_t *dev)
{
uint8_t ret = 0x00;
if (dev->oldb & 0x01)
ret |= 0x04;
if (dev->oldb & 0x02)
ret |= 0x02;
if (dev->oldb & 0x04)
ret |= 0x01;
return ret;
}
static int64_t
sermouse_transmit_period(mouse_t *dev, int bps, int rps)
{
double dbps = (double) bps;
double dusec = (double) TIMER_USEC;
double temp = 0.0;
int word_len;
switch (dev->format) {
case 0:
case 1: /* Mouse Systems and Three Byte Packed formats: 8 data, no parity, 2 stop, 1 start */
word_len = 11;
break;
case 2: /* Hexadecimal format - 8 data, no parity, 1 stop, 1 start - number of stop bits is a guess because
it is not documented anywhere. */
word_len = 10;
break;
case 3:
case 6: /* Bit Pad One formats: 7 data, even parity, 2 stop, 1 start */
word_len = 11;
break;
case 5: /* MM Series format: 8 data, odd parity, 1 stop, 1 start */
word_len = 11;
break;
default:
case 7: /* Microsoft-compatible format: 7 data, no parity, 1 stop, 1 start */
word_len = 9;
break;
}
if (rps == -1)
temp = (double) word_len;
else {
temp = (double) rps;
temp = (9600.0 - (temp * 33.0));
temp /= rps;
}
temp = (1000000.0 / dbps) * temp;
temp *= dusec;
return (int64_t) temp;
}
static void
sermouse_update_delta(mouse_t *dev, int *local, int *global)
{
int min, max;
if (dev->format == 3) {
min = -2048;
max = 2047;
} else {
min = -128;
max = 127;
}
if (*global > max) {
*local = max;
*global -= max;
} else if (*global < min) {
*local = min;
*global += -min;
} else {
*local = *global;
*global = 0;
}
}
static uint8_t
sermouse_update_data(mouse_t *dev)
{
uint8_t ret = 0;
int delta_x, delta_y, delta_z;
/* Update the deltas and the delays. */
sermouse_update_delta(dev, &delta_x, &dev->rel_x);
sermouse_update_delta(dev, &delta_y, &dev->rel_y);
sermouse_update_delta(dev, &delta_z, &dev->rel_z);
sermouse_report(delta_x, delta_y, delta_z, dev->oldb, dev);
mouse_serial_log("delta_x = %i, delta_y = %i, delta_z = %i, dev->oldb = %02X\n",
delta_x, delta_y, delta_z, dev->oldb);
if (delta_x || delta_y || delta_z || (dev->oldb != dev->lastb) || !dev->on_change)
ret = 1;
dev->lastb = dev->oldb;
return ret;
}
static void
sermouse_report_prepare(mouse_t *dev)
{
if (sermouse_update_data(dev)) {
/* Start sending data. */
dev->report_phase = REPORT_PHASE_TRANSMIT;
dev->report_pos = 0;
dev->report_delay += dev->transmit_period;
} else {
dev->report_phase = REPORT_PHASE_PREPARE;
if (dev->report_period == 0LL)
dev->report_delay += dev->transmit_period;
else
dev->report_delay += dev->report_period;
}
}
static void
sermouse_report_timer(void *priv)
{
mouse_t *dev = (mouse_t *)priv;
if (dev->report_phase == REPORT_PHASE_PREPARE)
sermouse_report_prepare(dev);
else {
/* If using the Mouse Systems format, update data because
the last two bytes are the X and Y delta since bytes 1
and 2 were transmitted. */
if (!dev->format && (dev->report_pos == 3))
sermouse_update_data(dev);
serial_write_fifo(dev->serial, dev->data[dev->report_pos]);
if (++dev->report_pos == dev->data_len) {
if (dev->report_delay == 0LL)
sermouse_report_prepare(dev);
else {
if (dev->report_period == 0LL)
dev->report_delay += dev->transmit_period;
else
dev->report_delay += dev->report_period;
dev->report_phase = REPORT_PHASE_PREPARE;
}
} else
dev->report_delay += dev->transmit_period;
}
}
/* Callback timer expired, now send our "mouse ID" to the serial port. */
static void
sermouse_timer(void *priv)
sermouse_command_timer(void *priv)
{
mouse_t *dev = (mouse_t *)priv;
switch (dev->phase) {
switch (dev->command_phase) {
case PHASE_ID:
serial_write_fifo(dev->serial, dev->id[dev->pos]);
dev->pos++;
if (dev->pos == dev->id_len) {
dev->delay = 0LL;
dev->pos = 0;
dev->phase = PHASE_IDLE;
} else
dev->delay += dev->period;
serial_write_fifo(dev->serial, dev->id[dev->command_pos]);
sermouse_command_pos_check(dev, dev->id_len);
if ((dev->command_phase == PHASE_IDLE) && (dev->type != MOUSE_TYPE_MSYSTEMS)) {
/* This resets back to Microsoft-compatible mode. */
dev->report_delay = 0LL;
dev->report_phase = REPORT_PHASE_PREPARE;
dev->format = 7;
dev->transmit_period = sermouse_transmit_period(dev, 1200, -1);
sermouse_report_timer((void *) dev);
}
break;
case PHASE_DATA:
serial_write_fifo(dev->serial, dev->data[dev->pos]);
dev->pos++;
if (dev->pos == dev->data_len) {
dev->delay = 0LL;
dev->pos = 0;
dev->phase = PHASE_IDLE;
} else
dev->delay += dev->period;
serial_write_fifo(dev->serial, dev->data[dev->command_pos]);
sermouse_command_pos_check(dev, dev->data_len);
break;
case PHASE_STATUS:
serial_write_fifo(dev->serial, dev->status);
dev->delay = 0LL;
dev->pos = 0;
dev->phase = PHASE_IDLE;
sermouse_command_phase_idle(dev);
break;
case PHASE_DIAGNOSTIC:
if (dev->pos)
if (dev->command_pos)
serial_write_fifo(dev->serial, 0x00);
else /* This should return the last button status, bits 2,1,0 = L,M,R. */
serial_write_fifo(dev->serial, 0x00);
dev->pos++;
if (dev->pos == 3) {
dev->delay = 0LL;
dev->pos = 0;
dev->phase = PHASE_IDLE;
} else
dev->delay += dev->period;
else
serial_write_fifo(dev->serial, sermouse_last_button_status(dev));
sermouse_command_pos_check(dev, 3);
break;
case PHASE_FORMAT_AND_REVISION:
serial_write_fifo(dev->serial, 0x10 | (dev->format << 1));
dev->delay = 0LL;
dev->pos = 0;
dev->phase = PHASE_IDLE;
sermouse_command_phase_idle(dev);
break;
case PHASE_BUTTONS:
serial_write_fifo(dev->serial, dev->but);
sermouse_command_phase_idle(dev);
break;
default:
dev->delay = 0LL;
dev->pos = 0;
dev->phase = PHASE_IDLE;
sermouse_command_phase_idle(dev);
break;
}
}
@@ -352,8 +505,10 @@ sermouse_poll(int x, int y, int z, int b, void *priv)
{
mouse_t *dev = (mouse_t *)priv;
if (!x && !y && (b == dev->oldb) && dev->continuous)
if (!x && !y && !z && (b == dev->oldb)) {
dev->oldb = b;
return(1);
}
dev->oldb = b;
dev->abs_x += x;
@@ -379,51 +534,71 @@ sermouse_poll(int x, int y, int z, int b, void *priv)
if (y <- 128) y = -128;
}
/* No report if we're either in prompt mode,
or the mouse wants data. */
if (!dev->prompt && !dev->want_data)
sermouse_report(x, y, z, b, dev);
dev->rel_x += x;
dev->rel_y += y;
dev->rel_z += z;
return(0);
}
static void
ltsermouse_prompt_mode(mouse_t *dev, int prompt)
{
dev->prompt = prompt;
dev->status &= 0xBF;
if (prompt)
dev->status |= 0x40;
}
static void
ltsermouse_command_phase(mouse_t *dev, int phase)
{
dev->command_pos = 0;
dev->command_phase = phase;
dev->command_delay = dev->transmit_period;
}
static void
ltsermouse_set_report_period(mouse_t *dev, int rps)
{
dev->report_delay = dev->report_period = sermouse_transmit_period(dev, 9600, rps);
ltsermouse_prompt_mode(dev, 0);
dev->report_phase = REPORT_PHASE_PREPARE;
}
static void
ltsermouse_write(struct serial_s *serial, void *priv, uint8_t data)
{
mouse_t *dev = (mouse_t *)priv;
#if 0
/* Make sure to stop any transmission when we receive a byte. */
if (dev->phase != PHASE_IDLE) {
dev->delay = 0LL;
dev->phase = PHASE_IDLE;
}
#endif
/* Stop reporting when we're processing a command. */
dev->report_phase = REPORT_PHASE_PREPARE;
dev->report_delay = 0LL;
if (dev->want_data) switch (dev->want_data) {
case 0x2A:
dev->data_len--;
dev->want_data = 0;
dev->delay = 0LL;
dev->phase = PHASE_IDLE;
switch (data) {
default:
mouse_serial_log("Serial mouse: Invalid period %02X, using 1200 bps\n", data);
case 0x6E:
dev->period = 7500LL; /* 1200 bps */
dev->transmit_period = sermouse_transmit_period(dev, 1200, -1);
break;
case 0x6F:
dev->period = 3750LL; /* 2400 bps */
dev->transmit_period = sermouse_transmit_period(dev, 2400, -1);
break;
case 0x70:
dev->period = 1875LL; /* 4800 bps */
dev->transmit_period = sermouse_transmit_period(dev, 4800, -1);
break;
case 0x71:
dev->period = 938LL; /* 9600 bps */
dev->transmit_period = sermouse_transmit_period(dev, 9600, -1);
break;
}
dev->period *= TIMER_USEC;
break;
} else switch (data) {
case 0x2A:
@@ -431,33 +606,43 @@ ltsermouse_write(struct serial_s *serial, void *priv, uint8_t data)
dev->data_len = 1;
break;
case 0x44: /* Set prompt mode */
dev->prompt = 1;
dev->status |= 0x40;
ltsermouse_prompt_mode(dev, 1);
break;
case 0x50:
if (!dev->prompt) {
dev->prompt = 1;
dev->status |= 0x40;
}
/* TODO: Here we should send the current position. */
if (!dev->prompt)
ltsermouse_prompt_mode(dev, 1);
sermouse_update_data(dev);
ltsermouse_command_phase(dev, PHASE_DATA);
break;
case 0x73: /* Status */
dev->pos = 0;
dev->phase = PHASE_STATUS;
if (!dev->delay)
dev->delay = dev->period;
ltsermouse_command_phase(dev, PHASE_STATUS);
break;
case 0x4A: /* Report Rate Selection commands */
ltsermouse_set_report_period(dev, 10);
break;
case 0x4B:
ltsermouse_set_report_period(dev, 20);
break;
case 0x4C:
ltsermouse_set_report_period(dev, 35);
break;
case 0x52:
ltsermouse_set_report_period(dev, 50);
break;
case 0x4D:
ltsermouse_set_report_period(dev, 70);
break;
case 0x51:
ltsermouse_set_report_period(dev, 100);
break;
case 0x4E:
ltsermouse_set_report_period(dev, 150);
break;
case 0x4F:
dev->prompt = 0;
dev->status &= 0xBF;
// dev->continuous = (data == 0x4F);
ltsermouse_prompt_mode(dev, 0);
dev->report_delay = dev->report_period = 0LL;
dev->report_phase = REPORT_PHASE_PREPARE;
sermouse_report_timer((void *) dev);
break;
case 0x41:
dev->format = 6; /* Aboslute Bit Pad One Format */
@@ -482,16 +667,13 @@ ltsermouse_write(struct serial_s *serial, void *priv, uint8_t data)
dev->format = 2; /* Hexadecimal Format */
break;
case 0x05:
dev->pos = 0;
dev->phase = PHASE_DIAGNOSTIC;
if (!dev->delay)
dev->delay = dev->period;
ltsermouse_command_phase(dev, PHASE_DIAGNOSTIC);
break;
case 0x66:
dev->pos = 0;
dev->phase = PHASE_FORMAT_AND_REVISION;
if (!dev->delay)
dev->delay = dev->period;
ltsermouse_command_phase(dev, PHASE_FORMAT_AND_REVISION);
break;
case 0x6B:
ltsermouse_command_phase(dev, PHASE_BUTTONS);
break;
}
}
@@ -520,19 +702,19 @@ sermouse_init(const device_t *info)
memset(dev, 0x00, sizeof(mouse_t));
dev->name = info->name;
dev->but = device_get_config_int("buttons");
dev->continuous = 1;
if (dev->but > 2)
dev->flags |= FLAG_3BTN;
if (info->local == MOUSE_TYPE_MSYSTEMS) {
dev->period = 8333LL * TIMER_USEC; /* 1200 bps, 8 data bits, 1 start bit, 1 stop bit, no parity bit */
dev->on_change = 1;
dev->format = 0;
dev->type = info->local;
dev->id_len = 1;
dev->id[0] = 'H';
} else {
dev->on_change = !info->local;
dev->format = 7;
dev->status = 0x0f;
dev->period = 7500LL * TIMER_USEC; /* 1200 bps, 7 data bits, 1 start bit, 1 stop bit, no parity bit */
dev->id_len = 1;
dev->id[0] = 'M';
switch(dev->but) {
@@ -554,6 +736,21 @@ sermouse_init(const device_t *info)
}
}
dev->transmit_period = sermouse_transmit_period(dev, 1200, -1);
/* Default: Continuous reporting = no delay between reports. */
dev->report_phase = REPORT_PHASE_PREPARE;
dev->report_period = 0LL;
if (info->local == MOUSE_TYPE_MSYSTEMS)
dev->report_delay = dev->transmit_period;
else
dev->report_delay = 0LL;
/* Default: Doing nothing - command transmit timer deactivated. */
dev->command_phase = PHASE_IDLE;
dev->command_delay = 0LL;
dev->port = device_get_config_int("port");
/* Attach a serial port to the mouse. */
@@ -564,7 +761,8 @@ sermouse_init(const device_t *info)
mouse_serial_log("%s: port=COM%d\n", dev->name, dev->port + 1);
timer_add(sermouse_timer, &dev->delay, &dev->delay, dev);
timer_add(sermouse_report_timer, &dev->report_delay, &dev->report_delay, dev);
timer_add(sermouse_command_timer, &dev->command_delay, &dev->command_delay, dev);
/* Tell them how many buttons we have. */
mouse_set_buttons((dev->flags & FLAG_3BTN) ? 3 : 2);

View File

@@ -12,7 +12,7 @@
* it should be malloc'ed and then linked to the NETCARD def.
* Will be done later.
*
* Version: @(#)network.c 1.0.9 2018/10/22
* Version: @(#)network.c 1.0.10 2018/11/18
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -99,7 +99,7 @@ static netcard_t net_cards[] = {
int network_type;
int network_ndev;
int network_card;
char network_host[512];
char network_host[522];
netdev_t network_devs[32];
#ifdef ENABLE_NIC_LOG
int nic_do_log = ENABLE_NIC_LOG;

View File

@@ -389,172 +389,127 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
global_writefds = writefds;
global_xfds = xfds;
/* Update time */
updtime();
/*
* See if anything has timed out
*/
if (link_up) {
if (time_fasttimo && ((curtime - time_fasttimo) >= FAST_TIMO)) {
tcp_fasttimo();
time_fasttimo = 0;
}
if (do_slowtimo && ((curtime - last_slowtimo) >= SLOW_TIMO)) {
ip_slowtimo();
tcp_slowtimo();
last_slowtimo = curtime;
}
}
/*
* Check sockets
*/
if (link_up) {
/*
* Check TCP sockets
*/
for (so = tcb.so_next; so != &tcb; so = so_next) {
so_next = so->so_next;
/*
* FD_ISSET is meaningless on these sockets
* (and they can crash the program)
*/
if (so->so_state & SS_NOFDREF || so->s == -1)
continue;
/*
* Check for URG data
* This will soread as well, so no need to
* test for readfds below if this succeeds
*/
if (FD_ISSET(so->s, xfds))
sorecvoob(so);
/*
* Check sockets for reading
*/
else if (FD_ISSET(so->s, readfds)) {
/*
* Check for incoming connections
*/
if (so->so_state & SS_FACCEPTCONN) {
tcp_connect(so);
continue;
} /* else */
ret = soread(so);
/* Output it if we read something */
if (ret > 0)
tcp_output(sototcpcb(so));
}
/*
* Check sockets for writing
*/
if (FD_ISSET(so->s, writefds)) {
/*
* Check for non-blocking, still-connecting sockets
*/
if (so->so_state & SS_ISFCONNECTING) {
/* Connected */
so->so_state &= ~SS_ISFCONNECTING;
//ret = send(so->s, &ret, 0, 0);
//winsock2.h:549:32: note: expected 'const char *' but argument is of type 'int *'
//WINSOCK_API_LINKAGE int PASCAL send(SOCKET,const char*,int,int); JASON
//ret = send(so->s, "a", 1, 0); WHY THE HELL WAS THIS HERE?!
ret = send(so->s, (char *)&ret, 0, 0); //This is what it should be.
if (ret < 0) {
/* XXXXX Must fix, zero bytes is a NOP */
if (errno == EAGAIN || errno == EWOULDBLOCK ||
errno == EINPROGRESS || errno == ENOTCONN)
continue;
/* else failed */
so->so_state = SS_NOFDREF;
}
/* else so->so_state &= ~SS_ISFCONNECTING; */
/*
* Continue tcp_input
*/
tcp_input((struct SLIRPmbuf *)NULL, sizeof(struct ip), so);
/* continue; */
} else
ret = sowrite(so);
/*
* XXXXX If we wrote something (a lot), there
* could be a need for a window update.
* In the worst case, the remote will send
* a window probe to get things going again
*/
}
/*
* Probe a still-connecting, non-blocking socket
* to check if it's still alive
*/
#ifdef PROBE_CONN
if (so->so_state & SS_ISFCONNECTING) {
ret = recv(so->s, (char *)&ret, 0,0);
if (ret < 0) {
/* XXX */
if (errno == EAGAIN || errno == EWOULDBLOCK ||
errno == EINPROGRESS || errno == ENOTCONN)
continue; /* Still connecting, continue */
/* else failed */
so->so_state = SS_NOFDREF;
/* tcp_input will take care of it */
} else {
ret = send(so->s, (char *)&ret, 0,0);
if (ret < 0) {
/* XXX */
if (errno == EAGAIN || errno == EWOULDBLOCK ||
errno == EINPROGRESS || errno == ENOTCONN)
continue;
/* else failed */
so->so_state = SS_NOFDREF;
} else
so->so_state &= ~SS_ISFCONNECTING;
}
tcp_input((struct SLIRPmbuf *)NULL, sizeof(struct ip),so);
} /* SS_ISFCONNECTING */
#endif
}
/*
* Now UDP sockets.
* Incoming packets are sent straight away, they're not buffered.
* Incoming UDP data isn't buffered either.
*/
for (so = udb.so_next; so != &udb; so = so_next) {
so_next = so->so_next;
if (so->s != -1 && FD_ISSET(so->s, readfds)) {
sorecvfrom(so);
}
}
}
/*
* See if we can start outputting
*/
if (if_queued && link_up)
if_start();
/* Update time */
updtime();
/* clear global file descriptor sets.
* these reside on the stack in vl.c
* so they're unusable if we're not in
* slirp_select_fill or slirp_select_poll.
/*
* See if anything has timed out
*/
if (link_up) {
if (time_fasttimo && ((curtime - time_fasttimo) >= FAST_TIMO)) {
tcp_fasttimo();
time_fasttimo = 0;
}
if (do_slowtimo && ((curtime - last_slowtimo) >= SLOW_TIMO)) {
ip_slowtimo();
tcp_slowtimo();
last_slowtimo = curtime;
}
}
ret = 0;
/*
* Check sockets
*/
if (link_up) {
/*
* Check TCP sockets
*/
for (so = tcb.so_next; so != &tcb; so = so_next) {
so_next = so->so_next;
/*
* FD_ISSET is meaningless on these sockets
* (and they can crash the program)
*/
if (so->so_state & SS_NOFDREF || so->s == -1)
continue;
/*
* Check for URG data
* This will soread as well, so no need to
* test for readfds below if this succeeds
*/
if (FD_ISSET(so->s, xfds))
sorecvoob(so);
/*
* Check sockets for reading
*/
else if (FD_ISSET(so->s, readfds)) {
/*
* Check for incoming connections
*/
if (so->so_state & SS_FACCEPTCONN) {
tcp_connect(so);
continue;
}
ret = soread(so);
/* Output it if we read something */
if (ret > 0)
tcp_output(sototcpcb(so));
}
/*
* Check sockets for writing
*/
if (FD_ISSET(so->s, writefds)) {
/*
* Check for non-blocking, still-connecting sockets
*/
if (so->so_state & SS_ISFCONNECTING) {
/* Connected */
so->so_state &= ~SS_ISFCONNECTING;
ret = send(so->s, (char *)&ret, 0, 0);
if (ret < 0) {
/* XXXXX Must fix, zero bytes is a NOP */
if ((errno == EAGAIN) || (errno == EWOULDBLOCK) ||
(errno == EINPROGRESS) || (errno == ENOTCONN))
continue;
/* else failed */
so->so_state = SS_NOFDREF;
}
/*
* Continue tcp_input
*/
tcp_input((struct SLIRPmbuf *)NULL, sizeof(struct ip), so);
} else
ret = sowrite(so);
}
}
/*
* Now UDP sockets.
* Incoming packets are sent straight away, they're not buffered.
* Incoming UDP data isn't buffered either.
*/
global_readfds = NULL;
global_writefds = NULL;
global_xfds = NULL;
for (so = udb.so_next; so != &udb; so = so_next) {
so_next = so->so_next;
if (so->s != -1 && FD_ISSET(so->s, readfds))
sorecvfrom(so);
}
}
/*
* See if we can start outputting
*/
if (if_queued && link_up)
if_start();
/* clear global file descriptor sets.
* these reside on the stack in vl.c
* so they're unusable if we're not in
* slirp_select_fill or slirp_select_poll.
*/
global_readfds = NULL;
global_writefds = NULL;
global_xfds = NULL;
}
#define ETH_ALEN 6
@@ -701,10 +656,3 @@ int slirp_redir(int is_udp, int host_port,
}
return 0;
}
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
int guest_port)
{
return add_exec(&exec_list, do_pty, (char *)args,
addr_low_byte, htons(guest_port));
}

View File

@@ -8,7 +8,7 @@
*
* Main emulator module where most things are controlled.
*
* Version: @(#)pc.c 1.0.89 2018/11/05
* Version: @(#)pc.c 1.0.91 2018/11/14
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -256,7 +256,9 @@ fatal(const char *fmt, ...)
config_save();
dumppic();
#ifdef ENABLE_808X_LOG
dumpregs(1);
#endif
/* Make sure the message does not have a trailing newline. */
if ((sp = strchr(temp, '\n')) != NULL) *sp = '\0';
@@ -658,7 +660,7 @@ again2:
sound_init();
hdc_init(hdc_name);
hdc_init();
return(1);
}
@@ -758,6 +760,9 @@ pc_reset_hard_init(void)
/* Initialize the actual machine and its basic modules. */
machine_init();
/* Reset and reconfigure the serial ports. */
serial_standalone_init();
/* Reset and reconfigure the Sound Card layer. */
sound_card_reset();
@@ -895,7 +900,9 @@ pc_close(thread_t *ptr)
if (dump_on_exit)
dumppic();
#ifdef ENABLE_808X_LOG
dumpregs(0);
#endif
video_close();

View File

@@ -8,7 +8,7 @@
*
* Implementation of the Intel PIC chip emulation.
*
* Version: @(#)pic.c 1.0.2 2018/10/17
* Version: @(#)pic.c 1.0.4 2019/01/21
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
@@ -61,7 +61,7 @@ pic_updatepending()
{
uint16_t temp_pending = 0;
if (AT) {
if ((pic2.pend&~pic2.mask)&~pic2.mask2)
if ((pic2.pend & ~pic2.mask) & ~pic2.mask2)
pic.pend |= pic.icw3;
else
pic.pend &= ~pic.icw3;
@@ -135,7 +135,7 @@ pic_autoeoi()
pic_update_mask(&pic.mask2, pic.ins);
if (AT) {
if (((1 << c) == pic.icw3) && (pic2.pend&~pic2.mask)&~pic2.mask2)
if (((1 << c) == pic.icw3) && (pic2.pend & ~pic2.mask) & ~pic2.mask2)
pic.pend |= pic.icw3;
}
@@ -180,9 +180,9 @@ pic_write(uint16_t addr, uint8_t val, void *priv)
} else {
if (val & 16) { /*ICW1*/
pic.mask = 0;
pic.mask2=0;
pic.icw=1;
pic.icw1=val;
pic.mask2 = 0;
pic.icw = 1;
pic.icw1 = val;
pic.ins = 0;
pic_updatepending();
}
@@ -208,7 +208,7 @@ pic_write(uint16_t addr, uint8_t val, void *priv)
pic_update_mask(&pic.mask2, pic.ins);
if (AT) {
if (((1 << c) == pic.icw3) && (pic2.pend&~pic2.mask)&~pic2.mask2)
if (((1 << c) == pic.icw3) && (pic2.pend & ~pic2.mask) & ~pic2.mask2)
pic.pend |= pic.icw3;
}
@@ -217,8 +217,8 @@ pic_write(uint16_t addr, uint8_t val, void *priv)
pic.pend |= 1 << c;
}
if (c==1 && keywaiting)
intclear&=~1;
if ((c == 1) && keywaiting)
intclear &= ~1;
pic_updatepending();
return;
}
@@ -241,7 +241,10 @@ pic_read(uint16_t addr, void *priv)
}
if (pic.read) {
pic_log("Read PIC ins %02X\n", pic.ins);
return pic.ins | (pic2.ins ? 4 : 0);
if (AT)
return pic.ins | (pic2.ins ? 4 : 0);
else
return pic.ins;
}
return pic.pend;
}
@@ -481,12 +484,27 @@ pic_process_interrupt(PIC* target_pic, int c)
int pic_int = c & 7;
int pic_int_num = 1 << pic_int;
if (pending & pic_int_num) {
int in_service = 0;
#if 0
if (AT) {
in_service = (target_pic->ins & (pic_int_num - 1));
if (c >= 8)
in_service |= (pic.ins & 0x03);
}
if (!AT)
in_service = (target_pic->ins & (pic_int_num - 1));
#else
in_service = (target_pic->ins & (pic_int_num - 1));
if (AT && (c >= 8))
in_service |= (pic.ins & 0x03);
#endif
if ((pending & pic_int_num) && !in_service) {
target_pic->pend &= ~pic_int_num;
target_pic->ins |= pic_int_num;
pic_update_mask(&target_pic->mask2, target_pic->ins);
if (c >= 8) {
if (AT && (c >= 8)) {
pic.ins |= (1 << pic2.icw3); /*Cascade IRQ*/
pic_update_mask(&pic.mask2, pic.ins);
}
@@ -494,7 +512,7 @@ pic_process_interrupt(PIC* target_pic, int c)
pic_updatepending();
if (target_pic->icw4 & 0x02)
(c >= 8) ? pic2_autoeoi() : pic_autoeoi();
(AT && (c >= 8)) ? pic2_autoeoi() : pic_autoeoi();
if (!c)
pit_set_gate(&pit2, 0, 0);

View File

@@ -48,19 +48,43 @@ void setrtcconst(float clock)
void setpitclock(float clock)
{
/* Some calculations are done differently 4.77 MHz, 7.16 MHz, and 9.54 MHz CPU's, so that
loss of precision is avoided and the various component kept in better synchronization. */
cpuclock=clock;
PITCONST=clock/(1193181.0 + (2.0 / 3.0));
CGACONST=(clock/(19687503.0/11.0));
if (clock == 4772728.0) {
PITCONST=4.0;
CGACONST=(8.0 / 3.0);
} else if (clock == 7159092.0) {
/* 7.16 MHz CPU - simplify the calculation to avoid
loss of precision. */
PITCONST=6.0;
CGACONST=4.0;
} else if (clock == 9545456.0) {
/* 9.54 MHz CPU - simplify the calculation to avoid
loss of precision. */
PITCONST=8.0;
CGACONST=(8.0 / 1.5);
} else {
PITCONST=clock/1193182.0;
CGACONST=(clock/(19687503.0/11.0));
}
MDACONST=(clock/2032125.0);
VGACONST1=(clock/25175000.0);
VGACONST2=(clock/28322000.0);
isa_timing = clock/8000000.0;
bus_timing = clock/(double)cpu_busspeed;
video_update_timing();
xt_cpu_multi = (int64_t)((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
/* RTCCONST=clock/32768.0;
TIMER_USEC = (int64_t)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); */
if (clock == 4772728.0)
xt_cpu_multi = 3 * (1 << TIMER_SHIFT);
else if (clock == 7159092.0)
xt_cpu_multi = 2 * (1 << TIMER_SHIFT);
else if (clock == 9545456.0)
xt_cpu_multi = (int64_t)(1.5*(double)(1 << TIMER_SHIFT));
else
xt_cpu_multi = (int64_t)((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
device_speed_changed();
}
@@ -91,14 +115,6 @@ void clearpit()
pit.c[0]=(pit.l[0]<<2);
}
float pit_timer0_freq()
{
if (pit.l[0])
return (1193181.0 + (2.0 / 3.0))/(float)pit.l[0];
else
return (1193181.0 + (2.0 / 3.0))/(float)0x10000;
}
static void pit_set_out(PIT *pit, int t, int out)
{
pit->set_out_funcs[t](out, pit->out[t]);
@@ -306,7 +322,7 @@ static void pit_over(PIT *pit, int t)
int pit_get_timer_0()
{
int read = (int)((int64_t)((pit.c[0] + ((1LL << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT);
int read = (int)((pit.c[0] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT;
if (pit.m[0] == 2)
read++;
if (read < 0)
@@ -323,7 +339,7 @@ static int pit_read_timer(PIT *pit, int t)
timer_clock();
if (pit->using_timer[t] && !(pit->m[t] == 3 && !pit->gate[t]))
{
int read = (int)((int64_t)((pit->c[t] + ((1LL << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT);
int read = (int)((pit->c[t] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT;
if (pit->m[t] == 2)
read++;
if (read < 0)
@@ -343,6 +359,7 @@ void pit_write(uint16_t addr, uint8_t val, void *p)
{
PIT *pit = (PIT *)p;
int t;
double sv = 0.0;
switch (addr&3)
{
@@ -439,7 +456,9 @@ void pit_write(uint16_t addr, uint8_t val, void *p)
pit->wm[t]=0;
break;
}
speakval=(((float)pit->l[2]/(float)pit->l[0])*0x4000)-0x2000;
/* PIT latches are in fractions of 60 ms, so convert to sample using the formula below. */
sv = (((double) pit->l[2]) / 60.0) * 16384.0;
speakval = ((int) sv) - 0x2000;
if (speakval>0x2000) speakval=0x2000;
break;
}
@@ -527,7 +546,7 @@ void pit_set_using_timer(PIT *pit, int t, int using_timer)
if (pit->using_timer[t] && !using_timer)
pit->count[t] = pit_read_timer(pit, t);
if (!pit->using_timer[t] && using_timer)
pit->c[t] = (int64_t)((((int64_t) pit->count[t]) << TIMER_SHIFT) * PITCONST);
pit->c[t] = (int64_t)((((int64_t) pit->count[t]) << TIMER_SHIFT) * PITCONST);
pit->using_timer[t] = using_timer;
pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t];
timer_update_outstanding();

View File

@@ -8,7 +8,7 @@
*
* Provide centralized access to the PNG image handler.
*
* Version: @(#)png.c 1.0.4 2018/10/07
* Version: @(#)png.c 1.0.5 2018/11/19
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -66,100 +66,40 @@
#endif
static void *png_handle = NULL; /* handle to DLL */
# define PNGFUNC(x) PNG_ ## x
# define PNGFUNC(x) png_ ## x
/* Pointers to the real functions. */
static png_structp (*PNG_create_write_struct)(png_const_charp user_png_ver,
png_voidp error_ptr,
png_error_ptr error_fn,
png_error_ptr warn_fn);
static void (*PNG_destroy_write_struct)(png_structpp png_ptr_ptr,
png_infopp info_ptr_ptr);
static png_infop (*PNG_create_info_struct)(png_const_structrp png_ptr);
static void (*PNG_init_io)(png_structrp png_ptr, png_FILE_p fp);
static void (*PNG_set_IHDR)(png_const_structrp png_ptr,
png_inforp info_ptr, png_uint_32 width,
png_uint_32 height, int bit_depth,
int color_type, int interlace_method,
int compression_method,
int filter_method);
static png_size_t (*PNG_get_rowbytes)(png_const_structrp png_ptr,
png_const_inforp info_ptr);
static void (*PNG_write_info)(png_structrp png_ptr,
png_const_inforp info_ptr);
static void (*PNG_write_image)(png_structrp png_ptr,
png_bytepp image);
static void (*PNG_write_row)(png_structrp png_ptr,
png_bytep row);
static void (*PNG_write_rows)(png_structrp png_ptr,
png_bytepp rows, int num);
static void (*PNG_write_end)(png_structrp png_ptr,
png_inforp info_ptr);
#ifdef ENABLE_ESCP_LOG
int png_do_log = ENABLE_ESCP_LOG;
static dllimp_t png_imports[] = {
{ "png_create_write_struct", &PNG_create_write_struct },
{ "png_destroy_write_struct", &PNG_destroy_write_struct },
{ "png_create_info_struct", &PNG_create_info_struct },
{ "png_init_io", &PNG_init_io },
{ "png_set_IHDR", &PNG_set_IHDR },
{ "png_get_rowbytes", &PNG_get_rowbytes },
{ "png_write_info", &PNG_write_info },
{ "png_write_row", &PNG_write_row },
{ "png_write_rows", &PNG_write_rows },
{ "png_write_image", &PNG_write_image },
{ "png_write_end", &PNG_write_end },
{ NULL, NULL }
};
static void
png_log(const char *fmt, ...)
{
va_list ap;
if (escp_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define png_log(fmt, ...)
#endif
static void
error_handler(png_structp arg, const char *str)
{
pclog("PNG: stream 0x%08lx error '%s'\n", arg, str);
png_log("PNG: stream 0x%08lx error '%s'\n", arg, str);
}
static void
warning_handler(png_structp arg, const char *str)
{
pclog("PNG: stream 0x%08lx warning '%s'\n", arg, str);
}
/* Prepare the PNG library for use, load DLL if needed. */
int
png_load(void)
{
const char *fn = PATH_PNG_DLL;
/* If already loaded, good! */
if (png_handle != NULL) return(1);
/* Try loading the DLL. */
png_handle = dynld_module(fn, png_imports);
if (png_handle == NULL) {
ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2081);
pclog("PNG: unable to load '%s'; format disabled!\n", fn);
return(0);
} else
pclog("PNG: module '%s' loaded.\n", fn);
return(1);
}
/* PNG library no longer needed, unload DLL if needed. */
void
png_unload(void)
{
/* Unload the DLL if possible. */
if (png_handle != NULL)
dynld_close(png_handle);
png_handle = NULL;
png_log("PNG: stream 0x%08lx warning '%s'\n", arg, str);
}
@@ -173,18 +113,15 @@ png_write_gray(wchar_t *fn, int inv, uint8_t *pix, int16_t w, int16_t h)
int16_t x, y;
FILE *fp;
/* Load the DLL if needed, give up if that fails. */
if (! png_load()) return(0);
/* Create the image file. */
fp = plat_fopen(fn, L"wb");
if (fp == NULL) {
/* Yes, this looks weird. */
if (fp == NULL)
pclog("PNG: file %ls could not be opened for writing!\n", fn);
png_log("PNG: file %ls could not be opened for writing!\n", fn);
else
error:
pclog("PNG: fatal error, bailing out, error = %i\n", errno);
png_log("PNG: fatal error, bailing out, error = %i\n", errno);
if (png != NULL)
PNGFUNC(destroy_write_struct)(&png, &info);
if (fp != NULL)
@@ -196,13 +133,13 @@ error:
png = PNGFUNC(create_write_struct)(PNG_LIBPNG_VER_STRING, NULL,
error_handler, warning_handler);
if (png == NULL) {
pclog("PNG: create_write_struct failed!\n");
png_log("PNG: create_write_struct failed!\n");
goto error;
}
info = PNGFUNC(create_info_struct)(png);
if (info == NULL) {
pclog("PNG: create_info_struct failed!\n");
png_log("PNG: create_info_struct failed!\n");
goto error;
}
@@ -247,103 +184,81 @@ error:
/* Write the given BITMAP-format image as an 8-bit RGBA PNG image file. */
int
png_write_rgb(wchar_t *fn, uint8_t *pix, int16_t w, int16_t h)
void
png_write_rgb(wchar_t *fn, uint8_t *pix, int16_t w, int16_t h, uint16_t pitch, PALETTE palcol)
{
png_structp png = NULL;
png_infop info = NULL;
png_bytepp rows;
uint8_t *r, *b;
uint32_t *rgb;
png_bytep* rows;
png_color palette[256];
FILE *fp;
int y, x;
/* Load the DLL if needed, give up if that fails. */
if (! png_load()) return(0);
int i;
/* Create the image file. */
fp = plat_fopen(fn, L"wb");
if (fp == NULL) {
pclog("PNG: File %ls could not be opened for writing!\n", fn);
png_log("PNG: File %ls could not be opened for writing!\n", fn);
error:
if (png != NULL)
PNGFUNC(destroy_write_struct)(&png, &info);
if (fp != NULL)
(void)fclose(fp);
return(0);
return;
}
/* Initialize PNG stuff. */
png = PNGFUNC(create_write_struct)(PNG_LIBPNG_VER_STRING, NULL,
error_handler, warning_handler);
if (png == NULL) {
pclog("PNG: create_write_struct failed!\n");
png_log("PNG: create_write_struct failed!\n");
goto error;
}
info = PNGFUNC(create_info_struct)(png);
if (info == NULL) {
pclog("PNG: create_info_struct failed!\n");
png_log("PNG: create_info_struct failed!\n");
goto error;
}
/* Finalize the initing of png library */
PNGFUNC(init_io)(png, fp);
PNGFUNC(set_compression_level)(png, 9);
PNGFUNC(set_IHDR)(png, info, w, h, 8, PNG_COLOR_TYPE_RGB,
/* set other zlib parameters */
PNGFUNC(set_compression_mem_level)(png, 8);
PNGFUNC(set_compression_strategy)(png, PNG_Z_DEFAULT_STRATEGY);
PNGFUNC(set_compression_window_bits)(png, 15);
PNGFUNC(set_compression_method)(png, 8);
PNGFUNC(set_compression_buffer_size)(png, 8192);
PNGFUNC(set_IHDR)(png, info, w, h, 8, PNG_COLOR_TYPE_PALETTE,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
PNGFUNC(write_info)(png, info);
for (i = 0; i < 256; i++) {
palette[i].red = palcol[i].r;
palette[i].green = palcol[i].g;
palette[i].blue = palcol[i].b;
}
PNGFUNC(set_PLTE)(png, info, palette, 256);
/* Create a buffer for scanlines of pixels. */
rows = (png_bytepp)malloc(sizeof(png_bytep) * h);
for (y = 0; y < h; y++) {
rows = (png_bytep *)malloc(sizeof(png_bytep) * h);
for (i = 0; i < h; i++) {
/* Create a buffer for this scanline. */
rows[y] = (png_bytep)malloc(PNGFUNC(get_rowbytes)(png, info));
rows[i] = (pix + (i * pitch));
}
/*
* Process all scanlines in the image.
*
* Since the bitmap is in 'bottom-up' mode, we have to
* convert all pixels to RGB mode, but also 'flip' the
* image to the normal top-down mode.
*/
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
/* Get pointer to pixel in bitmap data. */
b = &pix[((y * w) + x) * 4];
/* Transform if needed. */
if (invert_display) {
rgb = (uint32_t *)b;
*rgb = video_color_transform(*rgb);
}
/* Get pointer to png row data. */
r = &rows[(h - 1) - y][x * 3];
/* Copy the pixel data. */
r[0] = b[2];
r[1] = b[1];
r[2] = b[0];
}
}
/* Write image to the file. */
PNGFUNC(write_image)(png, rows);
/* No longer need the row buffers. */
for (y = 0; y < h; y++)
free(rows[y]);
free(rows);
PNGFUNC(write_end)(png, NULL);
PNGFUNC(destroy_write_struct)(&png, &info);
PNGFUNC(set_rows)(png, info, rows);
PNGFUNC(write_png)(png, info, 0, NULL);
/* Clean up. */
(void)fclose(fp);
(void)fclose(fp);
return(1);
PNGFUNC(destroy_write_struct)(&png, &info);
/* No longer need the row buffers. */
free(rows);
}

View File

@@ -8,7 +8,7 @@
*
* Definitions for the centralized PNG image handler.
*
* Version: @(#)png_struct.h 1.0.1 2018/09/01
* Version: @(#)png_struct.h 1.0.2 2018/11/19
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -52,14 +52,11 @@
extern "C" {
#endif
extern int png_load(void);
extern void png_unload(void);
extern int png_write_gray(wchar_t *path, int invert,
uint8_t *pix, int16_t w, int16_t h);
extern int png_write_rgb(wchar_t *fn,
uint8_t *pix, int16_t w, int16_t h);
extern void png_write_rgb(wchar_t *fn,
uint8_t *pix, int16_t w, int16_t h, uint16_t pitch, PALETTE palcol);
#ifdef __cplusplus
}

View File

@@ -58,7 +58,8 @@
#define FONT_FILE_OCRB L"ocra.ttf"
extern const uint16_t *select_codepage(uint16_t num);
extern const void
select_codepage(uint16_t code, uint16_t *curmap);
#endif /*PRINTER_H*/

View File

@@ -572,18 +572,22 @@ static const struct {
/* Select a ASCII->Unicode mapping by CP number */
const uint16_t *
select_codepage(uint16_t code)
const void
select_codepage(uint16_t code, uint16_t *curmap)
{
int i;
int i = 0;
const uint16_t *map_to_use;
for (i = 0; maps[i].code != -1; i++)
if (maps[i].code == code) return(maps[i].map);
map_to_use = maps[0].map;
if (code == 0)
return(maps[0].map);
//ERRLOG("CPMAP: unsupported code page %i, using CP437...\n", code);
return(maps[0].map);
while (maps[i].code != 0) {
if (maps[i].code == code) {
map_to_use = maps[i].map;
break;
}
i++;
}
for (i = 0; i < 256; i++)
curmap[i] = map_to_use[i];
}

File diff suppressed because it is too large Load Diff

View File

@@ -101,6 +101,9 @@ typedef struct {
/* Output file name. */
wchar_t filename[1024];
/* Printer timeout. */
int64_t timeout;
/* page data (TODO: make configurable) */
double page_width, /* all in inches */
page_height,
@@ -193,6 +196,18 @@ new_page(prnt_t *dev)
}
static void
timeout_timer(void *priv)
{
prnt_t *dev = (prnt_t *) priv;
if (dev->page->dirty)
new_page(dev);
dev->timeout = 0LL;
}
static void
reset_printer(prnt_t *dev)
{
@@ -221,6 +236,8 @@ reset_printer(prnt_t *dev)
/* Create a file for this page. */
plat_tempfile(dev->filename, NULL, L".txt");
dev->timeout = 0LL;
}
@@ -280,7 +297,7 @@ process_char(prnt_t *dev, uint8_t ch)
case 0x11: /* select printer (DC1) */
/* Ignore. */
return 1;
return 0;
case 0x12: /* cancel condensed printing (DC2) */
/* Ignore. */
@@ -375,6 +392,8 @@ write_ctrl(uint8_t val, void *priv)
/* ACK it, will be read on next READ STATUS. */
dev->ack = 1;
dev->timeout = 500000LL * TIMER_USEC;
}
dev->ctrl = val;
@@ -427,6 +446,8 @@ prnt_init(const lpt_device_t *INFO)
//DEBUG("PRNT: created a virtual %ix%i page.\n", dev->page->w, dev->page->h);
timer_add(timeout_timer, &dev->timeout, &dev->timeout, dev);
return(dev);
}
@@ -458,5 +479,7 @@ const lpt_device_t lpt_prt_text_device = {
prnt_close,
write_data,
write_ctrl,
read_status
NULL,
read_status,
NULL
};

View File

@@ -13,7 +13,7 @@
* - c386sx16 BIOS fails checksum
* - the loadfont() calls should be done elsewhere
*
* Version: @(#)rom.c 1.0.42 2018/11/02
* Version: @(#)rom.c 1.0.43 2019/01/13
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -519,6 +519,13 @@ rom_load_bios(int rom_id)
biosmask = 0x3fff;
return(1);
case ROM_ZD_SUPERS: /* [8088] Zenith Data Systems SupersPort */
if (!rom_load_linear(
L"roms/machines/zdsupers/z184m v3.1d.10d",
0x000000, 32768, 0, rom)) break;
biosmask = 0x7fff;
return(1);
case ROM_CMDPC30:
if (! rom_load_interleaved(
L"roms/machines/cmdpc30/commodore pc 30 iii even.bin",

View File

@@ -8,7 +8,7 @@
*
* Definitions for the ROM image handler.
*
* Version: @(#)rom.h 1.0.20 2018/11/02
* Version: @(#)rom.h 1.0.21 2019/01/13
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2018 Fred N. van Kempen.
@@ -58,7 +58,8 @@ enum {
ROM_PC3086,
ROM_OLIM24,
ROM_TANDY1000SL2,
ROM_ZD_SUPERS,
ROM_T3100E,
ROM_AMI286,

View File

@@ -11,7 +11,7 @@
* 1 - BT-545S ISA;
* 2 - BT-958D PCI
*
* Version: @(#)scsi_buslogic.c 1.0.43 2018/10/28
* Version: @(#)scsi_buslogic.c 1.0.44 2018/11/11
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -1575,6 +1575,7 @@ buslogic_init(const device_t *info)
has_scam_rom = 0;
dev->fw_rev = "AA335";
dev->ha_bps = 5000000.0; /* normal SCSI */
dev->max_id = 15; /* wide SCSI */
break;
case CHIP_BUSLOGIC_ISA:
default:
@@ -1588,6 +1589,7 @@ buslogic_init(const device_t *info)
has_scam_rom = 0;
dev->fw_rev = "AA421E";
dev->ha_bps = 10000000.0; /* fast SCSI */
dev->max_id = 15; /* wide SCSI */
break;
case CHIP_BUSLOGIC_MCA:
strcpy(dev->name, "BT-640A");
@@ -1602,6 +1604,7 @@ buslogic_init(const device_t *info)
dev->pos_regs[1] = 0x07;
mca_add(buslogic_mca_read, buslogic_mca_write, dev);
dev->ha_bps = 5000000.0; /* normal SCSI */
dev->max_id = 15; /* wide SCSI */
break;
case CHIP_BUSLOGIC_VLB:
strcpy(dev->name, "BT-445S");
@@ -1610,11 +1613,14 @@ buslogic_init(const device_t *info)
bios_rom_mask = 0x3fff;
has_autoscsi_rom = 1;
autoscsi_rom_name = L"roms/scsi/buslogic/BT-445S_AutoSCSI.rom";
autoscsi_rom_size = 0x4000;
has_scam_rom = 0;
dev->fw_rev = "AA421E";
autoscsi_rom_size = 0x8000;
has_scam_rom = 1;
scam_rom_name = L"roms/scsi/buslogic/BT-445S_SCAM.rom";
scam_rom_size = 0x0200;
dev->fw_rev = "AA507B";
dev->bit32 = 1;
dev->ha_bps = 10000000.0; /* fast SCSI */
dev->max_id = 15; /* wide SCSI */
break;
case CHIP_BUSLOGIC_PCI:
strcpy(dev->name, "BT-958D");

View File

@@ -9,7 +9,7 @@
* Implementation of the CD-ROM drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
* Version: @(#)scsi_cdrom.c 1.0.68 2018/11/02
* Version: @(#)scsi_cdrom.c 1.0.69 2018/11/11
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
@@ -2025,6 +2025,8 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
case GPCMD_PLAY_AUDIO_TRACK_INDEX:
case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10:
case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12:
len = 0;
scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS);
switch(cdb[0]) {
@@ -2168,7 +2170,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
if (ret) {
scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length);
scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length,
len, 0);
alloc_length, 0);
} else
scsi_cdrom_buf_free(dev);
return;

View File

@@ -2652,6 +2652,7 @@ ncr53c8xx_init(const device_t *info)
if (dev->has_bios)
rom_init(&dev->bios, NCR53C8XX_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
if (dev->chip >= CHIP_825) {
if (dev->chip == CHIP_875) {
dev->chip_rev = 0x04;
dev->nvr_path = L"ncr53c875.nvr";

View File

@@ -56,11 +56,37 @@ serial_reset_port(serial_t *dev)
dev->iir = dev->ier = dev->lcr = dev->fcr = 0;
dev->fifo_enabled = 0;
dev->xmit_fifo_pos = dev->rcvr_fifo_pos = 0;
memset(dev->xmit_fifo, 0, 14);
memset(dev->xmit_fifo, 0, 16);
memset(dev->rcvr_fifo, 0, 14);
}
void
serial_transmit_period(serial_t *dev)
{
double ddlab, byte_period, bits, dusec;
ddlab = (double) dev->dlab;
/* Bit period based on DLAB. */
byte_period = (16000000.0 * ddlab) / 1846200.0;
/* Data bits according to LCR 1,0. */
bits = (double) ((dev->lcr & 0x03) + 5);
/* Stop bits. */
if (dev->lcr & 0x04)
bits += !(dev->lcr & 0x03) ? 1.5 : 2.0;
else
bits += 1.0;
/* Parity bits. */
if (dev->lcr & 0x08)
bits += 1.0;
byte_period *= bits;
dusec = (double) TIMER_USEC;
byte_period *= dusec;
dev->transmit_period = (int64_t) byte_period;
}
void
serial_update_ints(serial_t *dev)
{
@@ -73,7 +99,7 @@ serial_update_ints(serial_t *dev)
stat = 1;
dev->iir = 6;
} else if ((dev->ier & 1) && (dev->int_status & SERIAL_INT_RECEIVE)) {
/* Recieved data available */
/* Received data available */
stat = 1;
dev->iir = 4;
} else if ((dev->ier & 2) && (dev->int_status & SERIAL_INT_TRANSMIT)) {
@@ -99,21 +125,19 @@ serial_update_ints(serial_t *dev)
void
serial_write_fifo(serial_t *dev, uint8_t dat)
{
uint8_t old_lsr;
serial_log("serial_write_fifo(%08X, %02X, %i)\n", dev, dat, (dev->type >= SERIAL_NS16550) && dev->fifo_enabled);
if ((dev->type >= SERIAL_NS16550) && dev->fifo_enabled) {
/* FIFO mode. */
dev->rcvr_fifo[dev->rcvr_fifo_pos++] = dat;
dev->rcvr_fifo_pos %= dev->fifo_len;
old_lsr = dev->lsr;
dev->rcvr_fifo_pos %= dev->rcvr_fifo_len;
dev->lsr &= 0xfe;
dev->lsr |= (!dev->rcvr_fifo_pos);
dev->int_status &= SERIAL_INT_RECEIVE;
if (!dev->rcvr_fifo_pos)
if (!dev->rcvr_fifo_pos) {
dev->int_status |= SERIAL_INT_RECEIVE;
if ((old_lsr ^ dev->lsr) & 0x01)
serial_update_ints(dev);
}
} else {
/* Non-FIFO mode. */
dev->dat = dat;
@@ -125,7 +149,7 @@ serial_write_fifo(serial_t *dev, uint8_t dat)
void
serial_dev_write(serial_t *dev, uint8_t val)
serial_transmit(serial_t *dev, uint8_t val)
{
if (dev->mctrl & 0x10)
serial_write_fifo(dev, val);
@@ -134,47 +158,84 @@ serial_dev_write(serial_t *dev, uint8_t val)
}
static void
serial_transmit_timer(void *priv)
{
serial_t *dev = (serial_t *) priv;
if (dev->fifo_enabled) {
serial_transmit(dev, dev->xmit_fifo[dev->xmit_fifo_pos++]);
if (dev->xmit_fifo_pos == 16) {
dev->transmit_delay = 0LL;
dev->xmit_fifo_pos = 0;
/* Mark both FIFO and shift register as empty. */
dev->lsr |= 0x40;
} else
dev->transmit_delay += dev->transmit_period;
} else {
serial_transmit(dev, dev->thr);
dev->transmit_delay = 0LL;
/* Mark both THR and shift register as empty. */
dev->lsr |= 0x40;
}
}
void
serial_write(uint16_t addr, uint8_t val, void *p)
{
serial_t *dev = (serial_t *)p;
uint8_t new_msr, old_lsr, i;
uint8_t new_msr, old_lsr, old;
serial_log("UART: Write %02X to port %02X\n", val, addr);
switch (addr & 7) {
case 0:
if (dev->lcr & 0x80) {
dev->dlab1 = val;
dev->dlab = (dev->dlab & 0xff00) | val;
serial_transmit_period(dev);
return;
}
if ((dev->type >= SERIAL_NS16550) && dev->fifo_enabled) {
/* FIFO mode. */
dev->xmit_fifo[dev->xmit_fifo_pos++] = val;
dev->xmit_fifo_pos %= dev->fifo_len;
dev->xmit_fifo_pos &= 0x0f;
old_lsr = dev->lsr;
dev->lsr &= 0xdf;
if (!dev->xmit_fifo_pos) {
for (i = 0; i < dev->fifo_len; i++)
serial_dev_write(dev, dev->xmit_fifo[i]);
/* Indicate FIFO is no longer empty. */
if (dev->xmit_fifo_pos) {
/* FIFO not yet full. */
/* Update interrupts. */
dev->lsr &= 0x9f;
if ((old_lsr ^ dev->lsr) & 0x20)
serial_update_ints(dev);
} else {
/* FIFO full, begin transmitting. */
dev->transmit_delay = dev->transmit_period;
dev->lsr &= 0xbf;
/* Update interrupts. */
dev->lsr |= 0x20;
dev->int_status |= SERIAL_INT_TRANSMIT;
}
if ((old_lsr ^ dev->lsr) & 0x20)
serial_update_ints(dev);
}
} else {
/* Non-FIFO mode. */
/* Begin transmitting. */
dev->transmit_delay = dev->transmit_period;
dev->thr = val;
/* Clear bit 6 because shift register is full. */
dev->lsr &= 0xbf;
/* But set bit 5 before THR is empty. */
dev->lsr |= 0x20;
/* Update interrupts. */
dev->int_status |= SERIAL_INT_TRANSMIT;
serial_dev_write(dev, val);
serial_update_ints(dev);
}
break;
case 1:
if (dev->lcr & 0x80) {
dev->dlab2 = val;
dev->dlab = (dev->dlab & 0x00ff) | (val << 8);
serial_transmit_period(dev);
return;
}
dev->ier = val & 0xf;
@@ -184,6 +245,13 @@ serial_write(uint16_t addr, uint8_t val, void *p)
if (dev->type >= SERIAL_NS16550) {
dev->fcr = val & 0xf9;
dev->fifo_enabled = val & 0x01;
if (!dev->fifo_enabled) {
memset(dev->rcvr_fifo, 0, 14);
memset(dev->xmit_fifo, 0, 14);
dev->rcvr_fifo_pos = dev->xmit_fifo_pos = 0;
dev->rcvr_fifo_len = 1;
break;
}
if (val & 0x02) {
memset(dev->rcvr_fifo, 0, 14);
dev->rcvr_fifo_pos = 0;
@@ -194,22 +262,25 @@ serial_write(uint16_t addr, uint8_t val, void *p)
}
switch ((val >> 6) & 0x03) {
case 0:
dev->fifo_len = 1;
dev->rcvr_fifo_len = 1;
break;
case 1:
dev->fifo_len = 4;
dev->rcvr_fifo_len = 4;
break;
case 2:
dev->fifo_len = 8;
dev->rcvr_fifo_len = 8;
break;
case 3:
dev->fifo_len = 14;
dev->rcvr_fifo_len = 14;
break;
}
}
break;
case 3:
old = dev->lcr;
dev->lcr = val;
if ((old ^ val) & 0x0f)
serial_transmit_period(dev);
break;
case 4:
if ((val & 2) && !(dev->mctrl & 2)) {
@@ -261,25 +332,23 @@ uint8_t
serial_read(uint16_t addr, void *p)
{
serial_t *dev = (serial_t *)p;
uint8_t old_lsr, ret = 0;
uint8_t ret = 0;
switch (addr & 7) {
case 0:
if (dev->lcr & 0x80) {
ret = dev->dlab1;
ret = dev->dlab & 0xff;
break;
}
if ((dev->type >= SERIAL_NS16550) && dev->fifo_enabled) {
/* FIFO mode. */
ret = dev->rcvr_fifo[dev->rcvr_fifo_pos++];
dev->rcvr_fifo_pos %= dev->fifo_len;
old_lsr = dev->lsr;
dev->rcvr_fifo_pos %= dev->rcvr_fifo_len;
if (!dev->rcvr_fifo_pos) {
dev->lsr &= 0xfe;
dev->int_status &= ~SERIAL_INT_RECEIVE;
if ((old_lsr ^ dev->lsr) & 0x01)
serial_update_ints(dev);
serial_update_ints(dev);
}
} else {
ret = dev->dat;
@@ -287,10 +356,11 @@ serial_read(uint16_t addr, void *p)
dev->int_status &= ~SERIAL_INT_RECEIVE;
serial_update_ints(dev);
}
serial_log("Read data: %02X\n", ret);
break;
case 1:
if (dev->lcr & 0x80)
ret = dev->dlab2;
ret = (dev->dlab >> 8) & 0xff;
else
ret = dev->ier;
break;
@@ -401,23 +471,26 @@ serial_init(const device_t *info)
serial_t *dev = (serial_t *) malloc(sizeof(serial_t));
memset(dev, 0, sizeof(serial_t));
dev->base_address = next_inst ? 0x03f8 : 0x02f8;
dev->inst = next_inst;
if (serial_enabled[next_inst]) {
serial_log("Adding serial port %i...\n", next_inst);
io_sethandler(dev->base_address, 0x0008,
serial_read, NULL, NULL, serial_write, NULL, NULL, dev);
dev->irq = next_inst ? 4 : 3;
dev->type = info->local;
memset(&(serial_devices[next_inst]), 0, sizeof(serial_device_t));
dev->sd = &(serial_devices[next_inst]);
dev->sd->serial = dev;
serial_reset_port(dev);
if (next_inst)
if (next_inst || (info->flags & DEVICE_PCJR))
serial_setup(dev, SERIAL2_ADDR, SERIAL2_IRQ);
else
serial_setup(dev, SERIAL1_ADDR, SERIAL1_IRQ);
/* Default to 1200,N,7. */
dev->dlab = 96;
dev->fcr = 0x06;
serial_transmit_period(dev);
dev->transmit_delay = 0LL;
timer_add(serial_transmit_timer, &dev->transmit_delay, &dev->transmit_delay, dev);
}
next_inst++;
@@ -426,6 +499,20 @@ serial_init(const device_t *info)
}
void
serial_standalone_init(void) {
if (next_inst == 0) {
if (PCJR)
device_add(&i8250_pcjr_device);
else {
device_add_inst(&i8250_device, 1);
device_add_inst(&i8250_device, 2);
}
} else if (next_inst == 1)
device_add_inst(&i8250_device, 2);
};
const device_t i8250_device = {
"Intel 8250(-compatible) UART",
0,
@@ -435,6 +522,15 @@ const device_t i8250_device = {
NULL
};
const device_t i8250_pcjr_device = {
"Intel 8250(-compatible) UART for PCjr",
DEVICE_PCJR,
SERIAL_8250,
serial_init, serial_close, NULL,
NULL, NULL, NULL,
NULL
};
const device_t ns16540_device = {
"National Semiconductor NS16540(-compatible) UART",
0,

View File

@@ -8,7 +8,7 @@
*
* Definitions for the SERIAL card.
*
* Version: @(#)serial.h 1.0.8 2018/11/04
* Version: @(#)serial.h 1.0.9 2018/11/12
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2017,2018 Fred N. van Kempen.
@@ -35,7 +35,7 @@ typedef struct serial_s
{
uint8_t lsr, thr, mctrl, rcr,
iir, ier, lcr, msr;
uint8_t dlab1, dlab2;
uint16_t dlab;
uint8_t dat;
uint8_t int_status;
uint8_t scratch;
@@ -45,11 +45,11 @@ typedef struct serial_s
inst;
uint16_t base_address;
uint8_t fifo_len, fifo_enabled;
uint8_t fifo_enabled, rcvr_fifo_len;
uint8_t rcvr_fifo_pos, rcvr_fifo[14];
uint8_t xmit_fifo_pos, xmit_fifo[14];
uint8_t xmit_fifo_pos, xmit_fifo[16];
int64_t recieve_delay;
int64_t transmit_delay, transmit_period;
struct serial_device_s *sd;
} serial_t;
@@ -68,11 +68,14 @@ extern serial_t * serial_attach(int port,
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
void *priv);
extern void serial_remove(serial_t *dev);
extern void serial_set_type(serial_t *dev, int type);
extern void serial_setup(serial_t *dev, uint16_t addr, int irq);
extern void serial_clear_fifo(serial_t *dev);
extern void serial_write_fifo(serial_t *dev, uint8_t dat);
extern void serial_standalone_init(void);
extern const device_t i8250_device;
extern const device_t i8250_pcjr_device;
extern const device_t ns16540_device;
extern const device_t ns16550_device;

View File

@@ -9,7 +9,7 @@
* Implementation of the SMC FDC37C663 and FDC37C665 Super
* I/O Chips.
*
* Version: @(#)sio_fdc37c66x.c 1.0.13 2018/11/05
* Version: @(#)sio_fdc37c66x.c 1.0.14 2018/11/12
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -208,8 +208,8 @@ fdc37c66x_reset(fdc37c66x_t *dev)
serial_remove(dev->uart[0]);
serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ);
serial_remove(dev->uart[0]);
serial_setup(dev->uart[0], SERIAL2_ADDR, SERIAL2_IRQ);
serial_remove(dev->uart[1]);
serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ);
lpt2_remove();

View File

@@ -9,7 +9,7 @@
* Implementation of the SMC FDC37C932FR and FDC37C935 Super
* I/O Chips.
*
* Version: @(#)sio_fdc37c93x.c 1.0.14 2018/11/05
* Version: @(#)sio_fdc37c93x.c 1.0.15 2018/11/12
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2018 Miran Grca.

View File

@@ -8,7 +8,7 @@
*
* Emulation of the NatSemi PC87306 Super I/O chip.
*
* Version: @(#)sio_pc87306.c 1.0.14 2018/11/05
* Version: @(#)sio_pc87306.c 1.0.15 2018/11/12
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2018 Miran Grca.
@@ -370,7 +370,7 @@ pc87306_reset(pc87306_t *dev)
serial_remove(dev->uart[0]);
serial_remove(dev->uart[1]);
serial_handler(dev, 0);
serial_handler(dev, 0);
serial_handler(dev, 1);
fdc_reset(dev->fdc);
pc87306_gpio_init(dev);
}

View File

@@ -225,7 +225,7 @@ void* fluidsynth_init(const device_t *info)
/* Try loading the DLL. */
#ifdef _WIN32
fluidsynth_handle = dynld_module("libfluidsynth-1.dll", fluidsynth_imports);
fluidsynth_handle = dynld_module("libfluidsynth.dll", fluidsynth_imports);
#else
fluidsynth_handle = dynld_module("libfluidsynth.so", fluidsynth_imports);
#endif

View File

@@ -111,7 +111,9 @@ const lpt_device_t lpt_dac_device =
dac_close,
dac_write_data,
dac_write_ctrl,
dac_read_status
NULL,
dac_read_status,
NULL
};
const lpt_device_t lpt_dac_stereo_device =
{
@@ -120,5 +122,7 @@ const lpt_device_t lpt_dac_stereo_device =
dac_close,
dac_write_data,
dac_write_ctrl,
dac_read_status
NULL,
dac_read_status,
NULL
};

View File

@@ -116,5 +116,7 @@ const lpt_device_t dss_device =
dss_close,
dss_write_data,
dss_write_ctrl,
dss_read_status
NULL,
dss_read_status,
NULL
};

View File

@@ -8,61 +8,62 @@
#include "snd_speaker.h"
int speaker_mute = 0;
int speaker_gated = 0;
int speaker_mute = 0, speaker_gated = 0;
int speaker_enable = 0, was_speaker_enable = 0;
int gated,speakval,speakon;
static int16_t speaker_buffer[SOUNDBUFLEN];
static int32_t speaker_buffer[SOUNDBUFLEN];
static int speaker_pos = 0;
void speaker_update(void)
void
speaker_update(void)
{
int16_t val;
for (; speaker_pos < sound_pos_global; speaker_pos++)
{
if (speaker_gated && was_speaker_enable)
{
if (!pit.m[2] || pit.m[2]==4)
val = speakval;
else if (pit.l[2] < 0x40)
val = 0xa00;
else
val = speakon ? 0x1400 : 0;
}
else
val = was_speaker_enable ? 0x1400 : 0;
int32_t val;
if (!speaker_enable)
was_speaker_enable = 0;
if (speaker_pos >= sound_pos_global)
return;
speaker_buffer[speaker_pos] = val;
}
}
for (; speaker_pos < sound_pos_global; speaker_pos++) {
if (speaker_gated && was_speaker_enable) {
if (!pit.m[2] || pit.m[2]==4)
val = speakval;
else if (pit.l[2] < 0x40)
val = 0xa00;
else
val = speakon ? 0x1400 : 0;
} else
val = was_speaker_enable ? 0x1400 : 0;
static void speaker_get_buffer(int32_t *buffer, int len, void *p)
{
int c;
if (!speaker_enable)
was_speaker_enable = 0;
speaker_update();
if (!speaker_mute)
{
for (c = 0; c < len * 2; c++)
buffer[c] += speaker_buffer[c >> 1];
}
speaker_pos = 0;
speaker_buffer[speaker_pos] = val;
}
}
void speaker_init(void)
static void
speaker_get_buffer(int32_t *buffer, int len, void *p)
{
sound_add_handler(speaker_get_buffer, NULL);
speaker_mute = 0;
int c;
speaker_update();
if (!speaker_mute) {
for (c = 0; c < len * 2; c++)
buffer[c] += speaker_buffer[c >> 1];
}
speaker_pos = 0;
}
void
speaker_init(void)
{
sound_add_handler(speaker_get_buffer, NULL);
speaker_mute = 0;
}

View File

@@ -8,7 +8,7 @@
*
* Sound emulation core.
*
* Version: @(#)sound.c 1.0.25 2018/10/28
* Version: @(#)sound.c 1.0.26 2019/01/13
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -439,6 +439,10 @@ sound_card_reset(void)
mpu401_device_add();
if (GUS)
device_add(&gus_device);
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (GUSMAX)
device_add(&gusmax_device);
#endif
if (GAMEBLASTER)
device_add(&cms_device);
if (SSI2001)

View File

@@ -177,7 +177,7 @@ static void ati18800_recalctimings(svga_t *svga)
svga->vblankstart <<= 1;
}
if (!svga->scrblank && (ati18800->regs[0xb0] & 0x20)) /*Extended 256 colour modes*/
if (!svga->scrblank && ((ati18800->regs[0xb0] & 0x02) || (ati18800->regs[0xb0] & 0x04))) /*Extended 256 colour modes*/
{
svga->render = svga_render_8bpp_highres;
svga->bpp = 8;
@@ -210,7 +210,7 @@ static void *ati18800_init(const device_t *info)
break;
};
svga_init(&ati18800->svga, ati18800, 1 << 19, /*512kb*/
svga_init(&ati18800->svga, ati18800, 1 << 20, /*512kb*/
ati18800_recalctimings,
ati18800_in, ati18800_out,
NULL,

View File

@@ -123,37 +123,20 @@ static void ati28800_out(uint16_t addr, uint8_t val, void *p)
case 0x1cf:
old=ati28800->regs[ati28800->index];
ati28800->regs[ati28800->index] = val;
pclog("ATI write reg=%02x\n", ati28800->index);
ati28800_log("ATI write reg=%02x\n", ati28800->index);
switch (ati28800->index)
{
case 0xb2:
case 0xbe:
case 0xbd:
if (ati28800->regs[0xbe] & 8) /*Read/write bank mode*/
{
if (ati28800->regs[0xbd] & 4)
{
svga->read_bank = (((ati28800->regs[0xb2] >> 5) & 7) * 0x20000);
svga->write_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x20000);
}
else
{
svga->read_bank = (((ati28800->regs[0xb2] >> 5) & 7) * 0x10000);
svga->write_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x10000);
}
}
else /*Single bank mode*/
{
if (ati28800->regs[0xbd] & 4)
{
svga->read_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x20000);
svga->write_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x20000);
}
else
{
svga->read_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x10000);
svga->write_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x10000);
}
}
break;
case 0xb3:
@@ -183,6 +166,7 @@ static void ati28800_out(uint16_t addr, uint8_t val, void *p)
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val)
@@ -321,7 +305,7 @@ static uint8_t ati28800_in(uint16_t addr, void *p)
temp = svga->crtcreg;
break;
case 0x3D5:
temp = svga->crtc[svga->crtcreg];
temp = svga->crtc[svga->crtcreg];
break;
default:
temp = svga_in(addr, svga);
@@ -381,9 +365,11 @@ static void ati28800_recalctimings(svga_t *svga)
{
case 0x00: svga->clock = cpuclock / 42954000.0; break;
case 0x01: svga->clock = cpuclock / 48771000.0; break;
case 0x02: pclog ("clock 2\n"); break;
case 0x03: svga->clock = cpuclock / 36000000.0; break;
case 0x04: svga->clock = cpuclock / 50350000.0; break;
case 0x05: svga->clock = cpuclock / 56640000.0; break;
case 0x06: pclog ("clock 2\n"); break;
case 0x07: svga->clock = cpuclock / 44900000.0; break;
case 0x08: svga->clock = cpuclock / 30240000.0; break;
case 0x09: svga->clock = cpuclock / 32000000.0; break;
@@ -396,15 +382,15 @@ static void ati28800_recalctimings(svga_t *svga)
default: break;
}
if(ati28800->regs[0xb8] & 0x40) svga->clock *= 2;
if(ati28800->regs[0xb8] & 0x40)
svga->clock *= 2;
if (ati28800->regs[0xb6] & 0x10)
{
svga->hdisp <<= 1;
svga->htotal <<= 1;
svga->rowoffset <<= 1;
}
if (ati28800->regs[0xb6] & 0x10)
{
svga->hdisp <<= 1;
svga->htotal <<= 1;
svga->rowoffset <<= 1;
}
if(svga->crtc[0x17] & 4)
{

View File

@@ -0,0 +1,156 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of a AT&T 20c490/491 and 492/493 RAMDAC.
*
* Version: @(#)vid_att20c49x_ramdac.c 1.0.1 2019/01/12
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../device.h"
#include "../mem.h"
#include "video.h"
#include "vid_svga.h"
#include "vid_att20c49x_ramdac.h"
enum
{
ATT_490_1 = 0,
ATT_492_3
};
void
att49x_ramdac_out(uint16_t addr, uint8_t val, att49x_ramdac_t *ramdac, svga_t *svga)
{
switch (addr) {
case 0x3C6:
if (ramdac->state == 4) {
ramdac->state = 0;
ramdac->ctrl = val;
if (ramdac->type == ATT_490_1)
svga_set_ramdac_type(svga, (val & 2) ? RAMDAC_8BIT : RAMDAC_6BIT);
switch (val)
{
case 0:
svga->bpp = 8;
break;
case 0x20:
svga->bpp = 15;
break;
case 0x40:
svga->bpp = 24;
break;
case 0x60:
svga->bpp = 16;
break;
case 0x80:
case 0xa0:
svga->bpp = 15;
break;
case 0xc0:
svga->bpp = 16;
break;
case 0xe0:
svga->bpp = 24;
break;
}
svga_recalctimings(svga);
return;
}
ramdac->state = 0;
break;
case 0x3C7:
case 0x3C8:
case 0x3C9:
ramdac->state = 0;
break;
}
svga_out(addr, val, svga);
}
uint8_t
att49x_ramdac_in(uint16_t addr, att49x_ramdac_t *ramdac, svga_t *svga)
{
uint8_t temp;
temp = svga_in(addr, svga);
switch (addr) {
case 0x3C6:
if (ramdac->state == 4) {
ramdac->state = 0;
temp = ramdac->ctrl;
break;
}
ramdac->state++;
break;
case 0x3C7:
case 0x3C8:
case 0x3C9:
ramdac->state = 0;
break;
}
return temp;
}
static void *
att49x_ramdac_init(const device_t *info)
{
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) malloc(sizeof(att49x_ramdac_t));
memset(ramdac, 0, sizeof(att49x_ramdac_t));
ramdac->type = info->local;
return ramdac;
}
static void
att49x_ramdac_close(void *priv)
{
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) priv;
if (ramdac)
free(ramdac);
}
const device_t att490_ramdac_device =
{
"AT&T 20c490/20c491 RAMDAC",
0, ATT_490_1,
att49x_ramdac_init, att49x_ramdac_close,
NULL, NULL, NULL, NULL
};
const device_t att492_ramdac_device =
{
"AT&T 20c492/20c493 RAMDAC",
0, ATT_492_3,
att49x_ramdac_init, att49x_ramdac_close,
NULL, NULL, NULL, NULL
};

View File

@@ -0,0 +1,32 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Header of the emulation of a Sierra SC1502X RAMDAC.
*
* Used by the TLIVESA1 driver for ET4000.
*
* Version: @(#)vid_sc1502x_ramdac.h 1.0.0 2018/10/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
typedef struct
{
int type;
int state;
uint8_t ctrl;
} att49x_ramdac_t;
extern void att49x_ramdac_out(uint16_t addr, uint8_t val, att49x_ramdac_t *ramdac, svga_t *svga);
extern uint8_t att49x_ramdac_in(uint16_t addr, att49x_ramdac_t *ramdac, svga_t *svga);
extern const device_t att490_ramdac_device;
extern const device_t att492_ramdac_device;

102
src/video/vid_av9194.c Normal file
View File

@@ -0,0 +1,102 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* AV9194 clock generator emulation.
*
* Used by the S3 86c801 (V7-Mirage) card.
*
* Version: @(#)vid_av9194.c 1.0.1 2019/01/12
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2018 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../device.h"
#include "vid_av9194.h"
float
av9194_getclock(int clock, void *p)
{
float ret = 0.0;
switch (clock & 0x0f)
{
case 0:
ret = 25175000.0;
break;
case 1:
ret = 28322000.0;
break;
case 2:
ret = 40000000.0;
break;
case 4:
ret = 50000000.0;
break;
case 5:
ret = 77000000.0;
break;
case 6:
ret = 36000000.0;
break;
case 7:
ret = 44900000.0;
break;
case 8:
ret = 130000000.0;
break;
case 9:
ret = 120000000.0;
break;
case 0xa:
ret = 80000000.0;
break;
case 0xb:
ret = 31500000.0;
break;
case 0xc:
ret = 110000000.0;
break;
case 0xd:
ret = 65000000.0;
break;
case 0xe:
ret = 75000000.0;
break;
case 0xf:
ret = 94500000.0;
break;
}
return ret;
}
static void *
av9194_init(const device_t *info)
{
/* Return something non-NULL. */
return (void *) &av9194_device;
}
const device_t av9194_device =
{
"AV9194 Clock Generator",
0, 0,
av9194_init, NULL,
NULL, NULL, NULL, NULL
};

21
src/video/vid_av9194.h Normal file
View File

@@ -0,0 +1,21 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* AV9194 clock generator emulation.
*
* Used by the S3 86c801 (V7-Mirage) card.
*
* Version: @(#)vid_av9194.c 1.0.1 2019/01/12
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2018 Miran Grca.
*/
float av9194_getclock(int clock, void *p);
extern const device_t av9194_device;

View File

@@ -9,7 +9,7 @@
* Emulation of the Brooktree BT484-485A true colour RAMDAC
* family.
*
* Version: @(#)vid_bt48x_ramdac.c 1.0.14 2018/10/19
* Version: @(#)vid_bt48x_ramdac.c 1.0.16 2019/01/12
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* TheCollector1995,
@@ -42,22 +42,24 @@ enum {
static void
bt48x_set_bpp(bt48x_ramdac_t *ramdac, svga_t *svga)
{
if (!(ramdac->cr2 & 0x20))
if ((!(ramdac->cr2 & 0x20)) || ((ramdac->type >= BT485A) && ((ramdac->cr3 & 0x60) == 0x60)))
svga->bpp = 8;
else switch ((ramdac->cr1 >> 5) & 0x03) {
case 0:
else if ((ramdac->type >= BT485A) && ((ramdac->cr3 & 0x60) == 0x40))
svga->bpp = 24;
else switch (ramdac->cr1 & 0x60) {
case 0x00:
svga->bpp = 32;
break;
case 1:
case 0x20:
if (ramdac->cr1 & 0x08)
svga->bpp = 16;
else
svga->bpp = 15;
break;
case 2:
case 0x40:
svga->bpp = 8;
break;
case 3:
case 0x60:
svga->bpp = 4;
break;
}
@@ -80,7 +82,9 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *r
switch (rs) {
case 0x00: /* Palette Write Index Register (RS value = 0000) */
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
case 0x03:
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
svga->dac_pos = 0;
svga->dac_status = addr & 0x03;
svga->dac_addr = val;
@@ -93,12 +97,6 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *r
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
svga_out(addr, val, svga);
break;
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
svga->dac_pos = 0;
svga->dac_status = rs & 0x03;
ramdac->ext_addr = (val + (rs & 0x01)) & 255;
break;
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
svga->dac_status = 0;
svga->fullchange = changeframecount;
@@ -112,7 +110,7 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *r
svga->dac_pos++;
break;
case 2:
index = ramdac->ext_addr & 3;
index = svga->dac_addr & 3;
ramdac->extpal[index].r = svga->dac_r;
ramdac->extpal[index].g = svga->dac_g;
ramdac->extpal[index].b = val;
@@ -127,7 +125,7 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *r
if (o32 != svga->overscan_color)
svga_recalctimings(svga);
}
ramdac->ext_addr = (ramdac->ext_addr + 1) & 0xff;
svga->dac_addr = (svga->dac_addr + 1) & 0xff;
svga->dac_pos = 0;
break;
}
@@ -147,10 +145,12 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *r
break;
case 0x0a:
if ((ramdac->type >= BT485) && (ramdac->cr0 & 0x80)) {
switch ((svga->dac_addr & 0xff)) {
switch ((svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f))) {
case 0x01:
/* Command Register 3 (RS value = 1010) */
ramdac->cr3 = val;
if (ramdac->type >= BT485A)
bt48x_set_bpp(ramdac, svga);
svga->hwcursor.xsize = svga->hwcursor.ysize = (val & 4) ? 64 : 32;
svga->hwcursor.yoff = (svga->hwcursor.ysize == 32) ? 32 : 0;
svga->hwcursor.x = ramdac->hwc_x - svga->hwcursor.xsize;
@@ -224,16 +224,15 @@ bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, bt48x_ramdac_t *ramdac, svga_t
case 0x00: /* Palette Write Index Register (RS value = 0000) */
case 0x01: /* Palette Data Register (RS value = 0001) */
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
temp = svga_in(addr, svga);
break;
case 0x03: /* Palette Read Index Register (RS value = 0011) */
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
temp = svga->dac_addr & 0xff;
break;
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
temp = ramdac->ext_addr;
break;
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
index = (ramdac->ext_addr - 1) & 3;
index = (svga->dac_addr - 1) & 3;
svga->dac_status = 3;
switch (svga->dac_pos) {
case 0:
@@ -252,7 +251,7 @@ bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, bt48x_ramdac_t *ramdac, svga_t
break;
case 2:
svga->dac_pos=0;
ramdac->ext_addr = ramdac->ext_addr + 1;
svga->dac_addr = svga->dac_addr + 1;
if (svga->ramdac_type == RAMDAC_8BIT)
temp = ramdac->extpal[index].b;
else
@@ -263,9 +262,6 @@ bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, bt48x_ramdac_t *ramdac, svga_t
case 0x06: /* Command Register 0 (RS value = 0110) */
temp = ramdac->cr0;
break;
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
temp = ramdac->ext_addr;
break;
case 0x08: /* Command Register 1 (RS value = 1000) */
temp = ramdac->cr1;
break;
@@ -274,8 +270,9 @@ bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, bt48x_ramdac_t *ramdac, svga_t
break;
case 0x0a:
if ((ramdac->type >= BT485) && (ramdac->cr0 & 0x80)) {
switch ((svga->dac_addr & 0xff)) {
switch ((svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f))) {
case 0x00:
default:
temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00);
break;
case 0x01:

View File

@@ -9,7 +9,7 @@
* Header of the emulation of the Brooktree BT484-BT485A
* true colour RAMDAC family.
*
* Version: @(#)vid_bt485_ramdac.h 1.0.4 2018/10/04
* Version: @(#)vid_bt485_ramdac.h 1.0.5 2019/01/12
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* TheCollector1995,
@@ -31,7 +31,6 @@ typedef struct
uint8_t cr4;
uint8_t status;
uint8_t type;
uint8_t ext_addr;
} bt48x_ramdac_t;
extern void bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *ramdac, svga_t *svga);

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@
* Emulation of select Cirrus Logic cards (CL-GD 5428,
* CL-GD 5429, CL-GD 5430, CL-GD 5434 and CL-GD 5436 are supported).
*
* Version: @(#)vid_cl_54xx.c 1.0.26 2018/10/21
* Version: @(#)vid_cl_54xx.c 1.0.27 2019/01/13
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Barry Rodewald,
@@ -39,6 +39,8 @@
#include "vid_svga_render.h"
#include "vid_cl54xx.h"
#define BIOS_GD5420_PATH L"video/cirruslogic/5420.vbi"
#define BIOS_GD5422_PATH L"video/cirruslogic/cl5422.bin"
#define BIOS_GD5426_PATH L"roms/video/cirruslogic/Diamond SpeedStar PRO VLB v3.04.bin"
#define BIOS_GD5428_ISA_PATH L"roms/video/cirruslogic/5428.bin"
#define BIOS_GD5428_PATH L"roms/video/cirruslogic/vlbusjapan.BIN"
@@ -52,6 +54,10 @@
#define BIOS_GD5446_STB_PATH L"roms/video/cirruslogic/stb nitro64v.BIN"
#define BIOS_GD5480_PATH L"roms/video/cirruslogic/clgd5480.rom"
#define CIRRUS_ID_CLGD5402 0x89
#define CIRRUS_ID_CLGD5420 0x8a
#define CIRRUS_ID_CLGD5422 0x8c
#define CIRRUS_ID_CLGD5424 0x94
#define CIRRUS_ID_CLGD5426 0x90
#define CIRRUS_ID_CLGD5428 0x98
#define CIRRUS_ID_CLGD5429 0x9c
@@ -171,6 +177,8 @@ typedef struct gd54xx_t
uint8_t pci_regs[256];
uint8_t int_line;
uint8_t fc; /* Feature Connector */
int card;
uint32_t lfb_base;
@@ -208,15 +216,24 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx);
static void
gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga);
/* Returns 1 if the card is a 5422+ */
static int
gd54xx_is_5422(svga_t *svga)
{
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422)
return 1;
else
return 0;
}
/* Returns 1 if the card is a 5434, 5436/46, or 5480. */
static int
gd54xx_is_5434(svga_t *svga)
{
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434)
return 1;
else
return 0;
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434)
return 1;
else
return 0;
}
@@ -278,7 +295,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
if (svga->seqaddr > 5) {
o = svga->seqregs[svga->seqaddr & 0x1f];
svga->seqregs[svga->seqaddr & 0x1f] = val;
switch (svga->seqaddr & 0x1f) {
switch (svga->seqaddr) {
case 6:
val &= 0x17;
if (val == 0x12)
@@ -286,6 +303,28 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
else
svga->seqregs[6] = 0x0f;
break;
case 0x0a:
if (gd54xx_is_5434(svga))
svga->seqregs[0x0a] = val;
else { /* Hack to force memory size on some GD-542x BIOSes*/
val &= 0xe7;
switch (gd54xx->vram_size) {
case 0x80000:
svga->seqregs[0x0a] = val | 0x08;
break;
case 0x100000:
svga->seqregs[0x0a] = val | 0x10;
break;
case 0x200000:
svga->seqregs[0x0a] = val | 0x18;
break;
}
}
break;
case 0x0b: case 0x0c: case 0x0d: case 0x0e: /* VCLK stuff */
gd54xx->vclk_n[svga->seqaddr-0x0b] = val;
break;
@@ -311,20 +350,48 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
svga->hwcursor.xsize = svga->hwcursor.ysize = (val & CIRRUS_CURSOR_LARGE) ? 64 : 32;
svga->hwcursor.yoff = (svga->hwcursor.ysize == 32) ? 32 : 0;
if (val & CIRRUS_CURSOR_LARGE)
svga->hwcursor.addr = (((gd54xx->vram_size<<20)-0x4000) + ((svga->seqregs[0x13] & 0x3c) * 256));
svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((svga->seqregs[0x13] & 0x3c) * 256));
else
svga->hwcursor.addr = (((gd54xx->vram_size<<20)-0x4000) + ((svga->seqregs[0x13] & 0x3f) * 256));
svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((svga->seqregs[0x13] & 0x3f) * 256));
break;
case 0x13:
if (svga->seqregs[0x12] & CIRRUS_CURSOR_LARGE)
svga->hwcursor.addr = (((gd54xx->vram_size<<20)-0x4000) + ((val & 0x3c) * 256));
svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((val & 0x3c) * 256));
else
svga->hwcursor.addr = (((gd54xx->vram_size<<20)-0x4000) + ((val & 0x3f) * 256));
svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((val & 0x3f) * 256));
break;
case 0x15:
if (gd54xx_is_5434(svga)) {
/* Hack to force memory size on some GD-543x BIOSes*/
val &= 0xf8;
switch (gd54xx->vram_size) {
case 0x100000:
svga->seqregs[0x15] = val | 0x2;
break;
case 0x200000:
svga->seqregs[0x15] = val | 0x3;
break;
case 0x400000:
svga->seqregs[0x15] = val | 0x4;
break;
}
} else
return;
break;
case 0x07:
svga->set_reset_disabled = svga->seqregs[7] & 1;
if (!gd54xx_is_5422(svga)) {
svga->seqregs[svga->seqaddr] &= 0x0f;
gd543x_recalc_mapping(gd54xx);
}
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429)
svga->set_reset_disabled = svga->seqregs[7] & 1;
case 0x17:
gd543x_recalc_mapping(gd54xx);
if (gd54xx_is_5422(svga))
gd543x_recalc_mapping(gd54xx);
else
return;
break;
}
return;
@@ -660,6 +727,15 @@ gd54xx_recalc_banking(gd54xx_t *gd54xx)
{
svga_t *svga = &gd54xx->svga;
if (!gd54xx_is_5422(svga)) {
gd54xx->bank[0] = (svga->gdcreg[0x09] & 0x7f) << 12;
if (svga->gdcreg[0x0b] & CIRRUS_BANKING_DUAL)
gd54xx->bank[1] = (svga->gdcreg[0x0a] & 0x7f) << 12;
else
gd54xx->bank[1] = gd54xx->bank[0] + 0x8000;
}
else {
if (svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K)
gd54xx->bank[0] = svga->gdcreg[0x09] << 14;
else
@@ -670,11 +746,15 @@ gd54xx_recalc_banking(gd54xx_t *gd54xx)
gd54xx->bank[1] = svga->gdcreg[0x0a] << 14;
else
gd54xx->bank[1] = svga->gdcreg[0x0a] << 12;
} else
gd54xx->bank[1] = gd54xx->bank[0] + 0x8000;
}
else
gd54xx->bank[1] = gd54xx->bank[0] + 0x8000;
}
}
static void
gd543x_recalc_mapping(gd54xx_t *gd54xx)
{
@@ -842,19 +922,24 @@ gd54xx_recalctimings(svga_t *svga)
int d = (gd54xx->vclk_d[clocksel] & 0x3e) >> 1;
int m = gd54xx->vclk_d[clocksel] & 0x01 ? 2 : 1;
float freq = (14318184.0 * ((float)n / ((float)d * m)));
switch (svga->seqregs[7] & (gd54xx_is_5434(svga) ? 0xe : 6)) {
case 2:
freq /= 2.0;
break;
case 4:
if (!gd54xx_is_5434(svga))
freq /= 3.0;
break;
if (gd54xx_is_5422(svga)) {
switch (svga->seqregs[7] & (gd54xx_is_5434(svga) ? 0xe : 6)) {
case 2:
freq /= 2.0;
break;
case 4:
if (!gd54xx_is_5434(svga))
freq /= 3.0;
break;
}
}
svga->clock = cpuclock / freq;
}
svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff;
if (gd54xx->vram_size == (1 << 19)) /* Note : why 512Kb VRAM cards do not wrap */
svga->vram_display_mask = gd54xx->vram_mask;
else
svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff;
}
static
@@ -918,37 +1003,44 @@ void gd54xx_hwcursor_draw(svga_t *svga, int displine)
svga->hwcursor_latch.addr += pitch;
}
static void
gd54xx_rop(gd54xx_t *gd54xx, uint8_t *res, uint8_t *dst, const uint8_t *src) {
switch (gd54xx->blt.rop) {
case 0x00: *res = 0x00; break;
case 0x05: *res = *src & *dst; break;
case 0x06: *res = *dst; break;
case 0x09: *res = *src & ~*dst; break;
case 0x0b: *res = ~*dst; break;
case 0x0d: *res = *src; break;
case 0x0e: *res = 0xff; break;
case 0x50: *res = ~*src & *dst; break;
case 0x59: *res = *src ^ *dst; break;
case 0x6d: *res = *src | *dst; break;
case 0x90: *res = ~(*src | *dst); break;
case 0x95: *res = ~(*src ^ *dst); break;
case 0xad: *res = *src | ~*dst; break;
case 0xd0: *res = ~*src; break;
case 0xd6: *res = ~*src | *dst; break;
case 0xda: *res = ~(*src & *dst); break;
}
}
static void
gd54xx_memsrc_rop(gd54xx_t *gd54xx, svga_t *svga, uint8_t src, uint8_t dst)
{
uint8_t res = src;
svga->changedvram[(gd54xx->blt.dst_addr_backup & svga->vram_mask) >> 12] = changeframecount;
switch (gd54xx->blt.rop) {
case 0x00: res = 0; break;
case 0x05: res = src & dst; break;
case 0x06: res = dst; break;
case 0x09: res = src & ~dst; break;
case 0x0b: res = ~ dst; break;
case 0x0d: res = src; break;
case 0x0e: res = 0xff; break;
case 0x50: res = ~ src & dst; break;
case 0x59: res = src ^ dst; break;
case 0x6d: res = src | dst; break;
case 0x90: res = ~(src | dst); break;
case 0x95: res = ~(src ^ dst); break;
case 0xad: res = src | ~dst; break;
case 0xd0: res = ~src; break;
case 0xd6: res = ~src | dst; break;
case 0xda: res = ~(src & dst); break;
}
gd54xx_rop(gd54xx, &res, &dst, (const uint8_t *) &src);
/* handle transparency compare */
if(gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { /* TODO: 16-bit compare */
/* handle transparency compare */
if (gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { /* TODO: 16-bit compare */
/* if ROP result matches the transparency colour, don't change the pixel */
if((res & (~gd54xx->blt.trans_mask & 0xff)) == ((gd54xx->blt.trans_col & 0xff) & (~gd54xx->blt.trans_mask & 0xff)))
if ((res & (~gd54xx->blt.trans_mask & 0xff)) == ((gd54xx->blt.trans_col & 0xff) & (~gd54xx->blt.trans_mask & 0xff)))
return;
}
}
svga->vram[gd54xx->blt.dst_addr_backup & svga->vram_mask] = res;
}
@@ -1653,7 +1745,10 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p)
break;
case 0x0b:
gd54xx->blt.height = (gd54xx->blt.height & 0x00ff) | (val << 8);
gd54xx->blt.height &= 0x03ff;
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436)
gd54xx->blt.height &= 0x07ff;
else
gd54xx->blt.height &= 0x03ff;
break;
case 0x0c:
gd54xx->blt.dst_pitch = (gd54xx->blt.dst_pitch & 0xff00) | val;
@@ -1843,6 +1938,20 @@ gd543x_mmio_readl(uint32_t addr, void *p)
}
static uint8_t
gd54xx_color_expand(gd54xx_t *gd54xx, int mask, int shift)
{
uint8_t ret;
if (gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP)
ret = gd54xx->blt.fg_col >> (shift << 3);
else
ret = mask ? (gd54xx->blt.fg_col >> (shift << 3)) : (gd54xx->blt.bg_col >> (shift << 3));
return ret;
}
static void
gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
{
@@ -1850,6 +1959,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
int x_max = 0;
int shift = 0, last_x = 0;
uint32_t src_addr = gd54xx->blt.src_addr;
switch (gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
case CIRRUS_BLTMODE_PIXELWIDTH8:
@@ -1881,7 +1991,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
gd54xx->blt.height_internal = gd54xx->blt.height;
gd54xx->blt.x_count = 0;
if ((gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND)) == (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND))
gd54xx->blt.y_count = gd54xx->blt.src_addr & 7;
gd54xx->blt.y_count = src_addr & 7;
else
gd54xx->blt.y_count = 0;
@@ -1915,13 +2025,12 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
if (gd54xx->blt.mode & CIRRUS_BLTMODE_MEMSYSSRC) {
if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) {
if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)
mask = (cpu_dat >> 31);
mask = !!(cpu_dat >> 31);
else
mask = cpu_dat & 0x80;
mask = !!(cpu_dat & 0x80);
switch (gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
case CIRRUS_BLTMODE_PIXELWIDTH8:
src = mask ? gd54xx->blt.fg_col : gd54xx->blt.bg_col;
shift = 0;
break;
case CIRRUS_BLTMODE_PIXELWIDTH16:
@@ -1935,7 +2044,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
break;
}
src = mask ? (gd54xx->blt.fg_col >> (shift << 3)) : (gd54xx->blt.bg_col >> (shift << 3));
src = gd54xx_color_expand(gd54xx, mask, shift);
if (shift == last_x) {
cpu_dat <<= 1;
@@ -1952,22 +2061,23 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
switch (gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND)) {
case 0x00:
src = svga->vram[gd54xx->blt.src_addr & svga->vram_mask];
src_addr += ((gd54xx->blt.mode & CIRRUS_BLTMODE_BACKWARDS) ? -1 : 1);
gd54xx->blt.src_addr += ((gd54xx->blt.mode & CIRRUS_BLTMODE_BACKWARDS) ? -1 : 1);
mask = 1;
break;
case CIRRUS_BLTMODE_PATTERNCOPY:
switch (gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
case CIRRUS_BLTMODE_PIXELWIDTH8:
src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~7)) + (gd54xx->blt.y_count << 3) + (gd54xx->blt.x_count & 7)];
src = svga->vram[(src_addr & (svga->vram_mask & ~7)) + (gd54xx->blt.y_count << 3) + (gd54xx->blt.x_count & 7)];
break;
case CIRRUS_BLTMODE_PIXELWIDTH16:
src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~15)) + (gd54xx->blt.y_count << 4) + (gd54xx->blt.x_count & 15)];
src = svga->vram[(src_addr & (svga->vram_mask & ~15)) + (gd54xx->blt.y_count << 4) + (gd54xx->blt.x_count & 15)];
break;
case CIRRUS_BLTMODE_PIXELWIDTH24:
src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~31)) + (gd54xx->blt.y_count << 5) + (gd54xx->blt.x_count % 24)];
src = svga->vram[(src_addr & (svga->vram_mask & ~31)) + (gd54xx->blt.y_count << 5) + (gd54xx->blt.x_count % 24)];
break;
case CIRRUS_BLTMODE_PIXELWIDTH32:
src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~31)) + (gd54xx->blt.y_count << 5) + (gd54xx->blt.x_count & 31)];
src = svga->vram[(src_addr & (svga->vram_mask & ~31)) + (gd54xx->blt.y_count << 5) + (gd54xx->blt.x_count & 31)];
break;
}
mask = 1;
@@ -1975,23 +2085,23 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
case CIRRUS_BLTMODE_COLOREXPAND:
switch (gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
case CIRRUS_BLTMODE_PIXELWIDTH8:
mask = svga->vram[gd54xx->blt.src_addr & svga->vram_mask] & (0x80 >> gd54xx->blt.x_count);
mask = svga->vram[src_addr & svga->vram_mask] & (0x80 >> gd54xx->blt.x_count);
shift = 0;
break;
case CIRRUS_BLTMODE_PIXELWIDTH16:
mask = svga->vram[gd54xx->blt.src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count >> 1));
shift = (gd54xx->blt.dst_addr & 1);
mask = svga->vram[src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count >> 1));
shift = (gd54xx->blt.x_count & 1);
break;
case CIRRUS_BLTMODE_PIXELWIDTH24:
mask = svga->vram[gd54xx->blt.src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count / 3));
shift = (gd54xx->blt.dst_addr % 3);
mask = svga->vram[src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count / 3));
shift = (gd54xx->blt.x_count % 3);
break;
case CIRRUS_BLTMODE_PIXELWIDTH32:
mask = svga->vram[gd54xx->blt.src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count >> 2));
shift = (gd54xx->blt.dst_addr & 3);
mask = svga->vram[src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count >> 2));
shift = (gd54xx->blt.x_count & 3);
break;
}
src = mask ? (gd54xx->blt.fg_col >> (shift << 3)) : (gd54xx->blt.bg_col >> (shift << 3));
src = gd54xx_color_expand(gd54xx, mask, shift);
break;
case CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND:
if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) {
@@ -2000,37 +2110,36 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
shift = 0;
break;
case CIRRUS_BLTMODE_PIXELWIDTH16:
shift = (gd54xx->blt.dst_addr & 1);
shift = (gd54xx->blt.x_count & 1);
break;
case CIRRUS_BLTMODE_PIXELWIDTH24:
shift = (gd54xx->blt.dst_addr % 3);
shift = (gd54xx->blt.x_count % 3);
break;
case CIRRUS_BLTMODE_PIXELWIDTH32:
shift = (gd54xx->blt.dst_addr & 3);
shift = (gd54xx->blt.x_count & 3);
break;
}
src = (gd54xx->blt.fg_col >> (shift << 3));
} else {
switch (gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
case CIRRUS_BLTMODE_PIXELWIDTH8:
mask = svga->vram[(gd54xx->blt.src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> gd54xx->blt.x_count);
mask = svga->vram[(src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> gd54xx->blt.x_count);
shift = 0;
break;
case CIRRUS_BLTMODE_PIXELWIDTH16:
mask = svga->vram[(gd54xx->blt.src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> (gd54xx->blt.x_count >> 1));
shift = (gd54xx->blt.dst_addr & 1);
mask = svga->vram[(src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> (gd54xx->blt.x_count >> 1));
shift = (gd54xx->blt.x_count & 1);
break;
case CIRRUS_BLTMODE_PIXELWIDTH24:
mask = svga->vram[(gd54xx->blt.src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> (gd54xx->blt.x_count / 3));
shift = (gd54xx->blt.dst_addr % 3);
mask = svga->vram[(src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> (gd54xx->blt.x_count / 3));
shift = (gd54xx->blt.x_count % 3);
break;
case CIRRUS_BLTMODE_PIXELWIDTH32:
mask = svga->vram[(gd54xx->blt.src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> (gd54xx->blt.x_count >> 2));
shift = (gd54xx->blt.dst_addr & 3);
mask = svga->vram[(src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> (gd54xx->blt.x_count >> 2));
shift = (gd54xx->blt.x_count & 3);
break;
}
src = mask ? (gd54xx->blt.fg_col >> (shift << 3)) : (gd54xx->blt.bg_col >> (shift << 3));
src = gd54xx_color_expand(gd54xx, mask, shift);
}
break;
}
@@ -2039,34 +2148,13 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
dst = svga->vram[gd54xx->blt.dst_addr & svga->vram_mask];
svga->changedvram[(gd54xx->blt.dst_addr & svga->vram_mask) >> 12] = changeframecount;
switch (gd54xx->blt.rop) {
case 0x00: dst = 0; break;
case 0x05: dst = src & dst; break;
case 0x06: dst = dst; break;
case 0x09: dst = src & ~dst; break;
case 0x0b: dst = ~ dst; break;
case 0x0d: dst = src; break;
case 0x0e: dst = 0xff; break;
case 0x50: dst = ~ src & dst; break;
case 0x59: dst = src ^ dst; break;
case 0x6d: dst = src | dst; break;
case 0x90: dst = ~(src | dst); break;
case 0x95: dst = ~(src ^ dst); break;
case 0xad: dst = src | ~dst; break;
case 0xd0: dst = ~src; break;
case 0xd6: dst = ~src | dst; break;
case 0xda: dst = ~(src & dst); break;
}
if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
if ((gd54xx->blt.width_backup - gd54xx->blt.width) >= blt_mask &&
!((gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) && mask))
svga->vram[gd54xx->blt.dst_addr & svga->vram_mask] = dst;
} else {
if ((gd54xx->blt.width_backup - gd54xx->blt.width) >= blt_mask &&
!((gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) && !mask))
svga->vram[gd54xx->blt.dst_addr & svga->vram_mask] = dst;
}
gd54xx_rop(gd54xx, (uint8_t *) &dst, (uint8_t *) &dst, (const uint8_t *) &src);
if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_COLOREXPINV))
mask = !mask;
if ((gd54xx->blt.width_backup - gd54xx->blt.width) >= blt_mask &&
!((gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) && !mask))
svga->vram[gd54xx->blt.dst_addr & svga->vram_mask] = dst;
gd54xx->blt.dst_addr += ((gd54xx->blt.mode & CIRRUS_BLTMODE_BACKWARDS) ? -1 : 1);
@@ -2075,7 +2163,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
if (gd54xx->blt.x_count == x_max) {
gd54xx->blt.x_count = 0;
if ((gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND)) == CIRRUS_BLTMODE_COLOREXPAND)
gd54xx->blt.src_addr++;
src_addr++;
}
gd54xx->blt.width--;
@@ -2087,11 +2175,11 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
switch (gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND)) {
case 0x00:
gd54xx->blt.src_addr = gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr_backup + ((gd54xx->blt.mode & CIRRUS_BLTMODE_BACKWARDS) ? -gd54xx->blt.src_pitch : gd54xx->blt.src_pitch);
src_addr = gd54xx->blt.src_addr = gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr_backup + ((gd54xx->blt.mode & CIRRUS_BLTMODE_BACKWARDS) ? -gd54xx->blt.src_pitch : gd54xx->blt.src_pitch);
break;
case CIRRUS_BLTMODE_COLOREXPAND:
if (gd54xx->blt.x_count != 0)
gd54xx->blt.src_addr++;
src_addr++;
break;
}
@@ -2210,18 +2298,28 @@ cl_pci_write(int func, int addr, uint8_t val, void *p)
static void
*gd54xx_init(const device_t *info)
{
gd54xx_t *gd54xx = malloc(sizeof(gd54xx_t));
svga_t *svga = &gd54xx->svga;
int id = info->local & 0xff;
wchar_t *romfn = NULL;
memset(gd54xx, 0, sizeof(gd54xx_t));
gd54xx_t *gd54xx = malloc(sizeof(gd54xx_t));
svga_t *svga = &gd54xx->svga;
int id = info->local & 0xff;
int vram;
wchar_t *romfn = NULL;
memset(gd54xx, 0, sizeof(gd54xx_t));
gd54xx->pci = !!(info->flags & DEVICE_PCI);
gd54xx->vlb = !!(info->flags & DEVICE_VLB);
gd54xx->pci = !!(info->flags & DEVICE_PCI);
gd54xx->vlb = !!(info->flags & DEVICE_VLB);
gd54xx->rev = 0;
gd54xx->has_bios = 1;
switch (id) {
gd54xx->rev = 0;
gd54xx->has_bios = 1;
switch (id) {
case CIRRUS_ID_CLGD5402:
case CIRRUS_ID_CLGD5420:
romfn = BIOS_GD5420_PATH;
break;
case CIRRUS_ID_CLGD5422:
case CIRRUS_ID_CLGD5424:
romfn = BIOS_GD5422_PATH;
break;
case CIRRUS_ID_CLGD5426:
romfn = BIOS_GD5426_PATH;
break;
@@ -2273,39 +2371,63 @@ static void
case CIRRUS_ID_CLGD5480:
romfn = BIOS_GD5480_PATH;
break;
}
}
gd54xx->vram_size = device_get_config_int("memory");
gd54xx->vram_mask = (gd54xx->vram_size << 20) - 1;
if (id >= CIRRUS_ID_CLGD5420)
vram = device_get_config_int("memory");
else
vram = 0;
if (vram)
gd54xx->vram_size = vram << 20;
else
gd54xx->vram_size = 1 << 19;
gd54xx->vram_mask = gd54xx->vram_size - 1;
if (romfn)
rom_init(&gd54xx->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
if (romfn)
rom_init(&gd54xx->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
if (info->flags & DEVICE_ISA)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_isa);
else
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_vlb_pci);
if (info->flags & DEVICE_ISA)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_isa);
else
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_vlb_pci);
svga_init(&gd54xx->svga, gd54xx, gd54xx->vram_size << 20,
svga_init(&gd54xx->svga, gd54xx, gd54xx->vram_size,
gd54xx_recalctimings, gd54xx_in, gd54xx_out,
gd54xx_hwcursor_draw, NULL);
svga->ven_write = gd54xx_write_modes45;
svga->ven_write = gd54xx_write_modes45;
mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel);
mem_mapping_set_p(&svga->mapping, gd54xx);
mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel);
mem_mapping_set_p(&svga->mapping, gd54xx);
mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, gd543x_mmio_read, gd543x_mmio_readw, gd543x_mmio_readl, gd543x_mmio_write, gd543x_mmio_writew, gd543x_mmio_writel, NULL, 0, gd54xx);
mem_mapping_add(&gd54xx->linear_mapping, 0, 0, gd54xx_readb_linear, gd54xx_readw_linear, gd54xx_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear, NULL, 0, svga);
mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, gd543x_mmio_read, gd543x_mmio_readw, gd543x_mmio_readl, gd543x_mmio_write, gd543x_mmio_writew, gd543x_mmio_writel, NULL, 0, gd54xx);
mem_mapping_add(&gd54xx->linear_mapping, 0, 0, gd54xx_readb_linear, gd54xx_readw_linear, gd54xx_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear, NULL, 0, svga);
io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx);
io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx);
svga->hwcursor.yoff = 32;
svga->hwcursor.xoff = 0;
svga->hwcursor.yoff = 32;
svga->hwcursor.xoff = 0;
gd54xx->vclk_n[0] = 0x4a;
gd54xx->vclk_d[0] = 0x2b;
gd54xx->vclk_n[1] = 0x5b;
gd54xx->vclk_d[1] = 0x2f;
if (id >= CIRRUS_ID_CLGD5420) {
gd54xx->vclk_n[0] = 0x4a;
gd54xx->vclk_d[0] = 0x2b;
gd54xx->vclk_n[1] = 0x5b;
gd54xx->vclk_d[1] = 0x2f;
gd54xx->vclk_n[2] = 0x45;
gd54xx->vclk_d[2] = 0x30;
gd54xx->vclk_n[3] = 0x7e;
gd54xx->vclk_d[3] = 0x33;
}
else {
gd54xx->vclk_n[0] = 0x66;
gd54xx->vclk_d[0] = 0x3b;
gd54xx->vclk_n[1] = 0x5b;
gd54xx->vclk_d[1] = 0x2f;
gd54xx->vclk_n[1] = 0x45;
gd54xx->vclk_d[1] = 0x2c;
gd54xx->vclk_n[1] = 0x7e;
gd54xx->vclk_d[1] = 0x33;
}
gd54xx->bank[1] = 0x8000;
@@ -2323,6 +2445,18 @@ static void
return gd54xx;
}
static int
gd5420_available(void)
{
return rom_present(BIOS_GD5420_PATH);
}
static int
gd5422_available(void)
{
return rom_present(BIOS_GD5422_PATH);
}
static int
gd5426_available(void)
{
@@ -2423,6 +2557,26 @@ gd54xx_force_redraw(void *p)
gd54xx->svga.fullchange = changeframecount;
}
static const device_config_t gd5422_config[] =
{
{
"memory","Memory size",CONFIG_SELECTION,"",1,
{
{
"512 KB",0
},
{
"1 MB",1
},
{
""
}
},
},
{
"","",-1
}
};
static const device_config_t gd5428_config[] =
{
@@ -2505,6 +2659,55 @@ static const device_config_t gd5434_config[] =
}
};
const device_t gd5402_isa_device =
{
"Cirrus Logic GD-5402 (ACUMOS AVGA2)",
DEVICE_AT | DEVICE_ISA,
CIRRUS_ID_CLGD5402,
gd54xx_init, gd54xx_close,
NULL,
gd5420_available, /* Common BIOS between 5402 and 5420 */
gd54xx_speed_changed,
gd54xx_force_redraw,
NULL,
};
const device_t gd5420_isa_device =
{
"Cirrus Logic GD-5420",
DEVICE_AT | DEVICE_ISA,
CIRRUS_ID_CLGD5420,
gd54xx_init, gd54xx_close,
NULL,
gd5420_available, /* Common BIOS between 5402 and 5420 */
gd54xx_speed_changed,
gd54xx_force_redraw,
gd5422_config,
};
const device_t gd5422_isa_device = {
"Cirrus Logic GD-5422",
DEVICE_AT | DEVICE_ISA,
CIRRUS_ID_CLGD5422,
gd54xx_init, gd54xx_close,
NULL,
gd5422_available, /* Common BIOS between 5422 and 5424 */
gd54xx_speed_changed,
gd54xx_force_redraw,
gd5422_config,
};
const device_t gd5424_vlb_device = {
"Cirrus Logic GD-5424",
DEVICE_VLB,
CIRRUS_ID_CLGD5424,
gd54xx_init, gd54xx_close,
NULL,
gd5422_available, /* Common BIOS between 5422 and 5424 */
gd54xx_speed_changed,
gd54xx_force_redraw,
gd5422_config,
};
const device_t gd5426_vlb_device =
{
"Cirrus Logic CL-GD 5426 (VLB)",

View File

@@ -1,6 +1,12 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#if defined(DEV_BRANCH)
extern const device_t gd5402_isa_device;
extern const device_t gd5420_isa_device;
extern const device_t gd5422_isa_device;
extern const device_t gd5424_vlb_device;
#endif
extern const device_t gd5426_vlb_device;
extern const device_t gd5428_isa_device;
extern const device_t gd5428_vlb_device;

View File

@@ -376,7 +376,7 @@ void *compaq_cga_init(const device_t *info)
cga_comp_init(self->cga.revision);
timer_add(compaq_cga_poll, &self->cga.vidtime, TIMER_ALWAYS_ENABLED, self);
mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self);
mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, self->cga.vram, MEM_MAPPING_EXTERNAL, self);
io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, self);
if (info->local) {

View File

@@ -9,7 +9,7 @@
* Emulation of the EGA, Chips & Technologies SuperEGA, and
* AX JEGA graphics cards.
*
* Version: @(#)vid_ega.c 1.0.18 2018/09/19
* Version: @(#)vid_ega.c 1.0.19 2018/12/31
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -200,7 +200,7 @@ void ega_out(uint16_t addr, uint8_t val, void *p)
ega->attrff ^= 1;
break;
case 0x3c2:
egaswitchread = val & 0xc;
egaswitchread = (val & 0xc) >> 2;
ega->vres = !(val & 0x80);
ega->pallook = ega->vres ? pallook16 : pallook64;
ega->vidclock = val & 4; /*printf("3C2 write %02X\n",val);*/
@@ -308,13 +308,7 @@ uint8_t ega_in(uint16_t addr, void *p)
case 0x3c1:
return ega->attrregs[ega->attraddr];
case 0x3c2:
switch (egaswitchread)
{
case 0xc: return (egaswitches & 1) ? 0x10 : 0;
case 0x8: return (egaswitches & 2) ? 0x10 : 0;
case 0x4: return (egaswitches & 4) ? 0x10 : 0;
case 0x0: return (egaswitches & 8) ? 0x10 : 0;
}
return (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00;
break;
case 0x3c4:
return ega->seqaddr;
@@ -968,7 +962,7 @@ void ega_init(ega_t *ega, int monitor_type, int is_mono)
egaswitches = monitor_type & 0xf;
ega->vram_limit = 256 * 1024;
ega->vrammask = ega->vram_limit-1;
ega->vrammask = ega->vram_limit - 1;
old_overscan_color = 0;
@@ -1030,10 +1024,10 @@ static void *ega_standalone_init(const device_t *info)
}
monitor_type = device_get_config_int("monitor_type");
ega_init(ega, monitor_type, (monitor_type & 0xf) == 10);
ega_init(ega, monitor_type, (monitor_type & 0x0F) == 0x0B);
ega->vram_limit = device_get_config_int("memory") * 1024;
ega->vrammask = ega->vram_limit-1;
ega->vrammask = ega->vram_limit - 1;
mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega);
timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega);
@@ -1185,6 +1179,15 @@ static void ega_speed_changed(void *p)
}
/* SW1 SW2 SW3 SW4
OFF OFF ON OFF Monochrome (5151) 1011 0x0B
ON OFF OFF ON Color 40x25 (5153) 0110 0x06
OFF OFF OFF ON Color 80x25 (5153) 0111 0x07
ON ON ON OFF Enhanced Color - Normal Mode (5154) 1000 0x08
OFF ON ON OFF Enhanced Color - Enhanced Mode (5154) 1001 0x09
0 = Switch closed (ON);
1 = Switch open (OFF). */
static const device_config_t ega_config[] =
{
{
@@ -1211,28 +1214,32 @@ static const device_config_t ega_config[] =
.selection =
{
{
.description = "EGA Colour, 40x25",
.value = 6
.description = "Monochrome (5151/MDA) (white)",
.value = 0x0B | (DISPLAY_WHITE << 4)
},
{
.description = "EGA Colour, 80x25",
.value = 7
.description = "Monochrome (5151/MDA) (green)",
.value = 0x0B | (DISPLAY_GREEN << 4)
},
{
.description = "EGA Colour, ECD",
.value = 9
.description = "Monochrome (5151/MDA) (amber)",
.value = 0x0B | (DISPLAY_AMBER << 4)
},
{
.description = "EGA Monochrome (white)",
.value = 10 | (DISPLAY_WHITE << 4)
.description = "Color 40x25 (5153/CGA)",
.value = 0x06
},
{
.description = "EGA Monochrome (green)",
.value = 10 | (DISPLAY_GREEN << 4)
.description = "Color 80x25 (5153/CGA)",
.value = 0x07
},
{
.description = "EGA Monochrome (amber)",
.value = 10 | (DISPLAY_AMBER << 4)
.description = "Enhanced Color - Normal Mode (5154/ECD)",
.value = 0x08
},
{
.description = "Enhanced Color - Enhanced Mode (5154/ECD)",
.value = 0x09
},
{
.description = ""

View File

@@ -8,7 +8,7 @@
*
* Hercules emulation.
*
* Version: @(#)vid_hercules.c 1.0.15 2018/10/28
* Version: @(#)vid_hercules.c 1.0.16 2018/11/18
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -382,7 +382,7 @@ hercules_init(const device_t *info)
mem_mapping_add(&dev->mapping, 0xb0000, 0x08000,
hercules_read,NULL,NULL, hercules_write,NULL,NULL,
NULL, MEM_MAPPING_EXTERNAL, dev);
dev->vram, MEM_MAPPING_EXTERNAL, dev);
io_sethandler(0x03b0, 16,
hercules_in,NULL,NULL, hercules_out,NULL,NULL, dev);

View File

@@ -8,7 +8,7 @@
*
* Hercules Plus emulation.
*
* Version: @(#)vid_herculesplus.c 1.0.13 2018/10/28
* Version: @(#)vid_herculesplus.c 1.0.14 2018/11/18
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -613,7 +613,7 @@ herculesplus_init(const device_t *info)
mem_mapping_add(&dev->mapping, 0xb0000, 0x10000,
herculesplus_read,NULL,NULL,
herculesplus_write,NULL,NULL,
NULL, MEM_MAPPING_EXTERNAL, dev);
dev->vram, MEM_MAPPING_EXTERNAL, dev);
io_sethandler(0x03b0, 16,
herculesplus_in,NULL, NULL, herculesplus_out,NULL,NULL, dev);

View File

@@ -8,7 +8,7 @@
*
* S3 emulation.
*
* Version: @(#)vid_s3.c 1.0.25 2018/10/04
* Version: @(#)vid_s3.c 1.0.26 2019/01/12
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -33,9 +33,14 @@
#include "vid_svga.h"
#include "vid_svga_render.h"
#include "vid_sdac_ramdac.h"
#include "vid_att20c49x_ramdac.h"
#include "vid_bt48x_ramdac.h"
#include "vid_av9194.h"
#include "vid_icd2061.h"
#include "../cpu/cpu.h"
#define ROM_V7MIRAGE_86C801 L"roms/video/s3/v7mirage.vbi"
#define ROM_PHOENIX_86C805 L"roms/video/s3/805.vbi"
#define ROM_PARADISE_BAHAMAS64 L"roms/video/s3/bahamas64.bin"
#define ROM_PHOENIX_VISION864 L"roms/video/s3/86c864p.bin"
#define ROM_DIAMOND_STEALTH64_964 L"roms/video/s3/964_107h.rom"
@@ -53,17 +58,23 @@ enum
S3_PHOENIX_TRIO64,
S3_PHOENIX_TRIO64_ONBOARD,
S3_PHOENIX_VISION864,
S3_DIAMOND_STEALTH64_764
S3_DIAMOND_STEALTH64_764,
S3_V7MIRAGE_86C801,
S3_PHOENIX_86C805
};
enum
{
S3_86C801,
S3_86C805,
S3_VISION864,
S3_VISION964,
S3_TRIO32,
S3_TRIO64
};
static video_timings_t timing_s3_86c801 = {VIDEO_ISA, 4, 4, 5, 20, 20, 35};
static video_timings_t timing_s3_86c805 = {VIDEO_BUS, 4, 4, 5, 20, 20, 35};
static video_timings_t timing_s3_stealth64 = {VIDEO_BUS, 2, 2, 4, 26, 26, 42};
static video_timings_t timing_s3_vision864 = {VIDEO_BUS, 4, 4, 5, 20, 20, 35};
static video_timings_t timing_s3_vision964 = {VIDEO_BUS, 2, 2, 4, 20, 20, 35};
@@ -116,7 +127,6 @@ typedef struct s3_t
rom_t bios_rom;
svga_t svga;
icd2061_t icd2061;
uint8_t bank;
uint8_t ma_ext;
@@ -131,8 +141,6 @@ typedef struct s3_t
int packed_mmio;
int p86c911_compat;
uint32_t linear_base, linear_size;
uint8_t pci_regs[256];
@@ -140,7 +148,8 @@ typedef struct s3_t
uint32_t vram_mask;
uint8_t status_9ae8;
uint8_t data_available;
struct
{
uint16_t subsys_cntl;
@@ -1011,7 +1020,7 @@ void s3_out(uint16_t addr, uint8_t val, void *p)
case 0x3c2:
if (s3->chip == S3_VISION964) {
if (((val >> 2) & 3) != 3)
icd2061_write(&s3->icd2061, (val >> 2) & 3);
icd2061_write(svga->clock_gen, (val >> 2) & 3);
}
break;
@@ -1037,18 +1046,20 @@ void s3_out(uint16_t addr, uint8_t val, void *p)
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
if ((svga->crtc[0x55] & 0x03) == 0x00)
rs2 = !!(svga->crtc[0x43] & 2);
rs2 = !!(svga->crtc[0x43] & 0x02);
else
rs2 = (svga->crtc[0x55] & 0x01);
if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64)
svga_out(addr, val, svga);
else if (s3->chip == S3_VISION964) {
if (!(svga->crtc[0x45] & 0x02))
if (!(svga->crtc[0x45] & 0x20))
rs3 = !!(svga->crtc[0x55] & 0x02);
else
rs3 = 0;
bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga);
} else
} else if (s3->chip == S3_86C801 || s3->chip == S3_86C805)
att49x_ramdac_out(addr, val, svga->ramdac, svga);
else
sdac_ramdac_out(addr, rs2, val, svga->ramdac, svga);
return;
@@ -1060,7 +1071,14 @@ void s3_out(uint16_t addr, uint8_t val, void *p)
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) return;
if ((svga->crtcreg >= 0x20) && (svga->crtcreg < 0x40) &&
(svga->crtcreg != 0x36) && (svga->crtcreg != 0x38) &&
(svga->crtcreg != 0x39) && ((svga->crtc[0x38] & 0xcc) != 0x48))
return;
if ((svga->crtcreg >= 0x40) && ((svga->crtc[0x39] & 0xe0) != 0xa0))
return;
if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5))
return;
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
switch (svga->crtcreg)
@@ -1132,6 +1150,8 @@ void s3_out(uint16_t addr, uint8_t val, void *p)
svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16);
if ((s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) && svga->bpp == 32)
svga->hwcursor.x <<= 1;
else if ((s3->chip == S3_86C801 || s3->chip == S3_86C805) && (svga->bpp == 15 || svga->bpp == 16))
svga->hwcursor.x >>= 1;
break;
case 0x4a:
@@ -1173,7 +1193,7 @@ void s3_out(uint16_t addr, uint8_t val, void *p)
case 0x42:
if (s3->chip == S3_VISION964) {
if (((svga->miscout >> 2) & 3) == 3)
icd2061_write(&s3->icd2061, svga->crtc[0x42] & 0x0f);
icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f);
}
break;
@@ -1233,7 +1253,9 @@ uint8_t s3_in(uint16_t addr, void *p)
else if (s3->chip == S3_VISION964) {
rs3 = !!(svga->crtc[0x55] & 0x02);
return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga);
} else
} else if (s3->chip == S3_86C801 || s3->chip == S3_86C805)
return att49x_ramdac_in(addr, svga->ramdac, svga);
else
return sdac_ramdac_in(addr, rs2, svga->ramdac, svga);
break;
@@ -1259,6 +1281,10 @@ uint8_t s3_in(uint16_t addr, void *p)
return temp;
case 0x69: return s3->ma_ext;
case 0x6a: return s3->bank;
/* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C
to be mirrors of 59 and 5A. */
case 0x6b: return svga->crtc[0x59];
case 0x6c: return svga->crtc[0x5a] & 0x80;
}
return svga->crtc[svga->crtcreg];
}
@@ -1295,9 +1321,15 @@ void s3_recalctimings(svga_t *svga)
svga->clock = cpuclock / svga->getclock(svga->crtc[0x42] & 0x0f, svga->clock_gen);
else
svga->clock = cpuclock / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen);
} else if (s3->chip == S3_86C801 || s3->chip == S3_86C805) {
svga->interlace = svga->crtc[0x42] & 0x20;
if (((svga->miscout >> 2) & 3) == 3)
svga->clock = cpuclock / svga->getclock(svga->crtc[0x42] & 0x0f, svga->clock_gen);
else
svga->clock = cpuclock / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen);
} else {
svga->interlace = svga->crtc[0x42] & 0x20;
svga->clock = cpuclock / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen);
svga->clock = cpuclock / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen);
}
switch (svga->crtc[0x67] >> 4)
@@ -1315,19 +1347,22 @@ void s3_recalctimings(svga_t *svga)
case 8:
svga->render = svga_render_8bpp_highres;
break;
case 15:
svga->render = svga_render_15bpp_highres;
if (s3->chip != S3_VISION964)
case 15:
svga->render = svga_render_15bpp_highres;
if (s3->chip != S3_VISION964 && s3->chip != S3_86C801)
svga->hdisp /= 2;
break;
case 16:
svga->render = svga_render_16bpp_highres;
if (s3->chip != S3_VISION964)
if (s3->chip != S3_VISION964 && s3->chip != S3_86C801)
svga->hdisp /= 2;
break;
case 24:
case 24:
svga->render = svga_render_24bpp_highres;
svga->hdisp /= 3;
if (s3->chip != S3_86C801 && s3->chip != S3_86C805)
svga->hdisp /= 3;
else
svga->hdisp = (svga->hdisp * 2) / 3;
break;
case 32:
svga->render = svga_render_32bpp_highres;
@@ -1341,7 +1376,7 @@ void s3_recalctimings(svga_t *svga)
void s3_updatemapping(s3_t *s3)
{
svga_t *svga = &s3->svga;
if (!(s3->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))
{
mem_mapping_disable(&svga->mapping);
@@ -1377,8 +1412,9 @@ void s3_updatemapping(s3_t *s3)
break;
}
if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/
if ((svga->crtc[0x58] & 0x10) || (s3->accel.advfunc_cntl & 0x10))
{
/*Linear framebuffer*/
mem_mapping_disable(&svga->mapping);
s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24);
@@ -1397,6 +1433,8 @@ void s3_updatemapping(s3_t *s3)
switch (s3->chip) {
case S3_TRIO32:
case S3_TRIO64:
case S3_86C801:
case S3_86C805:
s3->linear_size = 0x400000;
break;
default:
@@ -1469,6 +1507,7 @@ void s3_accel_out(uint16_t port, uint8_t val, void *p)
break;
case 0x4ae8:
s3->accel.advfunc_cntl = val;
s3_updatemapping(s3);
break;
}
}
@@ -1541,19 +1580,29 @@ uint8_t s3_accel_in(uint16_t port, void *p)
case 0x9ae8:
if (!s3->blitter_busy)
wake_fifo_thread(s3);
if (FIFO_FULL)
if (FIFO_FULL && s3->chip != S3_86C801 && s3->chip != S3_86C805)
return 0xff; /*FIFO full*/
return 0; /*FIFO empty*/
case 0x9ae9:
if (!s3->blitter_busy)
wake_fifo_thread(s3);
temp = 0;
if (!FIFO_EMPTY)
temp |= 0x02; /*Hardware busy*/
if (s3->chip == S3_86C801 || s3->chip == S3_86C805)
{
if (!FIFO_EMPTY)
temp |= 0x02;
if (s3->data_available)
temp |= 0x01;
}
else
temp |= s3->status_9ae8; /*FIFO empty*/
if (FIFO_FULL)
temp |= 0xf8; /*FIFO full*/
{
if (!FIFO_EMPTY)
temp |= 0x02; /*Hardware busy*/
else
temp |= s3->status_9ae8; /*FIFO empty*/
if (FIFO_FULL)
temp |= 0xf8; /*FIFO full*/
}
return temp;
case 0xa2e8:
@@ -1805,7 +1854,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3;
uint32_t rd_mask = s3->accel.rd_mask;
int cmd = s3->accel.cmd >> 13;
if ((s3->chip == S3_TRIO64) && (s3->accel.cmd & (1 << 11)))
cmd |= 8;
@@ -1845,6 +1894,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
if (s3->bpp == 0) compare &= 0xff;
if (s3->bpp == 1) compare &= 0xffff;
switch (cmd)
{
case 1: /*Draw line*/
@@ -1859,10 +1909,12 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
}
s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/
s3->data_available = 0;
if ((s3->accel.cmd & 0x100) && !cpu_input)
{
s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/
s3->data_available = 1;
return; /*Wait for data from CPU*/
}
@@ -2008,10 +2060,12 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
}
s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/
s3->data_available = 0;
if ((s3->accel.cmd & 0x100) && !cpu_input)
{
s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/
s3->data_available = 1;
return; /*Wait for data from CPU*/
}
@@ -2741,15 +2795,14 @@ void s3_pci_write(int func, int addr, uint8_t val, void *p)
s3_updatemapping(s3);
break;
case 0x12:
svga->crtc[0x5a] = val & 0x80;
/* svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); */
s3_updatemapping(s3);
case 0x12:
svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80);
s3_updatemapping(s3);
break;
case 0x13:
svga->crtc[0x59] = val;
s3_updatemapping(s3);
break;
case 0x13:
svga->crtc[0x59] = val;
s3_updatemapping(s3);
break;
case 0x30: case 0x32: case 0x33:
if (!s3->has_bios)
@@ -2795,6 +2848,16 @@ static void *s3_init(const device_t *info)
uint32_t vram_size;
switch(info->local) {
case S3_V7MIRAGE_86C801:
bios_fn = ROM_V7MIRAGE_86C801;
chip = S3_86C801;
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801);
break;
case S3_PHOENIX_86C805:
bios_fn = ROM_PHOENIX_86C805;
chip = S3_86C805;
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805);
break;
case S3_PARADISE_BAHAMAS64:
bios_fn = ROM_PARADISE_BAHAMAS64;
chip = S3_VISION864;
@@ -2882,39 +2945,43 @@ static void *s3_init(const device_t *info)
s3_hwcursor_draw,
NULL);
switch (vram) {
case 0: /* 512 kB */
svga->vram_mask = (1 << 19) - 1;
svga->vram_max = 2 << 20;
break;
case 1: /* 1 MB */
/* VRAM in first MB, mirrored in 2nd MB, 3rd and 4th MBs are open bus.
if (s3->chip != S3_86C801 && s3->chip != S3_86C805) {
switch (vram) {
case 0: /* 512 kB */
svga->vram_mask = (1 << 19) - 1;
svga->vram_max = 2 << 20;
break;
case 1: /* 1 MB */
/* VRAM in first MB, mirrored in 2nd MB, 3rd and 4th MBs are open bus.
This works with the #9 9FX BIOS, and matches how my real Trio64 behaves,
but does not work with the Phoenix EDO BIOS. Possibly an FPM/EDO difference? */
svga->vram_mask = (1 << 20) - 1;
svga->vram_max = 2 << 20;
break;
case 2:
default: /*2 MB */
/* VRAM in first 2 MB, 3rd and 4th MBs are open bus. */
svga->vram_mask = (2 << 20) - 1;
svga->vram_max = 2 << 20;
break;
case 4: /*4MB*/
svga->vram_mask = (4 << 20) - 1;
svga->vram_max = 4 << 20;
break;
case 8: /*8MB*/
svga->vram_mask = (8 << 20) - 1;
svga->vram_max = 8 << 20;
break;
This works with the #9 9FX BIOS, and matches how my real Trio64 behaves,
but does not work with the Phoenix EDO BIOS. Possibly an FPM/EDO difference? */
svga->vram_mask = (1 << 20) - 1;
svga->vram_max = 2 << 20;
break;
case 2:
default: /*2 MB */
/* VRAM in first 2 MB, 3rd and 4th MBs are open bus. */
svga->vram_mask = (2 << 20) - 1;
svga->vram_max = 2 << 20;
break;
case 4: /*4MB*/
svga->vram_mask = (4 << 20) - 1;
svga->vram_max = 4 << 20;
break;
case 8: /*8MB*/
svga->vram_mask = (8 << 20) - 1;
svga->vram_max = 8 << 20;
break;
}
}
if (info->flags & DEVICE_PCI)
svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5);
else
else if (info->flags & DEVICE_VLB)
svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5);
else
svga->crtc[0x36] = 3 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5);
svga->crtc[0x37] = 1 | (7 << 5);
svga->vblank_start = s3_vblank_start;
@@ -2939,6 +3006,34 @@ static void *s3_init(const device_t *info)
s3->int_line = 0;
switch(info->local) {
case S3_V7MIRAGE_86C801:
svga->decode_mask = (2 << 20) - 1;
stepping = 0xa0; /*86C801/86C805*/
s3->id = stepping;
s3->id_ext = stepping;
s3->id_ext_pci = 0;
s3->packed_mmio = 0;
svga->crtc[0x5a] = 0x0a;
svga->ramdac = device_add(&att490_ramdac_device);
svga->clock_gen = device_add(&av9194_device);
svga->getclock = av9194_getclock;
break;
case S3_PHOENIX_86C805:
svga->decode_mask = (2 << 20) - 1;
stepping = 0xa0; /*86C801/86C805*/
s3->id = stepping;
s3->id_ext = stepping;
s3->id_ext_pci = 0;
s3->packed_mmio = 0;
svga->crtc[0x5a] = 0x0a;
svga->ramdac = device_add(&att492_ramdac_device);
svga->clock_gen = device_add(&av9194_device);
svga->getclock = av9194_getclock;
break;
case S3_PARADISE_BAHAMAS64:
case S3_PHOENIX_VISION864:
svga->decode_mask = (8 << 20) - 1;
@@ -2962,12 +3057,12 @@ static void *s3_init(const device_t *info)
s3->id_ext = s3->id_ext_pci = stepping;
s3->packed_mmio = 1;
svga->crtc[0x5a] = 0x0a;
svga->ramdac = device_add(&bt485_ramdac_device);
svga->clock_gen = device_add(&icd2061_device);
svga->getclock = icd2061_getclock;
break;
case S3_PHOENIX_TRIO32:
svga->decode_mask = (4 << 20) - 1;
s3->id = 0xe1; /*Trio32*/
@@ -3003,6 +3098,16 @@ static void *s3_init(const device_t *info)
return s3;
}
static int s3_v7mirage_86c801_available(void)
{
return rom_present(ROM_V7MIRAGE_86C801);
}
static int s3_phoenix_86c805_available(void)
{
return rom_present(ROM_PHOENIX_86C805);
}
static int s3_bahamas64_available(void)
{
return rom_present(ROM_PARADISE_BAHAMAS64);
@@ -3159,6 +3264,34 @@ static const device_config_t s3_config[] =
}
};
const device_t s3_v7mirage_86c801_isa_device =
{
"SPEA V7 Mirage (S3 86c801) ISA",
DEVICE_AT | DEVICE_ISA,
S3_V7MIRAGE_86C801,
s3_init,
s3_close,
NULL,
s3_v7mirage_86c801_available,
s3_speed_changed,
s3_force_redraw,
s3_9fx_config
};
const device_t s3_phoenix_86c805_vlb_device =
{
"Phoenix S3 86c805 VLB",
DEVICE_VLB,
S3_PHOENIX_86C805,
s3_init,
s3_close,
NULL,
s3_phoenix_86c805_available,
s3_speed_changed,
s3_force_redraw,
s3_9fx_config
};
const device_t s3_bahamas64_vlb_device =
{
"Paradise Bahamas 64 (S3 Vision864) VLB",

View File

@@ -9,7 +9,7 @@
* Emulation of the S3 Trio32, S3 Trio64, and S3 Vision864
* graphics cards.
*
* Version: @(#)vid_s3.h 1.0.3 2018/09/19
* Version: @(#)vid_s3.h 1.0.4 2019/01/12
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -17,6 +17,8 @@
* Copyright 2016-2018 Miran Grca.
*/
const device_t s3_v7mirage_86c801_isa_device;
const device_t s3_phoenix_86c805_vlb_device;
const device_t s3_bahamas64_vlb_device;
const device_t s3_bahamas64_pci_device;
const device_t s3_9fx_vlb_device;
@@ -32,4 +34,3 @@ const device_t s3_diamond_stealth64_pci_device;
const device_t s3_diamond_stealth64_vlb_device;
const device_t s3_diamond_stealth64_964_pci_device;
const device_t s3_diamond_stealth64_964_vlb_device;
/* const device_t s3_miro_vision964_device; */

View File

@@ -2967,7 +2967,7 @@ static void dest_pixel_lit_texture_modulate(s3d_state_t *state)
static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2)
{
svga_t *svga = &virge->svga;
uint8_t *vram = virge->svga.vram;
uint8_t *vram = svga->vram;
int x_dir = s3d_tri->tlr ? 1 : -1;
@@ -3022,7 +3022,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3
y_count -= diff_y;
}
if ((state->y - y_count) < s3d_tri->clip_t)
y_count = state->y - s3d_tri->clip_t;
y_count = (state->y - s3d_tri->clip_t) + 1;
}
dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str);
@@ -3065,7 +3065,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3
if (xe < s3d_tri->clip_l)
goto tri_skip_line;
if (xe > s3d_tri->clip_r)
xe = s3d_tri->clip_r;
xe = s3d_tri->clip_r + 1;
if (x < s3d_tri->clip_l)
{
int diff_x = s3d_tri->clip_l - x;
@@ -3090,7 +3090,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3
if (xe > s3d_tri->clip_r)
goto tri_skip_line;
if (xe < s3d_tri->clip_l)
xe = s3d_tri->clip_l;
xe = s3d_tri->clip_l - 1;
if (x > s3d_tri->clip_r)
{
int diff_x = x - s3d_tri->clip_r;
@@ -3115,6 +3115,9 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3
dest_addr = dest_offset + (x * (bpp + 1));
z_addr = z_offset + (x << 1);
x &= 0xfff;
xe &= 0xfff;
for (; x != xe; x = (x + x_dir) & 0xfff)
{
update = 1;

View File

@@ -33,6 +33,7 @@
#include "vid_ati18800.h"
#include "vid_ati28800.h"
//#include "vid_ati_mach8.h"
#include "vid_ati_mach64.h"
#include "vid_cga.h"
#include "vid_cl54xx.h"
@@ -49,6 +50,7 @@
#include "vid_oak_oti.h"
#include "vid_paradise.h"
#include "vid_s3.h"
//#include "vid_s3_911.h"
#include "vid_s3_virge.h"
#include "vid_sigma.h"
#include "vid_tgui9440.h"
@@ -73,6 +75,7 @@ video_cards[] = {
{ "None", "none", NULL },
{ "Internal", "internal", NULL },
{ "[ISA] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_isa", &mach64gx_isa_device },
//{ "[ISA] ATI Graphics Ultra (Mach8)", "mach8_isa", &mach8_device },
{ "[ISA] ATI Korean VGA (ATI-28800-5)", "ati28800k", &ati28800k_device },
{ "[ISA] ATI VGA-88 (ATI-18800-1)", "ati18800v", &ati18800_vga88_device },
{ "[ISA] ATI VGA Charger (ATI-28800-5)", "ati28800", &ati28800_device },
@@ -85,6 +88,11 @@ video_cards[] = {
#endif
{ "[ISA] CGA", "cga", &cga_device },
{ "[ISA] Chips & Technologies SuperEGA", "superega", &sega_device },
#if defined(DEV_BRANCH)
{ "[ISA] Cirrus Logic CL-GD 5402", "cl_gd5402_isa", &gd5402_isa_device },
{ "[ISA] Cirrus Logic CL-GD 5420", "cl_gd5420_isa", &gd5420_isa_device },
{ "[ISA] Cirrus Logic CL-GD 5422", "cl_gd5422_isa", &gd5422_isa_device },
#endif
{ "[ISA] Cirrus Logic CL-GD 5428", "cl_gd5428_isa", &gd5428_isa_device },
{ "[ISA] Cirrus Logic CL-GD 5429", "cl_gd5429_isa", &gd5429_isa_device },
{ "[ISA] Cirrus Logic CL-GD 5434", "cl_gd5434_isa", &gd5434_isa_device },
@@ -106,9 +114,11 @@ video_cards[] = {
{ "[ISA] Paradise WD90C30-LR", "wd90c30", &paradise_wd90c30_device },
{ "[ISA] Plantronics ColorPlus", "plantronics", &colorplus_device },
{ "[ISA] Sigma Color 400", "sigma400", &sigma_device },
{ "[ISA] SPEA V7 Mirage (S3 86c801)", "px_s3_v7_801_isa", &s3_v7mirage_86c801_isa_device },
#if defined(DEV_BRANCH) && defined(USE_TI)
{ "[ISA] TI CF62011 SVGA", "ti_cf62011", &ti_cf62011_device },
#endif
{ "[ISA] Trident TVGA8900B", "tvga8900b", &tvga8900b_device },
{ "[ISA] Trident TVGA8900D", "tvga8900d", &tvga8900d_device },
{ "[ISA] Trigem Korean VGA (ET4000AX)", "tgkorvga", &et4000k_isa_device },
{ "[ISA] Tseng ET4000AX", "et4000ax", &et4000_isa_device },
@@ -140,6 +150,9 @@ video_cards[] = {
{ "[PCI] Trident TGUI9440", "tgui9440_pci", &tgui9440_pci_device },
{ "[VLB] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_vlb", &mach64gx_vlb_device },
{ "[VLB] Cardex Tseng ET4000/w32p", "et4000w32p_vlb", &et4000w32p_cardex_vlb_device },
#if defined(DEV_BRANCH)
{ "[VLB] Cirrus Logic CL-GD 5424", "cl_gd5424_vlb", &gd5424_vlb_device },
#endif
{ "[VLB] Cirrus Logic CL-GD 5428", "cl_gd5428_vlb", &gd5428_vlb_device },
{ "[VLB] Cirrus Logic CL-GD 5429", "cl_gd5429_vlb", &gd5429_vlb_device },
{ "[VLB] Cirrus Logic CL-GD 5434", "cl_gd5434_vlb", &gd5434_vlb_device },
@@ -152,6 +165,7 @@ video_cards[] = {
{ "[VLB] Diamond Stealth 64 VRAM (S3 Vision964)", "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device },
{ "[VLB] Number Nine 9FX (S3 Trio64)", "n9_9fx_vlb", &s3_9fx_vlb_device },
{ "[VLB] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_vlb", &s3_bahamas64_vlb_device },
{ "[VLB] Phoenix S3 86c805", "px_86c805_vlb", &s3_phoenix_86c805_vlb_device },
{ "[VLB] Phoenix S3 Vision864", "px_vision864_vlb", &s3_phoenix_vision864_vlb_device },
{ "[VLB] Phoenix S3 Trio32", "px_trio32_vlb", &s3_phoenix_trio32_vlb_device },
{ "[VLB] Phoenix S3 Trio64", "px_trio64_vlb", &s3_phoenix_trio64_vlb_device },

View File

@@ -258,7 +258,7 @@ void tgui_out(uint16_t addr, uint8_t val, void *p)
break;
case 0xC:
if (svga->seqregs[0xe] & 0x80)
svga->seqregs[0xc] = val;
svga->seqregs[0xc] = val;
break;
case 0xd:
if (tgui->oldmode)
@@ -517,15 +517,6 @@ void tgui_recalctimings(svga_t *svga)
svga->interlace = svga->crtc[0x1e] & 4;
if (svga->interlace && tgui->type < TGUI_9440)
svga->rowoffset >>= 1;
if (svga->crtc[0x17] & 4)
{
svga->vtotal *= 2;
svga->dispend *= 2;
svga->vsyncstart *= 2;
svga->split *= 2;
svga->vblankstart *= 2;
}
if (tgui->type >= TGUI_9440)
{

View File

@@ -8,7 +8,7 @@
*
* Trident TVGA (8900D) emulation.
*
* Version: @(#)vid_tvga.c 1.0.8 2018/10/04
* Version: @(#)vid_tvga.c 1.0.9 2018/12/28
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -32,6 +32,11 @@
#include "vid_tkd8001_ramdac.h"
#include "vid_tvga.h"
#define TVGA8900B_ID 0x03
#define TVGA8900CLD_ID 0x33
#define ROM_TVGA_8900B L"roms/video/tvga/tvga8900B.VBI"
#define ROM_TVGA_8900CLD L"roms/video/tvga/trident.bin"
typedef struct tvga_t
{
@@ -41,6 +46,7 @@ typedef struct tvga_t
svga_t svga;
rom_t bios_rom;
uint8_t card_id;
uint8_t tvga_3d8, tvga_3d9;
int oldmode;
@@ -184,7 +190,7 @@ uint8_t tvga_in(uint16_t addr, void *p)
if ((svga->seqaddr & 0xf) == 0xb)
{
tvga->oldmode = 0;
return 0x33; /*TVGA8900D*/
return tvga->card_id; /*Must be at least a TVGA8900*/
}
if ((svga->seqaddr & 0xf) == 0xd)
{
@@ -237,15 +243,16 @@ void tvga_recalctimings(svga_t *svga)
if (svga->bpp == 24)
svga->hdisp = (svga->crtc[1] + 1) * 8;
if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000;
if ((svga->crtc[0x27] & 0x01) == 0x01) svga->ma_latch |= 0x20000;
if ((svga->crtc[0x27] & 0x02) == 0x02) svga->ma_latch |= 0x40000;
if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000;
if ((svga->crtc[0x27] & 0x01) == 0x01) svga->ma_latch |= 0x20000;
if ((svga->crtc[0x27] & 0x02) == 0x02) svga->ma_latch |= 0x40000;
if (tvga->oldctrl2 & 0x10)
{
svga->rowoffset <<= 1;
svga->ma_latch <<= 1;
}
if (svga->gdcreg[0xf] & 0x08)
{
svga->htotal *= 2;
@@ -253,7 +260,7 @@ void tvga_recalctimings(svga_t *svga)
svga->hdisp_time *= 2;
}
svga->interlace = (svga->crtc[0x1e] & 4);
svga->interlace = (svga->crtc[0x1e] & 4);
if (svga->interlace)
svga->rowoffset >>= 1;
@@ -273,7 +280,7 @@ void tvga_recalctimings(svga_t *svga)
switch (svga->bpp)
{
case 8:
svga->render = svga_render_8bpp_highres;
svga->render = svga_render_8bpp_highres;
break;
case 15:
svga->render = svga_render_15bpp_highres;
@@ -293,8 +300,9 @@ void tvga_recalctimings(svga_t *svga)
}
static void *tvga8900d_init(const device_t *info)
static void *tvga_init(const device_t *info)
{
const wchar_t *bios_fn;
tvga_t *tvga = malloc(sizeof(tvga_t));
memset(tvga, 0, sizeof(tvga_t));
@@ -302,8 +310,23 @@ static void *tvga8900d_init(const device_t *info)
tvga->vram_size = device_get_config_int("memory") << 10;
tvga->vram_mask = tvga->vram_size - 1;
rom_init(&tvga->bios_rom, L"roms/video/tvga/trident.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
tvga->card_id = info->local;
switch (info->local)
{
case TVGA8900B_ID:
bios_fn = ROM_TVGA_8900B;
break;
case TVGA8900CLD_ID:
bios_fn = ROM_TVGA_8900CLD;
break;
default:
free(tvga);
return NULL;
}
rom_init(&tvga->bios_rom, (wchar_t *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
svga_init(&tvga->svga, tvga, tvga->vram_size,
tvga_recalctimings,
@@ -318,9 +341,14 @@ static void *tvga8900d_init(const device_t *info)
return tvga;
}
static int tvga8900b_available(void)
{
return rom_present(ROM_TVGA_8900B);
}
static int tvga8900d_available(void)
{
return rom_present(L"roms/video/tvga/trident.bin");
return rom_present(ROM_TVGA_8900CLD);
}
void tvga_close(void *p)
@@ -371,12 +399,26 @@ static const device_config_t tvga_config[] =
}
};
const device_t tvga8900b_device =
{
"Trident TVGA 8900B",
DEVICE_ISA,
TVGA8900B_ID,
tvga_init,
tvga_close,
NULL,
tvga8900b_available,
tvga_speed_changed,
tvga_force_redraw,
tvga_config
};
const device_t tvga8900d_device =
{
"Trident TVGA 8900D",
DEVICE_ISA,
0,
tvga8900d_init,
TVGA8900CLD_ID,
tvga_init,
tvga_close,
NULL,
tvga8900d_available,

View File

@@ -1,4 +1,5 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
extern const device_t tvga8900b_device;
extern const device_t tvga8900d_device;

View File

@@ -8,7 +8,7 @@
*
* Application resource script for Windows.
*
* Version: @(#)86Box.rc 1.0.42 2018/09/06
* Version: @(#)86Box.rc 1.0.44 2018/11/19
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -850,7 +850,7 @@ END
STRINGTABLE DISCARDABLE
BEGIN
IDS_2080 "E&xport to 86F..."
IDS_2081 "Unable to initialize FluidSynth, make sure you have the following libraries\nin your 86Box folder:\n\nlibfluidsynth.dll\nlibglib-2.0-0.dll\nlibiconv-2.dll\nlibintl-8.dll\nlibpcre-1.dll"
IDS_2081 "Unable to initialize FluidSynth, libfluidsynth.dll is required"
IDS_2082 "Bus"
IDS_2083 "File"
IDS_2084 "C"
@@ -887,8 +887,10 @@ BEGIN
IDS_2115 "%u"
IDS_2116 "%u MB (CHS: %i, %i, %i)"
IDS_2117 "Floppy %i (%s): %ls"
IDS_2118 "All images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.DDI;*.DSK;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.DDI;*.DSK;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.DDI;*.DSK;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.DDI;*.DSK;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F)\0*.86F\0All files (*.*)\0*.*\0"
IDS_2118 "All images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0"
IDS_2119 "You must save the settings first before attempting to configure the memory boards"
IDS_2120 "Unable to initialize FreeType, freetype.dll is required"
IDS_2121 "Unable to initialize SDL, SDL2.dll is required"
END
STRINGTABLE DISCARDABLE

View File

@@ -8,7 +8,7 @@
#
# Makefile for Win32 (MinGW32) environment.
#
# Version: @(#)Makefile.mingw 1.0.134 2018/10/26
# Version: @(#)Makefile.mingw 1.0.136 2019/01/13
#
# Authors: Miran Grca, <mgrca8@gmail.com>
# Fred N. van Kempen, <decwiz@yahoo.com>
@@ -47,6 +47,9 @@ ifeq ($(DEV_BUILD), y)
ifndef D2D
D2D := y
endif
ifndef GUS_MAX
GUS_MAX := y
endif
ifndef I686
I686 := y
endif
@@ -87,6 +90,9 @@ else
ifndef D2D
D2D := n
endif
ifndef GUS_MAX
GUS_MAX := n
endif
ifndef I686
I686 := n
endif
@@ -295,7 +301,7 @@ ifneq ($(WX), n)
UIOBJ := wx_main.o wx_ui.o wx_stbar.o wx_render.o
else
UIOBJ := win_ui.o win_stbar.o \
win_ddraw.o win_d2d.o win_d3d.o win_sdl.o \
win_ddraw.o win_d3d.o win_sdl.o \
win_dialog.o win_about.o \
win_settings.o win_devconf.o win_snd_gain.o \
win_new_floppy.o win_jsconf.o
@@ -323,6 +329,7 @@ ifeq ($(D2D), y)
OPTS += -DUSE_D2D
RFLAGS += -DUSE_D2D
D2DLIB := -ld2d1
D2DOBJ := win_d2d.o
endif
ifeq ($(VNC), y)
@@ -361,6 +368,11 @@ OPTS += -DUSE_CRASHDUMP
DEVBROBJ += win_crashdump.o
endif
ifeq ($(GUS_MAX), y)
OPTS += -DUSE_GUSMAX
DEVBROBJ += snd_cs423x.o
endif
ifeq ($(I686), y)
OPTS += -DUSE_I686
endif
@@ -431,6 +443,7 @@ MCHOBJ := machine.o machine_table.o \
m_xt.o m_xt_compaq.o \
m_xt_t1000.o m_xt_t1000_vid.o \
m_xt_xi8088.o \
m_xt_zenith.o \
m_pcjr.o \
m_amstrad.o \
m_europc.o \
@@ -461,7 +474,7 @@ DEVOBJ := bugger.o isamem.o isartc.o lpt.o $(SERIAL) \
FDDOBJ := fdd.o fdc.o fdi2raw.o \
fdd_common.o fdd_86f.o \
fdd_fdi.o fdd_imd.o fdd_img.o fdd_json.o \
fdd_td0.o
fdd_mfm.o fdd_td0.o
HDDOBJ := hdd.o \
hdd_image.o hdd_table.o \
@@ -470,7 +483,7 @@ HDDOBJ := hdd.o \
hdc_xta.o \
hdc_esdi_at.o hdc_esdi_mca.o \
hdc_xtide.o hdc_ide.o
CDROMOBJ := cdrom.o \
cdrom_dosbox.o cdrom_image.o
@@ -539,6 +552,7 @@ VIDOBJ := video.o \
vid_ati18800.o vid_ati28800.o \
vid_ati_mach64.o vid_ati68860_ramdac.o \
vid_bt48x_ramdac.o \
vid_av9194.o \
vid_icd2061.o vid_ics2595.o \
vid_cl54xx.o \
vid_et4000.o vid_sc1502x_ramdac.o \
@@ -548,6 +562,7 @@ VIDOBJ := video.o \
vid_ti_cf62011.o \
vid_tvga.o \
vid_tgui9440.o vid_tkd8001_ramdac.o \
vid_att20c49x_ramdac.o \
vid_s3.o vid_s3_virge.o \
vid_sdac_ramdac.o \
vid_voodoo.o
@@ -560,7 +575,7 @@ PLATOBJ := win.o \
OBJ := $(MAINOBJ) $(INTELOBJ) $(CPUOBJ) $(MCHOBJ) $(DEVOBJ) \
$(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(HDDOBJ) \
$(USBOBJ) $(NETOBJ) $(PRINTOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) \
$(PLATOBJ) $(UIOBJ) $(FSYNTHOBJ) $(MUNTOBJ) \
$(PLATOBJ) $(UIOBJ) $(D2DOBJ) $(FSYNTHOBJ) $(MUNTOBJ) \
$(DEVBROBJ)
ifdef EXOBJ
OBJ += $(EXOBJ)

View File

@@ -1,4 +1,4 @@
/*
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
@@ -8,7 +8,7 @@
*
* Windows resource defines.
*
* Version: @(#)resource.h 1.0.28 2018/09/02
* Version: @(#)resource.h 1.0.30 2019/01/19
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -149,6 +149,7 @@
#define IDC_CHECK_MPU401 1077
#define IDC_CONFIGURE_MPU401 1078
#define IDC_CHECK_FLOAT 1079
#define IDC_CHECK_GUSMAX 1080
#define IDC_COMBO_NET_TYPE 1090 /* network config */
#define IDC_COMBO_PCAP 1091
@@ -264,10 +265,18 @@
#define IDM_VID_RESIZE 40040
#define IDM_VID_REMEMBER 40041
#define IDM_VID_DDRAW 40050
#ifdef USE_D2D
#define IDM_VID_D2D 40051
#define IDM_VID_D3D 40052
#define IDM_VID_SDL 40053
#define IDM_VID_VNC 40054
#else
#define IDM_VID_D3D 40051
#define IDM_VID_SDL 40052
#ifdef USE_VNC
#define IDM_VID_VNC 40053
#endif
#endif
#define IDM_VID_SCALE_1X 40055
#define IDM_VID_SCALE_2X 40056
#define IDM_VID_SCALE_3X 40057

View File

@@ -8,7 +8,7 @@
*
* Platform main support module for Windows.
*
* Version: @(#)win.c 1.0.54 2018/10/18
* Version: @(#)win.c 1.0.55 2018/11/19
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -86,7 +86,9 @@ static struct {
} vid_apis[2][RENDERERS_NUM] = {
{
{ "DDraw", 1, (int(*)(void*))ddraw_init, ddraw_close, NULL, ddraw_pause },
#ifdef USE_D2D
{ "D2D", 1, (int(*)(void*))d2d_init, d2d_close, NULL, d2d_pause },
#endif
{ "D3D", 1, (int(*)(void*))d3d_init, d3d_close, d3d_resize, d3d_pause },
{ "SDL", 1, (int(*)(void*))sdl_init, sdl_close, NULL, sdl_pause }
#ifdef USE_VNC
@@ -95,7 +97,9 @@ static struct {
},
{
{ "DDraw", 1, (int(*)(void*))ddraw_init_fs, ddraw_close, NULL, ddraw_pause },
#ifdef USE_D2D
{ "D2D", 1, (int(*)(void*))d2d_init_fs, d2d_close, NULL, d2d_pause },
#endif
{ "D3D", 1, (int(*)(void*))d3d_init_fs, d3d_close, NULL, d3d_pause },
{ "SDL", 1, (int(*)(void*))sdl_init_fs, sdl_close, sdl_resize, sdl_pause }
#ifdef USE_VNC
@@ -633,7 +637,6 @@ plat_vidapi_name(int api)
case 1:
name = "d2d";
break;
#endif
case 2:
name = "d3d";
@@ -642,9 +645,22 @@ plat_vidapi_name(int api)
case 3:
name = "sdl";
break;
#else
case 1:
name = "d3d";
break;
case 2:
name = "sdl";
break;
#endif
#ifdef USE_VNC
#ifdef USE_D2D
case 4:
#else
case 3:
#endif
name = "vnc";
break;
#endif
@@ -753,7 +769,7 @@ take_screenshot(void)
time_t now;
win_log("Screenshot: video API is: %i\n", vid_api);
if ((vid_api < 0) || (vid_api > 2)) return;
if ((vid_api < 0) || (vid_api >= RENDERERS_NUM)) return;
memset(fn, 0, sizeof(fn));
memset(path, 0, sizeof(path));
@@ -780,7 +796,6 @@ take_screenshot(void)
case 1: /* d2d */
d2d_take_screenshot(path);
break;
#endif
case 2: /* d3d9 */
d3d_take_screenshot(path);
@@ -789,9 +804,22 @@ take_screenshot(void)
case 3: /* sdl */
sdl_take_screenshot(path);
break;
#else
case 1: /* d3d9 */
d3d_take_screenshot(path);
break;
case 2: /* sdl */
sdl_take_screenshot(path);
break;
#endif
#ifdef USE_VNC
#ifdef USE_D2D
case 4: /* vnc */
#else
case 3: /* vnc */
#endif
vnc_take_screenshot(path);
break;
#endif

View File

@@ -59,10 +59,18 @@
#define WM_SENDSSTATUS 0x8896
#ifdef USE_VNC
#ifdef USE_D2D
#define RENDERERS_NUM 5
#else
#define RENDERERS_NUM 4
#endif
#else
#ifdef USE_D2D
#define RENDERERS_NUM 4
#else
#define RENDERERS_NUM 3
#endif
#endif
extern HINSTANCE hinstance;

View File

@@ -11,7 +11,7 @@
* NOTES: This code should be re-merged into a single init() with a
* 'fullscreen' argument, indicating FS mode is requested.
*
* Version: @(#)win_ddraw.cpp 1.0.12 2018/10/18
* Version: @(#)win_ddraw.cpp 1.0.13 2018/11/18
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -186,9 +186,7 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap)
}
if (ys2 <= 250) {
bmpInfo.bmiHeader.biSizeImage <<= 1;
pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage);
pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage << 1);
if (pBuf2 == NULL) {
ddraw_log("[SavePNG] Unable to Allocate Secondary Bitmap Memory");
free(pBuf);
@@ -196,7 +194,6 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap)
return;
}
bmpInfo.bmiHeader.biHeight <<= 1;
}
ddraw_log("save png w=%i h=%i\n", bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight);
@@ -205,6 +202,11 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap)
GetDIBits(hdc, hBitmap, 0, bmpInfo.bmiHeader.biHeight, pBuf, &bmpInfo, DIB_RGB_COLORS);
if (pBuf2) {
bmpInfo.bmiHeader.biSizeImage <<= 1;
bmpInfo.bmiHeader.biHeight <<= 1;
}
png_set_IHDR(png_ptr, info_ptr, bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight,
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

View File

@@ -8,7 +8,7 @@
*
* Joystick interface to host device.
*
* Version: @(#)win_joystick.cpp 1.0.10 2018/10/18
* Version: @(#)win_joystick.cpp 1.0.11 2018/11/11
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -85,7 +85,7 @@ BOOL CALLBACK DIEnumDeviceObjectsCallback(
lpddoi->guidType == GUID_RxAxis || lpddoi->guidType == GUID_RyAxis || lpddoi->guidType == GUID_RzAxis ||
lpddoi->guidType == GUID_Slider)
{
strncpy(state->axis[state->nr_axes].name, lpddoi->tszName, sizeof(state->axis[state->nr_axes].name));
memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(state->axis[state->nr_axes].name) + 1);
joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType);
if (lpddoi->guidType == GUID_XAxis)
state->axis[state->nr_axes].id = 0;
@@ -103,13 +103,13 @@ BOOL CALLBACK DIEnumDeviceObjectsCallback(
}
else if (lpddoi->guidType == GUID_Button)
{
strncpy(state->button[state->nr_buttons].name, lpddoi->tszName, sizeof(state->button[state->nr_buttons].name));
memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(state->button[state->nr_buttons].name) + 1);
joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType);
state->nr_buttons++;
}
else if (lpddoi->guidType == GUID_POV)
{
strncpy(state->pov[state->nr_povs].name, lpddoi->tszName, sizeof(state->pov[state->nr_povs].name));
memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(state->pov[state->nr_povs].name) + 1);
joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType);
state->nr_povs++;
}
@@ -155,7 +155,7 @@ void joystick_init()
joystick_log("Joystick %i :\n", c);
joystick_log(" tszInstanceName = %s\n", device_instance.tszInstanceName);
joystick_log(" tszProductName = %s\n", device_instance.tszProductName);
strncpy(plat_joystick_state[c].name, device_instance.tszInstanceName, 64);
memcpy(plat_joystick_state[c].name, device_instance.tszInstanceName, 260);
memset(&devcaps, 0, sizeof(devcaps));
devcaps.dwSize = sizeof(devcaps);

View File

@@ -29,6 +29,7 @@ static void rebuild_axis_button_selections(HWND hdlg)
HWND h;
int joystick;
int c, d;
char s[269];
h = GetDlgItem(hdlg, IDC_CONFIG_BASE);
joystick = SendMessage(h, CB_GETCURSEL, 0, 0);
@@ -53,8 +54,6 @@ static void rebuild_axis_button_selections(HWND hdlg)
}
for (d = 0; d < plat_joystick_state[joystick-1].nr_povs; d++)
{
char s[80];
sprintf(s, "%s (X axis)", plat_joystick_state[joystick-1].pov[d].name);
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s);
sprintf(s, "%s (Y axis)", plat_joystick_state[joystick-1].pov[d].name);
@@ -98,8 +97,6 @@ static void rebuild_axis_button_selections(HWND hdlg)
{
for (d = 0; d < plat_joystick_state[joystick-1].nr_povs; d++)
{
char s[80];
sprintf(s, "%s (X axis)", plat_joystick_state[joystick-1].pov[d].name);
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s);
sprintf(s, "%s (Y axis)", plat_joystick_state[joystick-1].pov[d].name);
@@ -294,6 +291,7 @@ uint8_t joystickconfig_open(HWND hwnd, int joy_nr, int type)
int y = 10;
int id = IDC_CONFIG_BASE;
int c;
char s[269];
joystickconfig_changed = 0;
@@ -462,8 +460,6 @@ uint8_t joystickconfig_open(HWND hwnd, int joy_nr, int type)
for (c = 0; c < joystick_get_pov_count(type)*2; c++)
{
char s[80];
/*Combo box*/
item = (DLGITEMTEMPLATE *)data;
item->x = 70;

View File

@@ -8,7 +8,7 @@
*
* Handle the New Floppy Image dialog.
*
* Version: @(#)win_new_floppy.c 1.0.9 2018/10/02
* Version: @(#)win_new_floppy.c 1.0.10 2019/01/17
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
@@ -75,7 +75,7 @@ create_86f(WCHAR *file_name, disk_size_t disk_size, uint8_t rpm_mode)
FILE *f;
uint32_t magic = 0x46423638;
uint16_t version = 0x020B;
uint16_t version = 0x020C;
uint16_t dflags = 0;
uint16_t tflags = 0;
uint32_t index_hole_pos = 0;

Some files were not shown because too many files have changed in this diff Show More