mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 09:35:32 -07:00
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:
@@ -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. */
|
||||
|
||||
@@ -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 :=
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
42
src/config.c
42
src/config.c
@@ -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, §ion->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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
5687
src/cpu/808x.c
5687
src/cpu/808x.c
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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}
|
||||
};
|
||||
|
||||
102
src/cpu/x86.h
102
src/cpu/x86.h
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
21
src/device.h
21
src/device.h
@@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
22
src/dma.c
22
src/dma.c
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
469
src/floppy/fdd_mfm.c
Normal 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
26
src/floppy/fdd_mfm.h
Normal 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*/
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
41
src/lpt.c
41
src/lpt.c
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
113
src/machine/m_xt_zenith.c
Normal 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);
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 },
|
||||
|
||||
74
src/mem.c
74
src/mem.c
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
11
src/pc.c
11
src/pc.c
@@ -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();
|
||||
|
||||
|
||||
44
src/pic.c
44
src/pic.c
@@ -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);
|
||||
|
||||
55
src/pit.c
55
src/pit.c
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
|
||||
166
src/serial.c
166
src/serial.c
@@ -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,
|
||||
|
||||
13
src/serial.h
13
src/serial.h
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
156
src/video/vid_att20c49x_ramdac.c
Normal file
156
src/video/vid_att20c49x_ramdac.c
Normal 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
|
||||
};
|
||||
32
src/video/vid_att20c49x_ramdac.h
Normal file
32
src/video/vid_att20c49x_ramdac.h
Normal 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
102
src/video/vid_av9194.c
Normal 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
21
src/video/vid_av9194.h
Normal 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;
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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)",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 = ""
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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; */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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", ¶dise_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 },
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user